Chameleon

Chameleon Svn Source Tree

Root/branches/slice/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);
815hd++;
816}
817
818 // Also scanning CD/DVD drive.
819if (biosDevIsCDROM(gBIOSDev))
820{
821bvCount = 0;
822scanBootVolumes(gBIOSDev, &bvCount);
823msglog("biosDevIsCDROM and bvCount=%d\n", bvCount);
824}
825
826*count = bvCount; //Slice - !
827
828}
829
830//==========================================================================
831
832BVRef selectBootVolume( BVRef chain )
833{
834bool filteredChain = false;
835bool foundPrimary = false;
836BVRef bvr, bvr1 = 0, bvr2 = 0;
837
838if (chain->filtered) filteredChain = true;
839
840#ifdef UNUSED
841if (multiboot_partition_set)
842for ( bvr = chain; bvr; bvr = bvr->next ){
843msglog("Check muiltiboot: biosdev=%d type=0x%x flags=0x%x part_no=%d\n",
844 bvr->biosdev, bvr->type, bvr->flags, bvr->part_no);
845if ( bvr->part_no == multiboot_partition && bvr->biosdev == gBIOSDev )
846return bvr;
847}
848#endif
849/*
850 * Checking "Default Partition" key in system configuration - use format: hd(x,y), the volume UUID or label -
851 * to override the default selection.
852 * We accept only kBVFlagSystemVolume or kBVFlagForeignBoot volumes.
853 */
854char *val = XMLDecode(getStringForKey(kDefaultPartition, &bootInfo->bootConfig));
855 if (val) {
856 for ( bvr = chain; bvr; bvr = bvr->next ) {
857 if (matchVolumeToString(bvr, val, false)) {
858 free(val);
859 return bvr;
860 }
861 }
862 free(val);
863 }
864
865/*
866 * Scannig the volume chain backwards and trying to find
867 * a HFS+ volume with valid boot record signature.
868 * If not found any active partition then we will
869 * select this volume as the boot volume.
870 */
871for ( bvr = chain; bvr; bvr = bvr->next )
872{
873//msglog("scanning chain: biosdev=%d type=0x%x flags=0x%x part_no=%d\n",
874// bvr->biosdev, bvr->type, bvr->flags, bvr->part_no);
875if ( bvr->flags & kBVFlagPrimary && bvr->biosdev == gBIOSDev ) foundPrimary = true;
876// zhell -- Undo a regression that was introduced from r491 to 492.
877// if gBIOSBootVolume is set already, no change is required
878if ( bvr->flags & (kBVFlagBootable|kBVFlagSystemVolume)
879&& gBIOSBootVolume
880&& (!filteredChain || (filteredChain && bvr->visible))
881&& bvr->biosdev == gBIOSDev )
882bvr2 = bvr;
883// zhell -- if gBIOSBootVolume is NOT set, we use the "if" statement
884// from r491,
885if ( bvr->flags & kBVFlagBootable
886&& ! gBIOSBootVolume
887&& bvr->biosdev == gBIOSDev )
888bvr2 = bvr;
889}
890
891
892/*
893 * Use the standard method for selecting the boot volume.
894 */
895if (foundPrimary)
896{
897for ( bvr = chain; bvr; bvr = bvr->next )
898{
899if ( bvr->flags & kBVFlagNativeBoot && bvr->biosdev == gBIOSDev ) bvr1 = bvr;
900if ( bvr->flags & kBVFlagPrimary && bvr->biosdev == gBIOSDev ) bvr2 = bvr;
901}
902//msglog("foundPrimary and flags bvr1=%x bvr2=%x\n", bvr1->flags, bvr2->flags);//foundPrimary and flags bvr1=a bvr2=4b
903}
904
905bvr = bvr2 ? bvr2 :
906bvr1 ? bvr1 : chain;
907
908return bvr;
909}
910
911//==========================================================================
912
913#define LP '('
914#define RP ')'
915int gBIOSDev;
916
917/*!
918 This is like boot2's gBootVolume except it is for the internal use of
919 libsaio to track which volume an unqualified path should be relative to.
920 This replaces bootInfo->kernDev as the carrier of this information.
921 */
922static BVRef gRootVolume;
923
924void setRootVolume(BVRef volume)
925{
926 gRootVolume = volume;
927 // Veto non-native FS. Basically that means don't allow the root volume to
928 // be set to a volume we can't read files from.
929 if(gRootVolume != NULL && ((gRootVolume->flags & kBVFlagNativeBoot) == 0))
930 gRootVolume = NULL;
931}
932
933void setBootGlobals(BVRef chain)
934{
935 // Record default boot device.
936 gBootVolume = selectBootVolume(chain);
937
938 // turbo - Save the ORIGINAL boot volume too for loading our mkext
939 if (!gBIOSBootVolume) gBIOSBootVolume = gBootVolume;
940
941 setRootVolume(gBootVolume);
942}
943
944/*!
945 Extracts the volume selector from the pathname, returns the selected
946 BVRef, and sets *outPath to the remainder of the path.
947 If the path did not include a volume selector then the current volume
948 is used. When called with a volume selector the current volume
949 is changed to the selected volume unless the volume selector is
950 that of a ramdisk.
951 */
952BVRef getBootVolumeRef( const char * path, const char ** outPath )
953{
954 const char * cp;
955 BVRef bvr = gRootVolume;
956 int biosdev = gBIOSDev;
957
958 // Search for left parenthesis in the path specification.
959
960 for (cp = path; *cp; cp++) {
961 if (*cp == LP || *cp == '/') break;
962 }
963
964 if (*cp != LP) // no left paren found
965 {
966 // Path is using the implicit current device so if there is
967 // no current device, then we must fail.
968 cp = path;
969 if ( gRootVolume == NULL )
970 return NULL;
971 }
972 else if ((cp - path) == 2) // found "xx("
973 {
974 const struct devsw * dp;
975 const char * xp = path;
976 int i;
977 int unit = -1;
978 int part = -1;
979
980 cp++;
981
982 // Check the 2 character device name pointed by 'xp'.
983
984 for (dp = devsw; dp->name; dp++)
985 {
986 if ((xp[0] == dp->name[0]) && (xp[1] == dp->name[1]))
987 break; // found matching entry
988 }
989 if (dp->name == NULL)
990 {
991 error("Unknown device '%c%c'\n", xp[0], xp[1]);
992 return NULL;
993 }
994
995 // Extract the optional unit number from the specification.
996 // hd(unit) or hd(unit, part).
997
998 i = 0;
999 while (*cp >= '0' && *cp <= '9')
1000 {
1001 i = i * 10 + *cp++ - '0';
1002 unit = i;
1003 }
1004
1005 // Unit is no longer optional and never really was.
1006 // If the user failed to specify it then the unit number from the previous kernDev
1007 // would have been used which makes little sense anyway.
1008 // For example, if the user did fd()/foobar and the current root device was the
1009 // second hard disk (i.e. unit 1) then fd() would select the second floppy drive!
1010 if(unit == -1)
1011 return NULL;
1012
1013 // Extract the optional partition number from the specification.
1014
1015 if (*cp == ',')
1016 part = atoi(++cp);
1017
1018 // If part is not specified part will be -1 whereas before it would have been
1019 // whatever the last partition was which makes about zero sense if the device
1020 // has been switched.
1021
1022 // Skip past the right paren.
1023
1024 for ( ; *cp && *cp != RP; cp++) /* LOOP */;
1025 if (*cp == RP) cp++;
1026
1027 biosdev = dp->biosdev + unit;
1028
1029 // turbo - bt(0,0) hook
1030 if (biosdev == 0x101)
1031 {
1032 // zef - use the ramdisk if available and the alias is active.
1033 if (gRAMDiskVolume != NULL && gRAMDiskBTAliased)
1034 bvr = gRAMDiskVolume;
1035 else
1036 bvr = gBIOSBootVolume;
1037 }
1038 else
1039 {
1040 bvr = newBootVolumeRef(biosdev, part);
1041 }
1042
1043 if(bvr == NULL)
1044 return NULL;
1045 }
1046 else
1047 {
1048 // Bad device specifier, skip past the right paren.
1049
1050 for ( cp++; *cp && *cp != RP; cp++) /* LOOP */;
1051 if (*cp == RP) cp++;
1052 // If gRootVolume was NULL, then bvr will be NULL as well which
1053 // should be caught by the caller.
1054 }
1055
1056 // Returns the file path following the device spec.
1057 // e.g. 'hd(1,b)mach_kernel' is reduced to 'mach_kernel'.
1058
1059 *outPath = cp;
1060
1061 return bvr;
1062}
1063
1064//==========================================================================
1065// Function name is a misnomer as scanBootVolumes usually calls diskScanBootVolumes
1066// which caches the information. So it's only allocated on the first run.
1067static BVRef newBootVolumeRef( int biosdev, int partno )
1068{
1069BVRef bvr, bvr1, bvrChain;
1070
1071bvr = bvr1 = NULL;
1072
1073 // Try resolving "rd" and "bt" devices first.
1074#ifndef OPTION_ROM
1075if (biosdev == kPseudoBIOSDevRAMDisk)
1076{
1077if (gRAMDiskVolume)
1078 bvr1 = gRAMDiskVolume;
1079}
1080else
1081#endif
1082if (biosdev == kPseudoBIOSDevBooter)
1083{
1084#ifndef OPTION_ROM
1085if (gRAMDiskVolume != NULL && gRAMDiskBTAliased)
1086bvr1 = gRAMDiskVolume;
1087else
1088#endif
1089bvr1 = gBIOSBootVolume;
1090}
1091else
1092{
1093// Fetch the volume list from the device.
1094
1095scanBootVolumes( biosdev, NULL );
1096bvrChain = getBVChainForBIOSDev(biosdev);
1097
1098// Look for a perfect match based on device and partition number.
1099
1100for ( bvr1 = NULL, bvr = bvrChain; bvr; bvr = bvr->next )
1101{
1102if ( ( bvr->flags & kBVFlagNativeBoot ) == 0 ) continue;
1103
1104bvr1 = bvr;
1105if ( bvr->part_no == partno ) break;
1106}
1107}
1108
1109return bvr ? bvr : bvr1;
1110}
1111
1112//==========================================================================
1113// getDeviceDescription() - Extracts unit number and partition number
1114// from bvr structure into "dw(u,p)" format.
1115// Returns length of the out string
1116int getDeviceDescription(BVRef bvr, char *str)
1117{
1118 if(!str)
1119 return 0;
1120
1121*str = '\0';
1122
1123if (bvr)
1124{
1125 const struct devsw *dp = devsw;
1126while(dp->name && bvr->biosdev >= dp->biosdev)
1127 dp++;
1128
1129dp--;
1130if (dp->name)
1131 return sprintf(str, "%s(%d,%d)", dp->name, bvr->biosdev - dp->biosdev, bvr->part_no);
1132}
1133
1134return 0;
1135}
1136

Archive Download this file

Revision: 689