Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 2471