Chameleon

Chameleon Svn Source Tree

Root/branches/azimutz/Chazi/i386/libsaio/sys.c

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

Archive Download this file

Revision: 618