]>
Commit | Line | Data |
---|---|---|
14c7c974 | 1 | /* |
57c72a9a | 2 | * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved. |
14c7c974 A |
3 | * |
4 | * @APPLE_LICENSE_HEADER_START@ | |
5 | * | |
57c72a9a | 6 | * Portions Copyright (c) 1999-2003 Apple Computer, Inc. All Rights |
4f6e3300 A |
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 | |
57c72a9a | 9 | * Source License Version 2.0 (the "License"). You may not use this file |
4f6e3300 A |
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 | 58 | #include "bootstruct.h" |
bba600dd A |
59 | #include <sys/md5.h> |
60 | #include <uuid/uuid.h> | |
61 | #include <Kernel/uuid/namespace.h> | |
75b89a82 A |
62 | |
63 | struct devsw { | |
64 | const char * name; | |
65 | unsigned char biosdev; | |
f083c6c3 | 66 | int type; |
14c7c974 A |
67 | }; |
68 | ||
75b89a82 A |
69 | static struct devsw devsw[] = |
70 | { | |
f083c6c3 A |
71 | { "sd", 0x80, kBIOSDevTypeHardDrive }, /* DEV_SD */ |
72 | { "hd", 0x80, kBIOSDevTypeHardDrive }, /* DEV_HD */ | |
73 | { "fd", 0x00, kBIOSDevTypeFloppy }, /* DEV_FD */ | |
74 | { "en", 0xE0, kBIOSDevTypeNetwork }, /* DEV_EN */ | |
75b89a82 A |
75 | { 0, 0 } |
76 | }; | |
14c7c974 | 77 | |
75b89a82 A |
78 | /* |
79 | * Max number of file descriptors. | |
80 | */ | |
81 | #define NFILES 6 | |
14c7c974 | 82 | |
75b89a82 | 83 | static struct iob iob[NFILES]; |
14c7c974 | 84 | |
75b89a82 | 85 | void * gFSLoadAddress = 0; |
14c7c974 | 86 | |
57c72a9a | 87 | //static BVRef getBootVolumeRef( const char * path, const char ** outPath ); |
75b89a82 | 88 | static BVRef newBootVolumeRef( int biosdev, int partno ); |
14c7c974 | 89 | |
57c72a9a A |
90 | //========================================================================== |
91 | // LoadVolumeFile - LOW-LEVEL FILESYSTEM FUNCTION. | |
92 | // Load the specified file from the specified volume | |
93 | // to the load buffer at LOAD_ADDR. | |
94 | // If the file is fat, load only the i386 portion. | |
95 | ||
96 | long LoadVolumeFile(BVRef bvr, const char *filePath) | |
97 | { | |
98 | long fileSize; | |
99 | ||
100 | // Read file into load buffer. The data in the load buffer will be | |
101 | // overwritten by the next LoadFile() call. | |
102 | ||
103 | gFSLoadAddress = (void *) LOAD_ADDR; | |
104 | ||
105 | fileSize = bvr->fs_loadfile(bvr, (char *)filePath); | |
106 | ||
107 | // Return the size of the file, or -1 if load failed. | |
108 | ||
109 | return fileSize; | |
110 | } | |
111 | ||
75b89a82 A |
112 | //========================================================================== |
113 | // LoadFile - LOW-LEVEL FILESYSTEM FUNCTION. | |
114 | // Load the specified file to the load buffer at LOAD_ADDR. | |
f083c6c3 | 115 | // If the file is fat, load only the i386 portion. |
14c7c974 | 116 | |
75b89a82 A |
117 | long LoadFile(const char * fileSpec) |
118 | { | |
119 | const char * filePath; | |
75b89a82 | 120 | BVRef bvr; |
14c7c974 | 121 | |
75b89a82 | 122 | // Resolve the boot volume from the file spec. |
14c7c974 | 123 | |
75b89a82 A |
124 | if ((bvr = getBootVolumeRef(fileSpec, &filePath)) == NULL) |
125 | return -1; | |
14c7c974 | 126 | |
57c72a9a A |
127 | return LoadVolumeFile(bvr, filePath); |
128 | } | |
129 | ||
130 | long ReadFileAtOffset(const char * fileSpec, void *buffer, unsigned long offset, unsigned long length) | |
131 | { | |
132 | const char *filePath; | |
133 | BVRef bvr; | |
134 | ||
135 | if ((bvr = getBootVolumeRef(fileSpec, &filePath)) == NULL) | |
136 | return -1; | |
137 | ||
138 | if (bvr->fs_readfile == NULL) | |
139 | return -1; | |
140 | ||
141 | return bvr->fs_readfile(bvr, (char *)filePath, buffer, offset, length); | |
142 | } | |
143 | ||
144 | long LoadThinFatFile(const char *fileSpec, void **binary) | |
145 | { | |
146 | const char *filePath; | |
147 | FSReadFile readFile; | |
148 | BVRef bvr; | |
bba600dd | 149 | unsigned long length, length2; |
57c72a9a A |
150 | |
151 | // Resolve the boot volume from the file spec. | |
152 | ||
153 | if ((bvr = getBootVolumeRef(fileSpec, &filePath)) == NULL) | |
154 | return -1; | |
155 | ||
156 | *binary = (void *)kLoadAddr; | |
157 | ||
75b89a82 A |
158 | // Read file into load buffer. The data in the load buffer will be |
159 | // overwritten by the next LoadFile() call. | |
14c7c974 | 160 | |
75b89a82 | 161 | gFSLoadAddress = (void *) LOAD_ADDR; |
14c7c974 | 162 | |
57c72a9a A |
163 | readFile = bvr->fs_readfile; |
164 | ||
165 | if (readFile != NULL) { | |
166 | // Read the first 4096 bytes (fat header) | |
167 | length = readFile(bvr, (char *)filePath, *binary, 0, 0x1000); | |
168 | if (length > 0) { | |
169 | if (ThinFatFile(binary, &length) == 0) { | |
170 | // We found a fat binary; read only the thin part | |
171 | length = readFile(bvr, (char *)filePath, | |
172 | (void *)kLoadAddr, (unsigned long)(*binary) - kLoadAddr, length); | |
173 | *binary = (void *)kLoadAddr; | |
174 | } else { | |
175 | // Not a fat binary; read the rest of the file | |
176 | length2 = readFile(bvr, (char *)filePath, (void *)(kLoadAddr + length), length, 0); | |
177 | if (length2 == -1) return -1; | |
178 | length += length2; | |
179 | } | |
180 | } | |
181 | } else { | |
182 | length = bvr->fs_loadfile(bvr, (char *)filePath); | |
183 | if (length > 0) { | |
184 | ThinFatFile(binary, &length); | |
185 | } | |
186 | } | |
187 | ||
188 | return length; | |
14c7c974 A |
189 | } |
190 | ||
bba600dd A |
191 | long GetFSUUID(char *spec, char *uuidStr) |
192 | { | |
193 | BVRef bvr; | |
194 | long rval = -1; | |
195 | const char *devSpec; | |
196 | ||
197 | if ((bvr = getBootVolumeRef(spec, &devSpec)) == NULL) | |
198 | return -1; | |
199 | ||
200 | if(bvr->fs_getuuid) | |
201 | rval = bvr->fs_getuuid(bvr, uuidStr); | |
202 | ||
203 | return rval; | |
204 | } | |
205 | ||
206 | ||
207 | // filesystem-specific getUUID functions call this shared string generator | |
208 | long CreateUUIDString(uint8_t uubytes[], int nbytes, char *uuidStr) | |
209 | { | |
210 | unsigned fmtbase, fmtidx, i; | |
211 | uint8_t uuidfmt[] = { 4, 2, 2, 2, 6 }; | |
212 | char *p = uuidStr; | |
213 | MD5_CTX md5c; | |
214 | uint8_t mdresult[16]; | |
215 | ||
216 | bzero(mdresult, sizeof(mdresult)); | |
217 | ||
218 | // just like AppleFileSystemDriver | |
219 | MD5Init(&md5c); | |
220 | MD5Update(&md5c, kFSUUIDNamespaceSHA1, sizeof(kFSUUIDNamespaceSHA1)); | |
221 | MD5Update(&md5c, uubytes, nbytes); | |
222 | MD5Final(mdresult, &md5c); | |
223 | ||
224 | // this UUID has been made version 3 style (i.e. via namespace) | |
225 | // see "-uuid-urn-" IETF draft (which otherwise copies byte for byte) | |
226 | mdresult[6] = 0x30 | ( mdresult[6] & 0x0F ); | |
227 | mdresult[8] = 0x80 | ( mdresult[8] & 0x3F ); | |
228 | ||
229 | ||
230 | // generate the text: e.g. 5EB1869F-C4FA-3502-BDEB-3B8ED5D87292 | |
231 | i = 0; fmtbase = 0; | |
232 | for(fmtidx = 0; fmtidx < sizeof(uuidfmt); fmtidx++) { | |
233 | for(i=0; i < uuidfmt[fmtidx]; i++) { | |
234 | uint8_t byte = mdresult[fmtbase+i]; | |
235 | char nib; | |
236 | ||
237 | nib = byte >> 4; | |
238 | *p = nib + '0'; // 0x4 -> '4' | |
239 | if(*p > '9') *p = (nib - 9 + ('A'-1)); // 0xB -> 'B' | |
240 | p++; | |
241 | ||
242 | nib = byte & 0xf; | |
243 | *p = nib + '0'; // 0x4 -> '4' | |
244 | if(*p > '9') *p = (nib - 9 + ('A'-1)); // 0xB -> 'B' | |
245 | p++; | |
246 | ||
247 | } | |
248 | fmtbase += i; | |
249 | if(fmtidx < sizeof(uuidfmt)-1) | |
250 | *(p++) = '-'; | |
251 | else | |
252 | *p = '\0'; | |
253 | } | |
254 | ||
255 | return 0; | |
256 | } | |
257 | ||
57c72a9a | 258 | |
75b89a82 A |
259 | //========================================================================== |
260 | // GetDirEntry - LOW-LEVEL FILESYSTEM FUNCTION. | |
261 | // Fetch the next directory entry for the given directory. | |
262 | ||
263 | long GetDirEntry(const char * dirSpec, long * dirIndex, const char ** name, | |
264 | long * flags, long * time) | |
14c7c974 | 265 | { |
75b89a82 A |
266 | const char * dirPath; |
267 | BVRef bvr; | |
268 | ||
269 | // Resolve the boot volume from the dir spec. | |
270 | ||
271 | if ((bvr = getBootVolumeRef(dirSpec, &dirPath)) == NULL) | |
14c7c974 | 272 | return -1; |
75b89a82 A |
273 | |
274 | // Return 0 on success, or -1 if there are no additional entries. | |
275 | ||
276 | return bvr->fs_getdirentry( bvr, | |
277 | /* dirPath */ (char *)dirPath, | |
278 | /* dirIndex */ dirIndex, | |
57c72a9a | 279 | /* dirEntry */ (char **)name, flags, time, 0, 0 ); |
14c7c974 A |
280 | } |
281 | ||
75b89a82 A |
282 | //========================================================================== |
283 | // GetFileInfo - LOW-LEVEL FILESYSTEM FUNCTION. | |
284 | // Get attributes for the specified file. | |
285 | ||
57c72a9a | 286 | static char* gMakeDirSpec; |
f083c6c3 | 287 | |
75b89a82 A |
288 | long GetFileInfo(const char * dirSpec, const char * name, |
289 | long * flags, long * time) | |
14c7c974 | 290 | { |
75b89a82 A |
291 | long index = 0; |
292 | const char * entryName; | |
293 | ||
57c72a9a A |
294 | if (gMakeDirSpec == 0) |
295 | gMakeDirSpec = (char *)malloc(1024); | |
296 | ||
f083c6c3 A |
297 | if (!dirSpec) { |
298 | long idx, len; | |
299 | ||
300 | len = strlen(name); | |
301 | ||
302 | for (idx = len; idx && (name[idx] != '/' && name[idx] != '\\'); idx--) {} | |
303 | if (idx == 0) { | |
304 | gMakeDirSpec[0] = '/'; | |
305 | gMakeDirSpec[1] = '\0'; | |
306 | } else { | |
307 | idx++; | |
308 | strncpy(gMakeDirSpec, name, idx); | |
309 | name += idx; | |
310 | } | |
311 | dirSpec = gMakeDirSpec; | |
312 | } | |
313 | ||
75b89a82 A |
314 | while (GetDirEntry(dirSpec, &index, &entryName, flags, time) == 0) |
315 | { | |
316 | if (strcmp(entryName, name) == 0) | |
317 | return 0; // success | |
318 | } | |
319 | return -1; // file not found | |
14c7c974 A |
320 | } |
321 | ||
57c72a9a A |
322 | long GetFileBlock(const char *fileSpec, unsigned long long *firstBlock) |
323 | { | |
324 | const char * filePath; | |
325 | BVRef bvr; | |
326 | ||
327 | // Resolve the boot volume from the file spec. | |
328 | ||
329 | if ((bvr = getBootVolumeRef(fileSpec, &filePath)) == NULL) { | |
330 | printf("Boot volume for '%s' is bogus\n", fileSpec); | |
331 | return -1; | |
332 | } | |
333 | ||
334 | return bvr->fs_getfileblock(bvr, (char *)filePath, firstBlock); | |
335 | } | |
336 | ||
75b89a82 A |
337 | //========================================================================== |
338 | // iob_from_fdesc() | |
339 | // | |
340 | // Return a pointer to an allocated 'iob' based on the file descriptor | |
341 | // provided. Returns NULL if the file descriptor given is invalid. | |
342 | ||
343 | static struct iob * iob_from_fdesc(int fdesc) | |
14c7c974 | 344 | { |
75b89a82 A |
345 | register struct iob * io; |
346 | ||
347 | if (fdesc < 0 || fdesc >= NFILES || | |
348 | ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0) | |
349 | return NULL; | |
350 | else | |
351 | return io; | |
14c7c974 A |
352 | } |
353 | ||
57c72a9a | 354 | #if UNUSED |
75b89a82 A |
355 | //========================================================================== |
356 | // openmem() | |
357 | ||
358 | int openmem(char * buf, int len) | |
14c7c974 | 359 | { |
75b89a82 A |
360 | int fdesc; |
361 | struct iob * io; | |
14c7c974 | 362 | |
75b89a82 | 363 | // Locate a free descriptor slot. |
14c7c974 | 364 | |
75b89a82 A |
365 | for (fdesc = 0; fdesc < NFILES; fdesc++) |
366 | if (iob[fdesc].i_flgs == 0) | |
367 | goto gotfile; | |
14c7c974 | 368 | |
75b89a82 | 369 | stop("Out of file descriptors"); |
14c7c974 | 370 | |
75b89a82 A |
371 | gotfile: |
372 | io = &iob[fdesc]; | |
373 | bzero(io, sizeof(*io)); | |
14c7c974 | 374 | |
75b89a82 A |
375 | // Mark the descriptor as taken. Set the F_MEM flag to indicate |
376 | // that the file buffer is provided by the caller. | |
14c7c974 | 377 | |
75b89a82 A |
378 | io->i_flgs = F_ALLOC | F_MEM; |
379 | io->i_buf = buf; | |
380 | io->i_filesize = len; | |
14c7c974 | 381 | |
75b89a82 | 382 | return fdesc; |
14c7c974 | 383 | } |
57c72a9a | 384 | #endif |
14c7c974 | 385 | |
75b89a82 A |
386 | //========================================================================== |
387 | // open() - Open the file specified by 'path' for reading. | |
14c7c974 | 388 | |
75b89a82 | 389 | int open(const char * path, int flags) |
14c7c974 | 390 | { |
75b89a82 A |
391 | int fdesc, i; |
392 | struct iob * io; | |
393 | const char * filePath; | |
394 | BVRef bvr; | |
14c7c974 | 395 | |
75b89a82 | 396 | // Locate a free descriptor slot. |
14c7c974 | 397 | |
75b89a82 A |
398 | for (fdesc = 0; fdesc < NFILES; fdesc++) |
399 | if (iob[fdesc].i_flgs == 0) | |
400 | goto gotfile; | |
14c7c974 | 401 | |
75b89a82 | 402 | stop("Out of file descriptors"); |
14c7c974 | 403 | |
75b89a82 A |
404 | gotfile: |
405 | io = &iob[fdesc]; | |
406 | bzero(io, sizeof(*io)); | |
407 | ||
408 | // Mark the descriptor as taken. | |
409 | ||
410 | io->i_flgs = F_ALLOC; | |
411 | ||
412 | // Resolve the boot volume from the file spec. | |
413 | ||
414 | if ((bvr = getBootVolumeRef(path, &filePath)) == NULL) | |
415 | goto error; | |
416 | ||
417 | // Find the next available memory block in the download buffer. | |
418 | ||
419 | io->i_buf = (char *) LOAD_ADDR; | |
14c7c974 | 420 | for (i = 0; i < NFILES; i++) |
75b89a82 A |
421 | { |
422 | if ((iob[i].i_flgs != F_ALLOC) || (i == fdesc)) continue; | |
423 | io->i_buf = max(iob[i].i_filesize + iob[i].i_buf, io->i_buf); | |
424 | } | |
425 | ||
426 | // Load entire file into memory. Unnecessary open() calls must | |
427 | // be avoided. | |
428 | ||
429 | gFSLoadAddress = io->i_buf; | |
430 | io->i_filesize = bvr->fs_loadfile(bvr, (char *)filePath); | |
f083c6c3 A |
431 | if (io->i_filesize < 0) { |
432 | goto error; | |
433 | } | |
75b89a82 A |
434 | |
435 | return fdesc; | |
436 | ||
437 | error: | |
438 | close(fdesc); | |
439 | return -1; | |
14c7c974 A |
440 | } |
441 | ||
75b89a82 A |
442 | //========================================================================== |
443 | // close() - Close a file descriptor. | |
14c7c974 | 444 | |
75b89a82 | 445 | int close(int fdesc) |
14c7c974 | 446 | { |
75b89a82 | 447 | struct iob * io; |
14c7c974 | 448 | |
75b89a82 A |
449 | if ((io = iob_from_fdesc(fdesc)) == NULL) |
450 | return (-1); | |
14c7c974 | 451 | |
75b89a82 | 452 | io->i_flgs = 0; |
14c7c974 | 453 | |
75b89a82 | 454 | return 0; |
14c7c974 | 455 | } |
75b89a82 A |
456 | |
457 | //========================================================================== | |
458 | // lseek() - Reposition the byte offset of the file descriptor from the | |
459 | // beginning of the file. Returns the relocated offset. | |
460 | ||
461 | int b_lseek(int fdesc, int offset, int ptr) | |
14c7c974 | 462 | { |
75b89a82 | 463 | struct iob * io; |
14c7c974 | 464 | |
75b89a82 A |
465 | if ((io = iob_from_fdesc(fdesc)) == NULL) |
466 | return (-1); | |
14c7c974 | 467 | |
75b89a82 | 468 | io->i_offset = offset; |
14c7c974 | 469 | |
75b89a82 | 470 | return offset; |
14c7c974 A |
471 | } |
472 | ||
75b89a82 A |
473 | //========================================================================== |
474 | // tell() - Returns the byte offset of the file descriptor. | |
14c7c974 | 475 | |
75b89a82 | 476 | int tell(int fdesc) |
14c7c974 | 477 | { |
75b89a82 | 478 | struct iob * io; |
14c7c974 | 479 | |
75b89a82 A |
480 | if ((io = iob_from_fdesc(fdesc)) == NULL) |
481 | return 0; | |
482 | ||
483 | return io->i_offset; | |
14c7c974 A |
484 | } |
485 | ||
75b89a82 A |
486 | //========================================================================== |
487 | // read() - Read up to 'count' bytes of data from the file descriptor | |
488 | // into the buffer pointed to by buf. | |
489 | ||
490 | int read(int fdesc, char * buf, int count) | |
14c7c974 | 491 | { |
75b89a82 A |
492 | struct iob * io; |
493 | ||
494 | if ((io = iob_from_fdesc(fdesc)) == NULL) | |
495 | return (-1); | |
496 | ||
f083c6c3 | 497 | if ((io->i_offset + count) > (unsigned int)io->i_filesize) |
75b89a82 A |
498 | count = io->i_filesize - io->i_offset; |
499 | ||
500 | if (count <= 0) | |
501 | return 0; // end of file | |
502 | ||
503 | bcopy(io->i_buf + io->i_offset, buf, count); | |
504 | ||
505 | io->i_offset += count; | |
506 | ||
507 | return count; | |
14c7c974 A |
508 | } |
509 | ||
75b89a82 A |
510 | //========================================================================== |
511 | // file_size() - Returns the size of the file described by the file | |
512 | // descriptor. | |
513 | ||
514 | int file_size(int fdesc) | |
14c7c974 | 515 | { |
75b89a82 A |
516 | struct iob * io; |
517 | ||
518 | if ((io = iob_from_fdesc(fdesc)) == 0) | |
519 | return 0; | |
520 | ||
521 | return io->i_filesize; | |
14c7c974 A |
522 | } |
523 | ||
75b89a82 A |
524 | //========================================================================== |
525 | ||
57c72a9a A |
526 | struct dirstuff * vol_opendir(BVRef bvr, const char * path) |
527 | { | |
528 | struct dirstuff * dirp = 0; | |
529 | ||
530 | dirp = (struct dirstuff *) malloc(sizeof(struct dirstuff)); | |
531 | if (dirp == NULL) | |
532 | goto error; | |
533 | ||
534 | dirp->dir_path = newString(path); | |
535 | if (dirp->dir_path == NULL) | |
536 | goto error; | |
537 | ||
538 | dirp->dir_bvr = bvr; | |
539 | ||
540 | return dirp; | |
541 | ||
542 | error: | |
543 | closedir(dirp); | |
544 | return NULL; | |
545 | } | |
546 | ||
547 | //========================================================================== | |
548 | ||
75b89a82 | 549 | struct dirstuff * opendir(const char * path) |
14c7c974 | 550 | { |
75b89a82 A |
551 | struct dirstuff * dirp = 0; |
552 | const char * dirPath; | |
553 | BVRef bvr; | |
554 | ||
555 | if ((bvr = getBootVolumeRef(path, &dirPath)) == NULL) | |
556 | goto error; | |
557 | ||
558 | dirp = (struct dirstuff *) malloc(sizeof(struct dirstuff)); | |
559 | if (dirp == NULL) | |
560 | goto error; | |
561 | ||
562 | dirp->dir_path = newString(dirPath); | |
563 | if (dirp->dir_path == NULL) | |
564 | goto error; | |
565 | ||
566 | dirp->dir_bvr = bvr; | |
567 | ||
568 | return dirp; | |
14c7c974 | 569 | |
75b89a82 A |
570 | error: |
571 | closedir(dirp); | |
572 | return NULL; | |
14c7c974 A |
573 | } |
574 | ||
75b89a82 | 575 | //========================================================================== |
14c7c974 | 576 | |
75b89a82 | 577 | int closedir(struct dirstuff * dirp) |
14c7c974 | 578 | { |
75b89a82 A |
579 | if (dirp) { |
580 | if (dirp->dir_path) free(dirp->dir_path); | |
581 | free(dirp); | |
582 | } | |
583 | return 0; | |
14c7c974 A |
584 | } |
585 | ||
75b89a82 A |
586 | //========================================================================== |
587 | ||
588 | int readdir(struct dirstuff * dirp, const char ** name, long * flags, | |
589 | long * time) | |
14c7c974 | 590 | { |
75b89a82 A |
591 | return dirp->dir_bvr->fs_getdirentry( dirp->dir_bvr, |
592 | /* dirPath */ dirp->dir_path, | |
593 | /* dirIndex */ &dirp->dir_index, | |
57c72a9a A |
594 | /* dirEntry */ (char **)name, flags, time, |
595 | 0, 0); | |
596 | } | |
597 | ||
598 | //========================================================================== | |
599 | ||
600 | int readdir_ext(struct dirstuff * dirp, const char ** name, long * flags, | |
601 | long * time, FinderInfo *finderInfo, long *infoValid) | |
602 | { | |
603 | return dirp->dir_bvr->fs_getdirentry( dirp->dir_bvr, | |
604 | /* dirPath */ dirp->dir_path, | |
605 | /* dirIndex */ &dirp->dir_index, | |
606 | /* dirEntry */ (char **)name, | |
607 | flags, time, | |
608 | finderInfo, infoValid); | |
14c7c974 A |
609 | } |
610 | ||
75b89a82 A |
611 | //========================================================================== |
612 | ||
613 | int currentdev() | |
14c7c974 | 614 | { |
bba600dd A |
615 | printf("currentdev = %d\n", bootInfo->kernDev); |
616 | return bootInfo->kernDev; | |
14c7c974 A |
617 | } |
618 | ||
75b89a82 A |
619 | //========================================================================== |
620 | ||
621 | int switchdev(int dev) | |
14c7c974 | 622 | { |
bba600dd | 623 | bootInfo->kernDev = dev; |
75b89a82 A |
624 | return dev; |
625 | } | |
14c7c974 | 626 | |
75b89a82 | 627 | //========================================================================== |
14c7c974 | 628 | |
75b89a82 A |
629 | const char * usrDevices() |
630 | { | |
f083c6c3 A |
631 | if (gBootFileType == kNetworkDeviceType) |
632 | return ""; | |
633 | return "/private/Drivers/i386"; | |
75b89a82 | 634 | } |
14c7c974 | 635 | |
75b89a82 | 636 | //========================================================================== |
14c7c974 | 637 | |
f083c6c3 A |
638 | const char * systemConfigDir() |
639 | { | |
640 | if (gBootFileType == kNetworkDeviceType) | |
641 | return ""; | |
642 | return "/Library/Preferences/SystemConfiguration"; | |
643 | } | |
644 | ||
645 | //========================================================================== | |
646 | ||
647 | int gBootFileType; | |
648 | ||
75b89a82 A |
649 | BVRef scanBootVolumes( int biosdev, int * count ) |
650 | { | |
651 | BVRef bvr = 0; | |
14c7c974 | 652 | |
f083c6c3 A |
653 | bvr = diskScanBootVolumes(biosdev, count); |
654 | if (bvr == NULL) { | |
655 | bvr = nbpScanBootVolumes(biosdev, count); | |
656 | if (bvr != NULL) { | |
657 | gBootFileType = kNetworkDeviceType; | |
658 | } | |
659 | } else { | |
660 | gBootFileType = kBlockDeviceType; | |
75b89a82 A |
661 | } |
662 | return bvr; | |
14c7c974 A |
663 | } |
664 | ||
75b89a82 | 665 | //========================================================================== |
14c7c974 | 666 | |
75b89a82 A |
667 | BVRef selectBootVolume( BVRef chain ) |
668 | { | |
669 | BVRef bvr, bvr1 = 0, bvr2 = 0; | |
14c7c974 | 670 | |
75b89a82 A |
671 | for ( bvr = chain; bvr; bvr = bvr->next ) |
672 | { | |
673 | if ( bvr->flags & kBVFlagNativeBoot ) bvr1 = bvr; | |
674 | if ( bvr->flags & kBVFlagPrimary ) bvr2 = bvr; | |
675 | } | |
14c7c974 | 676 | |
f083c6c3 A |
677 | bvr = bvr2 ? bvr2 : |
678 | bvr1 ? bvr1 : chain; | |
14c7c974 | 679 | |
75b89a82 | 680 | return bvr; |
14c7c974 A |
681 | } |
682 | ||
75b89a82 A |
683 | //========================================================================== |
684 | ||
14c7c974 A |
685 | #define LP '(' |
686 | #define RP ')' | |
f083c6c3 | 687 | int gBIOSDev; |
14c7c974 | 688 | |
57c72a9a | 689 | BVRef getBootVolumeRef( const char * path, const char ** outPath ) |
14c7c974 | 690 | { |
75b89a82 A |
691 | const char * cp; |
692 | BVRef bvr; | |
bba600dd A |
693 | int type = B_TYPE( bootInfo->kernDev ); |
694 | int unit = B_UNIT( bootInfo->kernDev ); | |
695 | int part = B_PARTITION( bootInfo->kernDev ); | |
75b89a82 A |
696 | int biosdev = gBIOSDev; |
697 | static BVRef lastBVR = 0; | |
698 | static int lastKernDev; | |
699 | ||
700 | // Search for left parenthesis in the path specification. | |
701 | ||
702 | for (cp = path; *cp; cp++) { | |
703 | if (*cp == LP || *cp == '/') break; | |
14c7c974 | 704 | } |
14c7c974 | 705 | |
75b89a82 A |
706 | if (*cp != LP) // no left paren found |
707 | { | |
708 | cp = path; | |
bba600dd | 709 | if ( lastBVR && lastKernDev == bootInfo->kernDev ) |
75b89a82 A |
710 | { |
711 | bvr = lastBVR; | |
712 | goto quick_exit; | |
713 | } | |
714 | } | |
715 | else if ((cp - path) == 2) // found "xx(" | |
716 | { | |
717 | const struct devsw * dp; | |
718 | const char * xp = path; | |
719 | int i; | |
720 | ||
721 | cp++; | |
722 | ||
723 | // Check the 2 character device name pointed by 'xp'. | |
724 | ||
725 | for (dp = devsw; dp->name; dp++) | |
726 | { | |
727 | if ((xp[0] == dp->name[0]) && (xp[1] == dp->name[1])) | |
728 | break; // found matching entry | |
729 | } | |
730 | if (dp->name == NULL) | |
731 | { | |
732 | error("Unknown device '%c%c'\n", xp[0], xp[1]); | |
733 | return NULL; | |
734 | } | |
735 | type = dp - devsw; // kerndev type | |
736 | ||
737 | // Extract the optional unit number from the specification. | |
738 | // hd(unit) or hd(unit, part). | |
739 | ||
740 | i = 0; | |
741 | while (*cp >= '0' && *cp <= '9') | |
742 | { | |
743 | i = i * 10 + *cp++ - '0'; | |
744 | unit = i; | |
745 | } | |
746 | ||
747 | // Extract the optional partition number from the specification. | |
748 | ||
749 | if (*cp == ',') | |
750 | part = atoi(++cp); | |
751 | ||
752 | // Skip past the right paren. | |
753 | ||
754 | for ( ; *cp && *cp != RP; cp++) /* LOOP */; | |
755 | if (*cp == RP) cp++; | |
756 | ||
f083c6c3 | 757 | biosdev = dp->biosdev + unit; |
75b89a82 A |
758 | } |
759 | else | |
760 | { | |
761 | // Bad device specifier, skip past the right paren. | |
14c7c974 | 762 | |
75b89a82 A |
763 | for ( cp++; *cp && *cp != RP; cp++) /* LOOP */; |
764 | if (*cp == RP) cp++; | |
765 | } | |
14c7c974 | 766 | |
75b89a82 A |
767 | if ((bvr = newBootVolumeRef(biosdev, part)) == NULL) |
768 | { | |
769 | // error("newBootVolumeRef() error\n"); | |
770 | return NULL; | |
771 | } | |
14c7c974 | 772 | |
75b89a82 A |
773 | // Record the most recent device parameters in the |
774 | // KernBootStruct. | |
14c7c974 | 775 | |
bba600dd | 776 | bootInfo->kernDev = biosdev; |
14c7c974 | 777 | |
75b89a82 | 778 | lastBVR = bvr; |
bba600dd | 779 | lastKernDev = bootInfo->kernDev; |
14c7c974 | 780 | |
75b89a82 A |
781 | quick_exit: |
782 | // Returns the file path following the device spec. | |
783 | // e.g. 'hd(1,b)mach_kernel' is reduced to 'mach_kernel'. | |
14c7c974 | 784 | |
75b89a82 | 785 | *outPath = cp; |
14c7c974 | 786 | |
75b89a82 | 787 | return bvr; |
14c7c974 A |
788 | } |
789 | ||
75b89a82 | 790 | //========================================================================== |
14c7c974 | 791 | |
75b89a82 | 792 | static BVRef newBootVolumeRef( int biosdev, int partno ) |
14c7c974 | 793 | { |
75b89a82 | 794 | BVRef bvr, bvr1, bvrChain; |
14c7c974 | 795 | |
75b89a82 | 796 | // Fetch the volume list from the device. |
14c7c974 | 797 | |
75b89a82 A |
798 | bvrChain = scanBootVolumes( biosdev, NULL ); |
799 | ||
800 | // Look for a perfect match based on device and partition number. | |
801 | ||
802 | for ( bvr1 = NULL, bvr = bvrChain; bvr; bvr = bvr->next ) | |
803 | { | |
804 | if ( ( bvr->flags & kBVFlagNativeBoot ) == 0 ) continue; | |
805 | ||
806 | bvr1 = bvr; | |
807 | if ( bvr->part_no == partno ) break; | |
808 | } | |
809 | ||
810 | return bvr ? bvr : bvr1; | |
14c7c974 | 811 | } |