]>
git.saurik.com Git - apple/boot.git/blob - i386/libsaio/sys.c
b4e88ed56b0d9d3aeb812240e6ea3ff7b237fb14
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Portions Copyright (c) 1999 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 1.1 (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
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
22 * @APPLE_LICENSE_HEADER_END@
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.
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
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.
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.
54 * @(#)sys.c 7.1 (Berkeley) 6/5/86
61 unsigned char biosdev
;
64 static struct devsw devsw
[] =
66 { "sd", 0x80 }, /* DEV_SD */
67 { "hd", 0x80 }, /* DEV_HD */
68 { "fd", 0x00 }, /* DEV_FD */
69 { "en", 0xE0 }, /* DEV_EN */
74 * Max number of file descriptors.
78 static struct iob iob
[NFILES
];
80 void * gFSLoadAddress
= 0;
82 static BVRef
getBootVolumeRef( const char * path
, const char ** outPath
);
83 static BVRef
newBootVolumeRef( int biosdev
, int partno
);
85 //==========================================================================
86 // LoadFile - LOW-LEVEL FILESYSTEM FUNCTION.
87 // Load the specified file to the load buffer at LOAD_ADDR.
89 long LoadFile(const char * fileSpec
)
91 const char * filePath
;
95 // Resolve the boot volume from the file spec.
97 if ((bvr
= getBootVolumeRef(fileSpec
, &filePath
)) == NULL
)
100 // Read file into load buffer. The data in the load buffer will be
101 // overwritten by the next LoadFile() call.
103 gFSLoadAddress
= (void *) LOAD_ADDR
;
105 fileSize
= bvr
->fs_loadfile(bvr
, (char *)filePath
);
107 // Return the size of the file, or -1 if load failed.
112 //==========================================================================
113 // GetDirEntry - LOW-LEVEL FILESYSTEM FUNCTION.
114 // Fetch the next directory entry for the given directory.
116 long GetDirEntry(const char * dirSpec
, long * dirIndex
, const char ** name
,
117 long * flags
, long * time
)
119 const char * dirPath
;
122 // Resolve the boot volume from the dir spec.
124 if ((bvr
= getBootVolumeRef(dirSpec
, &dirPath
)) == NULL
)
127 // Return 0 on success, or -1 if there are no additional entries.
129 return bvr
->fs_getdirentry( bvr
,
130 /* dirPath */ (char *)dirPath
,
131 /* dirIndex */ dirIndex
,
132 /* dirEntry */ (char **)name
, flags
, time
);
135 //==========================================================================
136 // GetFileInfo - LOW-LEVEL FILESYSTEM FUNCTION.
137 // Get attributes for the specified file.
139 long GetFileInfo(const char * dirSpec
, const char * name
,
140 long * flags
, long * time
)
143 const char * entryName
;
145 while (GetDirEntry(dirSpec
, &index
, &entryName
, flags
, time
) == 0)
147 if (strcmp(entryName
, name
) == 0)
150 return -1; // file not found
153 //==========================================================================
156 // Return a pointer to an allocated 'iob' based on the file descriptor
157 // provided. Returns NULL if the file descriptor given is invalid.
159 static struct iob
* iob_from_fdesc(int fdesc
)
161 register struct iob
* io
;
163 if (fdesc
< 0 || fdesc
>= NFILES
||
164 ((io
= &iob
[fdesc
])->i_flgs
& F_ALLOC
) == 0)
170 //==========================================================================
173 int openmem(char * buf
, int len
)
178 // Locate a free descriptor slot.
180 for (fdesc
= 0; fdesc
< NFILES
; fdesc
++)
181 if (iob
[fdesc
].i_flgs
== 0)
184 stop("Out of file descriptors");
188 bzero(io
, sizeof(*io
));
190 // Mark the descriptor as taken. Set the F_MEM flag to indicate
191 // that the file buffer is provided by the caller.
193 io
->i_flgs
= F_ALLOC
| F_MEM
;
195 io
->i_filesize
= len
;
200 //==========================================================================
201 // open() - Open the file specified by 'path' for reading.
203 int open(const char * path
, int flags
)
207 const char * filePath
;
210 // Locate a free descriptor slot.
212 for (fdesc
= 0; fdesc
< NFILES
; fdesc
++)
213 if (iob
[fdesc
].i_flgs
== 0)
216 stop("Out of file descriptors");
220 bzero(io
, sizeof(*io
));
222 // Mark the descriptor as taken.
224 io
->i_flgs
= F_ALLOC
;
226 // Resolve the boot volume from the file spec.
228 if ((bvr
= getBootVolumeRef(path
, &filePath
)) == NULL
)
231 // Find the next available memory block in the download buffer.
233 io
->i_buf
= (char *) LOAD_ADDR
;
234 for (i
= 0; i
< NFILES
; i
++)
236 if ((iob
[i
].i_flgs
!= F_ALLOC
) || (i
== fdesc
)) continue;
237 io
->i_buf
= max(iob
[i
].i_filesize
+ iob
[i
].i_buf
, io
->i_buf
);
240 // Load entire file into memory. Unnecessary open() calls must
243 gFSLoadAddress
= io
->i_buf
;
244 io
->i_filesize
= bvr
->fs_loadfile(bvr
, (char *)filePath
);
245 if (io
->i_filesize
< 0) goto error
;
254 //==========================================================================
255 // close() - Close a file descriptor.
261 if ((io
= iob_from_fdesc(fdesc
)) == NULL
)
269 //==========================================================================
270 // lseek() - Reposition the byte offset of the file descriptor from the
271 // beginning of the file. Returns the relocated offset.
273 int b_lseek(int fdesc
, int offset
, int ptr
)
277 if ((io
= iob_from_fdesc(fdesc
)) == NULL
)
280 io
->i_offset
= offset
;
285 //==========================================================================
286 // tell() - Returns the byte offset of the file descriptor.
292 if ((io
= iob_from_fdesc(fdesc
)) == NULL
)
298 //==========================================================================
299 // read() - Read up to 'count' bytes of data from the file descriptor
300 // into the buffer pointed to by buf.
302 int read(int fdesc
, char * buf
, int count
)
306 if ((io
= iob_from_fdesc(fdesc
)) == NULL
)
309 if (io
->i_offset
+ count
> io
->i_filesize
)
310 count
= io
->i_filesize
- io
->i_offset
;
313 return 0; // end of file
315 bcopy(io
->i_buf
+ io
->i_offset
, buf
, count
);
317 io
->i_offset
+= count
;
322 //==========================================================================
323 // file_size() - Returns the size of the file described by the file
326 int file_size(int fdesc
)
330 if ((io
= iob_from_fdesc(fdesc
)) == 0)
333 return io
->i_filesize
;
336 //==========================================================================
338 struct dirstuff
* opendir(const char * path
)
340 struct dirstuff
* dirp
= 0;
341 const char * dirPath
;
344 if ((bvr
= getBootVolumeRef(path
, &dirPath
)) == NULL
)
347 dirp
= (struct dirstuff
*) malloc(sizeof(struct dirstuff
));
351 dirp
->dir_path
= newString(dirPath
);
352 if (dirp
->dir_path
== NULL
)
364 //==========================================================================
366 int closedir(struct dirstuff
* dirp
)
369 if (dirp
->dir_path
) free(dirp
->dir_path
);
375 //==========================================================================
377 int readdir(struct dirstuff
* dirp
, const char ** name
, long * flags
,
380 return dirp
->dir_bvr
->fs_getdirentry( dirp
->dir_bvr
,
381 /* dirPath */ dirp
->dir_path
,
382 /* dirIndex */ &dirp
->dir_index
,
383 /* dirEntry */ (char **)name
, flags
, time
);
386 //==========================================================================
390 return kernBootStruct
->kernDev
;
393 //==========================================================================
395 int switchdev(int dev
)
397 kernBootStruct
->kernDev
= dev
;
401 //==========================================================================
403 const char * usrDevices()
405 return (B_TYPE(currentdev()) == DEV_EN
) ? "" : "/private/Drivers/i386";
408 //==========================================================================
410 BVRef
scanBootVolumes( int biosdev
, int * count
)
414 switch ( BIOS_DEV_TYPE( biosdev
) )
416 case kBIOSDevTypeFloppy
:
417 case kBIOSDevTypeHardDrive
:
418 bvr
= diskScanBootVolumes( biosdev
, count
);
420 case kBIOSDevTypeNetwork
:
421 bvr
= nbpScanBootVolumes( biosdev
, count
);
427 //==========================================================================
429 void getBootVolumeDescription( BVRef bvr
, char * str
, long strMaxLen
)
431 bvr
->description( bvr
, str
, strMaxLen
);
434 //==========================================================================
436 BVRef
selectBootVolume( BVRef chain
)
438 BVRef bvr
, bvr1
= 0, bvr2
= 0;
440 for ( bvr
= chain
; bvr
; bvr
= bvr
->next
)
442 if ( bvr
->flags
& kBVFlagNativeBoot
) bvr1
= bvr
;
443 if ( bvr
->flags
& kBVFlagPrimary
) bvr2
= bvr
;
452 //==========================================================================
458 static BVRef
getBootVolumeRef( const char * path
, const char ** outPath
)
462 int type
= B_TYPE( kernBootStruct
->kernDev
);
463 int unit
= B_UNIT( kernBootStruct
->kernDev
);
464 int part
= B_PARTITION( kernBootStruct
->kernDev
);
465 int biosdev
= gBIOSDev
;
466 static BVRef lastBVR
= 0;
467 static int lastKernDev
;
469 // Search for left parenthesis in the path specification.
471 for (cp
= path
; *cp
; cp
++) {
472 if (*cp
== LP
|| *cp
== '/') break;
475 if (*cp
!= LP
) // no left paren found
478 if ( lastBVR
&& lastKernDev
== kernBootStruct
->kernDev
)
484 else if ((cp
- path
) == 2) // found "xx("
486 const struct devsw
* dp
;
487 const char * xp
= path
;
492 // Check the 2 character device name pointed by 'xp'.
494 for (dp
= devsw
; dp
->name
; dp
++)
496 if ((xp
[0] == dp
->name
[0]) && (xp
[1] == dp
->name
[1]))
497 break; // found matching entry
499 if (dp
->name
== NULL
)
501 error("Unknown device '%c%c'\n", xp
[0], xp
[1]);
504 type
= dp
- devsw
; // kerndev type
506 // Extract the optional unit number from the specification.
507 // hd(unit) or hd(unit, part).
510 while (*cp
>= '0' && *cp
<= '9')
512 i
= i
* 10 + *cp
++ - '0';
516 // Extract the optional partition number from the specification.
521 // Skip past the right paren.
523 for ( ; *cp
&& *cp
!= RP
; cp
++) /* LOOP */;
526 biosdev
= dp
->biosdev
;
530 // Bad device specifier, skip past the right paren.
532 for ( cp
++; *cp
&& *cp
!= RP
; cp
++) /* LOOP */;
536 biosdev
+= (unit
& kBIOSDevUnitMask
);
538 if ((bvr
= newBootVolumeRef(biosdev
, part
)) == NULL
)
540 // error("newBootVolumeRef() error\n");
544 // Record the most recent device parameters in the
547 kernBootStruct
->kernDev
= MAKEKERNDEV(type
, unit
, bvr
->part_no
);
550 lastKernDev
= kernBootStruct
->kernDev
;
553 // Returns the file path following the device spec.
554 // e.g. 'hd(1,b)mach_kernel' is reduced to 'mach_kernel'.
561 //==========================================================================
563 static BVRef
newBootVolumeRef( int biosdev
, int partno
)
565 BVRef bvr
, bvr1
, bvrChain
;
567 // Fetch the volume list from the device.
569 bvrChain
= scanBootVolumes( biosdev
, NULL
);
571 // Look for a perfect match based on device and partition number.
573 for ( bvr1
= NULL
, bvr
= bvrChain
; bvr
; bvr
= bvr
->next
)
575 if ( ( bvr
->flags
& kBVFlagNativeBoot
) == 0 ) continue;
578 if ( bvr
->part_no
== partno
) break;
581 return bvr
? bvr
: bvr1
;