1 /* 2 * Copyright 2003-2007, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "Handle.h" 8 9 #include <boot/platform.h> 10 #include <util/kernel_cpp.h> 11 12 #include <unistd.h> 13 #include <errno.h> 14 #include <dirent.h> 15 #include <limits.h> 16 #include <string.h> 17 #include <stdio.h> 18 19 20 // we're using some libroot specials 21 extern int __libc_argc; 22 extern char **__libc_argv; 23 extern const char *__progname; 24 25 extern bool gShowMenu; 26 27 28 static status_t 29 get_device(const char *path, Node **_device) 30 { 31 Handle *device = new Handle(path); 32 if (device == NULL) 33 return B_NO_MEMORY; 34 35 if (device->InitCheck() != B_OK) { 36 fprintf(stderr, "%s: Could not open image \"%s\": %s\n", 37 __progname, path, strerror(device->InitCheck())); 38 39 delete device; 40 return B_ERROR; 41 } 42 43 *_device = device; 44 return B_OK; 45 } 46 47 48 static status_t 49 add_device(const char *path, NodeList *list) 50 { 51 Node *device; 52 status_t status = get_device(path, &device); 53 if (status < B_OK) 54 return status; 55 56 printf("add \"%s\" to list of boot devices\n", path); 57 list->Add(device); 58 59 return B_OK; 60 } 61 62 63 static status_t 64 recursive_add_device(const char *path, NodeList *list) 65 { 66 DIR *dir = opendir(path); 67 if (dir == NULL) 68 return errno; 69 70 struct dirent *dirent; 71 while ((dirent = readdir(dir)) != NULL) { 72 // we don't care about names with a leading dot (incl. "." and "..") 73 if (dirent->d_name[0] == '.') 74 continue; 75 76 char nextPath[PATH_MAX]; 77 strcpy(nextPath, path); 78 strcat(nextPath, "/"); 79 strcat(nextPath, dirent->d_name); 80 81 // Note, this doesn't care about if it's a directory or not! 82 if (!strcmp(dirent->d_name, "raw") 83 && add_device(nextPath, list) == B_OK) 84 continue; 85 86 recursive_add_device(nextPath, list); 87 } 88 closedir(dir); 89 90 return B_OK; 91 } 92 93 94 static char * 95 get_next_argument(int32 *cookie, bool options) 96 { 97 int32 i = *cookie + 1; 98 99 if (i == 1 && !options) { 100 // filter out options at the start 101 while (i < __libc_argc && __libc_argv[i][0] == '-') 102 i++; 103 } 104 105 for (; i < __libc_argc; i++) { 106 // Options come at the start 107 if (options && __libc_argv[i][0] != '-') 108 return NULL; 109 110 *cookie = i; 111 return __libc_argv[i]; 112 } 113 114 return NULL; 115 } 116 117 118 static char * 119 get_next_option(int32 *cookie) 120 { 121 return get_next_argument(cookie, true); 122 } 123 124 125 static char * 126 get_next_device(int32 *cookie) 127 { 128 return get_next_argument(cookie, false); 129 } 130 131 132 // #pragma mark - 133 134 135 status_t 136 platform_add_boot_device(struct stage2_args *args, NodeList *devicesList) 137 { 138 // we accept a boot device from the command line 139 status_t status = B_ERROR; 140 Node *device; 141 142 int32 cookie = 0; 143 char *path = get_next_device(&cookie); 144 if (path != NULL) 145 status = get_device(path, &device); 146 else 147 status = get_device("/boot/home/test-file-device", &device); 148 149 if (status == B_OK) 150 devicesList->Add(device); 151 152 return status; 153 } 154 155 156 status_t 157 platform_get_boot_partition(struct stage2_args *args, Node *device, 158 NodeList *list, boot::Partition **_partition) 159 { 160 NodeIterator iterator = list->GetIterator(); 161 boot::Partition *partition = NULL; 162 while ((partition = (boot::Partition *)iterator.Next()) != NULL) { 163 // just take the first partition 164 *_partition = partition; 165 return B_OK; 166 } 167 168 return B_ENTRY_NOT_FOUND; 169 } 170 171 172 status_t 173 platform_add_block_devices(struct stage2_args *args, NodeList *list) 174 { 175 int32 cookie = 0; 176 if (get_next_device(&cookie) != NULL) { 177 // add the devices provided on the command line 178 char *path; 179 while ((path = get_next_device(&cookie)) != NULL) 180 add_device(path, list); 181 } 182 183 bool addDevices = true; 184 bool scsi = true; 185 char *option; 186 cookie = 0; 187 while ((option = get_next_option(&cookie)) != NULL) { 188 if (!strcmp(option, "--no-devices")) 189 addDevices = false; 190 else if (!strcmp(option, "--no-scsi")) 191 scsi = false; 192 else if (!strcmp(option, "--menu")) 193 gShowMenu = true; 194 else { 195 fprintf(stderr, "usage: %s [OPTIONS] [image ...]\n" 196 " --no-devices\tDon't add real devices from /dev/disk\n" 197 " --no-scsi\tDon't add SCSI devices (might be problematic with some\n" 198 "\t\tUSB mass storage drivers)\n" 199 " --menu\tShow boot menu\n", __progname); 200 exit(0); 201 } 202 } 203 204 if (addDevices) { 205 recursive_add_device("/dev/disk/ide", list); 206 recursive_add_device("/dev/disk/virtual", list); 207 208 if (scsi) 209 recursive_add_device("/dev/disk/scsi", list); 210 } 211 212 return B_OK; 213 } 214 215 216 status_t 217 platform_register_boot_device(Node *device) 218 { 219 return B_OK; 220 } 221