/* * Compile and dump the device tree * * Copyright 2013 Google Inc. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #include /* you can't include string.h due to conflicts with coreboot prototypes. */ void *memcpy(void *m1, void *m2, size_t s); struct device_operations default_dev_ops_root = { .read_resources = NULL, .set_resources = NULL, .enable_resources = NULL, .init = NULL, .scan_bus = NULL, .reset_bus = NULL, }; extern struct device dev_root; struct device *all_devices = &dev_root; const char mainboard_name[] = "showdt"; /* * Warning: This function uses a static buffer. Don't call it more than once * from the same print statement! */ const char *dev_path(device_t dev) { static char buffer[DEVICE_PATH_MAX]; buffer[0] = '\0'; if (!dev) { memcpy(buffer, "", 7); } else { switch(dev->path.type) { case DEVICE_PATH_ROOT: memcpy(buffer, "Root Device", 12); break; case DEVICE_PATH_PCI: #if CONFIG_PCI_BUS_SEGN_BITS sprintf(buffer, "PCI: %04x:%02x:%02x.%01x", dev->bus->secondary >> 8, dev->bus->secondary & 0xff, PCI_SLOT(dev->path.pci.devfn), PCI_FUNC(dev->path.pci.devfn)); #else sprintf(buffer, "PCI: %02x:%02x.%01x", dev->bus->secondary, PCI_SLOT(dev->path.pci.devfn), PCI_FUNC(dev->path.pci.devfn)); #endif break; case DEVICE_PATH_PNP: sprintf(buffer, "PNP: %04x.%01x", dev->path.pnp.port, dev->path.pnp.device); break; case DEVICE_PATH_I2C: sprintf(buffer, "I2C: %02x:%02x", dev->bus->secondary, dev->path.i2c.device); break; case DEVICE_PATH_APIC: sprintf(buffer, "APIC: %02x", dev->path.apic.apic_id); break; case DEVICE_PATH_IOAPIC: sprintf(buffer, "IOAPIC: %02x", dev->path.ioapic.ioapic_id); break; case DEVICE_PATH_DOMAIN: sprintf(buffer, "DOMAIN: %04x", dev->path.domain.domain); break; case DEVICE_PATH_CPU_CLUSTER: sprintf(buffer, "CPU_CLUSTER: %01x", dev->path.cpu_cluster.cluster); break; case DEVICE_PATH_CPU: sprintf(buffer, "CPU: %02x", dev->path.cpu.id); break; case DEVICE_PATH_CPU_BUS: sprintf(buffer, "CPU_BUS: %02x", dev->path.cpu_bus.id); break; case DEVICE_PATH_MMIO: sprintf(buffer, "MMIO: %08x", dev->path.mmio.addr); break; default: printf("Unknown device path type: %d\n", dev->path.type); break; } } return buffer; } void show_devs_tree(struct device *dev, int debug_level, int depth, int linknum) { char depth_str[20] = ""; int i; struct device *sibling; struct bus *link; for (i = 0; i < depth; i++) depth_str[i] = ' '; depth_str[i] = '\0'; printf("%s%s: enabled %d%s\n", depth_str, dev_path(dev), dev->enabled, dev->chip_ops ? ":has a chip":""); for (link = dev->link_list; link; link = link->next) { for (sibling = link->children; sibling; sibling = sibling->sibling) show_devs_tree(sibling, debug_level, depth + 1, i); } } void show_all_devs_tree(int debug_level, const char *msg) { printf("Show all devs in tree form...%s\n", msg); show_devs_tree(all_devices, debug_level, 0, -1); } void show_devs_subtree(struct device *root, int debug_level, const char *msg) { printf("Show all devs in subtree %s...%s\n", dev_path(root), msg); printf("%s\n", msg); show_devs_tree(root, debug_level, 0, -1); } void show_all_devs(int debug_level, const char *msg) { struct device *dev; printf("Show all devs...%s\n", msg); for (dev = all_devices; dev; dev = dev->next) { printf("%s: enabled %d%s\n", dev_path(dev), dev->enabled, dev->chip_ops ? ":has a chip":""); } } main() { show_all_devs(1, ""); show_all_devs_tree(1, ""); } /* * Example: (yank this and paste into M-x compile in emacs) * or tail -2 showdt.c | head -1 |sh * or whatever. cc -I ../src -I ../src/include -I ../src/arch/arm/include/ -include build/mainboard/google/snow/static.c showdt.c */