]>
Commit | Line | Data |
---|---|---|
14c7c974 A |
1 | /* |
2 | * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. | |
3 | * | |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
4f6e3300 A |
6 | * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights |
7 | * Reserved. This file contains Original Code and/or Modifications of | |
8 | * Original Code as defined in and that are subject to the Apple Public | |
9 | * Source License Version 1.1 (the "License"). You may not use this file | |
10 | * except in compliance with the License. Please obtain a copy of the | |
11 | * License at http://www.apple.com/publicsource and read it before using | |
12 | * this file. | |
14c7c974 A |
13 | * |
14 | * The Original Code and all software distributed under the License are | |
4f6e3300 | 15 | * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
14c7c974 A |
16 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
17 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
4f6e3300 A |
18 | * FITNESS FOR A PARTICULAR PURPOSE OR NON- INFRINGEMENT. Please see the |
19 | * License for the specific language governing rights and limitations | |
20 | * under the License. | |
14c7c974 A |
21 | * |
22 | * @APPLE_LICENSE_HEADER_END@ | |
23 | */ | |
24 | /* | |
25 | * Mach Operating System | |
26 | * Copyright (c) 1990 Carnegie-Mellon University | |
27 | * Copyright (c) 1989 Carnegie-Mellon University | |
28 | * Copyright (c) 1988 Carnegie-Mellon University | |
29 | * Copyright (c) 1987 Carnegie-Mellon University | |
30 | * All rights reserved. The CMU software License Agreement specifies | |
31 | * the terms and conditions for use and redistribution. | |
32 | * | |
33 | */ | |
34 | /* | |
35 | * HISTORY | |
36 | * Revision 2.3 88/08/08 13:47:07 rvb | |
37 | * Allocate buffers dynamically vs statically. | |
38 | * Now b[i] and i_fs and i_buf, are allocated dynamically. | |
39 | * boot_calloc(size) allocates and zeros a buffer rounded to a NPG | |
40 | * boundary. | |
41 | * Generalize boot spec to allow, xx()/mach, xx(n,[a..h])/mach, | |
42 | * xx([a..h])/mach, ... | |
43 | * Also default "xx" if unspecified and alloc just "/mach", | |
44 | * where everything is defaulted | |
45 | * Add routine, ptol(), to parse partition letters. | |
46 | * | |
47 | */ | |
48 | ||
49 | /* | |
50 | * Copyright (c) 1982, 1986 Regents of the University of California. | |
51 | * All rights reserved. The Berkeley software License Agreement | |
52 | * specifies the terms and conditions for redistribution. | |
53 | * | |
54 | * @(#)sys.c 7.1 (Berkeley) 6/5/86 | |
55 | */ | |
56 | ||
14c7c974 | 57 | #include "libsaio.h" |
f083c6c3 A |
58 | #include "bootstruct.h" |
59 | ||
75b89a82 A |
60 | |
61 | struct devsw { | |
62 | const char * name; | |
63 | unsigned char biosdev; | |
f083c6c3 | 64 | int type; |
14c7c974 A |
65 | }; |
66 | ||
75b89a82 A |
67 | static struct devsw devsw[] = |
68 | { | |
f083c6c3 A |
69 | { "sd", 0x80, kBIOSDevTypeHardDrive }, /* DEV_SD */ |
70 | { "hd", 0x80, kBIOSDevTypeHardDrive }, /* DEV_HD */ | |
71 | { "fd", 0x00, kBIOSDevTypeFloppy }, /* DEV_FD */ | |
72 | { "en", 0xE0, kBIOSDevTypeNetwork }, /* DEV_EN */ | |
75b89a82 A |
73 | { 0, 0 } |
74 | }; | |
14c7c974 | 75 | |
75b89a82 A |
76 | /* |
77 | * Max number of file descriptors. | |
78 | */ | |
79 | #define NFILES 6 | |
14c7c974 | 80 | |
75b89a82 | 81 | static struct iob iob[NFILES]; |
14c7c974 | 82 | |
75b89a82 | 83 | void * gFSLoadAddress = 0; |
14c7c974 | 84 | |
75b89a82 A |
85 | static BVRef getBootVolumeRef( const char * path, const char ** outPath ); |
86 | static BVRef newBootVolumeRef( int biosdev, int partno ); | |
14c7c974 | 87 | |
75b89a82 A |
88 | //========================================================================== |
89 | // LoadFile - LOW-LEVEL FILESYSTEM FUNCTION. | |
90 | // Load the specified file to the load buffer at LOAD_ADDR. | |
f083c6c3 | 91 | // If the file is fat, load only the i386 portion. |
14c7c974 | 92 | |
75b89a82 A |
93 | long LoadFile(const char * fileSpec) |
94 | { | |
95 | const char * filePath; | |
96 | long fileSize; | |
97 | BVRef bvr; | |
14c7c974 | 98 | |
75b89a82 | 99 | // Resolve the boot volume from the file spec. |
14c7c974 | 100 | |
75b89a82 A |
101 | if ((bvr = getBootVolumeRef(fileSpec, &filePath)) == NULL) |
102 | return -1; | |
14c7c974 | 103 | |
75b89a82 A |
104 | // Read file into load buffer. The data in the load buffer will be |
105 | // overwritten by the next LoadFile() call. | |
14c7c974 | 106 | |
75b89a82 | 107 | gFSLoadAddress = (void *) LOAD_ADDR; |
14c7c974 | 108 | |
75b89a82 | 109 | fileSize = bvr->fs_loadfile(bvr, (char *)filePath); |
14c7c974 | 110 | |
75b89a82 | 111 | // Return the size of the file, or -1 if load failed. |
14c7c974 | 112 | |
75b89a82 | 113 | return fileSize; |
14c7c974 A |
114 | } |
115 | ||
75b89a82 A |
116 | //========================================================================== |
117 | // GetDirEntry - LOW-LEVEL FILESYSTEM FUNCTION. | |
118 | // Fetch the next directory entry for the given directory. | |
119 | ||
120 | long GetDirEntry(const char * dirSpec, long * dirIndex, const char ** name, | |
121 | long * flags, long * time) | |
14c7c974 | 122 | { |
75b89a82 A |
123 | const char * dirPath; |
124 | BVRef bvr; | |
125 | ||
126 | // Resolve the boot volume from the dir spec. | |
127 | ||
128 | if ((bvr = getBootVolumeRef(dirSpec, &dirPath)) == NULL) | |
14c7c974 | 129 | return -1; |
75b89a82 A |
130 | |
131 | // Return 0 on success, or -1 if there are no additional entries. | |
132 | ||
133 | return bvr->fs_getdirentry( bvr, | |
134 | /* dirPath */ (char *)dirPath, | |
135 | /* dirIndex */ dirIndex, | |
136 | /* dirEntry */ (char **)name, flags, time ); | |
14c7c974 A |
137 | } |
138 | ||
75b89a82 A |
139 | //========================================================================== |
140 | // GetFileInfo - LOW-LEVEL FILESYSTEM FUNCTION. | |
141 | // Get attributes for the specified file. | |
142 | ||
f083c6c3 A |
143 | static char gMakeDirSpec[1024]; |
144 | ||
75b89a82 A |
145 | long GetFileInfo(const char * dirSpec, const char * name, |
146 | long * flags, long * time) | |
14c7c974 | 147 | { |
75b89a82 A |
148 | long index = 0; |
149 | const char * entryName; | |
150 | ||
f083c6c3 A |
151 | if (!dirSpec) { |
152 | long idx, len; | |
153 | ||
154 | len = strlen(name); | |
155 | ||
156 | for (idx = len; idx && (name[idx] != '/' && name[idx] != '\\'); idx--) {} | |
157 | if (idx == 0) { | |
158 | gMakeDirSpec[0] = '/'; | |
159 | gMakeDirSpec[1] = '\0'; | |
160 | } else { | |
161 | idx++; | |
162 | strncpy(gMakeDirSpec, name, idx); | |
163 | name += idx; | |
164 | } | |
165 | dirSpec = gMakeDirSpec; | |
166 | } | |
167 | ||
75b89a82 A |
168 | while (GetDirEntry(dirSpec, &index, &entryName, flags, time) == 0) |
169 | { | |
170 | if (strcmp(entryName, name) == 0) | |
171 | return 0; // success | |
172 | } | |
173 | return -1; // file not found | |
14c7c974 A |
174 | } |
175 | ||
75b89a82 A |
176 | //========================================================================== |
177 | // iob_from_fdesc() | |
178 | // | |
179 | // Return a pointer to an allocated 'iob' based on the file descriptor | |
180 | // provided. Returns NULL if the file descriptor given is invalid. | |
181 | ||
182 | static struct iob * iob_from_fdesc(int fdesc) | |
14c7c974 | 183 | { |
75b89a82 A |
184 | register struct iob * io; |
185 | ||
186 | if (fdesc < 0 || fdesc >= NFILES || | |
187 | ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) | |
188 | return NULL; | |
189 | else | |
190 | return io; | |
14c7c974 A |
191 | } |
192 | ||
75b89a82 A |
193 | //========================================================================== |
194 | // openmem() | |
195 | ||
196 | int openmem(char * buf, int len) | |
14c7c974 | 197 | { |
75b89a82 A |
198 | int fdesc; |
199 | struct iob * io; | |
14c7c974 | 200 | |
75b89a82 | 201 | // Locate a free descriptor slot. |
14c7c974 | 202 | |
75b89a82 A |
203 | for (fdesc = 0; fdesc < NFILES; fdesc++) |
204 | if (iob[fdesc].i_flgs == 0) | |
205 | goto gotfile; | |
14c7c974 | 206 | |
75b89a82 | 207 | stop("Out of file descriptors"); |
14c7c974 | 208 | |
75b89a82 A |
209 | gotfile: |
210 | io = &iob[fdesc]; | |
211 | bzero(io, sizeof(*io)); | |
14c7c974 | 212 | |
75b89a82 A |
213 | // Mark the descriptor as taken. Set the F_MEM flag to indicate |
214 | // that the file buffer is provided by the caller. | |
14c7c974 | 215 | |
75b89a82 A |
216 | io->i_flgs = F_ALLOC | F_MEM; |
217 | io->i_buf = buf; | |
218 | io->i_filesize = len; | |
14c7c974 | 219 | |
75b89a82 | 220 | return fdesc; |
14c7c974 A |
221 | } |
222 | ||
75b89a82 A |
223 | //========================================================================== |
224 | // open() - Open the file specified by 'path' for reading. | |
14c7c974 | 225 | |
75b89a82 | 226 | int open(const char * path, int flags) |
14c7c974 | 227 | { |
75b89a82 A |
228 | int fdesc, i; |
229 | struct iob * io; | |
230 | const char * filePath; | |
231 | BVRef bvr; | |
14c7c974 | 232 | |
75b89a82 | 233 | // Locate a free descriptor slot. |
14c7c974 | 234 | |
75b89a82 A |
235 | for (fdesc = 0; fdesc < NFILES; fdesc++) |
236 | if (iob[fdesc].i_flgs == 0) | |
237 | goto gotfile; | |
14c7c974 | 238 | |
75b89a82 | 239 | stop("Out of file descriptors"); |
14c7c974 | 240 | |
75b89a82 A |
241 | gotfile: |
242 | io = &iob[fdesc]; | |
243 | bzero(io, sizeof(*io)); | |
244 | ||
245 | // Mark the descriptor as taken. | |
246 | ||
247 | io->i_flgs = F_ALLOC; | |
248 | ||
249 | // Resolve the boot volume from the file spec. | |
250 | ||
251 | if ((bvr = getBootVolumeRef(path, &filePath)) == NULL) | |
252 | goto error; | |
253 | ||
254 | // Find the next available memory block in the download buffer. | |
255 | ||
256 | io->i_buf = (char *) LOAD_ADDR; | |
14c7c974 | 257 | for (i = 0; i < NFILES; i++) |
75b89a82 A |
258 | { |
259 | if ((iob[i].i_flgs != F_ALLOC) || (i == fdesc)) continue; | |
260 | io->i_buf = max(iob[i].i_filesize + iob[i].i_buf, io->i_buf); | |
261 | } | |
262 | ||
263 | // Load entire file into memory. Unnecessary open() calls must | |
264 | // be avoided. | |
265 | ||
266 | gFSLoadAddress = io->i_buf; | |
267 | io->i_filesize = bvr->fs_loadfile(bvr, (char *)filePath); | |
f083c6c3 A |
268 | if (io->i_filesize < 0) { |
269 | goto error; | |
270 | } | |
75b89a82 A |
271 | |
272 | return fdesc; | |
273 | ||
274 | error: | |
275 | close(fdesc); | |
276 | return -1; | |
14c7c974 A |
277 | } |
278 | ||
75b89a82 A |
279 | //========================================================================== |
280 | // close() - Close a file descriptor. | |
14c7c974 | 281 | |
75b89a82 | 282 | int close(int fdesc) |
14c7c974 | 283 | { |
75b89a82 | 284 | struct iob * io; |
14c7c974 | 285 | |
75b89a82 A |
286 | if ((io = iob_from_fdesc(fdesc)) == NULL) |
287 | return (-1); | |
14c7c974 | 288 | |
75b89a82 | 289 | io->i_flgs = 0; |
14c7c974 | 290 | |
75b89a82 | 291 | return 0; |
14c7c974 | 292 | } |
75b89a82 A |
293 | |
294 | //========================================================================== | |
295 | // lseek() - Reposition the byte offset of the file descriptor from the | |
296 | // beginning of the file. Returns the relocated offset. | |
297 | ||
298 | int b_lseek(int fdesc, int offset, int ptr) | |
14c7c974 | 299 | { |
75b89a82 | 300 | struct iob * io; |
14c7c974 | 301 | |
75b89a82 A |
302 | if ((io = iob_from_fdesc(fdesc)) == NULL) |
303 | return (-1); | |
14c7c974 | 304 | |
75b89a82 | 305 | io->i_offset = offset; |
14c7c974 | 306 | |
75b89a82 | 307 | return offset; |
14c7c974 A |
308 | } |
309 | ||
75b89a82 A |
310 | //========================================================================== |
311 | // tell() - Returns the byte offset of the file descriptor. | |
14c7c974 | 312 | |
75b89a82 | 313 | int tell(int fdesc) |
14c7c974 | 314 | { |
75b89a82 | 315 | struct iob * io; |
14c7c974 | 316 | |
75b89a82 A |
317 | if ((io = iob_from_fdesc(fdesc)) == NULL) |
318 | return 0; | |
319 | ||
320 | return io->i_offset; | |
14c7c974 A |
321 | } |
322 | ||
75b89a82 A |
323 | //========================================================================== |
324 | // read() - Read up to 'count' bytes of data from the file descriptor | |
325 | // into the buffer pointed to by buf. | |
326 | ||
327 | int read(int fdesc, char * buf, int count) | |
14c7c974 | 328 | { |
75b89a82 A |
329 | struct iob * io; |
330 | ||
331 | if ((io = iob_from_fdesc(fdesc)) == NULL) | |
332 | return (-1); | |
333 | ||
f083c6c3 | 334 | if ((io->i_offset + count) > (unsigned int)io->i_filesize) |
75b89a82 A |
335 | count = io->i_filesize - io->i_offset; |
336 | ||
337 | if (count <= 0) | |
338 | return 0; // end of file | |
339 | ||
340 | bcopy(io->i_buf + io->i_offset, buf, count); | |
341 | ||
342 | io->i_offset += count; | |
343 | ||
344 | return count; | |
14c7c974 A |
345 | } |
346 | ||
75b89a82 A |
347 | //========================================================================== |
348 | // file_size() - Returns the size of the file described by the file | |
349 | // descriptor. | |
350 | ||
351 | int file_size(int fdesc) | |
14c7c974 | 352 | { |
75b89a82 A |
353 | struct iob * io; |
354 | ||
355 | if ((io = iob_from_fdesc(fdesc)) == 0) | |
356 | return 0; | |
357 | ||
358 | return io->i_filesize; | |
14c7c974 A |
359 | } |
360 | ||
75b89a82 A |
361 | //========================================================================== |
362 | ||
363 | struct dirstuff * opendir(const char * path) | |
14c7c974 | 364 | { |
75b89a82 A |
365 | struct dirstuff * dirp = 0; |
366 | const char * dirPath; | |
367 | BVRef bvr; | |
368 | ||
369 | if ((bvr = getBootVolumeRef(path, &dirPath)) == NULL) | |
370 | goto error; | |
371 | ||
372 | dirp = (struct dirstuff *) malloc(sizeof(struct dirstuff)); | |
373 | if (dirp == NULL) | |
374 | goto error; | |
375 | ||
376 | dirp->dir_path = newString(dirPath); | |
377 | if (dirp->dir_path == NULL) | |
378 | goto error; | |
379 | ||
380 | dirp->dir_bvr = bvr; | |
381 | ||
382 | return dirp; | |
14c7c974 | 383 | |
75b89a82 A |
384 | error: |
385 | closedir(dirp); | |
386 | return NULL; | |
14c7c974 A |
387 | } |
388 | ||
75b89a82 | 389 | //========================================================================== |
14c7c974 | 390 | |
75b89a82 | 391 | int closedir(struct dirstuff * dirp) |
14c7c974 | 392 | { |
75b89a82 A |
393 | if (dirp) { |
394 | if (dirp->dir_path) free(dirp->dir_path); | |
395 | free(dirp); | |
396 | } | |
397 | return 0; | |
14c7c974 A |
398 | } |
399 | ||
75b89a82 A |
400 | //========================================================================== |
401 | ||
402 | int readdir(struct dirstuff * dirp, const char ** name, long * flags, | |
403 | long * time) | |
14c7c974 | 404 | { |
75b89a82 A |
405 | return dirp->dir_bvr->fs_getdirentry( dirp->dir_bvr, |
406 | /* dirPath */ dirp->dir_path, | |
407 | /* dirIndex */ &dirp->dir_index, | |
408 | /* dirEntry */ (char **)name, flags, time ); | |
14c7c974 A |
409 | } |
410 | ||
75b89a82 A |
411 | //========================================================================== |
412 | ||
413 | int currentdev() | |
14c7c974 | 414 | { |
f083c6c3 | 415 | return bootArgs->kernDev; |
14c7c974 A |
416 | } |
417 | ||
75b89a82 A |
418 | //========================================================================== |
419 | ||
420 | int switchdev(int dev) | |
14c7c974 | 421 | { |
f083c6c3 | 422 | bootArgs->kernDev = dev; |
75b89a82 A |
423 | return dev; |
424 | } | |
14c7c974 | 425 | |
75b89a82 | 426 | //========================================================================== |
14c7c974 | 427 | |
75b89a82 A |
428 | const char * usrDevices() |
429 | { | |
f083c6c3 A |
430 | if (gBootFileType == kNetworkDeviceType) |
431 | return ""; | |
432 | return "/private/Drivers/i386"; | |
75b89a82 | 433 | } |
14c7c974 | 434 | |
75b89a82 | 435 | //========================================================================== |
14c7c974 | 436 | |
f083c6c3 A |
437 | const char * systemConfigDir() |
438 | { | |
439 | if (gBootFileType == kNetworkDeviceType) | |
440 | return ""; | |
441 | return "/Library/Preferences/SystemConfiguration"; | |
442 | } | |
443 | ||
444 | //========================================================================== | |
445 | ||
446 | int gBootFileType; | |
447 | ||
75b89a82 A |
448 | BVRef scanBootVolumes( int biosdev, int * count ) |
449 | { | |
450 | BVRef bvr = 0; | |
14c7c974 | 451 | |
f083c6c3 A |
452 | bvr = diskScanBootVolumes(biosdev, count); |
453 | if (bvr == NULL) { | |
454 | bvr = nbpScanBootVolumes(biosdev, count); | |
455 | if (bvr != NULL) { | |
456 | gBootFileType = kNetworkDeviceType; | |
457 | } | |
458 | } else { | |
459 | gBootFileType = kBlockDeviceType; | |
75b89a82 A |
460 | } |
461 | return bvr; | |
14c7c974 A |
462 | } |
463 | ||
75b89a82 | 464 | //========================================================================== |
14c7c974 | 465 | |
75b89a82 | 466 | void getBootVolumeDescription( BVRef bvr, char * str, long strMaxLen ) |
14c7c974 | 467 | { |
75b89a82 | 468 | bvr->description( bvr, str, strMaxLen ); |
14c7c974 A |
469 | } |
470 | ||
75b89a82 | 471 | //========================================================================== |
14c7c974 | 472 | |
75b89a82 A |
473 | BVRef selectBootVolume( BVRef chain ) |
474 | { | |
475 | BVRef bvr, bvr1 = 0, bvr2 = 0; | |
14c7c974 | 476 | |
75b89a82 A |
477 | for ( bvr = chain; bvr; bvr = bvr->next ) |
478 | { | |
479 | if ( bvr->flags & kBVFlagNativeBoot ) bvr1 = bvr; | |
480 | if ( bvr->flags & kBVFlagPrimary ) bvr2 = bvr; | |
481 | } | |
14c7c974 | 482 | |
f083c6c3 A |
483 | bvr = bvr2 ? bvr2 : |
484 | bvr1 ? bvr1 : chain; | |
14c7c974 | 485 | |
75b89a82 | 486 | return bvr; |
14c7c974 A |
487 | } |
488 | ||
75b89a82 A |
489 | //========================================================================== |
490 | ||
14c7c974 A |
491 | #define LP '(' |
492 | #define RP ')' | |
f083c6c3 | 493 | int gBIOSDev; |
14c7c974 | 494 | |
75b89a82 | 495 | static BVRef getBootVolumeRef( const char * path, const char ** outPath ) |
14c7c974 | 496 | { |
75b89a82 A |
497 | const char * cp; |
498 | BVRef bvr; | |
f083c6c3 A |
499 | int type = B_TYPE( bootArgs->kernDev ); |
500 | int unit = B_UNIT( bootArgs->kernDev ); | |
501 | int part = B_PARTITION( bootArgs->kernDev ); | |
75b89a82 A |
502 | int biosdev = gBIOSDev; |
503 | static BVRef lastBVR = 0; | |
504 | static int lastKernDev; | |
505 | ||
506 | // Search for left parenthesis in the path specification. | |
507 | ||
508 | for (cp = path; *cp; cp++) { | |
509 | if (*cp == LP || *cp == '/') break; | |
14c7c974 | 510 | } |
14c7c974 | 511 | |
75b89a82 A |
512 | if (*cp != LP) // no left paren found |
513 | { | |
514 | cp = path; | |
f083c6c3 | 515 | if ( lastBVR && lastKernDev == bootArgs->kernDev ) |
75b89a82 A |
516 | { |
517 | bvr = lastBVR; | |
518 | goto quick_exit; | |
519 | } | |
520 | } | |
521 | else if ((cp - path) == 2) // found "xx(" | |
522 | { | |
523 | const struct devsw * dp; | |
524 | const char * xp = path; | |
525 | int i; | |
526 | ||
527 | cp++; | |
528 | ||
529 | // Check the 2 character device name pointed by 'xp'. | |
530 | ||
531 | for (dp = devsw; dp->name; dp++) | |
532 | { | |
533 | if ((xp[0] == dp->name[0]) && (xp[1] == dp->name[1])) | |
534 | break; // found matching entry | |
535 | } | |
536 | if (dp->name == NULL) | |
537 | { | |
538 | error("Unknown device '%c%c'\n", xp[0], xp[1]); | |
539 | return NULL; | |
540 | } | |
541 | type = dp - devsw; // kerndev type | |
542 | ||
543 | // Extract the optional unit number from the specification. | |
544 | // hd(unit) or hd(unit, part). | |
545 | ||
546 | i = 0; | |
547 | while (*cp >= '0' && *cp <= '9') | |
548 | { | |
549 | i = i * 10 + *cp++ - '0'; | |
550 | unit = i; | |
551 | } | |
552 | ||
553 | // Extract the optional partition number from the specification. | |
554 | ||
555 | if (*cp == ',') | |
556 | part = atoi(++cp); | |
557 | ||
558 | // Skip past the right paren. | |
559 | ||
560 | for ( ; *cp && *cp != RP; cp++) /* LOOP */; | |
561 | if (*cp == RP) cp++; | |
562 | ||
f083c6c3 | 563 | biosdev = dp->biosdev + unit; |
75b89a82 A |
564 | } |
565 | else | |
566 | { | |
567 | // Bad device specifier, skip past the right paren. | |
14c7c974 | 568 | |
75b89a82 A |
569 | for ( cp++; *cp && *cp != RP; cp++) /* LOOP */; |
570 | if (*cp == RP) cp++; | |
571 | } | |
14c7c974 | 572 | |
75b89a82 A |
573 | if ((bvr = newBootVolumeRef(biosdev, part)) == NULL) |
574 | { | |
575 | // error("newBootVolumeRef() error\n"); | |
576 | return NULL; | |
577 | } | |
14c7c974 | 578 | |
75b89a82 A |
579 | // Record the most recent device parameters in the |
580 | // KernBootStruct. | |
14c7c974 | 581 | |
f083c6c3 | 582 | bootArgs->kernDev = biosdev; |
14c7c974 | 583 | |
75b89a82 | 584 | lastBVR = bvr; |
f083c6c3 | 585 | lastKernDev = bootArgs->kernDev; |
14c7c974 | 586 | |
75b89a82 A |
587 | quick_exit: |
588 | // Returns the file path following the device spec. | |
589 | // e.g. 'hd(1,b)mach_kernel' is reduced to 'mach_kernel'. | |
14c7c974 | 590 | |
75b89a82 | 591 | *outPath = cp; |
14c7c974 | 592 | |
75b89a82 | 593 | return bvr; |
14c7c974 A |
594 | } |
595 | ||
75b89a82 | 596 | //========================================================================== |
14c7c974 | 597 | |
75b89a82 | 598 | static BVRef newBootVolumeRef( int biosdev, int partno ) |
14c7c974 | 599 | { |
75b89a82 | 600 | BVRef bvr, bvr1, bvrChain; |
14c7c974 | 601 | |
75b89a82 | 602 | // Fetch the volume list from the device. |
14c7c974 | 603 | |
75b89a82 A |
604 | bvrChain = scanBootVolumes( biosdev, NULL ); |
605 | ||
606 | // Look for a perfect match based on device and partition number. | |
607 | ||
608 | for ( bvr1 = NULL, bvr = bvrChain; bvr; bvr = bvr->next ) | |
609 | { | |
610 | if ( ( bvr->flags & kBVFlagNativeBoot ) == 0 ) continue; | |
611 | ||
612 | bvr1 = bvr; | |
613 | if ( bvr->part_no == partno ) break; | |
614 | } | |
615 | ||
616 | return bvr ? bvr : bvr1; | |
14c7c974 | 617 | } |