/* * Copyright 2003-2006, Axel Dörfler, axeld@pinc-software.de. * Copyright 2010, Andreas Färber * All rights reserved. Distributed under the terms of the MIT License. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "Handle.h" #include "machine.h" #define ENABLE_ISCSI char sBootPath[192]; status_t platform_add_boot_device(struct stage2_args *args, NodeList *devicesList) { // print out the boot path (to be removed later?) int length = of_getprop(gChosen, "bootpath", sBootPath, sizeof(sBootPath)); if (length <= 1) return B_ENTRY_NOT_FOUND; printf("boot path = \"%s\"\n", sBootPath); intptr_t node = of_finddevice(sBootPath); if (node != OF_FAILED) { char type[16]; of_getprop(node, "device_type", type, sizeof(type)); printf("boot type = %s\n", type); // If the boot device is a network device, we try to find a // "remote disk" at this point. if (strcmp(type, "network") == 0) { // init the net stack status_t error = net_stack_init(); if (error != B_OK) return error; ip_addr_t bootAddress = 0; char* bootArgs = strrchr(sBootPath, ':'); if (bootArgs != NULL) { bootArgs++; char* comma = strchr(bootArgs, ','); if (comma != NULL && comma - bootArgs > 0) { comma[0] = '\0'; bootAddress = ip_parse_address(bootArgs); comma[0] = ','; } } if (bootAddress == 0) { intptr_t package = of_finddevice("/options"); char defaultServerIP[16]; int bytesRead = of_getprop(package, "default-server-ip", defaultServerIP, sizeof(defaultServerIP) - 1); if (bytesRead != OF_FAILED && bytesRead > 1) { defaultServerIP[bytesRead] = '\0'; bootAddress = ip_parse_address(defaultServerIP); } } // init a native remote disk, if possible RemoteDisk *remoteDisk = RemoteDisk::FindAnyRemoteDisk(); if (remoteDisk != NULL) { devicesList->Add(remoteDisk); return B_OK; } return B_ENTRY_NOT_FOUND; } if (strcmp("block", type) != 0) { printf("boot device is not a block device!\n"); return B_ENTRY_NOT_FOUND; } } else printf("could not open boot path.\n"); /* char name[256]; strcpy(name, sBootPath); strcat(name, ":kernel_ppc"); int kernel = of_open(name); if (kernel == OF_FAILED) { puts("open kernel failed"); } else puts("open kernel succeeded"); */ int handle = of_open(sBootPath); if (handle == OF_FAILED) { puts("\t\t(open failed)"); return B_ERROR; } Handle *device = new(nothrow) Handle(handle); if (device == NULL) return B_NO_MEMORY; devicesList->Add(device); return B_OK; } status_t platform_get_boot_partitions(struct stage2_args *args, Node *device, NodeList *list, NodeList *partitionList) { NodeIterator iterator = list->GetIterator(); boot::Partition *partition = NULL; while ((partition = (boot::Partition *)iterator.Next()) != NULL) { // ToDo: just take the first partition for now partitionList->Insert(partition); return B_OK; } return B_ENTRY_NOT_FOUND; } void platform_cleanup_devices() { net_stack_cleanup(); } #define DUMPED_BLOCK_SIZE 16 void dumpBlock(const char *buffer, int size, const char *prefix) { int i; for (i = 0; i < size;) { int start = i; printf(prefix); for (; i < start+DUMPED_BLOCK_SIZE; i++) { if (!(i % 4)) printf(" "); if (i >= size) printf(" "); else printf("%02x", *(unsigned char *)(buffer + i)); } printf(" "); for (i = start; i < start + DUMPED_BLOCK_SIZE; i++) { if (i < size) { char c = buffer[i]; if (c < 30) printf("."); else printf("%c", c); } else break; } printf("\n"); } } status_t platform_add_block_devices(stage2_args *args, NodeList *devicesList) { // add all block devices to the list of possible boot devices intptr_t cookie = 0; char path[256]; status_t status; while ((status = of_get_next_device(&cookie, 0, "block", path, sizeof(path))) == B_OK) { if (!strcmp(path, sBootPath)) { // don't add the boot device twice continue; } // Adjust the arguments passed to the open command so that // the disk-label package is by-passed - unfortunately, // this is implementation specific (and I found no docs // for the Apple OF disk-label usage, of course) // SUN's OpenBoot: //strcpy(path + strlen(path), ":nolabel"); // Apple: if (gMachine & MACHINE_MAC) strcpy(path + strlen(path), ":0"); printf("\t%s\n", path); intptr_t handle = of_open(path); if (handle == OF_FAILED) { puts("\t\t(failed)"); continue; } Handle *device = new(nothrow) Handle(handle); printf("\t\t(could open device, handle = %p, node = %p)\n", (void *)handle, device); devicesList->Add(device); } printf("\t(loop ended with %ld)\n", status); return B_OK; } status_t platform_register_boot_device(Node *device) { disk_identifier disk; disk.bus_type = UNKNOWN_BUS; disk.device_type = UNKNOWN_DEVICE; disk.device.unknown.size = device->Size(); gBootVolume.SetData(BOOT_VOLUME_DISK_IDENTIFIER, B_RAW_TYPE, &disk, sizeof(disk_identifier)); return B_OK; }