Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 1076