]>
git.saurik.com Git - apple/boot.git/blob - i386/libsaio/sys.c
da632159501a0d7356e49cc73723bbfe2162ee0a
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
58 #include "bootstruct.h"
63 unsigned char biosdev
;
67 static struct devsw devsw
[] =
69 { "sd", 0x80, kBIOSDevTypeHardDrive
}, /* DEV_SD */
70 { "hd", 0x80, kBIOSDevTypeHardDrive
}, /* DEV_HD */
71 { "fd", 0x00, kBIOSDevTypeFloppy
}, /* DEV_FD */
72 { "en", 0xE0, kBIOSDevTypeNetwork
}, /* DEV_EN */
77 * Max number of file descriptors.
81 static struct iob iob
[NFILES
];
83 void * gFSLoadAddress
= 0;
85 static BVRef
getBootVolumeRef( const char * path
, const char ** outPath
);
86 static BVRef
newBootVolumeRef( int biosdev
, int partno
);
88 //==========================================================================
89 // LoadFile - LOW-LEVEL FILESYSTEM FUNCTION.
90 // Load the specified file to the load buffer at LOAD_ADDR.
91 // If the file is fat, load only the i386 portion.
93 long LoadFile(const char * fileSpec
)
95 const char * filePath
;
99 // Resolve the boot volume from the file spec.
101 if ((bvr
= getBootVolumeRef(fileSpec
, &filePath
)) == NULL
)
104 // Read file into load buffer. The data in the load buffer will be
105 // overwritten by the next LoadFile() call.
107 gFSLoadAddress
= (void *) LOAD_ADDR
;
109 fileSize
= bvr
->fs_loadfile(bvr
, (char *)filePath
);
111 // Return the size of the file, or -1 if load failed.
116 //==========================================================================
117 // GetDirEntry - LOW-LEVEL FILESYSTEM FUNCTION.
118 // Fetch the next directory entry for the given directory.
120 long GetDirEntry(const char * dirSpec
, long * dirIndex
, const char ** name
,
121 long * flags
, long * time
)
123 const char * dirPath
;
126 // Resolve the boot volume from the dir spec.
128 if ((bvr
= getBootVolumeRef(dirSpec
, &dirPath
)) == NULL
)
131 // Return 0 on success, or -1 if there are no additional entries.
133 return bvr
->fs_getdirentry( bvr
,
134 /* dirPath */ (char *)dirPath
,
135 /* dirIndex */ dirIndex
,
136 /* dirEntry */ (char **)name
, flags
, time
);
139 //==========================================================================
140 // GetFileInfo - LOW-LEVEL FILESYSTEM FUNCTION.
141 // Get attributes for the specified file.
143 static char gMakeDirSpec
[1024];
145 long GetFileInfo(const char * dirSpec
, const char * name
,
146 long * flags
, long * time
)
149 const char * entryName
;
156 for (idx
= len
; idx
&& (name
[idx
] != '/' && name
[idx
] != '\\'); idx
--) {}
158 gMakeDirSpec
[0] = '/';
159 gMakeDirSpec
[1] = '\0';
162 strncpy(gMakeDirSpec
, name
, idx
);
165 dirSpec
= gMakeDirSpec
;
168 while (GetDirEntry(dirSpec
, &index
, &entryName
, flags
, time
) == 0)
170 if (strcmp(entryName
, name
) == 0)
173 return -1; // file not found
176 //==========================================================================
179 // Return a pointer to an allocated 'iob' based on the file descriptor
180 // provided. Returns NULL if the file descriptor given is invalid.
182 static struct iob
* iob_from_fdesc(int fdesc
)
184 register struct iob
* io
;
186 if (fdesc
< 0 || fdesc
>= NFILES
||
187 ((io
= &iob
[fdesc
])->i_flgs
& F_ALLOC
) == 0)
193 //==========================================================================
196 int openmem(char * buf
, int len
)
201 // Locate a free descriptor slot.
203 for (fdesc
= 0; fdesc
< NFILES
; fdesc
++)
204 if (iob
[fdesc
].i_flgs
== 0)
207 stop("Out of file descriptors");
211 bzero(io
, sizeof(*io
));
213 // Mark the descriptor as taken. Set the F_MEM flag to indicate
214 // that the file buffer is provided by the caller.
216 io
->i_flgs
= F_ALLOC
| F_MEM
;
218 io
->i_filesize
= len
;
223 //==========================================================================
224 // open() - Open the file specified by 'path' for reading.
226 int open(const char * path
, int flags
)
230 const char * filePath
;
233 // Locate a free descriptor slot.
235 for (fdesc
= 0; fdesc
< NFILES
; fdesc
++)
236 if (iob
[fdesc
].i_flgs
== 0)
239 stop("Out of file descriptors");
243 bzero(io
, sizeof(*io
));
245 // Mark the descriptor as taken.
247 io
->i_flgs
= F_ALLOC
;
249 // Resolve the boot volume from the file spec.
251 if ((bvr
= getBootVolumeRef(path
, &filePath
)) == NULL
)
254 // Find the next available memory block in the download buffer.
256 io
->i_buf
= (char *) LOAD_ADDR
;
257 for (i
= 0; i
< NFILES
; i
++)
259 if ((iob
[i
].i_flgs
!= F_ALLOC
) || (i
== fdesc
)) continue;
260 io
->i_buf
= max(iob
[i
].i_filesize
+ iob
[i
].i_buf
, io
->i_buf
);
263 // Load entire file into memory. Unnecessary open() calls must
266 gFSLoadAddress
= io
->i_buf
;
267 io
->i_filesize
= bvr
->fs_loadfile(bvr
, (char *)filePath
);
268 if (io
->i_filesize
< 0) {
279 //==========================================================================
280 // close() - Close a file descriptor.
286 if ((io
= iob_from_fdesc(fdesc
)) == NULL
)
294 //==========================================================================
295 // lseek() - Reposition the byte offset of the file descriptor from the
296 // beginning of the file. Returns the relocated offset.
298 int b_lseek(int fdesc
, int offset
, int ptr
)
302 if ((io
= iob_from_fdesc(fdesc
)) == NULL
)
305 io
->i_offset
= offset
;
310 //==========================================================================
311 // tell() - Returns the byte offset of the file descriptor.
317 if ((io
= iob_from_fdesc(fdesc
)) == NULL
)
323 //==========================================================================
324 // read() - Read up to 'count' bytes of data from the file descriptor
325 // into the buffer pointed to by buf.
327 int read(int fdesc
, char * buf
, int count
)
331 if ((io
= iob_from_fdesc(fdesc
)) == NULL
)
334 if ((io
->i_offset
+ count
) > (unsigned int)io
->i_filesize
)
335 count
= io
->i_filesize
- io
->i_offset
;
338 return 0; // end of file
340 bcopy(io
->i_buf
+ io
->i_offset
, buf
, count
);
342 io
->i_offset
+= count
;
347 //==========================================================================
348 // file_size() - Returns the size of the file described by the file
351 int file_size(int fdesc
)
355 if ((io
= iob_from_fdesc(fdesc
)) == 0)
358 return io
->i_filesize
;
361 //==========================================================================
363 struct dirstuff
* opendir(const char * path
)
365 struct dirstuff
* dirp
= 0;
366 const char * dirPath
;
369 if ((bvr
= getBootVolumeRef(path
, &dirPath
)) == NULL
)
372 dirp
= (struct dirstuff
*) malloc(sizeof(struct dirstuff
));
376 dirp
->dir_path
= newString(dirPath
);
377 if (dirp
->dir_path
== NULL
)
389 //==========================================================================
391 int closedir(struct dirstuff
* dirp
)
394 if (dirp
->dir_path
) free(dirp
->dir_path
);
400 //==========================================================================
402 int readdir(struct dirstuff
* dirp
, const char ** name
, long * flags
,
405 return dirp
->dir_bvr
->fs_getdirentry( dirp
->dir_bvr
,
406 /* dirPath */ dirp
->dir_path
,
407 /* dirIndex */ &dirp
->dir_index
,
408 /* dirEntry */ (char **)name
, flags
, time
);
411 //==========================================================================
415 return bootArgs
->kernDev
;
418 //==========================================================================
420 int switchdev(int dev
)
422 bootArgs
->kernDev
= dev
;
426 //==========================================================================
428 const char * usrDevices()
430 if (gBootFileType
== kNetworkDeviceType
)
432 return "/private/Drivers/i386";
435 //==========================================================================
437 const char * systemConfigDir()
439 if (gBootFileType
== kNetworkDeviceType
)
441 return "/Library/Preferences/SystemConfiguration";
444 //==========================================================================
448 BVRef
scanBootVolumes( int biosdev
, int * count
)
452 bvr
= diskScanBootVolumes(biosdev
, count
);
454 bvr
= nbpScanBootVolumes(biosdev
, count
);
456 gBootFileType
= kNetworkDeviceType
;
459 gBootFileType
= kBlockDeviceType
;
464 //==========================================================================
466 void getBootVolumeDescription( BVRef bvr
, char * str
, long strMaxLen
)
468 bvr
->description( bvr
, str
, strMaxLen
);
471 //==========================================================================
473 BVRef
selectBootVolume( BVRef chain
)
475 BVRef bvr
, bvr1
= 0, bvr2
= 0;
477 for ( bvr
= chain
; bvr
; bvr
= bvr
->next
)
479 if ( bvr
->flags
& kBVFlagNativeBoot
) bvr1
= bvr
;
480 if ( bvr
->flags
& kBVFlagPrimary
) bvr2
= bvr
;
489 //==========================================================================
495 static BVRef
getBootVolumeRef( const char * path
, const char ** outPath
)
499 int type
= B_TYPE( bootArgs
->kernDev
);
500 int unit
= B_UNIT( bootArgs
->kernDev
);
501 int part
= B_PARTITION( bootArgs
->kernDev
);
502 int biosdev
= gBIOSDev
;
503 static BVRef lastBVR
= 0;
504 static int lastKernDev
;
506 // Search for left parenthesis in the path specification.
508 for (cp
= path
; *cp
; cp
++) {
509 if (*cp
== LP
|| *cp
== '/') break;
512 if (*cp
!= LP
) // no left paren found
515 if ( lastBVR
&& lastKernDev
== bootArgs
->kernDev
)
521 else if ((cp
- path
) == 2) // found "xx("
523 const struct devsw
* dp
;
524 const char * xp
= path
;
529 // Check the 2 character device name pointed by 'xp'.
531 for (dp
= devsw
; dp
->name
; dp
++)
533 if ((xp
[0] == dp
->name
[0]) && (xp
[1] == dp
->name
[1]))
534 break; // found matching entry
536 if (dp
->name
== NULL
)
538 error("Unknown device '%c%c'\n", xp
[0], xp
[1]);
541 type
= dp
- devsw
; // kerndev type
543 // Extract the optional unit number from the specification.
544 // hd(unit) or hd(unit, part).
547 while (*cp
>= '0' && *cp
<= '9')
549 i
= i
* 10 + *cp
++ - '0';
553 // Extract the optional partition number from the specification.
558 // Skip past the right paren.
560 for ( ; *cp
&& *cp
!= RP
; cp
++) /* LOOP */;
563 biosdev
= dp
->biosdev
+ unit
;
567 // Bad device specifier, skip past the right paren.
569 for ( cp
++; *cp
&& *cp
!= RP
; cp
++) /* LOOP */;
573 if ((bvr
= newBootVolumeRef(biosdev
, part
)) == NULL
)
575 // error("newBootVolumeRef() error\n");
579 // Record the most recent device parameters in the
582 bootArgs
->kernDev
= biosdev
;
585 lastKernDev
= bootArgs
->kernDev
;
588 // Returns the file path following the device spec.
589 // e.g. 'hd(1,b)mach_kernel' is reduced to 'mach_kernel'.
596 //==========================================================================
598 static BVRef
newBootVolumeRef( int biosdev
, int partno
)
600 BVRef bvr
, bvr1
, bvrChain
;
602 // Fetch the volume list from the device.
604 bvrChain
= scanBootVolumes( biosdev
, NULL
);
606 // Look for a perfect match based on device and partition number.
608 for ( bvr1
= NULL
, bvr
= bvrChain
; bvr
; bvr
= bvr
->next
)
610 if ( ( bvr
->flags
& kBVFlagNativeBoot
) == 0 ) continue;
613 if ( bvr
->part_no
== partno
) break;
616 return bvr
? bvr
: bvr1
;