Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 1174