static void determine_machine(void) { gMachine = MACHINE_UNKNOWN; int root = of_finddevice("/"); char buffer[64]; int length; // TODO : Probe other OpenFirmware platforms and set gMachine as needed if ((length = of_getprop(root, "device_type", buffer, sizeof(buffer) - 1)) != OF_FAILED) { buffer[length] = '\0'; if (!strcasecmp("chrp", buffer)) gMachine = MACHINE_CHRP; else if (!strcasecmp("bootrom", buffer)) gMachine = MACHINE_MAC; } else gMachine = MACHINE_MAC; if ((length = of_getprop(root, "model", buffer, sizeof(buffer) - 1)) != OF_FAILED) { buffer[length] = '\0'; if (!strcasecmp("pegasos", buffer)) gMachine |= MACHINE_PEGASOS; } if ((length = of_getprop(root, "name", buffer, sizeof(buffer) - 1)) != OF_FAILED) { buffer[length] = '\0'; if (!strcasecmp("openbiosteam,openbios", buffer)) gMachine |= MACHINE_QEMU; } }
extern "C" void start(void *openFirmwareEntry) { char bootargs[512]; // stage2 args - might be set via the command line one day stage2_args args; args.heap_size = HEAP_SIZE; args.arguments = NULL; of_init((int (*)(void*))openFirmwareEntry); // check for arguments if (of_getprop(gChosen, "bootargs", bootargs, sizeof(bootargs)) != OF_FAILED) { static const char *sArgs[] = { NULL, NULL }; sArgs[0] = (const char *)bootargs; args.arguments = sArgs; args.arguments_count = 1; } determine_machine(); console_init(); if ((gMachine & MACHINE_QEMU) != 0) dprintf("OpenBIOS (QEMU?) OpenFirmware machine detected\n"); else if ((gMachine & MACHINE_PEGASOS) != 0) dprintf("Pegasos PowerPC machine detected\n"); else dprintf("Apple PowerPC machine assumed\n"); // Initialize and take over MMU and set the OpenFirmware callbacks - it // will ask us for memory after that instead of maintaining it itself // (the kernel will need to adjust the callback later on as well) arch_mmu_init(); if (boot_arch_cpu_init() != B_OK) of_exit(); if (init_real_time_clock() != B_OK) of_exit(); // check for key presses once sBootOptions = 0; int key = console_check_for_key(); if (key == 32) { // space bar: option menu sBootOptions |= BOOT_OPTION_MENU; } else if (key == 27) { // ESC: debug output sBootOptions |= BOOT_OPTION_DEBUG_OUTPUT; } gKernelArgs.platform_args.openfirmware_entry = openFirmwareEntry; main(&args); // if everything goes fine, main() never returns of_exit(); }
ULONG findMem(APTR ofw, ULONG orig_MSR) { ULONG volatile *mem=(APTR)(16*1024*1024); ULONG msr; int i; ULONG dev_handle, res, size; ULONG mem_info[2]; asm volatile("mfmsr %0":"=r"(msr)); while(ofw && ((ULONG)ofw < 0x10000000)) { asm volatile("mtmsr %0"::"r"(orig_MSR)); of_init(ofw); res = of_finddevice("/memory@0", &dev_handle); if (res) break; res = of_getprop(dev_handle, "reg", mem_info, sizeof(mem_info), &size); if (res) break; mem = (ULONG *)mem_info[1]; break; } asm volatile("mtmsr %0"::"r"(msr)); return (ULONG)mem; }
int32 of_size_cells(int package) { uint32 size_cells; if (of_getprop(package, "#size-cells", &size_cells, sizeof(size_cells)) == OF_FAILED) return OF_FAILED; return size_cells; }
int32 of_address_cells(int package) { uint32 address_cells; if (of_getprop(package, "#address-cells", &address_cells, sizeof(address_cells)) == OF_FAILED) return OF_FAILED; return address_cells; }
status_t console_init(void) { int input, output; if (of_getprop(gChosen, "stdin", &input, sizeof(int)) == OF_FAILED) return B_ERROR; if (of_getprop(gChosen, "stdout", &output, sizeof(int)) == OF_FAILED) return B_ERROR; sInput.SetHandle(input); sOutput.SetHandle(output); // now that we're initialized, enable stdio functionality stdin = (FILE *)&sInput; stdout = stderr = (FILE *)&sOutput; return B_OK; }
int s2_text_init(kernel_args *ka) { int i; int screen_handle; screen_handle = of_finddevice("screen"); if(screen_handle != 0) { of_getprop(screen_handle, "width", &screen_size_x, sizeof(screen_size_x)); of_getprop(screen_handle, "height", &screen_size_y, sizeof(screen_size_y)); of_getprop(screen_handle, "address", &framebuffer, sizeof(framebuffer)); of_getprop(screen_handle, "depth", &screen_depth, sizeof(screen_depth)); } else { // XXX hard coded framebuffer = (unsigned char *)0x96008000; screen_size_x = 1024; screen_size_y = 768; } back_color = 0x0; draw_color = 0xff; char_x = char_y = 0; num_cols = screen_size_x / CHAR_WIDTH; num_rows = screen_size_y / CHAR_HEIGHT; for(i = 0; i<screen_size_x * screen_size_y; i++) { framebuffer[i] = back_color; } ka->fb.enabled = 1; ka->fb.x_size = screen_size_x; ka->fb.y_size = screen_size_y; ka->fb.bit_depth = screen_depth; ka->fb.mapping.start = (unsigned long)framebuffer; ka->fb.mapping.size = ka->fb.x_size * ka->fb.y_size * ka->fb.bit_depth / 8; ka->fb.phys_addr.start = ka->fb.mapping.start; ka->fb.phys_addr.size = ka->fb.mapping.size; printf("framebuffer at %p\n", framebuffer); printf("screen_handle = 0x%x\n", screen_handle); return 0; }
static int check_of_version(void) { phandle oprom, chosen; char version[64]; oprom = of_finddevice("/openprom"); if (oprom == (phandle) -1) return 0; if (of_getprop(oprom, "model", version, sizeof(version)) <= 0) return 0; version[sizeof(version)-1] = 0; printf("OF version = '%s'\r\n", version); if (!string_match(version, "Open Firmware, 1.") && !string_match(version, "FirmWorks,3.")) return 0; chosen = of_finddevice("/chosen"); if (chosen == (phandle) -1) { chosen = of_finddevice("/chosen@0"); if (chosen == (phandle) -1) { printf("no chosen\n"); return 0; } } if (of_getprop(chosen, "mmu", &chosen_mmu, sizeof(chosen_mmu)) <= 0) { printf("no mmu\n"); return 0; } memory = (ihandle) of_call_prom("open", 1, 1, "/memory"); if (memory == (ihandle) -1) { memory = (ihandle) of_call_prom("open", 1, 1, "/memory@0"); if (memory == (ihandle) -1) { printf("no memory node\n"); return 0; } } printf("old OF detected\r\n"); return 1; }
uval rtas_instantiate(uval mem, uval msr) { phandle pkg; sval ret; sval32 size; ihandle rtas; rtas_msr = msr; pkg = of_finddevice("/rtas"); if (pkg == OF_FAILURE) return mem; ret = of_getprop(pkg, "rtas-size", &size, sizeof (size)); assert(ret != OF_FAILURE, "of_getprop(rtas-size)"); /* FIXME: Hack for SLOF. We want OF to show rtas is present * with size 0. Linux detects hyperrtas, and uses LPAR * interfaces, but won't use RTAS, which doesn't really exist, * until we implement an RTAS layer. */ if (size==0) return 0; ret = call_of("open", 1, 1, &rtas, "/rtas"); if (ret == OF_SUCCESS) { sval32 res[2]; mem = ALIGN_UP(mem, PGSIZE); ret = call_of("call-method", 3, 2, res, "instantiate-rtas", rtas, mem); assert(ret == OF_SUCCESS, "call-method(/instantiate-rtas)"); hprintf("rtas located at 0x%x\n", res[1]); rtas_entry = res[1]; rtas_base = mem; return ALIGN_UP(mem + size, PGSIZE); } return 0; }
status_t openfirmware_get_property(int package, const char *propertyName, PropertyValue &value) { value.length = of_getproplen(package, propertyName); if (value.length < 0) return B_ENTRY_NOT_FOUND; value.value = (char*)malloc(value.length); if (!value.value) return B_NO_MEMORY; if (of_getprop(package, propertyName, value.value, value.length) == OF_FAILED) { return B_ERROR; } return B_OK; }
unsigned long decompress_kernel(unsigned long load_addr, int num_words, unsigned long cksum, RESIDUAL *residual, void *OFW_interface) { int timer; extern unsigned long start; char *cp, ch; unsigned long i; BATU *u; BATL *l; unsigned long TotalMemory; unsigned long orig_MSR; int dev_handle; int mem_info[2]; int res, size; unsigned char board_type; unsigned char base_mod; lines = 25; cols = 80; orig_x = 0; orig_y = 24; /* * IBM's have the MMU on, so we have to disable it or * things get really unhappy in the kernel when * trying to setup the BATs with the MMU on * -- Cort */ flush_instruction_cache(); _put_HID0(_get_HID0() & ~0x0000C000); _put_MSR((orig_MSR = _get_MSR()) & ~0x0030); #if defined(CONFIG_SERIAL_CONSOLE) com_port = (struct NS16550 *)NS16550_init(0); #endif /* CONFIG_SERIAL_CONSOLE */ vga_init(0xC0000000); if (residual) { /* Is this Motorola PPCBug? */ if ((1 & residual->VitalProductData.FirmwareSupports) && (1 == residual->VitalProductData.FirmwareSupplier)) { board_type = inb(0x800) & 0xF0; /* If this is genesis 2 board then check for no * keyboard controller and more than one processor. */ if (board_type == 0xe0) { base_mod = inb(0x803); /* if a MVME2300/2400 or a Sitka then no keyboard */ if((base_mod == 0xFA) || (base_mod == 0xF9) || (base_mod == 0xE1)) { keyb_present = 0; /* no keyboard */ } } } memcpy(hold_residual,residual,sizeof(RESIDUAL)); } else { /* Assume 32M in the absence of more info... */ TotalMemory = 0x02000000; /* * This is a 'best guess' check. We want to make sure * we don't try this on a PReP box without OF * -- Cort */ while (OFW_interface && ((unsigned long)OFW_interface < 0x10000000) ) { /* The MMU needs to be on when we call OFW */ _put_MSR(orig_MSR); of_init(OFW_interface); /* get handle to memory description */ res = of_finddevice("/memory@0", &dev_handle); // puthex(res); puts("\n"); if (res) break; /* get the info */ // puts("get info = "); res = of_getprop(dev_handle, "reg", mem_info, sizeof(mem_info), &size); // puthex(res); puts(", info = "); puthex(mem_info[0]); // puts(" "); puthex(mem_info[1]); puts("\n"); if (res) break; TotalMemory = mem_info[1]; break; } hold_residual->TotalMemory = TotalMemory; residual = hold_residual; /* Turn MMU back off */ _put_MSR(orig_MSR & ~0x0030); } /* assume the chunk below 8M is free */ end_avail = (char *)0x00800000; /* tell the user where we were loaded at and where we * were relocated to for debugging this process */ puts("loaded at: "); puthex(load_addr); puts(" "); puthex((unsigned long)(load_addr + (4*num_words))); puts("\n"); if ( (unsigned long)load_addr != (unsigned long)&start ) { puts("relocated to: "); puthex((unsigned long)&start); puts(" "); puthex((unsigned long)((unsigned long)&start + (4*num_words))); puts("\n"); } if ( residual ) { puts("board data at: "); puthex((unsigned long)residual); puts(" "); puthex((unsigned long)((unsigned long)residual + sizeof(RESIDUAL))); puts("\n"); puts("relocated to: "); puthex((unsigned long)hold_residual); puts(" "); puthex((unsigned long)((unsigned long)hold_residual + sizeof(RESIDUAL))); puts("\n"); } /* we have to subtract 0x10000 here to correct for objdump including the size of the elf header which we strip -- Cort */ zimage_start = (char *)(load_addr - 0x10000 + ZIMAGE_OFFSET); zimage_size = ZIMAGE_SIZE; if ( INITRD_OFFSET ) initrd_start = load_addr - 0x10000 + INITRD_OFFSET; else initrd_start = 0; initrd_end = INITRD_SIZE + initrd_start; /* * Find a place to stick the zimage and initrd and * relocate them if we have to. -- Cort */ avail_ram = (char *)PAGE_ALIGN((unsigned long)_end); puts("zimage at: "); puthex((unsigned long)zimage_start); puts(" "); puthex((unsigned long)(zimage_size+zimage_start)); puts("\n"); if ( (unsigned long)zimage_start <= 0x00800000 ) { memcpy( (void *)avail_ram, (void *)zimage_start, zimage_size ); zimage_start = (char *)avail_ram; puts("relocated to: "); puthex((unsigned long)zimage_start); puts(" "); puthex((unsigned long)zimage_size+(unsigned long)zimage_start); puts("\n"); avail_ram += zimage_size; } /* relocate initrd */ if ( initrd_start ) { puts("initrd at: "); puthex(initrd_start); puts(" "); puthex(initrd_end); puts("\n"); if ( (unsigned long)initrd_start <= 0x00800000 ) { memcpy( (void *)avail_ram, (void *)initrd_start, initrd_end-initrd_start ); puts("relocated to: "); initrd_end = (unsigned long) avail_ram + (initrd_end-initrd_start); initrd_start = (unsigned long)avail_ram; puthex((unsigned long)initrd_start); puts(" "); puthex((unsigned long)initrd_end); puts("\n"); } avail_ram = (char *)PAGE_ALIGN((unsigned long)initrd_end); } avail_ram = (char *)0x00400000; end_avail = (char *)0x00800000; puts("avail ram: "); puthex((unsigned long)avail_ram); puts(" "); puthex((unsigned long)end_avail); puts("\n"); if (keyb_present) CRT_tstc(); /* Forces keyboard to be initialized */ puts("\nLinux/PPC load: "); timer = 0; cp = cmd_line; memcpy (cmd_line, cmd_preset, sizeof(cmd_preset)); while ( *cp ) putc(*cp++); while (timer++ < 5*1000) { if (tstc()) { while ((ch = getc()) != '\n' && ch != '\r') { if (ch == '\b') { if (cp != cmd_line) { cp--; puts("\b \b"); } } else { *cp++ = ch; putc(ch); } } break; /* Exit 'timer' loop */ } udelay(1000); /* 1 msec */ } *cp = 0; puts("\n"); puts("Uncompressing Linux..."); gunzip(0, 0x400000, zimage_start, &zimage_size); puts("done.\n"); { struct bi_record *rec; rec = (struct bi_record *)PAGE_ALIGN(zimage_size); rec->tag = BI_FIRST; rec->size = sizeof(struct bi_record); rec = (struct bi_record *)((unsigned long)rec + rec->size); rec->tag = BI_BOOTLOADER_ID; memcpy( (void *)rec->data, "prepboot", 9); rec->size = sizeof(struct bi_record) + 8 + 1; rec = (struct bi_record *)((unsigned long)rec + rec->size); rec->tag = BI_MACHTYPE; rec->data[0] = _MACH_prep; rec->data[1] = 1; rec->size = sizeof(struct bi_record) + sizeof(unsigned long); rec = (struct bi_record *)((unsigned long)rec + rec->size); rec->tag = BI_CMD_LINE; memcpy( (char *)rec->data, cmd_line, strlen(cmd_line)+1); rec->size = sizeof(struct bi_record) + strlen(cmd_line) + 1; rec = (struct bi_record *)((ulong)rec + rec->size); rec->tag = BI_LAST; rec->size = sizeof(struct bi_record); rec = (struct bi_record *)((unsigned long)rec + rec->size); } puts("Now booting the kernel\n"); return (unsigned long)hold_residual; }
void _start(int arg1, int arg2, void *openfirmware) { int chosen; of_init(openfirmware); /* open the input and output handle */ chosen = of_finddevice("/chosen"); of_getprop(chosen, "stdin", &of_input_handle, sizeof(of_input_handle)); of_getprop(chosen, "stdout", &of_output_handle, sizeof(of_output_handle)); puts("this is a test\n"); init_serial(); restart: puts("waiting for command\n"); { int base_address; int entry_point; int length; int command; unsigned char *ptr; void (*func)(int, int, void *); serial_read_int32(&command); if(command != 0x99) { puts("bad command, restarting\n"); goto restart; } serial_read_int32(&base_address); serial_read_int32(&length); serial_read_int32(&entry_point); puts("read base and length, claiming\n"); puts("base "); write_hex(base_address); puts("\nlength "); write_hex(length); puts("\nentry_point "); write_hex(entry_point); puts("\n"); ptr = (void *)base_address; of_claim(base_address, length, 0); puts("reading data\n"); serial_read(ptr, length); puts("done reading data, calling function\n"); func = (void *)entry_point; func(arg1, arg2, openfirmware); } of_exit(); }
status_t ppc_openfirmware_probe_grackle(int deviceNode, const StringArrayPropertyValue &compatibleValue) { if (!compatibleValue.ContainsElement("grackle")) return B_ERROR; uint32_t busrange[2]; if (of_getprop(deviceNode, "bus-range", busrange, sizeof(busrange)) != 8) return B_ERROR; grackle_host_bridge *bridge = (grackle_host_bridge*)malloc(sizeof(grackle_host_bridge)); if (bridge == NULL) return B_NO_MEMORY; bridge->device_node = deviceNode; bridge->address_registers = 0xfec00000; bridge->data_registers = 0xfee00000; bridge->bus = busrange[0]; memset(bridge->ranges, 0, sizeof(bridge->ranges)); int bytesRead = of_getprop(deviceNode, "ranges", bridge->ranges, sizeof(bridge->ranges)); if (bytesRead < 0) { dprintf("ppc_openfirmware_probe_grackle: Could not get ranges.\n"); free(bridge); return B_ERROR; } bridge->range_count = bytesRead / sizeof(grackle_range); grackle_range *ioRange = NULL; grackle_range *memoryRanges[2]; int memoryRangeCount = 0; for (int i = 0; i < bridge->range_count; i++) { grackle_range *range = bridge->ranges + i; switch (range->pci_hi & OFW_PCI_PHYS_HI_SPACEMASK) { case OFW_PCI_PHYS_HI_SPACE_CONFIG: break; case OFW_PCI_PHYS_HI_SPACE_IO: ioRange = range; break; case OFW_PCI_PHYS_HI_SPACE_MEM32: memoryRanges[memoryRangeCount++] = range; break; case OFW_PCI_PHYS_HI_SPACE_MEM64: break; } } if (ioRange == NULL) { dprintf("ppc_openfirmware_probe_grackle: Can't find io range.\n"); free(bridge); return B_ERROR; } if (memoryRangeCount == 0) { dprintf("ppc_openfirmware_probe_grackle: Can't find mem ranges.\n"); free(bridge); return B_ERROR; } status_t error = pci_controller_add(&sGracklePCIController, bridge); if (error != B_OK) free(bridge); return error; }
static status_t find_physical_memory_ranges(size_t &total) { int memory; dprintf("checking for memory...\n"); if (of_getprop(gChosen, "memory", &memory, sizeof(int)) == OF_FAILED) return B_ERROR; int package = of_instance_to_package(memory); total = 0; // Memory base addresses are provided in 32 or 64 bit flavors // #address-cells and #size-cells matches the number of 32-bit 'cells' // representing the length of the base address and size fields int root = of_finddevice("/"); int32 regAddressCells = of_address_cells(root); int32 regSizeCells = of_size_cells(root); if (regAddressCells == OF_FAILED || regSizeCells == OF_FAILED) { dprintf("finding base/size length counts failed, assume 32-bit.\n"); regAddressCells = 1; regSizeCells = 1; } // NOTE : Size Cells of 2 is possible in theory... but I haven't seen it yet. if (regAddressCells > 2 || regSizeCells > 1) { panic("%s: Unsupported OpenFirmware cell count detected.\n" "Address Cells: %" B_PRId32 "; Size Cells: %" B_PRId32 " (CPU > 64bit?).\n", __func__, regAddressCells, regSizeCells); return B_ERROR; } // On 64-bit PowerPC systems (G5), our mem base range address is larger if (regAddressCells == 2) { struct of_region<uint64> regions[64]; int count = of_getprop(package, "reg", regions, sizeof(regions)); if (count == OF_FAILED) count = of_getprop(memory, "reg", regions, sizeof(regions)); if (count == OF_FAILED) return B_ERROR; count /= sizeof(regions[0]); for (int32 i = 0; i < count; i++) { if (regions[i].size <= 0) { dprintf("%ld: empty region\n", i); continue; } dprintf("%" B_PRIu32 ": base = %" B_PRIu64 "," "size = %" B_PRIu32 "\n", i, regions[i].base, regions[i].size); total += regions[i].size; if (insert_physical_memory_range((addr_t)regions[i].base, regions[i].size) != B_OK) { dprintf("cannot map physical memory range " "(num ranges = %" B_PRIu32 ")!\n", gKernelArgs.num_physical_memory_ranges); return B_ERROR; } } return B_OK; } // Otherwise, normal 32-bit PowerPC G3 or G4 have a smaller 32-bit one struct of_region<uint32> regions[64]; int count = of_getprop(package, "reg", regions, sizeof(regions)); if (count == OF_FAILED) count = of_getprop(memory, "reg", regions, sizeof(regions)); if (count == OF_FAILED) return B_ERROR; count /= sizeof(regions[0]); for (int32 i = 0; i < count; i++) { if (regions[i].size <= 0) { dprintf("%ld: empty region\n", i); continue; } dprintf("%" B_PRIu32 ": base = %" B_PRIu32 "," "size = %" B_PRIu32 "\n", i, regions[i].base, regions[i].size); total += regions[i].size; if (insert_physical_memory_range((addr_t)regions[i].base, regions[i].size) != B_OK) { dprintf("cannot map physical memory range " "(num ranges = %" B_PRIu32 ")!\n", gKernelArgs.num_physical_memory_ranges); return B_ERROR; } } return B_OK; }