Chameleon

Chameleon Svn Source Tree

Root/branches/azimutz/Chazileon/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/* 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
82extern int multiboot_partition;
83extern int multiboot_partition_set;
84
85struct devsw {
86 const char * name;
87 // size increased from char to short to handle non-BIOS internal devices
88 unsigned short biosdev;
89 int type;
90};
91
92// Device entries must be ordered by bios device numbers.
93static struct devsw devsw[] =
94{
95//{ "fd", 0x00, kBIOSDevTypeFloppy }, /* DEV_FD */Azi:reminder
96//{ "sd", 0x80, kBIOSDevTypeHardDrive }, /* DEV_SD */||
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 Azi: or ramdisk bt aliased??
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. Azi:---
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
494//Azi: Ok, "path" is checked first so, i've been saying some bs :P
495if ((i = open(path, flags)) >= 0) {
496return i;
497}
498
499if (bvd == NULL || (len = strlen(bvd)) < 2) {
500return -1;
501}
502
503for (dp=devsw; dp->name; dp++) {
504if (bvd[0] == dp->name[0] && bvd[1] == dp->name[1]) {
505unit = 0;
506partition = 0;
507/* get optional unit and partition */
508if (len >= 5 && bvd[2] == '(') { /* min must be present xx(0) */
509cp = &bvd[3];
510i = 0;
511while ((cp - path) < len && isdigit(*cp)) {
512i = i * 10 + *cp++ - '0';
513unit = i;
514}
515if (*cp++ == ',') {
516i = 0;
517while ((cp - path) < len && isdigit(*cp)) {
518i = i * 10 + *cp++ - '0';
519partition = i;
520}
521}
522}
523bvr = newBootVolumeRef(dp->biosdev + unit, partition);
524return open_bvr(bvr, path, flags);
525}
526 }
527return -1;
528}
529
530//==========================================================================
531// close() - Close a file descriptor.
532
533int close(int fdesc)
534{
535 struct iob * io;
536
537 if ((io = iob_from_fdesc(fdesc)) == NULL)
538 return (-1);
539
540 io->i_flgs = 0;
541
542 return 0;
543}
544
545//==========================================================================
546// lseek() - Reposition the byte offset of the file descriptor from the
547// beginning of the file. Returns the relocated offset.
548
549int b_lseek(int fdesc, int offset, int ptr)
550{
551 struct iob * io;
552
553 if ((io = iob_from_fdesc(fdesc)) == NULL)
554 return (-1);
555
556 io->i_offset = offset;
557
558 return offset;
559}
560
561//==========================================================================
562// tell() - Returns the byte offset of the file descriptor.
563
564int tell(int fdesc)
565{
566 struct iob * io;
567
568 if ((io = iob_from_fdesc(fdesc)) == NULL)
569 return 0;
570
571 return io->i_offset;
572}
573
574//==========================================================================
575// read() - Read up to 'count' bytes of data from the file descriptor
576// into the buffer pointed to by buf.
577
578int read(int fdesc, char * buf, int count)
579{
580 struct iob * io;
581
582 if ((io = iob_from_fdesc(fdesc)) == NULL)
583 return (-1);
584
585 if ((io->i_offset + count) > (unsigned int)io->i_filesize)
586 count = io->i_filesize - io->i_offset;
587
588 if (count <= 0)
589 return 0; // end of file
590
591 bcopy(io->i_buf + io->i_offset, buf, count);
592
593 io->i_offset += count;
594
595 return count;
596}
597
598//==========================================================================
599// write() - Write up to 'count' bytes of data to the file descriptor
600// from the buffer pointed to by buf.
601
602int write(int fdesc, const char * buf, int count)
603{
604 struct iob * io;
605
606 if ((io = iob_from_fdesc(fdesc)) == NULL)
607 return (-1);
608
609 if ((io->i_offset + count) > (unsigned int)io->i_filesize)
610 count = io->i_filesize - io->i_offset;
611
612 if (count <= 0)
613 return 0; // end of file
614
615 bcopy(buf, io->i_buf + io->i_offset, count);
616
617 io->i_offset += count;
618
619 return count;
620}
621
622int writebyte(int fdesc, char value)
623{
624 struct iob * io;
625
626 if ((io = iob_from_fdesc(fdesc)) == NULL)
627 return (-1);
628
629 if ((io->i_offset + 1) > (unsigned int)io->i_filesize)
630 return 0; // end of file
631
632 io->i_buf[io->i_offset++] = value;
633
634 return 1;
635}
636
637int writeint(int fdesc, int value)
638{
639 struct iob * io;
640
641 if ((io = iob_from_fdesc(fdesc)) == NULL)
642 return (-1);
643
644 if ((io->i_offset + 4) > (unsigned int)io->i_filesize)
645 return 0; // end of file
646
647 bcopy(&value, io->i_buf + io->i_offset, 4);
648
649 io->i_offset += 4;
650
651 return 4;
652}
653
654//==========================================================================
655// file_size() - Returns the size of the file described by the file
656// descriptor.
657
658int file_size(int fdesc)
659{
660 struct iob * io;
661
662 if ((io = iob_from_fdesc(fdesc)) == 0)
663 return 0;
664
665 return io->i_filesize;
666}
667
668//==========================================================================
669
670struct dirstuff * vol_opendir(BVRef bvr, const char * path)
671{
672 struct dirstuff * dirp = 0;
673
674 dirp = (struct dirstuff *) malloc(sizeof(struct dirstuff));
675 if (dirp == NULL)
676 goto error;
677
678 dirp->dir_path = newString(path);
679 if (dirp->dir_path == NULL)
680 goto error;
681
682 dirp->dir_bvr = bvr;
683
684 return dirp;
685
686error:
687 closedir(dirp);
688 return NULL;
689}
690
691//==========================================================================
692
693struct dirstuff * opendir(const char * path)
694{
695 struct dirstuff * dirp = 0;
696 const char * dirPath;
697 BVRef bvr;
698
699 if ((bvr = getBootVolumeRef(path, &dirPath)) == NULL)
700 goto error;
701
702 dirp = (struct dirstuff *) malloc(sizeof(struct dirstuff));
703 if (dirp == NULL)
704 goto error;
705
706 dirp->dir_path = newString(dirPath);
707 if (dirp->dir_path == NULL)
708 goto error;
709
710 dirp->dir_bvr = bvr;
711
712 return dirp;
713
714error:
715 closedir(dirp);
716 return NULL;
717}
718
719//==========================================================================
720
721int closedir(struct dirstuff * dirp)
722{
723 if (dirp) {
724 if (dirp->dir_path) free(dirp->dir_path);
725 free(dirp);
726 }
727 return 0;
728}
729
730//==========================================================================
731
732int readdir(struct dirstuff * dirp, const char ** name, long * flags,
733 long * time)
734{
735 return dirp->dir_bvr->fs_getdirentry( dirp->dir_bvr,
736 /* dirPath */ dirp->dir_path,
737 /* dirIndex */ &dirp->dir_index,
738 /* dirEntry */ (char **)name, flags, time,
739 0, 0);
740}
741
742//==========================================================================
743
744int readdir_ext(struct dirstuff * dirp, const char ** name, long * flags,
745 long * time, FinderInfo *finderInfo, long *infoValid)
746{
747 return dirp->dir_bvr->fs_getdirentry( dirp->dir_bvr,
748 /* dirPath */ dirp->dir_path,
749 /* dirIndex */ &dirp->dir_index,
750 /* dirEntry */ (char **)name,
751 flags, time,
752 finderInfo, infoValid);
753}
754
755//==========================================================================
756
757const char * systemConfigDir()
758{
759 if (gBootFileType == kNetworkDeviceType)
760return "";
761 return "/Library/Preferences/SystemConfiguration";
762}
763
764//==========================================================================
765
766int gBootFileType;
767
768void scanBootVolumes( int biosdev, int * count )
769{
770 BVRef bvr = 0;
771
772 bvr = diskScanBootVolumes(biosdev, count);
773 if (bvr == NULL)
774 {
775 bvr = nbpScanBootVolumes(biosdev, count);
776 if (bvr != NULL)
777 {
778 gBootFileType = kNetworkDeviceType;
779 }
780 }
781 else
782 {
783 gBootFileType = kBlockDeviceType;
784 }
785}
786
787//==========================================================================
788
789void scanDisks(int biosdev, int *count)
790{
791 #define MAX_HDD_COUNT 32
792 int bvCount;
793 int hd = 0;
794
795 // Testing up to MAX_HDD_COUNT hard drives.
796while(!testBiosread(0x80 + hd, 0) && hd < MAX_HDD_COUNT)
797{
798 bvCount = 0;
799 scanBootVolumes(0x80 + hd, &bvCount);
800 hd++;
801}
802
803 // Also scanning CD/DVD drive.
804if (biosDevIsCDROM(gBIOSDev))
805{
806 bvCount = 0;
807 scanBootVolumes(gBIOSDev, &bvCount);
808}
809}
810
811//==========================================================================
812
813BVRef selectBootVolume( BVRef chain )
814{
815bool filteredChain = false;
816bool foundPrimary = false;
817BVRef bvr, bvr1 = 0, bvr2 = 0;
818
819if (chain->filtered) filteredChain = true;
820
821if (multiboot_partition_set)
822for ( bvr = chain; bvr; bvr = bvr->next )
823if ( bvr->part_no == multiboot_partition && bvr->biosdev == gBIOSDev )
824return bvr;
825
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 */
831
832char *val = XMLDecode(getStringForKey(kDefaultPartitionKey, &bootInfo->bootConfig));
833 if (val) {
834 for ( bvr = chain; bvr; bvr = bvr->next ) {
835 if (matchVolumeToString(bvr, val, false)) {
836 free(val);
837 return bvr;
838 }
839 }
840 free(val);
841 }
842
843/*
844 * Scannig the volume chain backwards and trying to find
845 * a HFS+ volume with valid boot record signature.
846 * If not found any active partition then we will
847 * select this volume as the boot volume.
848 */
849for ( bvr = chain; bvr; bvr = bvr->next )
850{
851if ( bvr->flags & kBVFlagPrimary && bvr->biosdev == gBIOSDev ) foundPrimary = true;
852// zhell -- Undo a regression that was introduced from r491 to 492.
853// if gBIOSBootVolume is set already, no change is required
854if ( bvr->flags & (kBVFlagBootable|kBVFlagSystemVolume)
855&& gBIOSBootVolume
856&& (!filteredChain || (filteredChain && bvr->visible))
857&& bvr->biosdev == gBIOSDev )
858bvr2 = bvr;
859// zhell -- if gBIOSBootVolume is NOT set, we use the "if" statement
860// from r491,
861if ( bvr->flags & kBVFlagBootable
862&& ! gBIOSBootVolume
863&& bvr->biosdev == gBIOSDev )
864bvr2 = bvr;
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 : bvr1 ? bvr1 : chain;
880
881return bvr;
882}
883
884//==========================================================================
885
886#define LP '('
887#define RP ')'
888int gBIOSDev;
889
890/*!
891 This is like boot2's gBootVolume except it is for the internal use of
892 libsaio to track which volume an unqualified path should be relative to.
893 This replaces bootInfo->kernDev as the carrier of this information.
894 */
895static BVRef gRootVolume;
896
897void setRootVolume(BVRef volume)
898{
899 gRootVolume = volume;
900 // Veto non-native FS. Basically that means don't allow the root volume to
901 // be set to a volume we can't read files from.
902 if(gRootVolume != NULL && ((gRootVolume->flags & kBVFlagNativeBoot) == 0))
903 gRootVolume = NULL;
904}
905
906void setBootGlobals(BVRef chain)
907{
908 // Record default boot device.
909 gBootVolume = selectBootVolume(chain);
910
911 // turbo - Save the ORIGINAL boot volume too for loading our mkext
912 if (!gBIOSBootVolume) gBIOSBootVolume = gBootVolume;
913
914 setRootVolume(gBootVolume);
915}
916
917/*!
918 Extracts the volume selector from the pathname, returns the selected
919 BVRef, and sets *outPath to the remainder of the path.
920 If the path did not include a volume selector then the current volume
921 is used. When called with a volume selector the current volume
922 is changed to the selected volume unless the volume selector is
923 that of a ramdisk.
924 */
925BVRef getBootVolumeRef( const char * path, const char ** outPath )
926{
927 const char * cp;
928 BVRef bvr = gRootVolume;
929 int biosdev = gBIOSDev;
930
931 // Search for left parenthesis in the path specification.
932//Azi: and the slash??
933 for (cp = path; *cp; cp++) {
934 if (*cp == LP || *cp == '/') break;
935 }
936
937 if (*cp != LP) // no left paren found Azi: meaning it can still have a /
938 {
939 // Path is using the implicit current device so if there is
940 // no current device, then we must fail.
941 cp = path;
942 if ( gRootVolume == NULL )
943 return NULL;
944 }
945 else if ((cp - path) == 2) // found "xx("
946 {
947 const struct devsw * dp;
948 const char * xp = path;
949 int i;
950 int unit = -1;
951 int part = -1;
952
953 cp++;
954
955 // Check the 2 character device name pointed by 'xp'.
956
957 for (dp = devsw; dp->name; dp++)
958 {
959 if ((xp[0] == dp->name[0]) && (xp[1] == dp->name[1]))
960 break; // found matching entry
961 }
962 if (dp->name == NULL)
963 {
964 error("Unknown device '%c%c'\n", xp[0], xp[1]);
965 return NULL;
966 }
967
968 // Extract the optional unit number from the specification.
969 // hd(unit) or hd(unit, part).
970
971 i = 0;
972 while (*cp >= '0' && *cp <= '9')
973 {
974 i = i * 10 + *cp++ - '0';
975 unit = i;
976 }
977
978 // Unit is no longer optional and never really was.
979 // If the user failed to specify it then the unit number from the previous kernDev
980 // would have been used which makes little sense anyway.
981 // For example, if the user did fd()/foobar and the current root device was the
982 // second hard disk (i.e. unit 1) then fd() would select the second floppy drive!
983 if(unit == -1)
984 return NULL;
985
986 // Extract the optional partition number from the specification.
987
988 if (*cp == ',')
989 part = atoi(++cp);
990
991 // If part is not specified part will be -1 whereas before it would have been
992 // whatever the last partition was which makes about zero sense if the device
993 // has been switched.
994
995 // Skip past the right paren.
996
997 for ( ; *cp && *cp != RP; cp++) /* LOOP */;
998 if (*cp == RP) cp++;
999
1000 biosdev = dp->biosdev + unit;
1001 bvr = newBootVolumeRef(biosdev, part);
1002
1003 if(bvr == NULL)
1004 return NULL;
1005 }
1006 else
1007 {
1008 // Bad device specifier, skip past the right paren.
1009
1010 for ( cp++; *cp && *cp != RP; cp++) /* LOOP */;
1011 if (*cp == RP) cp++;
1012 // If gRootVolume was NULL, then bvr will be NULL as well which
1013 // should be caught by the caller.
1014 }
1015
1016 // Returns the file path following the device spec.
1017 // e.g. 'hd(1,b)mach_kernel' is reduced to 'mach_kernel'.
1018
1019 *outPath = cp;
1020
1021 return bvr;
1022}
1023
1024//==========================================================================
1025// Function name is a misnomer as scanBootVolumes usually calls diskScanBootVolumes
1026// which caches the information. So it's only allocated on the first run.
1027static BVRef newBootVolumeRef( int biosdev, int partno )
1028{
1029BVRef bvr, bvr1, bvrChain;
1030
1031bvr = bvr1 = NULL;
1032
1033 // Try resolving "rd" and "bt" devices first.
1034if (biosdev == kPseudoBIOSDevRAMDisk)
1035{
1036if (gRAMDiskVolume)
1037 bvr1 = gRAMDiskVolume;
1038}
1039else if (biosdev == kPseudoBIOSDevBooter)
1040{
1041if (gRAMDiskVolume != NULL && gRAMDiskBTAliased)
1042bvr1 = gRAMDiskVolume;
1043else
1044bvr1 = gBIOSBootVolume;
1045}
1046else
1047{
1048// Fetch the volume list from the device.
1049
1050scanBootVolumes( biosdev, NULL );
1051bvrChain = getBVChainForBIOSDev(biosdev);
1052
1053// Look for a perfect match based on device and partition number.
1054
1055for ( bvr1 = NULL, bvr = bvrChain; bvr; bvr = bvr->next )
1056{
1057if ( ( bvr->flags & kBVFlagNativeBoot ) == 0 ) continue;
1058
1059bvr1 = bvr;
1060if ( bvr->part_no == partno ) break;
1061}
1062}
1063
1064return bvr ? bvr : bvr1;
1065}
1066
1067//==========================================================================
1068// getDeviceDescription() - Extracts unit number and partition number
1069// from bvr structure into "dw(u,p)" format.
1070// Returns length of the out string
1071int getDeviceDescription(BVRef bvr, char *str)
1072{
1073 if(!str)
1074 return 0;
1075
1076*str = '\0';
1077
1078if (bvr)
1079{
1080 const struct devsw *dp = devsw;
1081while(dp->name && bvr->biosdev >= dp->biosdev)
1082 dp++;
1083
1084dp--;
1085if (dp->name)
1086 return sprintf(str, "%s(%d,%d)", dp->name, bvr->biosdev - dp->biosdev, bvr->part_no);
1087}
1088
1089return 0;
1090}
1091

Archive Download this file

Revision: 418