Chameleon

Chameleon Svn Source Tree

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

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

Archive Download this file

Revision: 1065