]>
git.saurik.com Git - apple/boot.git/blob - i386/libsaio/sys.c
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
8 * This file contains Original Code and/or Modifications of Original Code
9 * as defined in and that are subject to the Apple Public Source License
10 * Version 2.0 (the 'License'). You may not use this file except in
11 * compliance with the License. Please obtain a copy of the License at
12 * http://www.opensource.apple.com/apsl/ and read it before using this
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
20 * Please see the License for the specific language governing rights and
21 * limitations under the License.
23 * @APPLE_LICENSE_HEADER_END@
26 * Mach Operating System
27 * Copyright (c) 1990 Carnegie-Mellon University
28 * Copyright (c) 1989 Carnegie-Mellon University
29 * Copyright (c) 1988 Carnegie-Mellon University
30 * Copyright (c) 1987 Carnegie-Mellon University
31 * All rights reserved. The CMU software License Agreement specifies
32 * the terms and conditions for use and redistribution.
37 * Revision 2.3 88/08/08 13:47:07 rvb
38 * Allocate buffers dynamically vs statically.
39 * Now b[i] and i_fs and i_buf, are allocated dynamically.
40 * boot_calloc(size) allocates and zeros a buffer rounded to a NPG
42 * Generalize boot spec to allow, xx()/mach, xx(n,[a..h])/mach,
43 * xx([a..h])/mach, ...
44 * Also default "xx" if unspecified and alloc just "/mach",
45 * where everything is defaulted
46 * Add routine, ptol(), to parse partition letters.
51 * Copyright (c) 1982, 1986 Regents of the University of California.
52 * All rights reserved. The Berkeley software License Agreement
53 * specifies the terms and conditions for redistribution.
55 * @(#)sys.c 7.1 (Berkeley) 6/5/86
59 #include "bootstruct.h"
64 unsigned char biosdev
;
68 static struct devsw devsw
[] =
70 { "sd", 0x80, kBIOSDevTypeHardDrive
}, /* DEV_SD */
71 { "hd", 0x80, kBIOSDevTypeHardDrive
}, /* DEV_HD */
72 { "fd", 0x00, kBIOSDevTypeFloppy
}, /* DEV_FD */
73 { "en", 0xE0, kBIOSDevTypeNetwork
}, /* DEV_EN */
78 * Max number of file descriptors.
82 static struct iob iob
[NFILES
];
84 void * gFSLoadAddress
= 0;
86 static BVRef
getBootVolumeRef( const char * path
, const char ** outPath
);
87 static BVRef
newBootVolumeRef( int biosdev
, int partno
);
89 //==========================================================================
90 // LoadFile - LOW-LEVEL FILESYSTEM FUNCTION.
91 // Load the specified file to the load buffer at LOAD_ADDR.
92 // If the file is fat, load only the i386 portion.
94 long LoadFile(const char * fileSpec
)
96 const char * filePath
;
100 // Resolve the boot volume from the file spec.
102 if ((bvr
= getBootVolumeRef(fileSpec
, &filePath
)) == NULL
)
105 // Read file into load buffer. The data in the load buffer will be
106 // overwritten by the next LoadFile() call.
108 gFSLoadAddress
= (void *) LOAD_ADDR
;
110 fileSize
= bvr
->fs_loadfile(bvr
, (char *)filePath
);
112 // Return the size of the file, or -1 if load failed.
117 //==========================================================================
118 // GetDirEntry - LOW-LEVEL FILESYSTEM FUNCTION.
119 // Fetch the next directory entry for the given directory.
121 long GetDirEntry(const char * dirSpec
, long * dirIndex
, const char ** name
,
122 long * flags
, long * time
)
124 const char * dirPath
;
127 // Resolve the boot volume from the dir spec.
129 if ((bvr
= getBootVolumeRef(dirSpec
, &dirPath
)) == NULL
)
132 // Return 0 on success, or -1 if there are no additional entries.
134 return bvr
->fs_getdirentry( bvr
,
135 /* dirPath */ (char *)dirPath
,
136 /* dirIndex */ dirIndex
,
137 /* dirEntry */ (char **)name
, flags
, time
);
140 //==========================================================================
141 // GetFileInfo - LOW-LEVEL FILESYSTEM FUNCTION.
142 // Get attributes for the specified file.
144 static char gMakeDirSpec
[1024];
146 long GetFileInfo(const char * dirSpec
, const char * name
,
147 long * flags
, long * time
)
150 const char * entryName
;
157 for (idx
= len
; idx
&& (name
[idx
] != '/' && name
[idx
] != '\\'); idx
--) {}
159 gMakeDirSpec
[0] = '/';
160 gMakeDirSpec
[1] = '\0';
163 strncpy(gMakeDirSpec
, name
, idx
);
166 dirSpec
= gMakeDirSpec
;
169 while (GetDirEntry(dirSpec
, &index
, &entryName
, flags
, time
) == 0)
171 if (strcmp(entryName
, name
) == 0)
174 return -1; // file not found
177 //==========================================================================
180 // Return a pointer to an allocated 'iob' based on the file descriptor
181 // provided. Returns NULL if the file descriptor given is invalid.
183 static struct iob
* iob_from_fdesc(int fdesc
)
185 register struct iob
* io
;
187 if (fdesc
< 0 || fdesc
>= NFILES
||
188 ((io
= &iob
[fdesc
])->i_flgs
& F_ALLOC
) == 0)
194 //==========================================================================
197 int openmem(char * buf
, int len
)
202 // Locate a free descriptor slot.
204 for (fdesc
= 0; fdesc
< NFILES
; fdesc
++)
205 if (iob
[fdesc
].i_flgs
== 0)
208 stop("Out of file descriptors");
212 bzero(io
, sizeof(*io
));
214 // Mark the descriptor as taken. Set the F_MEM flag to indicate
215 // that the file buffer is provided by the caller.
217 io
->i_flgs
= F_ALLOC
| F_MEM
;
219 io
->i_filesize
= len
;
224 //==========================================================================
225 // open() - Open the file specified by 'path' for reading.
227 int open(const char * path
, int flags
)
231 const char * filePath
;
234 // Locate a free descriptor slot.
236 for (fdesc
= 0; fdesc
< NFILES
; fdesc
++)
237 if (iob
[fdesc
].i_flgs
== 0)
240 stop("Out of file descriptors");
244 bzero(io
, sizeof(*io
));
246 // Mark the descriptor as taken.
248 io
->i_flgs
= F_ALLOC
;
250 // Resolve the boot volume from the file spec.
252 if ((bvr
= getBootVolumeRef(path
, &filePath
)) == NULL
)
255 // Find the next available memory block in the download buffer.
257 io
->i_buf
= (char *) LOAD_ADDR
;
258 for (i
= 0; i
< NFILES
; i
++)
260 if ((iob
[i
].i_flgs
!= F_ALLOC
) || (i
== fdesc
)) continue;
261 io
->i_buf
= max(iob
[i
].i_filesize
+ iob
[i
].i_buf
, io
->i_buf
);
264 // Load entire file into memory. Unnecessary open() calls must
267 gFSLoadAddress
= io
->i_buf
;
268 io
->i_filesize
= bvr
->fs_loadfile(bvr
, (char *)filePath
);
269 if (io
->i_filesize
< 0) {
280 //==========================================================================
281 // close() - Close a file descriptor.
287 if ((io
= iob_from_fdesc(fdesc
)) == NULL
)
295 //==========================================================================
296 // lseek() - Reposition the byte offset of the file descriptor from the
297 // beginning of the file. Returns the relocated offset.
299 int b_lseek(int fdesc
, int offset
, int ptr
)
303 if ((io
= iob_from_fdesc(fdesc
)) == NULL
)
306 io
->i_offset
= offset
;
311 //==========================================================================
312 // tell() - Returns the byte offset of the file descriptor.
318 if ((io
= iob_from_fdesc(fdesc
)) == NULL
)
324 //==========================================================================
325 // read() - Read up to 'count' bytes of data from the file descriptor
326 // into the buffer pointed to by buf.
328 int read(int fdesc
, char * buf
, int count
)
332 if ((io
= iob_from_fdesc(fdesc
)) == NULL
)
335 if ((io
->i_offset
+ count
) > (unsigned int)io
->i_filesize
)
336 count
= io
->i_filesize
- io
->i_offset
;
339 return 0; // end of file
341 bcopy(io
->i_buf
+ io
->i_offset
, buf
, count
);
343 io
->i_offset
+= count
;
348 //==========================================================================
349 // file_size() - Returns the size of the file described by the file
352 int file_size(int fdesc
)
356 if ((io
= iob_from_fdesc(fdesc
)) == 0)
359 return io
->i_filesize
;
362 //==========================================================================
364 struct dirstuff
* opendir(const char * path
)
366 struct dirstuff
* dirp
= 0;
367 const char * dirPath
;
370 if ((bvr
= getBootVolumeRef(path
, &dirPath
)) == NULL
)
373 dirp
= (struct dirstuff
*) malloc(sizeof(struct dirstuff
));
377 dirp
->dir_path
= newString(dirPath
);
378 if (dirp
->dir_path
== NULL
)
390 //==========================================================================
392 int closedir(struct dirstuff
* dirp
)
395 if (dirp
->dir_path
) free(dirp
->dir_path
);
401 //==========================================================================
403 int readdir(struct dirstuff
* dirp
, const char ** name
, long * flags
,
406 return dirp
->dir_bvr
->fs_getdirentry( dirp
->dir_bvr
,
407 /* dirPath */ dirp
->dir_path
,
408 /* dirIndex */ &dirp
->dir_index
,
409 /* dirEntry */ (char **)name
, flags
, time
);
412 //==========================================================================
416 return bootArgs
->kernDev
;
419 //==========================================================================
421 int switchdev(int dev
)
423 bootArgs
->kernDev
= dev
;
427 //==========================================================================
429 const char * usrDevices()
431 if (gBootFileType
== kNetworkDeviceType
)
433 return "/private/Drivers/i386";
436 //==========================================================================
438 const char * systemConfigDir()
440 if (gBootFileType
== kNetworkDeviceType
)
442 return "/Library/Preferences/SystemConfiguration";
445 //==========================================================================
449 BVRef
scanBootVolumes( int biosdev
, int * count
)
453 bvr
= diskScanBootVolumes(biosdev
, count
);
455 bvr
= nbpScanBootVolumes(biosdev
, count
);
457 gBootFileType
= kNetworkDeviceType
;
460 gBootFileType
= kBlockDeviceType
;
465 //==========================================================================
467 void getBootVolumeDescription( BVRef bvr
, char * str
, long strMaxLen
)
469 bvr
->description( bvr
, str
, strMaxLen
);
472 //==========================================================================
474 BVRef
selectBootVolume( BVRef chain
)
476 BVRef bvr
, bvr1
= 0, bvr2
= 0;
478 for ( bvr
= chain
; bvr
; bvr
= bvr
->next
)
480 if ( bvr
->flags
& kBVFlagNativeBoot
) bvr1
= bvr
;
481 if ( bvr
->flags
& kBVFlagPrimary
) bvr2
= bvr
;
490 //==========================================================================
496 static BVRef
getBootVolumeRef( const char * path
, const char ** outPath
)
500 int type
= B_TYPE( bootArgs
->kernDev
);
501 int unit
= B_UNIT( bootArgs
->kernDev
);
502 int part
= B_PARTITION( bootArgs
->kernDev
);
503 int biosdev
= gBIOSDev
;
504 static BVRef lastBVR
= 0;
505 static int lastKernDev
;
507 // Search for left parenthesis in the path specification.
509 for (cp
= path
; *cp
; cp
++) {
510 if (*cp
== LP
|| *cp
== '/') break;
513 if (*cp
!= LP
) // no left paren found
516 if ( lastBVR
&& lastKernDev
== bootArgs
->kernDev
)
522 else if ((cp
- path
) == 2) // found "xx("
524 const struct devsw
* dp
;
525 const char * xp
= path
;
530 // Check the 2 character device name pointed by 'xp'.
532 for (dp
= devsw
; dp
->name
; dp
++)
534 if ((xp
[0] == dp
->name
[0]) && (xp
[1] == dp
->name
[1]))
535 break; // found matching entry
537 if (dp
->name
== NULL
)
539 error("Unknown device '%c%c'\n", xp
[0], xp
[1]);
542 type
= dp
- devsw
; // kerndev type
544 // Extract the optional unit number from the specification.
545 // hd(unit) or hd(unit, part).
548 while (*cp
>= '0' && *cp
<= '9')
550 i
= i
* 10 + *cp
++ - '0';
554 // Extract the optional partition number from the specification.
559 // Skip past the right paren.
561 for ( ; *cp
&& *cp
!= RP
; cp
++) /* LOOP */;
564 biosdev
= dp
->biosdev
+ unit
;
568 // Bad device specifier, skip past the right paren.
570 for ( cp
++; *cp
&& *cp
!= RP
; cp
++) /* LOOP */;
574 if ((bvr
= newBootVolumeRef(biosdev
, part
)) == NULL
)
576 // error("newBootVolumeRef() error\n");
580 // Record the most recent device parameters in the
583 bootArgs
->kernDev
= biosdev
;
586 lastKernDev
= bootArgs
->kernDev
;
589 // Returns the file path following the device spec.
590 // e.g. 'hd(1,b)mach_kernel' is reduced to 'mach_kernel'.
597 //==========================================================================
599 static BVRef
newBootVolumeRef( int biosdev
, int partno
)
601 BVRef bvr
, bvr1
, bvrChain
;
603 // Fetch the volume list from the device.
605 bvrChain
= scanBootVolumes( biosdev
, NULL
);
607 // Look for a perfect match based on device and partition number.
609 for ( bvr1
= NULL
, bvr
= bvrChain
; bvr
; bvr
= bvr
->next
)
611 if ( ( bvr
->flags
& kBVFlagNativeBoot
) == 0 ) continue;
614 if ( bvr
->part_no
== partno
) break;
617 return bvr
? bvr
: bvr1
;