示例#1
0
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);
}
示例#2
0
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);
}