* Copyright 2024, Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* JΓ©rΓ΄me Duval <jerome.duval@gmail.com>
*/
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <OS.h>
extern const char *__progname;
static const char *kCommandName = __progname;
static const char *kUsage =
"Usage: %s [ <options> ] [ command ] [ args ]\n"
"\n"
"Options:\n"
" --count <n> - Read n registers.\n"
;
static void
print_usage(bool error)
{
fprintf((error ? stderr : stdout), kUsage, kCommandName);
}
static void
print_usage_and_exit(bool error)
{
print_usage(error);
exit(error ? 1 : 0);
}
int
main(int argc, const char *const *argv)
{
const char *const *programArgs = NULL;
int32_t programArgCount = 0;
uint32_t count = 1;
for (int argi = 1; argi < argc; argi++) {
const char *arg = argv[argi];
if (arg[0] == '-') {
if (strcmp(arg, "-h") == 0 || strcmp(arg, "--help") == 0) {
print_usage_and_exit(false);
} else if (strcmp(arg, "--count") == 0) {
count = strtol(argv[++argi], (char **)NULL, 10);
if (count == 0 && errno != 0)
print_usage_and_exit(true);
} else {
print_usage_and_exit(true);
}
} else {
programArgs = argv + argi;
programArgCount = argc - argi;
break;
}
}
bool write = false;
uint32 value = 0;
if (programArgCount < 2) {
print_usage_and_exit(true);
}
if (strcmp(programArgs[0], "read") == 0) {
if (programArgCount >= 4) {
const char *arg = programArgs[1];
if (arg[0] == '-') {
if (strcmp(arg, "--count") == 0) {
count = strtol(programArgs[2], (char **)NULL, 10);
if (count == 0 && errno != 0)
print_usage_and_exit(true);
programArgCount -= 2;
programArgs += 2;
} else {
print_usage_and_exit(true);
}
}
}
} else if (strcmp(programArgs[0], "write") == 0) {
write = true;
} else
print_usage_and_exit(true);
programArgCount--;
programArgs++;
area_id area = find_area("intel extreme mmio");
if (area < 0) {
fprintf(stderr, "couldn't find intel extreme mmio area\n");
exit(1);
}
void* regs;
uint32 protection = B_READ_AREA | (write ? B_WRITE_AREA : 0);
area_id clone = clone_area("clone regs", ®s, B_ANY_ADDRESS, protection, area);
if (clone < B_OK) {
fprintf(stderr, "couldn't clone intel extreme mmio area\n");
exit(1);
}
while (programArgCount > 0) {
const char* arg = programArgs[0];
programArgCount--;
programArgs++;
if (write) {
if (programArgCount < 1)
print_usage_and_exit(true);
const char* val = programArgs[0];
if (val[0] == '0' && (val[1] == 'x' || val[1] == 'X'))
value = strtol(val + 2, (char **)NULL, 16);
else
value = strtol(val, (char **)NULL, 10);
if (value == 0 && errno != 0)
print_usage_and_exit(true);
programArgCount--;
programArgs++;
}
uint64_t address;
if (arg[0] == '0' && (arg[1] == 'x' || arg[1] == 'X')) {
address = strtol(arg + 2, (char **)NULL, 16);
} else
address = strtol(arg, (char **)NULL, 10);
if (address == 0 && errno != 0)
print_usage_and_exit(true);
for (uint32_t i = 0; i < count; i++) {
addr_t addr = (addr_t)regs + address + i * sizeof(uint32);
if (write) {
*(uint32*)addr = value;
} else {
printf("(0x%08" B_PRIxADDR "): 0x%08" B_PRIx32 "\n", address + i * sizeof(uint32), *(uint32*)addr);
}
}
}
delete_area(clone);
exit(0);
}