]>
git.saurik.com Git - apple/boot.git/blob - i386/libsaio/sys.c
e8b75b449d8ebe82fdb136a1932f4156f14ccff6
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
57 #include <sys/param.h>
58 #include <ufs/ufs/dir.h>
59 #include <sys/reboot.h>
60 #include <architecture/byte_order.h>
61 #include "ufs_byteorder.h"
64 #include "kernBootStruct.h"
65 #include "stringConstants.h"
66 #include <ufs/ffs/fs.h>
72 extern int ram_debug_sarld
; // in load.c
76 #define SYS_MESSAGES 1
77 #define CHECK_CAREFULLY 0
83 #define DPRINT(x) { printf x; }
84 #define DSPRINT(x) { printf x; sleep(2); }
85 #define RDPRINT(x) { if (ram_debug_sarld) printf x; }
86 #define RDSPRINT(x) { if (ram_debug_sarld) printf x; sleep(2); }
102 //#############################################################################
104 //# Disk filesystem functions.
106 //#############################################################################
108 static ino_t
dlook(char *s
, struct iob
*io
);
109 static char * xx(char *str
, struct iob
*file
);
110 static int ffs(register long mask
);
112 extern int label_secsize
;
114 #define BIG_ENDIAN_INTEL_FS __LITTLE_ENDIAN__
117 #define ICACHE_SIZE 256
118 #define ICACHE_READAHEAD 8 // read behind and read ahead
119 static cache_t
* icache
;
123 #define DCACHE_SIZE 16 // 1k (DIRBLKSIZ) blocks
124 static cache_t
* dcache
;
127 #define DEV_BSIZE label_secsize
130 static int open_init
;
133 static struct fs
* fs_block
;
134 static int fs_block_valid
;
136 #define SUPERBLOCK_ERROR "Bad superblock: error %d\n"
138 /*==========================================================================
142 static struct iob
* iob_from_fdesc(int fdesc
)
144 register struct iob
* file
;
146 if (fdesc
< 0 || fdesc
>= NFILES
||
147 ((file
= &iob
[fdesc
])->i_flgs
& F_ALLOC
) == 0)
154 /***************************************************************************
158 ***************************************************************************/
160 /*==========================================================================
165 openi(int n
, struct iob
* io
)
168 int cc
, i
, j
, n_round
;
174 icache
= cacheInit(ICACHE_SIZE
, sizeof(struct dinode
));
179 io
->i_bn
= fsbtodb(io
->i_ffs
, ino_to_fsba(io
->i_ffs
, n
)) + io
->i_boff
;
180 io
->i_cc
= io
->i_ffs
->fs_bsize
;
181 io
->i_ma
= io
->i_buf
;
184 if (cacheFind(icache
, n
, 0, (char **)&ip
) == 1) {
185 io
->i_ino
.i_din
= *ip
;
190 dp
= (struct dinode
*)io
->i_buf
;
191 n_round
= (n
/ INOPB(io
->i_ffs
)) * INOPB(io
->i_ffs
);
193 /* Read multiple inodes into cache */
194 for (i
= max(ino_to_fsbo(io
->i_ffs
, n
) - ICACHE_READAHEAD
, 0),
195 j
= min(i
+2*ICACHE_READAHEAD
, INOPB(io
->i_ffs
)); i
< j
; i
++) {
196 cacheFind(icache
, n_round
+ i
, 0, (char **)&ip
);
198 #if BIG_ENDIAN_INTEL_FS
199 #warning Building with Big Endian changes
200 byte_swap_dinode_in(&dp
[i
]);
201 #endif /* BIG_ENDIAN_INTEL_FS */
204 if (i
== ino_to_fsbo(io
->i_ffs
, n
)) {
205 io
->i_ino
.i_din
= *ip
;
211 #if BIG_ENDIAN_INTEL_FS
212 byte_swap_dinode_in(&dp
[ino_to_fsbo(io
->i_ffs
, n
)]);
213 #endif /* BIG_ENDIAN_INTEL_FS */
215 io
->i_ino
.i_din
= dp
[ino_to_fsbo(io
->i_ffs
, n
)];
218 io
->i_ino
.i_number
= n
;
222 /*==========================================================================
227 readlink(struct iob
* io
, char * buf
, int len
)
229 register struct inode
* ip
;
236 io
->i_flgs
|= F_FILE
;
237 if (read(io
- iob
, buf
, len
) < 0)
240 if (ip
->i_icflags
& IC_FASTLINK
) {
241 if (ip
->i_size
> len
)
243 bcopy(ip
->i_symlink
, buf
, ip
->i_size
);
248 io
->i_flgs
|= F_FILE
;
249 if (read(io
- iob
, buf
, len
) < 0)
256 /*==========================================================================
261 find(char * path
, struct iob
* file
)
266 char * lbuf
= malloc(MAXPATHLEN
+ 1);
270 if (path
==NULL
|| *path
=='\0') {
271 error("null path\n");
274 #endif CHECK_CAREFULLY
276 DSPRINT(("in find: path=%s\n", path
));
280 if (openi(n
, file
) < 0)
282 DPRINT(("openi failed\n"));
285 error("bad root inode\n");
290 DPRINT(("openi ok\n"));
297 while(*q
!= '/' && *q
!= '\0')
301 if (q
== path
) path
= "." ; /* "/" means "/." */
304 if ((n
= dlook(path
, file
)) != 0)
308 if (openi(n
, file
) < 0)
316 /* Check for symlinks */
317 if (file
->i_ino
.i_mode
& IFLNK
) {
318 char *buf
= malloc(MAXPATHLEN
+ 1);
319 if (readlink(file
, buf
, MAXPATHLEN
+ 1) < 0)
327 if (openi(parent
, file
) < 0) {
345 /*==========================================================================
350 sbmap(struct iob
* io
, daddr_t bn
)
352 register struct inode
* ip
;
360 error("bn negative\n");
366 * blocks 0..NDADDR are direct blocks
375 * addresses NIADDR have single and double indirect blocks.
376 * the first step is to determine how many levels of indirection.
378 RDPRINT(("In NINADDR\n"));
382 for (j
= NIADDR
; j
> 0; j
--) {
383 sh
*= NINDIR(io
->i_ffs
);
391 error("bn ovf %d\n", bn
);
397 * fetch the first indirect block address from the inode
399 nb
= ip
->i_ib
[NIADDR
- j
];
402 error("bn void %d\n",bn
);
408 * fetch through the indirect blocks
410 for (; j
<= NIADDR
; j
++) {
411 if (blknos
[j
] != nb
) {
412 io
->i_bn
= fsbtodb(io
->i_ffs
, nb
) + io
->i_boff
;
413 if (b
[j
] == (char *)0)
414 b
[j
] = malloc(MAXBSIZE
);
416 io
->i_cc
= io
->i_ffs
->fs_bsize
;
418 RDPRINT(("Indir block read\n"));
420 if (devread(io
) != io
->i_ffs
->fs_bsize
) {
422 error("bn %d: read error\n", io
->i_bn
);
428 bap
= (daddr_t
*)b
[j
];
429 sh
/= NINDIR(io
->i_ffs
);
430 i
= (bn
/ sh
) % NINDIR(io
->i_ffs
);
431 #if BIG_ENDIAN_INTEL_FS
432 nb
= NXSwapBigLongToHost(bap
[i
]);
433 #else /* BIG_ENDIAN_INTEL_FS */
435 #endif /* BIG_ENDIAN_INTEL_FS */
438 error("bn void %d\n",bn
);
447 /*==========================================================================
451 static struct dirstuff
*
452 disk_opendir(char * path
)
454 register struct dirstuff
* dirp
;
457 dirp
= (struct dirstuff
*)malloc(sizeof(struct dirstuff
));
458 if (dirp
== (struct dirstuff
*)-1)
461 DPRINT(("Calling open in opendir\n"));
464 DPRINT(("open failed \n"));
469 DPRINT(("open ok fd is %d \n", fd
));
472 iob
[fd
].dirbuf_blkno
= -1;
477 /*==========================================================================
482 disk_closedir(struct dirstuff
* dirp
)
484 close(dirp
->io
- iob
);
489 /*==========================================================================
490 * get next entry in a directory.
492 static struct direct
*
493 disk_readdir(struct dirstuff
* dirp
)
496 register struct iob
* io
;
504 dcache
= cacheInit(DCACHE_SIZE
, DIRBLKSIZ
);
510 if (dirp
->loc
>= io
->i_ino
.i_size
)
512 off
= blkoff(io
->i_ffs
, dirp
->loc
);
513 lbn
= lblkno(io
->i_ffs
, dirp
->loc
);
516 dirblkno
= dirp
->loc
/ DIRBLKSIZ
;
517 if (cacheFind(dcache
, io
->i_ino
.i_number
, dirblkno
, &bp
)) {
518 dp
= (struct direct
*)(bp
+ (dirp
->loc
% DIRBLKSIZ
));
521 if (io
->dirbuf_blkno
!= lbn
)
524 if((d
= sbmap(io
, lbn
)) == 0)
526 io
->i_bn
= fsbtodb(io
->i_ffs
, d
) + io
->i_boff
;
527 io
->i_ma
= io
->i_buf
;
528 io
->i_cc
= blksize(io
->i_ffs
, &io
->i_ino
, lbn
);
533 error("bn %d: directory read error\n", io
->i_bn
);
537 #if BIG_ENDIAN_INTEL_FS
538 byte_swap_dir_block_in(io
->i_buf
, io
->i_cc
);
539 #endif /* BIG_ENDIAN_INTEL_FS */
542 bcopy(io
->i_buf
+ dirblkno
* DIRBLKSIZ
, bp
, DIRBLKSIZ
);
543 dp
= (struct direct
*)(io
->i_buf
+ off
);
547 dp
= (struct direct
*)(io
->i_buf
+ off
);
549 dirp
->loc
+= dp
->d_reclen
;
551 if (dp
->d_ino
!= 0) return (dp
);
555 /*==========================================================================
566 register struct inode
* ip
;
567 struct dirstuff dirp
;
570 if (s
== NULL
|| *s
== '\0')
573 if ((ip
->i_mode
& IFMT
) != IFDIR
) {
575 error(". before %s not a dir\n", s
);
579 if (ip
->i_size
== 0) {
581 error("%s: 0 length dir\n", s
);
588 io
->dirbuf_blkno
= -1;
590 for (dp
= disk_readdir(&dirp
); dp
!= NULL
; dp
= disk_readdir(&dirp
)) {
591 DPRINT(("checking name %s\n", dp
->d_name
));
594 if (dp
->d_namlen
== len
&& !strcmp(s
, dp
->d_name
))
600 /*==========================================================================
607 register struct iob
* io
;
610 int c
, lbn
, off
, size
, diff
;
612 if ((io
= iob_from_fdesc(fdesc
)) == 0) {
616 RDPRINT(("In getch\n"));
620 if ((io
->i_flgs
& F_FILE
) != 0) {
621 diff
= io
->i_ino
.i_size
- io
->i_offset
;
625 lbn
= lblkno(fs
, io
->i_offset
);
627 io
->i_bn
= fsbtodb(fs
, sbmap(io
, lbn
)) + io
->i_boff
;
629 io
->i_bn
= fsbtodb(fs
, sbmap(io
, lbn
)) + io
->i_boff
;
631 off
= blkoff(fs
, io
->i_offset
);
632 size
= blksize(fs
, &io
->i_ino
, lbn
);
636 io
->i_bn
= io
->i_offset
/ DEV_BSIZE
;
642 RDPRINT(("gc: bn=%x; off=%x\n",io
->i_bn
, io
->i_offset
));
644 io
->i_ma
= io
->i_buf
;
646 if (devread(io
) < 0) {
649 if ((io
->i_flgs
& F_FILE
) != 0) {
650 if (io
->i_offset
- off
+ size
>= io
->i_ino
.i_size
)
651 io
->i_cc
= diff
+ off
;
663 /*==========================================================================
667 disk_read(int fdesc
, char * buf
, int count
)
670 register struct iob
* file
;
674 RDSPRINT(("IN READ\n"));
676 if ((file
= iob_from_fdesc(fdesc
)) == 0) {
680 if ((file
->i_flgs
&F_READ
) == 0) {
684 if ((file
->i_flgs
& F_MEM
) != 0) {
686 RDSPRINT(("In read FMEM\n"));
688 if (file
->i_offset
< file
->i_boff
) {
689 if (count
> (file
->i_boff
- file
->i_offset
))
690 count
= file
->i_boff
- file
->i_offset
;
691 bcopy(file
->i_buf
+ file
->i_offset
, buf
, count
);
692 file
->i_offset
+= count
;
700 if ((file
->i_flgs
& F_FILE
) == 0) {
703 file
->i_bn
= file
->i_boff
+ (file
->i_offset
/ DEV_BSIZE
);
705 RDPRINT(("In read nsmall fbn=%x; offset=%x;", file
->i_bn
,
707 RDSPRINT(("boff=%x\n", file
->i_boff
));
710 file
->i_offset
+= count
;
715 if (file
->i_offset
+count
> file
->i_ino
.i_size
)
716 count
= file
->i_ino
.i_size
- file
->i_offset
;
718 RDSPRINT(("In read nsmall count=%x;", count
));
720 if ((i
= count
) <= 0)
724 * While reading full blocks, do I/O into user buffer.
725 * Anything else uses getc().
729 RDSPRINT(("In lread while\n"));
730 off
= blkoff(fs
, file
->i_offset
);
731 lbn
= lblkno(fs
, file
->i_offset
);
732 size
= blksize(fs
, &file
->i_ino
, lbn
);
733 if (off
== 0 && size
<= i
) {
734 file
->i_bn
= fsbtodb(fs
, sbmap(file
, lbn
)) +
739 RDPRINT(("In read->devread\n"));
740 RDPRINT(("In read fbn=%x; offset=%x;", file
->i_bn
,
742 RDSPRINT((" boff=%x\n", file
->i_boff
));
744 if (devread(file
) < 0) {
747 file
->i_offset
+= size
;
753 RDSPRINT(("IN while nonread\n"));
759 *buf
++ = getch(fdesc
);
767 /*==========================================================================
768 * Disk (block device) functions.
771 disk_open(char * name
, struct iob
* file
, int how
)
776 // file->i_bn = (SBLOCK / DEV_BSIZE) + file->i_boff;
777 file
->i_bn
= (SBOFF
/label_secsize
) + file
->i_boff
;
780 if (file
->i_ffs
== 0) {
782 DPRINT(("No super block; reading one \n"));
783 fs_block
= (struct fs
*) malloc(SBSIZE
);
785 if (fs_block_valid
== 0) {
786 file
->i_ma
= (char *)fs_block
;
787 if (devread(file
) < 0) {
789 error(SUPERBLOCK_ERROR
, 1);
793 #if BIG_ENDIAN_INTEL_FS
794 byte_swap_superblock(fs_block
);
795 #endif /* BIG_ENDIAN_INTEL_FS */
796 DPRINT(("Read SB \n"));
799 file
->i_ffs
= fs_block
;
800 file
->i_buf
= malloc(MAXBSIZE
);
802 #if BIG_ENDIAN_INTEL_FS
803 DPRINT(("IN BE_FS code \n"));
805 if (file
->i_ffs
->fs_magic
!= FS_MAGIC
) {
806 DPRINT(("Bad magic in FS %d ; got %d\n", FS_MAGIC
,
807 file
->i_ffs
->fs_magic
));
808 error(SUPERBLOCK_ERROR
, 2);
812 * The following is a gross hack to boot disks that have an actual
813 * blocksize of 512 bytes but were written with a theoretical 1024
814 * byte blocksize (fsbtodb == 0).
816 * We can make this assumption because we can only boot disks with
817 * a 512 byte sector size.
819 DPRINT(("SB magic ok \n"));
820 if (file
->i_ffs
->fs_fsize
== 0) {
821 error(SUPERBLOCK_ERROR
,3);
824 file
->i_ffs
->fs_fsbtodb
= ffs(file
->i_ffs
->fs_fsize
/ DEV_BSIZE
) - 1;
825 #endif /* BIG_ENDIAN_INTEL_FS */
827 if ((i
= find(name
, file
)) == 0) {
828 DPRINT(("find() failed\n"));
834 error("Can't write files\n");
837 #endif CHECK_CAREFULLY
839 DPRINT(("calling openi \n"));
840 if (openi(i
, file
) < 0) {
841 DPRINT(("openi failed \n"));
845 DPRINT(("openi ok \n"));
849 file
->i_flgs
|= F_FILE
| (how
+1);
854 /*==========================================================================
859 ffs(register long mask
)
863 if (mask
== 0) return(0);
865 for (cnt
= 1; !(mask
& 1); cnt
++)
870 /*==========================================================================
880 for (i
= 0; i
< NFILES
; i
++)
881 if (iob
[i
].i_flgs
& (F_READ
| F_WRITE
))
882 error("flushdev: fd %d is open\n",i
);
893 /***************************************************************************
897 ***************************************************************************/
900 en_read(int fdesc
, char * buf
, int count
)
904 if ((file
= iob_from_fdesc(fdesc
)) == 0)
907 DSPRINT(("read[%d]: %x %x %d\n",
908 fdesc
, TFTP_ADDR
+ file
->i_offset
, (unsigned) buf
, count
));
910 bcopy((char *)(TFTP_ADDR
+ file
->i_offset
), buf
, count
);
911 file
->i_offset
+= count
;
917 en_open(char * name
, struct iob
* file
, int how
)
919 unsigned long txferSize
= TFTP_LEN
;
921 if (nbpTFTPReadFile(name
, &txferSize
, TFTP_ADDR
) != nbpStatusSuccess
)
926 file
->i_ino
.i_size
= txferSize
; // update the real size
932 en_devopen(char * name
, struct iob
* io
)
937 /***************************************************************************
939 * Dispatch functions.
941 ***************************************************************************/
943 /*==========================================================================
947 gen_read(int fdesc
, char * buf
, int count
)
951 if ((file
= iob_from_fdesc(fdesc
)) == 0)
954 return (file
->i_ino
.i_dev
== DEV_EN
) ?
955 en_read(fdesc
, buf
, count
) :
956 disk_read(fdesc
, buf
, count
);
959 /*==========================================================================
963 gen_open(char * name
, struct iob
* file
, int how
)
965 return (file
->i_ino
.i_dev
== DEV_EN
) ?
966 en_open(name
, file
, how
) : disk_open(name
, file
, how
);
969 /*==========================================================================
973 gen_devopen(char * name
, struct iob
* io
)
975 return (io
->i_ino
.i_dev
== DEV_EN
) ?
976 en_devopen(name
, io
) : devopen(name
, io
);
979 /*==========================================================================
985 return disk_flushdev();
988 /*==========================================================================
994 #define NET_ARCH_DEVICES ""
996 return (((currentdev() >> B_TYPESHIFT
) & B_TYPEMASK
) == DEV_EN
) ?
997 NET_ARCH_DEVICES
: ARCH_DEVICES
;
1000 /***************************************************************************
1002 * External functions.
1004 ***************************************************************************/
1006 /*==========================================================================
1010 opendir(char * path
)
1012 return disk_opendir(path
);
1015 /*==========================================================================
1019 closedir(struct dirstuff
* dirp
)
1021 return disk_closedir(dirp
);
1024 /*==========================================================================
1025 * get next entry in a directory.
1028 readdir(struct dirstuff
* dirp
)
1030 return disk_readdir(dirp
);
1033 /*==========================================================================
1037 b_lseek(int fdesc
, unsigned int addr
, int ptr
)
1039 register struct iob
* io
;
1041 RDPRINT(("In lseek addr= %x\n", addr
));
1045 error("Seek not from beginning of file\n");
1048 #endif /* CHECK_CAREFULLY */
1050 if ((io
= iob_from_fdesc(fdesc
)) == 0) {
1053 io
->i_offset
= addr
;
1054 io
->i_bn
= addr
/ DEV_BSIZE
;
1057 RDPRINT(("In end of lseek offset %x; bn %x\n", io
->i_offset
,io
->i_bn
));
1062 /*==========================================================================
1068 return iob
[fdesc
].i_offset
;
1071 /*==========================================================================
1075 read(int fdesc
, char * buf
, int count
)
1077 return gen_read(fdesc
, buf
, count
);
1080 /*==========================================================================
1084 openmem(char * buf
, int len
)
1086 register struct iob
* file
;
1089 for (fdesc
= 0; fdesc
< NFILES
; fdesc
++)
1090 if (iob
[fdesc
].i_flgs
== 0)
1092 stop("Out of file descriptor slots");
1095 (file
= &iob
[fdesc
])->i_flgs
|= F_ALLOC
;
1099 file
->i_flgs
|= F_MEM
;
1103 /*==========================================================================
1104 * Generic open call.
1107 open(char * str
, int how
)
1110 register struct iob
* file
;
1113 DSPRINT(("In open %s\n", str
));
1115 #if CHECK_CAREFULLY /* iob[] is in BSS, so it is guaranteed to be zero. */
1116 if (open_init
== 0) {
1118 for (i
= 0; i
< NFILES
; i
++)
1124 for (fdesc
= 0; fdesc
< NFILES
; fdesc
++)
1125 if (iob
[fdesc
].i_flgs
== 0)
1127 stop("Out of file descriptor slots");
1130 (file
= &iob
[fdesc
])->i_flgs
|= F_ALLOC
;
1132 if ((cp
= xx(str
, file
)) == (char *) -1)
1139 file
->i_flgs
|= how
+1;
1145 if (gen_open(cp
, file
, how
) == NO
) {
1152 /*==========================================================================
1158 static char * xx(char *str
, struct iob
*file
)
1160 register char *cp
= str
, *xp
;
1162 int old_dev
= kernBootStruct
->kernDev
;
1163 int dev
= (kernBootStruct
->kernDev
>> B_TYPESHIFT
) & B_TYPEMASK
;
1164 int unit
= (kernBootStruct
->kernDev
>> B_UNITSHIFT
) & B_UNITMASK
;
1165 int part
= (kernBootStruct
->kernDev
>> B_PARTITIONSHIFT
) & B_PARTITIONMASK
;
1170 biosOffset
= unit
; // set the device
1172 for (; *cp
&& *cp
!= LP
; cp
++) ;
1173 if (no_dev
= !*cp
) { // no left paren found
1176 } else if (cp
== str
) { // paren but no device
1184 for (dp
= devsw
; *dp
; dp
++)
1186 if ((xp
[0] == *dp
[0]) && (xp
[1] == *(dp
[0] + 1)))
1190 error("Unknown device '%c%c'\n",xp
[0],xp
[1]);
1191 return ((char *)-1);
1197 while (*cp
>= '0' && *cp
<= '9')
1199 i
= i
* 10 + *cp
++ - '0';
1200 unit
= i
; // get the specified unit number
1203 biosOffset
= unit
; // set the device
1205 if (*cp
== RP
|| no_dev
)
1206 /* do nothing since ptol(")") returns 0 */ ;
1207 else if (*cp
== ',')
1208 part
= ptol(++cp
); // get the specified partition number
1209 else if (cp
[-1] == LP
)
1213 error("Missing offset specification\n");
1214 return ((char *)-1);
1217 for ( ;!no_dev
;) { // skip after the right paren
1226 file
->i_ino
.i_dev
= dev
= dp
- devsw
;
1227 file
->partition
= part
;
1228 file
->biosdev
= (BIOSDEV(dev
)) + biosOffset
;
1230 if (dev
== DEV_SD
) {
1231 file
->biosdev
+= kernBootStruct
->numIDEs
;
1233 else if (dev
== DEV_EN
) {
1234 file
->biosdev
= BIOS_DEV_EN
;
1236 else if (dev
== DEV_HD
&& kernBootStruct
->numIDEs
== 0) {
1237 error("No IDE drives detected\n");
1238 return ((char *)-1);
1241 kernBootStruct
->kernDev
= (dev
<< B_TYPESHIFT
) |
1242 (unit
<< B_UNITSHIFT
) |
1243 (part
<< B_PARTITIONSHIFT
);
1245 if (kernBootStruct
->kernDev
!= old_dev
)
1248 gen_devopen(str
, file
);
1252 if (!no_dev
&& *cp
) cp
++;
1259 /*==========================================================================
1265 register struct iob
* file
;
1268 if ((file
= iob_from_fdesc(fdesc
)) == 0)
1271 if ((file
->i_flgs
& F_MEM
) == 0) {
1272 // free((char *)file->i_ffs);
1278 for (i
=0;i
<NBUFS
;i
++)
1292 /*==========================================================================
1296 file_size(int fdesc
)
1298 register struct iob
* io
;
1300 if ((io
= iob_from_fdesc(fdesc
)) == 0)
1303 return io
->i_ino
.i_size
;
1306 /*==========================================================================
1307 * ensure that all device caches are flushed,
1308 * because we are about to change the device media
1316 /*==========================================================================
1325 for (i
= 0; i
< NFILES
; i
++)
1326 if (iob
[i
].i_flgs
!= 0)
1328 #endif CHECK_CAREFULLY
1330 /* textMode(); */ // can't call this function from here
1332 sleep(4); // about to halt
1336 /*==========================================================================
1341 return kernBootStruct
->kernDev
;
1344 /*==========================================================================
1351 kernBootStruct
->kernDev
= dev
;
1355 /*==========================================================================
1361 return gen_usrDevices();