Chameleon

Chameleon Svn Source Tree

Root/branches/meklort/i386/libsaio/sys.c

Source at commit 521 created 13 years 7 months ago.
By meklort, Modules, Modules everywhere
1/*
2 * Copyright (c) 1999-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 1999-2003 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 2.0 (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.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
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.c7.1 (Berkeley) 6/5/86
55 */
56
57/* Copyright 2007 VMware Inc.
58 "Preboot" ramdisk support added by David Elliott
59 */
60
61#include <AvailabilityMacros.h>
62
63#include "libsaio.h"
64#include "boot.h"
65#include "bootstruct.h"
66#include "disk.h"
67#include "ramdisk.h"
68#include "xml.h"
69#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
70# include <Kernel/libkern/crypto/md5.h>
71#else
72# include <sys/md5.h>
73#endif
74#include <uuid/uuid.h>
75#if 0 /* No OS X release has ever included this. */
76#include <Kernel/uuid/namespace.h>
77#else
78/* copied from uuid/namespace.h, just like BootX's fs.c does. */
79UUID_DEFINE( kFSUUIDNamespaceSHA1, 0xB3, 0xE2, 0x0F, 0x39, 0xF2, 0x92, 0x11, 0xD6, 0x97, 0xA4, 0x00, 0x30, 0x65, 0x43, 0xEC, 0xAC );
80#endif
81
82#ifdef UNUSED
83extern int multiboot_partition;
84extern int multiboot_partition_set;
85#endif
86
87struct devsw {
88 const char * name;
89 // size increased from char to short to handle non-BIOS internal devices
90 unsigned short biosdev;
91 int type;
92};
93
94// Device entries must be ordered by bios device numbers.
95static struct devsw devsw[] =
96{
97 { "hd", 0x80, kBIOSDevTypeHardDrive }, /* DEV_HD */
98 { "en", 0xE0, kBIOSDevTypeNetwork }, /* DEV_EN */
99 { "rd", 0x100, kBIOSDevTypeHardDrive },
100 { "bt", 0x101, kBIOSDevTypeHardDrive }, // turbo - type for booter partition
101 { 0, 0 }
102};
103
104// Pseudo BIOS devices
105enum {
106kPseudoBIOSDevRAMDisk = 0x100,
107kPseudoBIOSDevBooter = 0x101
108};
109
110/*
111 * Max number of file descriptors.
112 */
113#define NFILES 6
114
115static struct iob iob[NFILES];
116
117void * gFSLoadAddress = 0;
118
119// Turbo - save what we think is our original BIOS boot volume if we have one 0xab
120BVRef gBIOSBootVolume = NULL;
121BVRef gBootVolume;
122
123//static BVRef getBootVolumeRef( const char * path, const char ** outPath );
124static BVRef newBootVolumeRef( int biosdev, int partno );
125
126//==========================================================================
127// LoadVolumeFile - LOW-LEVEL FILESYSTEM FUNCTION.
128// Load the specified file from the specified volume
129// to the load buffer at LOAD_ADDR.
130// If the file is fat, load only the i386 portion.
131
132long LoadVolumeFile(BVRef bvr, const char *filePath)
133{
134 long fileSize;
135
136 // Read file into load buffer. The data in the load buffer will be
137 // overwritten by the next LoadFile() call.
138
139 gFSLoadAddress = (void *) LOAD_ADDR;
140
141 fileSize = bvr->fs_loadfile(bvr, (char *)filePath);
142
143 // Return the size of the file, or -1 if load failed.
144
145 return fileSize;
146}
147
148//==========================================================================
149// LoadFile - LOW-LEVEL FILESYSTEM FUNCTION.
150// Load the specified file to the load buffer at LOAD_ADDR.
151// If the file is fat, load only the i386 portion.
152
153long LoadFile(const char * fileSpec)
154{
155 const char * filePath;
156 BVRef bvr;
157
158 // Resolve the boot volume from the file spec.
159
160 if ((bvr = getBootVolumeRef(fileSpec, &filePath)) == NULL)
161 return -1;
162
163 return LoadVolumeFile(bvr, filePath);
164}
165
166long ReadFileAtOffset(const char * fileSpec, void *buffer, uint64_t offset, uint64_t length)
167{
168 const char *filePath;
169 BVRef bvr;
170
171 if ((bvr = getBootVolumeRef(fileSpec, &filePath)) == NULL)
172 return -1;
173
174 if (bvr->fs_readfile == NULL)
175 return -1;
176
177 return bvr->fs_readfile(bvr, (char *)filePath, buffer, offset, length);
178}
179
180long LoadThinFatFile(const char *fileSpec, void **binary)
181{
182 const char *filePath;
183 FSReadFile readFile;
184 BVRef bvr;
185 unsigned long length, length2;
186
187 // Resolve the boot volume from the file spec.
188
189 if ((bvr = getBootVolumeRef(fileSpec, &filePath)) == NULL)
190 return -1;
191
192 *binary = (void *)kLoadAddr;
193
194 // Read file into load buffer. The data in the load buffer will be
195 // overwritten by the next LoadFile() call.
196
197 gFSLoadAddress = (void *) LOAD_ADDR;
198
199 readFile = bvr->fs_readfile;
200
201 if (readFile != NULL) {
202 // Read the first 4096 bytes (fat header)
203 length = readFile(bvr, (char *)filePath, *binary, 0, 0x1000);
204 if (length > 0) {
205 if (ThinFatFile(binary, &length) == 0) {
206if (length == 0)
207return 0;
208 // We found a fat binary; read only the thin part
209 length = readFile(bvr, (char *)filePath,
210 (void *)kLoadAddr, (unsigned long)(*binary) - kLoadAddr, length);
211 *binary = (void *)kLoadAddr;
212 } else {
213 // Not a fat binary; read the rest of the file
214 length2 = readFile(bvr, (char *)filePath, (void *)(kLoadAddr + length), length, 0);
215 if (length2 == -1) return -1;
216 length += length2;
217 }
218 }
219 } else {
220 length = bvr->fs_loadfile(bvr, (char *)filePath);
221 if (length > 0) {
222 ThinFatFile(binary, &length);
223 }
224 }
225
226 return length;
227}
228
229#if UNUSED
230long GetFSUUID(char *spec, char *uuidStr)
231{
232 BVRef bvr;
233 long rval = -1;
234 const char *devSpec;
235
236 if ((bvr = getBootVolumeRef(spec, &devSpec)) == NULL)
237 return -1;
238
239 if(bvr->fs_getuuid)
240 rval = bvr->fs_getuuid(bvr, uuidStr);
241
242 return rval;
243}
244#endif
245
246// filesystem-specific getUUID functions call this shared string generator
247long CreateUUIDString(uint8_t uubytes[], int nbytes, char *uuidStr)
248{
249 unsigned fmtbase, fmtidx, i;
250 uint8_t uuidfmt[] = { 4, 2, 2, 2, 6 };
251 char *p = uuidStr;
252 MD5_CTX md5c;
253 uint8_t mdresult[16];
254
255 bzero(mdresult, sizeof(mdresult));
256
257 // just like AppleFileSystemDriver
258 MD5Init(&md5c);
259 MD5Update(&md5c, kFSUUIDNamespaceSHA1, sizeof(kFSUUIDNamespaceSHA1));
260 MD5Update(&md5c, uubytes, nbytes);
261 MD5Final(mdresult, &md5c);
262
263 // this UUID has been made version 3 style (i.e. via namespace)
264 // see "-uuid-urn-" IETF draft (which otherwise copies byte for byte)
265 mdresult[6] = 0x30 | ( mdresult[6] & 0x0F );
266 mdresult[8] = 0x80 | ( mdresult[8] & 0x3F );
267
268
269 // generate the text: e.g. 5EB1869F-C4FA-3502-BDEB-3B8ED5D87292
270 i = 0; fmtbase = 0;
271 for(fmtidx = 0; fmtidx < sizeof(uuidfmt); fmtidx++) {
272 for(i=0; i < uuidfmt[fmtidx]; i++) {
273 uint8_t byte = mdresult[fmtbase+i];
274 char nib;
275
276 nib = byte >> 4;
277 *p = nib + '0'; // 0x4 -> '4'
278 if(*p > '9') *p = (nib - 9 + ('A'-1)); // 0xB -> 'B'
279 p++;
280
281 nib = byte & 0xf;
282 *p = nib + '0'; // 0x4 -> '4'
283 if(*p > '9') *p = (nib - 9 + ('A'-1)); // 0xB -> 'B'
284 p++;
285
286 }
287 fmtbase += i;
288 if(fmtidx < sizeof(uuidfmt)-1)
289 *(p++) = '-';
290 else
291 *p = '\0';
292 }
293
294 return 0;
295}
296
297
298//==========================================================================
299// GetDirEntry - LOW-LEVEL FILESYSTEM FUNCTION.
300// Fetch the next directory entry for the given directory.
301
302long GetDirEntry(const char * dirSpec, long long * dirIndex, const char ** name,
303 long * flags, long * time)
304{
305 const char * dirPath;
306 BVRef bvr;
307
308 // Resolve the boot volume from the dir spec.
309
310 if ((bvr = getBootVolumeRef(dirSpec, &dirPath)) == NULL)
311 return -1;
312
313 // Return 0 on success, or -1 if there are no additional entries.
314
315 return bvr->fs_getdirentry( bvr,
316 /* dirPath */ (char *)dirPath,
317 /* dirIndex */ dirIndex,
318 /* dirEntry */ (char **)name, flags, time, 0, 0 );
319}
320
321//==========================================================================
322// GetFileInfo - LOW-LEVEL FILESYSTEM FUNCTION.
323// Get attributes for the specified file.
324
325static char* gMakeDirSpec;
326
327long GetFileInfo(const char * dirSpec, const char * name,
328 long * flags, long * time)
329{
330 long long index = 0;
331 const char * entryName;
332
333 if (gMakeDirSpec == 0)
334 gMakeDirSpec = (char *)malloc(1024);
335
336 if (!dirSpec) {
337 long idx, len;
338
339 len = strlen(name);
340
341 for (idx = len; idx && (name[idx] != '/' && name[idx] != '\\'); idx--) {}
342 if (idx == 0) {
343 gMakeDirSpec[0] = '/';
344 gMakeDirSpec[1] = '\0';
345 } else {
346 idx++;
347 strncpy(gMakeDirSpec, name, idx);
348 name += idx;
349 }
350 dirSpec = gMakeDirSpec;
351 }
352
353 while (GetDirEntry(dirSpec, &index, &entryName, flags, time) == 0)
354 {
355 if (strcmp(entryName, name) == 0)
356 return 0; // success
357 }
358 return -1; // file not found
359}
360
361long GetFileBlock(const char *fileSpec, unsigned long long *firstBlock)
362{
363 const char * filePath;
364 BVRef bvr;
365
366 // Resolve the boot volume from the file spec.
367
368 if ((bvr = getBootVolumeRef(fileSpec, &filePath)) == NULL) {
369 printf("Boot volume for '%s' is bogus\n", fileSpec);
370 return -1;
371 }
372
373 return bvr->fs_getfileblock(bvr, (char *)filePath, firstBlock);
374}
375
376//==========================================================================
377// GetFreeFD()
378
379static int GetFreeFd(void)
380{
381intfd;
382
383// Locate a free descriptor slot.
384for (fd = 0; fd < NFILES; fd++) {
385if (iob[fd].i_flgs == 0) {
386return fd;
387 }
388}
389stop("Out of file descriptors");
390// not reached
391return -1;
392}
393
394//==========================================================================
395// iob_from_fdesc()
396//
397// Return a pointer to an allocated 'iob' based on the file descriptor
398// provided. Returns NULL if the file descriptor given is invalid.
399
400static struct iob * iob_from_fdesc(int fdesc)
401{
402 register struct iob * io;
403
404 if (fdesc < 0 || fdesc >= NFILES ||
405 ((io = &iob[fdesc])->i_flgs & F_ALLOC) == 0)
406 return NULL;
407 else
408 return io;
409}
410
411//==========================================================================
412// openmem()
413
414int openmem(char * buf, int len)
415{
416 int fdesc;
417 struct iob * io;
418
419 fdesc = GetFreeFd();
420 io = &iob[fdesc];
421 bzero(io, sizeof(*io));
422
423 // Mark the descriptor as taken. Set the F_MEM flag to indicate
424 // that the file buffer is provided by the caller.
425
426 io->i_flgs = F_ALLOC | F_MEM;
427 io->i_buf = buf;
428 io->i_filesize = len;
429
430 return fdesc;
431}
432
433//==========================================================================
434// open() - Open the file specified by 'path' for reading.
435
436static int open_bvr(BVRef bvr, const char *filePath, int flags)
437{
438struct iob*io;
439intfdesc;
440inti;
441
442if (bvr == NULL) {
443return -1;
444}
445
446fdesc = GetFreeFd();
447io = &iob[fdesc];
448bzero(io, sizeof(*io));
449
450// Mark the descriptor as taken.
451io->i_flgs = F_ALLOC;
452
453// Find the next available memory block in the download buffer.
454io->i_buf = (char *) LOAD_ADDR;
455for (i = 0; i < NFILES; i++) {
456if ((iob[i].i_flgs != F_ALLOC) || (i == fdesc)) {
457continue;
458}
459io->i_buf = max(iob[i].i_filesize + iob[i].i_buf, io->i_buf);
460}
461
462// Load entire file into memory. Unnecessary open() calls must be avoided.
463gFSLoadAddress = io->i_buf;
464io->i_filesize = bvr->fs_loadfile(bvr, (char *)filePath);
465if (io->i_filesize < 0) {
466close(fdesc);
467return -1;
468}
469return fdesc;
470}
471
472int open(const char *path, int flags)
473{
474const char*filepath;
475BVRefbvr;
476
477// Resolve the boot volume from the file spec.
478if ((bvr = getBootVolumeRef(path, &filepath)) != NULL) {
479return open_bvr(bvr, filepath, flags);
480}
481return -1;
482}
483
484int open_bvdev(const char *bvd, const char *path, int flags)
485{
486 const struct devsw*dp;
487const char*cp;
488BVRefbvr;
489inti;
490intlen;
491intunit;
492intpartition;
493
494if ((i = open(path, flags)) >= 0) {
495return i;
496}
497
498if (bvd == NULL || (len = strlen(bvd)) < 2) {
499return -1;
500}
501
502for (dp=devsw; dp->name; dp++) {
503if (bvd[0] == dp->name[0] && bvd[1] == dp->name[1]) {
504unit = 0;
505partition = 0;
506/* get optional unit and partition */
507if (len >= 5 && bvd[2] == '(') { /* min must be present xx(0) */
508cp = &bvd[3];
509i = 0;
510while ((cp - path) < len && isdigit(*cp)) {
511i = i * 10 + *cp++ - '0';
512unit = i;
513}
514if (*cp++ == ',') {
515i = 0;
516while ((cp - path) < len && isdigit(*cp)) {
517i = i * 10 + *cp++ - '0';
518partition = i;
519}
520}
521}
522bvr = newBootVolumeRef(dp->biosdev + unit, partition);
523return open_bvr(bvr, path, flags);
524}
525 }
526return -1;
527}
528
529//==========================================================================
530// close() - Close a file descriptor.
531
532int close(int fdesc)
533{
534 struct iob * io;
535
536 if ((io = iob_from_fdesc(fdesc)) == NULL)
537 return (-1);
538
539 io->i_flgs = 0;
540
541 return 0;
542}
543
544//==========================================================================
545// lseek() - Reposition the byte offset of the file descriptor from the
546// beginning of the file. Returns the relocated offset.
547
548int b_lseek(int fdesc, int offset, int ptr)
549{
550 struct iob * io;
551
552 if ((io = iob_from_fdesc(fdesc)) == NULL)
553 return (-1);
554
555 io->i_offset = offset;
556
557 return offset;
558}
559
560//==========================================================================
561// tell() - Returns the byte offset of the file descriptor.
562
563int tell(int fdesc)
564{
565 struct iob * io;
566
567 if ((io = iob_from_fdesc(fdesc)) == NULL)
568 return 0;
569
570 return io->i_offset;
571}
572
573//==========================================================================
574// read() - Read up to 'count' bytes of data from the file descriptor
575// into the buffer pointed to by buf.
576
577int read(int fdesc, char * buf, int count)
578{
579 struct iob * io;
580
581 if ((io = iob_from_fdesc(fdesc)) == NULL)
582 return (-1);
583
584 if ((io->i_offset + count) > (unsigned int)io->i_filesize)
585 count = io->i_filesize - io->i_offset;
586
587 if (count <= 0)
588 return 0; // end of file
589
590 bcopy(io->i_buf + io->i_offset, buf, count);
591
592 io->i_offset += count;
593
594 return count;
595}
596
597//==========================================================================
598// write() - Write up to 'count' bytes of data to the file descriptor
599// from the buffer pointed to by buf.
600
601int write(int fdesc, const char * buf, int count)
602{
603 struct iob * io;
604
605 if ((io = iob_from_fdesc(fdesc)) == NULL)
606 return (-1);
607
608 if ((io->i_offset + count) > (unsigned int)io->i_filesize)
609 count = io->i_filesize - io->i_offset;
610
611 if (count <= 0)
612 return 0; // end of file
613
614 bcopy(buf, io->i_buf + io->i_offset, count);
615
616 io->i_offset += count;
617
618 return count;
619}
620
621int writebyte(int fdesc, char value)
622{
623 struct iob * io;
624
625 if ((io = iob_from_fdesc(fdesc)) == NULL)
626 return (-1);
627
628 if ((io->i_offset + 1) > (unsigned int)io->i_filesize)
629 return 0; // end of file
630
631 io->i_buf[io->i_offset++] = value;
632
633 return 1;
634}
635
636int writeint(int fdesc, int value)
637{
638 struct iob * io;
639
640 if ((io = iob_from_fdesc(fdesc)) == NULL)
641 return (-1);
642
643 if ((io->i_offset + 4) > (unsigned int)io->i_filesize)
644 return 0; // end of file
645
646 bcopy(&value, io->i_buf + io->i_offset, 4);
647
648 io->i_offset += 4;
649
650 return 4;
651}
652
653//==========================================================================
654// file_size() - Returns the size of the file described by the file
655// descriptor.
656
657int file_size(int fdesc)
658{
659 struct iob * io;
660
661 if ((io = iob_from_fdesc(fdesc)) == 0)
662 return 0;
663
664 return io->i_filesize;
665}
666
667//==========================================================================
668
669struct dirstuff * vol_opendir(BVRef bvr, const char * path)
670{
671 struct dirstuff * dirp = 0;
672
673 dirp = (struct dirstuff *) malloc(sizeof(struct dirstuff));
674 if (dirp == NULL)
675 goto error;
676
677 dirp->dir_path = newString(path);
678 if (dirp->dir_path == NULL)
679 goto error;
680
681 dirp->dir_bvr = bvr;
682
683 return dirp;
684
685error:
686 closedir(dirp);
687 return NULL;
688}
689
690//==========================================================================
691
692struct dirstuff * opendir(const char * path)
693{
694 struct dirstuff * dirp = 0;
695 const char * dirPath;
696 BVRef bvr;
697
698 if ((bvr = getBootVolumeRef(path, &dirPath)) == NULL)
699 goto error;
700
701 dirp = (struct dirstuff *) malloc(sizeof(struct dirstuff));
702 if (dirp == NULL)
703 goto error;
704
705 dirp->dir_path = newString(dirPath);
706 if (dirp->dir_path == NULL)
707 goto error;
708
709 dirp->dir_bvr = bvr;
710
711 return dirp;
712
713error:
714 closedir(dirp);
715 return NULL;
716}
717
718//==========================================================================
719
720int closedir(struct dirstuff * dirp)
721{
722 if (dirp) {
723 if (dirp->dir_path) free(dirp->dir_path);
724 free(dirp);
725 }
726 return 0;
727}
728
729//==========================================================================
730
731int readdir(struct dirstuff * dirp, const char ** name, long * flags,
732 long * time)
733{
734 return dirp->dir_bvr->fs_getdirentry( dirp->dir_bvr,
735 /* dirPath */ dirp->dir_path,
736 /* dirIndex */ &dirp->dir_index,
737 /* dirEntry */ (char **)name, flags, time,
738 0, 0);
739}
740
741//==========================================================================
742
743int readdir_ext(struct dirstuff * dirp, const char ** name, long * flags,
744 long * time, FinderInfo *finderInfo, long *infoValid)
745{
746 return dirp->dir_bvr->fs_getdirentry( dirp->dir_bvr,
747 /* dirPath */ dirp->dir_path,
748 /* dirIndex */ &dirp->dir_index,
749 /* dirEntry */ (char **)name,
750 flags, time,
751 finderInfo, infoValid);
752}
753
754//==========================================================================
755
756const char * systemConfigDir()
757{
758 if (gBootFileType == kNetworkDeviceType)
759return "";
760 return "/Library/Preferences/SystemConfiguration";
761}
762
763//==========================================================================
764
765int gBootFileType;
766
767void scanBootVolumes( int biosdev, int * count )
768{
769 BVRef bvr = 0;
770
771 bvr = diskScanBootVolumes(biosdev, count);
772 if (bvr == NULL)
773 {
774 bvr = nbpScanBootVolumes(biosdev, count);
775 if (bvr != NULL)
776 {
777 gBootFileType = kNetworkDeviceType;
778 }
779 }
780 else
781 {
782 gBootFileType = kBlockDeviceType;
783 }
784}
785
786//==========================================================================
787
788void scanDisks(int biosdev, int *count)
789{
790 #define MAX_HDD_COUNT 32
791 int bvCount;
792 int hd = 0;
793
794 // Testing up to MAX_HDD_COUNT hard drives.
795while(!testBiosread(0x80 + hd, 0) && hd < MAX_HDD_COUNT)
796{
797 bvCount = 0;
798 scanBootVolumes(0x80 + hd, &bvCount);
799 hd++;
800}
801
802 // Also scanning CD/DVD drive.
803if (biosDevIsCDROM(gBIOSDev))
804{
805 bvCount = 0;
806 scanBootVolumes(gBIOSDev, &bvCount);
807}
808}
809
810//==========================================================================
811
812BVRef selectBootVolume( BVRef chain )
813{
814bool filteredChain = false;
815bool foundPrimary = false;
816BVRef bvr, bvr1 = 0, bvr2 = 0;
817
818if (chain->filtered) filteredChain = true;
819
820#ifdef UNUSED
821if (multiboot_partition_set)
822for ( bvr = chain; bvr; bvr = bvr->next )
823if ( bvr->part_no == multiboot_partition && bvr->biosdev == gBIOSDev )
824return bvr;
825#endif
826/*
827 * Checking "Default Partition" key in system configuration - use format: hd(x,y), the volume UUID or label -
828 * to override the default selection.
829 * We accept only kBVFlagSystemVolume or kBVFlagForeignBoot volumes.
830 */
831char *val = XMLDecode(getStringForKey(kDefaultPartition, &bootInfo->bootConfig));
832 if (val) {
833 for ( bvr = chain; bvr; bvr = bvr->next ) {
834 if (matchVolumeToString(bvr, val, false)) {
835 free(val);
836 return bvr;
837 }
838 }
839 free(val);
840 }
841
842/*
843 * Scannig the volume chain backwards and trying to find
844 * a HFS+ volume with valid boot record signature.
845 * If not found any active partition then we will
846 * select this volume as the boot volume.
847 */
848for ( bvr = chain; bvr; bvr = bvr->next )
849{
850if ( bvr->flags & kBVFlagPrimary && bvr->biosdev == gBIOSDev ) foundPrimary = true;
851// zhell -- Undo a regression that was introduced from r491 to 492.
852// if gBIOSBootVolume is set already, no change is required
853if ( bvr->flags & (kBVFlagBootable|kBVFlagSystemVolume)
854&& gBIOSBootVolume
855&& (!filteredChain || (filteredChain && bvr->visible))
856&& bvr->biosdev == gBIOSDev )
857bvr2 = bvr;
858// zhell -- if gBIOSBootVolume is NOT set, we use the "if" statement
859// from r491,
860if ( bvr->flags & kBVFlagBootable
861&& ! gBIOSBootVolume
862&& bvr->biosdev == gBIOSDev )
863bvr2 = bvr;
864}
865
866
867/*
868 * Use the standrad method for selecting the boot volume.
869 */
870if (foundPrimary)
871{
872for ( bvr = chain; bvr; bvr = bvr->next )
873{
874if ( bvr->flags & kBVFlagNativeBoot && bvr->biosdev == gBIOSDev ) bvr1 = bvr;
875if ( bvr->flags & kBVFlagPrimary && bvr->biosdev == gBIOSDev ) bvr2 = bvr;
876}
877}
878
879bvr = bvr2 ? bvr2 :
880bvr1 ? bvr1 : chain;
881
882return bvr;
883}
884
885//==========================================================================
886
887#define LP '('
888#define RP ')'
889int gBIOSDev;
890
891/*!
892 This is like boot2's gBootVolume except it is for the internal use of
893 libsaio to track which volume an unqualified path should be relative to.
894 This replaces bootInfo->kernDev as the carrier of this information.
895 */
896static BVRef gRootVolume;
897
898void setRootVolume(BVRef volume)
899{
900 gRootVolume = volume;
901 // Veto non-native FS. Basically that means don't allow the root volume to
902 // be set to a volume we can't read files from.
903 if(gRootVolume != NULL && ((gRootVolume->flags & kBVFlagNativeBoot) == 0))
904 gRootVolume = NULL;
905}
906
907void setBootGlobals(BVRef chain)
908{
909 // Record default boot device.
910 gBootVolume = selectBootVolume(chain);
911
912 // turbo - Save the ORIGINAL boot volume too for loading our mkext
913 if (!gBIOSBootVolume) gBIOSBootVolume = gBootVolume;
914
915 setRootVolume(gBootVolume);
916}
917
918/*!
919 Extracts the volume selector from the pathname, returns the selected
920 BVRef, and sets *outPath to the remainder of the path.
921 If the path did not include a volume selector then the current volume
922 is used. When called with a volume selector the current volume
923 is changed to the selected volume unless the volume selector is
924 that of a ramdisk.
925 */
926BVRef getBootVolumeRef( const char * path, const char ** outPath )
927{
928 const char * cp;
929 BVRef bvr = gRootVolume;
930 int biosdev = gBIOSDev;
931
932 // Search for left parenthesis in the path specification.
933
934 for (cp = path; *cp; cp++) {
935 if (*cp == LP || *cp == '/') break;
936 }
937
938 if (*cp != LP) // no left paren found
939 {
940 // Path is using the implicit current device so if there is
941 // no current device, then we must fail.
942 cp = path;
943 if ( gRootVolume == NULL )
944 return NULL;
945 }
946 else if ((cp - path) == 2) // found "xx("
947 {
948 const struct devsw * dp;
949 const char * xp = path;
950 int i;
951 int unit = -1;
952 int part = -1;
953
954 cp++;
955
956 // Check the 2 character device name pointed by 'xp'.
957
958 for (dp = devsw; dp->name; dp++)
959 {
960 if ((xp[0] == dp->name[0]) && (xp[1] == dp->name[1]))
961 break; // found matching entry
962 }
963 if (dp->name == NULL)
964 {
965 error("Unknown device '%c%c'\n", xp[0], xp[1]);
966 return NULL;
967 }
968
969 // Extract the optional unit number from the specification.
970 // hd(unit) or hd(unit, part).
971
972 i = 0;
973 while (*cp >= '0' && *cp <= '9')
974 {
975 i = i * 10 + *cp++ - '0';
976 unit = i;
977 }
978
979 // Unit is no longer optional and never really was.
980 // If the user failed to specify it then the unit number from the previous kernDev
981 // would have been used which makes little sense anyway.
982 // For example, if the user did fd()/foobar and the current root device was the
983 // second hard disk (i.e. unit 1) then fd() would select the second floppy drive!
984 if(unit == -1)
985 return NULL;
986
987 // Extract the optional partition number from the specification.
988
989 if (*cp == ',')
990 part = atoi(++cp);
991
992 // If part is not specified part will be -1 whereas before it would have been
993 // whatever the last partition was which makes about zero sense if the device
994 // has been switched.
995
996 // Skip past the right paren.
997
998 for ( ; *cp && *cp != RP; cp++) /* LOOP */;
999 if (*cp == RP) cp++;
1000
1001 biosdev = dp->biosdev + unit;
1002 bvr = newBootVolumeRef(biosdev, part);
1003
1004 if(bvr == NULL)
1005 return NULL;
1006 }
1007 else
1008 {
1009 // Bad device specifier, skip past the right paren.
1010
1011 for ( cp++; *cp && *cp != RP; cp++) /* LOOP */;
1012 if (*cp == RP) cp++;
1013 // If gRootVolume was NULL, then bvr will be NULL as well which
1014 // should be caught by the caller.
1015 }
1016
1017 // Returns the file path following the device spec.
1018 // e.g. 'hd(1,b)mach_kernel' is reduced to 'mach_kernel'.
1019
1020 *outPath = cp;
1021
1022 return bvr;
1023}
1024
1025//==========================================================================
1026// Function name is a misnomer as scanBootVolumes usually calls diskScanBootVolumes
1027// which caches the information. So it's only allocated on the first run.
1028static BVRef newBootVolumeRef( int biosdev, int partno )
1029{
1030BVRef bvr, bvr1, bvrChain;
1031
1032bvr = bvr1 = NULL;
1033
1034 // Try resolving "rd" and "bt" devices first.
1035if (biosdev == kPseudoBIOSDevRAMDisk)
1036{
1037if (gRAMDiskVolume)
1038 bvr1 = gRAMDiskVolume;
1039}
1040else if (biosdev == kPseudoBIOSDevBooter)
1041{
1042if (gRAMDiskVolume != NULL && gRAMDiskBTAliased)
1043bvr1 = gRAMDiskVolume;
1044else
1045bvr1 = gBIOSBootVolume;
1046}
1047else
1048{
1049// Fetch the volume list from the device.
1050
1051scanBootVolumes( biosdev, NULL );
1052bvrChain = getBVChainForBIOSDev(biosdev);
1053
1054// Look for a perfect match based on device and partition number.
1055
1056for ( bvr1 = NULL, bvr = bvrChain; bvr; bvr = bvr->next )
1057{
1058if ( ( bvr->flags & kBVFlagNativeBoot ) == 0 ) continue;
1059
1060bvr1 = bvr;
1061if ( bvr->part_no == partno ) break;
1062}
1063}
1064
1065return bvr ? bvr : bvr1;
1066}
1067
1068//==========================================================================
1069// getDeviceDescription() - Extracts unit number and partition number
1070// from bvr structure into "dw(u,p)" format.
1071// Returns length of the out string
1072int getDeviceDescription(BVRef bvr, char *str)
1073{
1074 if(!str)
1075 return 0;
1076
1077*str = '\0';
1078
1079if (bvr)
1080{
1081 const struct devsw *dp = devsw;
1082while(dp->name && bvr->biosdev >= dp->biosdev)
1083 dp++;
1084
1085dp--;
1086if (dp->name)
1087 return sprintf(str, "%s(%d,%d)", dp->name, bvr->biosdev - dp->biosdev, bvr->part_no);
1088}
1089
1090return 0;
1091}
1092

Archive Download this file

Revision: 521