void ofw_construct_node(char **bufPtr, device_node_t *parent, device_node_t **sib, device_node_t **nodelist, unsigned long asic_base) { DeviceTreeNode *bufNode = (DeviceTreeNode *) *bufPtr; DeviceTreeNodeProperty *bufProp; device_node_t *node, *kid = NULL; property_t *prop; reg_property_t *reg; pci_reg_property_t *pciOFW; char *propData; int p, i; long *seenAAPL = NULL; int seenAssigned = FALSE; if (bufNode->nProperties == 0) return; node = (device_node_t *) ofw_alloc(sizeof(*node)); bzero((char *) node, sizeof(*node)); node->parent = parent; prop = NULL; *bufPtr = (char *) (bufNode + 1); if (*nodelist) (*nodelist)->allnext = node; else ofw_node_list = node; *nodelist = node; if (*sib) (*sib)->sibling = node; *sib = node; if (parent && parent->child == NULL) parent->child = node; for (p = 0; p < bufNode->nProperties; p++) { // Iterate through the list of properties. bufProp = (DeviceTreeNodeProperty *) *bufPtr; propData = (char *) (bufProp+1); *bufPtr = (char *) (next_prop(bufProp)); if (prop) { prop->next = ofw_alloc(sizeof(property_t)); prop = prop->next; } else { prop = ofw_alloc(sizeof(property_t)); node->properties = prop; } bzero((char *) prop, sizeof(*prop)); prop->value = (unsigned char *) propData; prop->length = bufProp->length; prop->name = bufProp->name; /* * Look through each property and build * up a convience shopping list for the node */ if (strcmp(bufProp->name, "name") == 0) { node->name = ofw_alloc(prop->length+1); strncpy(node->name, propData, prop->length); node->name[prop->length] = 0; /* Kind of device - dbdma, scsi, pram, etc */ } else if (strcmp(bufProp->name, "device_type") == 0) node->type = propData; /* Look for assigned addresses */ else if(strcmp(bufProp->name, "assigned-addresses") == 0) { seenAssigned = TRUE; node->addrs = reg = (reg_property_t *) ofw_alloc(bufProp->length); pciOFW = (pci_reg_property_t *) propData; for (i = 0; i < bufProp->length; reg++, pciOFW++) { reg->address = pciOFW->addr.addr_low; reg->size = pciOFW->size_low; i += sizeof(pci_reg_property_t); } node->n_addrs = i / sizeof(pci_reg_property_t); /* Look for register address */ } else if (strcmp(bufProp->name, "reg") == 0) { /* If the assigned-addresses property has * already been seen, don't bother with */ if (seenAssigned) continue; node->n_addrs = bufProp->length/sizeof(reg_property_t); node->addrs = (reg_property_t *)ofw_alloc(bufProp->length); bcopy_nc(propData, (char*)node->addrs, bufProp->length); /* Adjust the addresses - most are relative to * the asic which contains them */ for (i = 0; i < node->n_addrs; i++) node->addrs[i].address += asic_base; } else if (strcmp(bufProp->name, "AAPL,interrupts") == 0) { node->n_intrs = prop->length / sizeof(long); node->intrs = (unsigned long *) prop->value; } else if (strcmp(bufProp->name, "AAPL,address") == 0) seenAAPL = (long *) propData; } #if 0 /* * Override the register address values with Apple * defined ones if the property was seen. */ if (seenAAPL && !seenAssigned && node->n_addrs) { for (i = 0; i < node->n_addrs; i++) node->addrs[i].address = seenAAPL[i]; } #endif /* Is there a better way? */ if (node->type && node->n_addrs && strcmp(node->type, "dbdma") == 0) asic_base = node->addrs[0].address; kid = NULL; parent = node; for (i = 0; i < bufNode->nChildren; i++) ofw_construct_node(bufPtr, parent, &kid, nodelist, asic_base); }
void bootstrap(void) { version_print(); ofw_memmap(&bootinfo.memmap); void *bootinfo_pa = ofw_translate(&bootinfo); void *real_mode_pa = ofw_translate(&real_mode); void *loader_address_pa = ofw_translate((void *) LOADER_ADDRESS); printf("\nMemory statistics (total %llu MB)\n", bootinfo.memmap.total >> 20); printf(" %p|%p: real mode trampoline\n", &real_mode, real_mode_pa); printf(" %p|%p: boot info structure\n", &bootinfo, bootinfo_pa); printf(" %p|%p: kernel entry point\n", (void *) PA2KA(BOOT_OFFSET), (void *) BOOT_OFFSET); printf(" %p|%p: loader entry point\n", (void *) LOADER_ADDRESS, loader_address_pa); size_t i; for (i = 0; i < COMPONENTS; i++) printf(" %p|%p: %s image (%zu/%zu bytes)\n", components[i].start, ofw_translate(components[i].start), components[i].name, components[i].inflated, components[i].size); size_t dest[COMPONENTS]; size_t top = 0; size_t cnt = 0; bootinfo.taskmap.cnt = 0; for (i = 0; i < min(COMPONENTS, TASKMAP_MAX_RECORDS); i++) { top = ALIGN_UP(top, PAGE_SIZE); if (i > 0) { bootinfo.taskmap.tasks[bootinfo.taskmap.cnt].addr = (void *) PA2KA(top); bootinfo.taskmap.tasks[bootinfo.taskmap.cnt].size = components[i].inflated; str_cpy(bootinfo.taskmap.tasks[bootinfo.taskmap.cnt].name, BOOTINFO_TASK_NAME_BUFLEN, components[i].name); bootinfo.taskmap.cnt++; } dest[i] = top; top += components[i].inflated; cnt++; } void *balloc_base; void *balloc_base_pa; ofw_alloc("boot allocator area", &balloc_base, &balloc_base_pa, BALLOC_MAX_SIZE, loader_address_pa); printf(" %p|%p: boot allocator area\n", balloc_base, balloc_base_pa); void *inflate_base; void *inflate_base_pa; ofw_alloc("inflate area", &inflate_base, &inflate_base_pa, top, loader_address_pa); printf(" %p|%p: inflate area\n", inflate_base, inflate_base_pa); uintptr_t balloc_start = ALIGN_UP(top, PAGE_SIZE); size_t pages = (balloc_start + ALIGN_UP(BALLOC_MAX_SIZE, PAGE_SIZE)) >> PAGE_WIDTH; void *transtable; void *transtable_pa; ofw_alloc("translate table", &transtable, &transtable_pa, pages * sizeof(void *), loader_address_pa); printf(" %p|%p: translate table\n", transtable, transtable_pa); check_overlap("boot allocator area", balloc_base_pa, pages); check_overlap("inflate area", inflate_base_pa, pages); check_overlap("translate table", transtable_pa, pages); printf("\nInflating components ... "); for (i = cnt; i > 0; i--) { printf("%s ", components[i - 1].name); int err = inflate(components[i - 1].start, components[i - 1].size, inflate_base + dest[i - 1], components[i - 1].inflated); if (err != EOK) { printf("\n%s: Inflating error %d, halting.\n", components[i - 1].name, err); halt(); } } printf(".\n"); printf("Setting up boot allocator ...\n"); balloc_init(&bootinfo.ballocs, balloc_base, PA2KA(balloc_start), BALLOC_MAX_SIZE); printf("Setting up screens ...\n"); ofw_setup_screens(); printf("Canonizing OpenFirmware device tree ...\n"); bootinfo.ofw_root = ofw_tree_build(); printf("Setting up translate table ...\n"); for (i = 0; i < pages; i++) { uintptr_t off = i << PAGE_WIDTH; void *phys; if (off < balloc_start) phys = ofw_translate(inflate_base + off); else phys = ofw_translate(balloc_base + off - balloc_start); ((void **) transtable)[i] = phys; } printf("Booting the kernel...\n"); jump_to_kernel(bootinfo_pa, transtable_pa, pages, real_mode_pa); }