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

Archive Download this file

Revision: 318