Skip to content

Commit

Permalink
lib: acpi: add resource enumeration shell command
Browse files Browse the repository at this point in the history
add resource enumeration and acpi method shell commands such as
retrieve mmio, interrupt and gpio resources.

Signed-off-by: Najumon B.A <[email protected]>
  • Loading branch information
najumon1980 committed Oct 4, 2023
1 parent d52d385 commit c9ac74b
Showing 1 changed file with 142 additions and 6 deletions.
148 changes: 142 additions & 6 deletions lib/acpi/acpi_shell.c
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,14 @@ static void dump_dev_res(const struct shell *sh, ACPI_RESOURCE *res_lst)
shell_print(sh, "ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64\n\n");
break;
case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
ACPI_RESOURCE_EXTENDED_IRQ * ext_irq_res = &res->Data.ExtendedIrq;

shell_print(sh, "ACPI_RESOURCE_TYPE_EXTENDED_IRQ\n\n");
shell_print(sh, "Triggering:%x, Polarity:%x, Shareable:%x,",
ext_irq_res->Triggering, ext_irq_res->Polarity,
ext_irq_res->Shareable);
shell_print(sh, "InterruptCount:%d, Interrupts[0]:%x\n",
ext_irq_res->InterruptCount, ext_irq_res->Interrupts[0]);
break;
case ACPI_RESOURCE_TYPE_GENERIC_REGISTER:
shell_print(sh, "ACPI_RESOURCE_TYPE_GENERIC_REGISTER\n\n");
Expand Down Expand Up @@ -137,6 +144,7 @@ static void dump_dev_res(const struct shell *sh, ACPI_RESOURCE *res_lst)
shell_print(sh, "ACPI_RESOURCE_TYPE_PIN_GROUP_CONFIG\n\n");
break;
default:
shell_print(sh, "ACPI_RESOURCE_TYPE_ UNKNOWN\n\n");
}

res = ACPI_NEXT_RESOURCE(res);
Expand Down Expand Up @@ -220,18 +228,101 @@ static int dump_prt(const struct shell *sh, size_t argc, char **argv)
static int enum_dev(const struct shell *sh, size_t argc, char **argv)
{
struct acpi_dev *dev;
ACPI_RESOURCE *res_lst;

if (argc < 2) {
if (argc < 3) {
shell_error(sh, "Invalid Arugements [Eg: acpi enum PNP0103 0]\n");
return -EINVAL;
}

dev = acpi_device_get(argv[1], 0);
dev = acpi_device_get(argv[1], argv[2]);
if (!dev || !dev->res_lst) {
shell_error(sh, "acpi get device failed for HID: %s\n", argv[1]);
return -EIO;
}
shell_print(sh, "\nName:%s\n", dev->path ? dev->path : "Non");
dump_dev_res(sh, dev->res_lst);
shell_print(sh, "\nName:%s, Address:%llx\n", dev->path ? dev->path : "Non",
dev->dev_info->Address);

if (dev->path) {
if (!acpi_current_resource_get(dev->path, &res_lst)) {
dump_dev_res(sh, res_lst);
acpi_current_resource_free(res_lst);
}
}

return 0;
}

static int enum_all_dev(const struct shell *sh, size_t argc, char **argv)
{
struct acpi_dev *dev;

for (int i = 0; i < 1000; i++) {
dev = acpi_device_by_index_get(i);

if (!dev) {
shell_print(sh, "No more ACPI device found!\n");
break;
}

shell_print(sh, "%d) Name:%s, HID:%s\n", i, dev->path ? dev->path : "Non",
dev->dev_info->HardwareId.String ? dev->dev_info->HardwareId.String
: "");

if (dev->dev_info->ClassCode.String) {
shell_print(sh, "CLS:%s\n", dev->dev_info->ClassCode.String);
}

for (int j = 0; j < dev->dev_info->CompatibleIdList.Count; j++) {
shell_print(sh, "CID[%d]:%s\n", j,
dev->dev_info->CompatibleIdList.Ids[j].String
? dev->dev_info->CompatibleIdList.Ids[j].String
: "");
}
}

return 0;
}

static int get_acpi_dev_resource(const struct shell *sh, size_t argc, char **argv)
{
struct acpi_dev *dev;
struct acpi_irq_resource irq_res;
struct acpi_mmio_resource mmio_res;

if (argc < 3) {
return -EINVAL;
}

dev = acpi_device_get(argv[1], argv[2]);
if (!dev) {
shell_error(sh, "acpi get device failed for HID: %s\n", argv[1]);
return -EIO;
}

if (dev->path) {
shell_print(sh, "\nName:%s\n", dev->path);

if (!acpi_device_irq_resource_get(dev, &irq_res)) {

shell_print(sh, "**** IRQ resources ****\n");
for (int i = 0; i < irq_res.irq_vector_max; i++) {
shell_print(sh, "Irq Num: %x, Flags:%x\n", irq_res.irqs[i],
irq_res.flags);
}
}

if (!acpi_device_mmio_resource_get(dev, &mmio_res)) {

shell_print(sh, "**** MMIO resources ****\n");
for (int i = 0; i < ACPI_RESOURCE_COUNT_GET(&mmio_res); i++) {
shell_print(sh, "Type: %x, Address:%p, Size:%d\n",
ACPI_MULTI_RESOURCE_TYPE_GET(&mmio_res, i),
(void *)ACPI_MULTI_MMIO_GET(&mmio_res, i),
ACPI_MULTI_RESOURCE_SIZE_GET(&mmio_res, i));
}
}
}

return 0;
}
Expand Down Expand Up @@ -259,6 +350,42 @@ static int read_table(const struct shell *sh, size_t argc, char **argv)
return 0;
}

