Chameleon

Chameleon Svn Source Tree

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

Source at commit 543 created 13 years 6 months ago.
By meklort, Chameleon code shrinkage. Also moved a few things to modules.
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#ifndef OPTION_ROM
775 bvr = nbpScanBootVolumes(biosdev, count);
776 if (bvr != NULL)
777 {
778 gBootFileType = kNetworkDeviceType;
779 }
780#endif
781 }
782 else
783 {
784 gBootFileType = kBlockDeviceType;
785 }
786}
787
788//==========================================================================
789
790void scanDisks(int biosdev, int *count)
791{
792 #define MAX_HDD_COUNT 32
793 int bvCount;
794 int hd = 0;
795
796 // Testing up to MAX_HDD_COUNT hard drives.
797while(!testBiosread(0x80 + hd, 0) && hd < MAX_HDD_COUNT)
798{
799 bvCount = 0;
800 scanBootVolumes(0x80 + hd, &bvCount);
801 hd++;
802}
803
804 // Also scanning CD/DVD drive.
805if (biosDevIsCDROM(gBIOSDev))
806{
807 bvCount = 0;
808 scanBootVolumes(gBIOSDev, &bvCount);
809}
810}
811
812//==========================================================================
813
814BVRef selectBootVolume( BVRef chain )
815{
816bool filteredChain = false;
817bool foundPrimary = false;
818BVRef bvr, bvr1 = 0, bvr2 = 0;
819
820if (chain->filtered) filteredChain = true;
821
822#ifdef UNUSED
823if (multiboot_partition_set)
824for ( bvr = chain; bvr; bvr = bvr->next )
825if ( bvr->part_no == multiboot_partition && bvr->biosdev == gBIOSDev )
826return bvr;
827#endif
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(kDefaultPartition, &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.
1037#ifndef OPTION_ROM
1038if (biosdev == kPseudoBIOSDevRAMDisk)
1039{
1040if (gRAMDiskVolume)
1041 bvr1 = gRAMDiskVolume;
1042}
1043else
1044#endif
1045if (biosdev == kPseudoBIOSDevBooter)
1046{
1047#ifndef OPTION_ROM
1048if (gRAMDiskVolume != NULL && gRAMDiskBTAliased)
1049bvr1 = gRAMDiskVolume;
1050else
1051#endif
1052bvr1 = gBIOSBootVolume;
1053}
1054else
1055{
1056// Fetch the volume list from the device.
1057
1058scanBootVolumes( biosdev, NULL );
1059bvrChain = getBVChainForBIOSDev(biosdev);
1060
1061// Look for a perfect match based on device and partition number.
1062
1063for ( bvr1 = NULL, bvr = bvrChain; bvr; bvr = bvr->next )
1064{
1065if ( ( bvr->flags & kBVFlagNativeBoot ) == 0 ) continue;
1066
1067bvr1 = bvr;
1068if ( bvr->part_no == partno ) break;
1069}
1070}
1071
1072return bvr ? bvr : bvr1;
1073}
1074
1075//==========================================================================
1076// getDeviceDescription() - Extracts unit number and partition number
1077// from bvr structure into "dw(u,p)" format.
1078// Returns length of the out string
1079int getDeviceDescription(BVRef bvr, char *str)
1080{
1081 if(!str)
1082 return 0;
1083
1084*str = '\0';
1085
1086if (bvr)
1087{
1088 const struct devsw *dp = devsw;
1089while(dp->name && bvr->biosdev >= dp->biosdev)
1090 dp++;
1091
1092dp--;
1093if (dp->name)
1094 return sprintf(str, "%s(%d,%d)", dp->name, bvr->biosdev - dp->biosdev, bvr->part_no);
1095}
1096
1097return 0;
1098}
1099

Archive Download this file

Revision: 543