1 /* 2 * Copyright 2003-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "Handle.h" 8 #include "openfirmware.h" 9 #include "machine.h" 10 11 #include <boot/platform.h> 12 #include <boot/vfs.h> 13 #include <boot/stdio.h> 14 #include <boot/stage2.h> 15 #include <util/kernel_cpp.h> 16 17 #include <string.h> 18 19 20 char sBootPath[192]; 21 22 23 /** Gets all device types of the specified type by doing a 24 * depth-first searchi of the OpenFirmware device tree. 25 * 26 * The cookie has to be initialized to zero. 27 */ 28 29 static status_t 30 get_next_device(int *_cookie, const char *type, char *path, size_t pathSize) 31 { 32 int node = *_cookie; 33 34 if (node == 0) 35 node = of_peer(0); 36 37 while (true) { 38 int next = of_child(node); 39 if (next == OF_FAILED) 40 return B_ERROR; 41 42 if (next == 0) { 43 // no child node found 44 next = of_peer(node); 45 if (next == OF_FAILED) 46 return B_ERROR; 47 48 while (next == 0) { 49 // no peer node found, we are using the device 50 // tree itself as our search stack 51 52 next = of_parent(node); 53 if (next == OF_FAILED) 54 return B_ERROR; 55 56 if (next == 0) { 57 // We have searched the whole device tree 58 return B_ENTRY_NOT_FOUND; 59 } 60 61 // look into the next tree 62 node = next; 63 next = of_peer(node); 64 } 65 } 66 67 *_cookie = node = next; 68 69 char nodeType[16]; 70 int length; 71 if (of_getprop(node, "device_type", nodeType, sizeof(nodeType)) == OF_FAILED 72 || strcmp(nodeType, type) 73 || (length = of_package_to_path(node, path, pathSize - 1)) == OF_FAILED) 74 continue; 75 76 path[length] = '\0'; 77 return B_OK; 78 } 79 } 80 81 82 // #pragma mark - 83 84 85 status_t 86 platform_get_boot_device(struct stage2_args *args, Node **_device) 87 { 88 // print out the boot path (to be removed later?) 89 90 int length = of_getprop(gChosen, "bootpath", sBootPath, sizeof(sBootPath)); 91 if (length <= 1) 92 return B_ENTRY_NOT_FOUND; 93 printf("boot path = \"%s\"\n", sBootPath); 94 95 int node = of_finddevice(sBootPath); 96 if (node != OF_FAILED) { 97 char type[16]; 98 of_getprop(node, "device_type", type, sizeof(type)); 99 printf("boot type = %s\n", type); 100 if (strcmp("block", type)) { 101 printf("boot device is not a block device!\n"); 102 return B_ENTRY_NOT_FOUND; 103 } 104 } else 105 printf("could not open boot path.\n"); 106 107 /* char name[256]; 108 strcpy(name, sBootPath); 109 strcat(name, ":kernel_ppc"); 110 int kernel = of_open(name); 111 if (kernel == OF_FAILED) { 112 puts("open kernel failed"); 113 } else 114 puts("open kernel succeeded"); 115 */ 116 int handle = of_open(sBootPath); 117 if (handle == OF_FAILED) { 118 puts("\t\t(open failed)"); 119 return B_ERROR; 120 } 121 122 Handle *device = new Handle(handle); 123 if (device == NULL) 124 return B_NO_MEMORY; 125 126 *_device = device; 127 return B_OK; 128 } 129 130 131 status_t 132 platform_get_boot_partition(struct stage2_args *args, Node *device, 133 NodeList *list, boot::Partition **_partition) 134 { 135 NodeIterator iterator = list->GetIterator(); 136 boot::Partition *partition = NULL; 137 while ((partition = (boot::Partition *)iterator.Next()) != NULL) { 138 // ToDo: just take the first partition for now 139 *_partition = partition; 140 return B_OK; 141 } 142 143 return B_ENTRY_NOT_FOUND; 144 } 145 146 147 #define DUMPED_BLOCK_SIZE 16 148 149 void 150 dumpBlock(const char *buffer, int size, const char *prefix) 151 { 152 int i; 153 154 for (i = 0; i < size;) { 155 int start = i; 156 157 printf(prefix); 158 for (; i < start+DUMPED_BLOCK_SIZE; i++) { 159 if (!(i % 4)) 160 printf(" "); 161 162 if (i >= size) 163 printf(" "); 164 else 165 printf("%02x", *(unsigned char *)(buffer + i)); 166 } 167 printf(" "); 168 169 for (i = start; i < start + DUMPED_BLOCK_SIZE; i++) { 170 if (i < size) { 171 char c = buffer[i]; 172 173 if (c < 30) 174 printf("."); 175 else 176 printf("%c", c); 177 } else 178 break; 179 } 180 printf("\n"); 181 } 182 } 183 184 185 status_t 186 platform_add_block_devices(stage2_args *args, NodeList *devicesList) 187 { 188 // add all block devices to the list of possible boot devices 189 190 int cookie = 0; 191 char path[256]; 192 status_t status; 193 while ((status = get_next_device(&cookie, "block", path, sizeof(path))) == B_OK) { 194 if (!strcmp(path, sBootPath)) { 195 // don't add the boot device twice 196 continue; 197 } 198 199 // Adjust the arguments passed to the open command so that 200 // the disk-label package is by-passed - unfortunately, 201 // this is implementation specific (and I found no docs 202 // for the Apple OF disk-label usage, of course) 203 204 // SUN's OpenBoot: 205 //strcpy(path + strlen(path), ":nolabel"); 206 // Apple: 207 if (gMachine & MACHINE_MAC) 208 strcpy(path + strlen(path), ":0"); 209 210 printf("\t%s\n", path); 211 212 int handle = of_open(path); 213 if (handle == OF_FAILED) { 214 puts("\t\t(failed)"); 215 continue; 216 } 217 218 Handle *device = new Handle(handle); 219 printf("\t\t(could open device, handle = %p, node = %p)\n", (void *)handle, device); 220 221 devicesList->Add(device); 222 } 223 printf("\t(loop ended with %ld)\n", status); 224 225 return B_OK; 226 } 227 228 status_t 229 platform_register_boot_device(Node *device) 230 { 231 disk_identifier &disk = gKernelArgs.boot_disk.identifier; 232 233 disk.bus_type = UNKNOWN_BUS; 234 disk.device_type = UNKNOWN_DEVICE; 235 disk.device.unknown.size = device->Size(); 236 237 return B_OK; 238 } 239 240