static int invoke_method(const struct shell *sh, size_t argc, char **argv)
{
int status;
ACPI_OBJECT args[2];
ACPI_OBJECT_LIST arg_list;
ACPI_OBJECT acpi_obj;

if (argc < 4) {
return -EINVAL;
}

arg_list.Count = 2;
arg_list.Pointer = args;

args[0].Type = ACPI_TYPE_INTEGER;
args[0].Integer.Value = atoi(argv[2]);

args[1].Type = ACPI_TYPE_INTEGER;
args[1].Integer.Value = atoi(argv[3]);

shell_print(sh, "ACPI Invoke method: %s %lld %lld\n", argv[1], args[0].Integer.Value,
args[1].Integer.Value);

status = acpi_invoke_method(argv[1], &arg_list, &acpi_obj);
if (status) {
shell_error(sh, "ACPI get table failed: %d\n", status);
return status;
}
if (acpi_obj.Type == ACPI_TYPE_INTEGER) {
shell_print(sh, "Return info: %lld\n", acpi_obj.Integer.Value);
} else {
shell_print(sh, "Return info type: %d\n", acpi_obj.Type);
}
return 0;
}

SHELL_STATIC_SUBCMD_SET_CREATE(
sub_acpi,
SHELL_CMD(crs, NULL,
Expand All @@ -272,9 +399,18 @@ SHELL_STATIC_SUBCMD_SET_CREATE(
SHELL_CMD(enum, NULL,
"enumerate device using hid (for enum HPET timer device,eg:acpi enum PNP0103)",
enum_dev),
SHELL_CMD(rd_table, NULL,
"read acpi table (for read mad table, eg:acpi read_table APIC)",
SHELL_CMD(enum_all, NULL, "enumerate all device in acpi name space (eg:acpi enum_all)",
enum_all_dev),
SHELL_CMD(
dev_res, NULL,
"retrieve device resource (eg: acpi dev_res PNP0501 2)",
get_acpi_dev_resource),
SHELL_CMD(rd_table, NULL, "read ACPI table (eg: acpi read_table APIC)",
read_table),
SHELL_CMD(
method, NULL,
"invoke ACPI method (eg: acpi method \\_SB.GINF 2 6)",
invoke_method),
SHELL_SUBCMD_SET_END /* Array terminated. */
);

Expand Down

0 comments on commit c9ac74b

Please sign in to comment.