Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / i386 / boot / dosboot / sys.c
1 /*\r
2  * Mach Operating System\r
3  * Copyright (c) 1992, 1991 Carnegie Mellon University\r
4  * All Rights Reserved.\r
5  * \r
6  * Permission to use, copy, modify and distribute this software and its\r
7  * documentation is hereby granted, provided that both the copyright\r
8  * notice and this permission notice appear in all copies of the\r
9  * software, derivative works or modified versions, and any portions\r
10  * thereof, and that both notices appear in supporting documentation.\r
11  * \r
12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"\r
13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR\r
14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.\r
15  * \r
16  * Carnegie Mellon requests users of this software to return to\r
17  * \r
18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU\r
19  *  School of Computer Science\r
20  *  Carnegie Mellon University\r
21  *  Pittsburgh PA 15213-3890\r
22  * \r
23  * any improvements or extensions that they make and grant Carnegie Mellon\r
24  * the rights to redistribute these changes.\r
25  *\r
26  *      from: Mach, Revision 2.2  92/04/04  11:36:34  rpd\r
27  * $FreeBSD: src/sys/i386/boot/dosboot/sys.c,v 1.5 1999/08/28 00:43:25 peter Exp $\r
28  */\r
29 #include <stdio.h>\r
30 #include <string.h>\r
31 #include <memory.h>\r
32 \r
33 #define bcopy(a,b,c)    memcpy(b,a,c)\r
34 \r
35 #include "protmod.h"\r
36 #include "boot.h"\r
37 #include "dir.h"\r
38 \r
39 #define BUFSIZE 4096\r
40 #undef MAXBSIZE\r
41 #define MAXBSIZE 8192\r
42 \r
43 void ufs_read(char *buffer, long count);\r
44 static long block_map(long file_block);\r
45 \r
46 char buf[BUFSIZE], fsbuf[SBSIZE], iobuf[MAXBSIZE];\r
47 char mapbuf[MAXBSIZE];\r
48 long mapblock = 0;\r
49 \r
50 void xread(unsigned long addr, long size)\r
51 {\r
52         long count = BUFSIZE;\r
53         while (size > 0l) {\r
54                 if (BUFSIZE > size)\r
55                         count = size;\r
56                 ufs_read(buf, count);\r
57                 pm_copy(buf, addr, count);\r
58                 size -= count;\r
59                 addr += count;\r
60         }\r
61 }\r
62 \r
63 void ufs_read(char *buffer, long count)\r
64 {\r
65         long logno, off, size;\r
66         long cnt2, bnum2;\r
67 \r
68         while (count) {\r
69                 off = blkoff(fs, poff);\r
70                 logno = lblkno(fs, poff);\r
71                 cnt2 = size = blksize(fs, &inode, logno);\r
72                 bnum2 = fsbtodb(fs, block_map(logno)) + boff;\r
73                 cnt = cnt2;\r
74                 bnum = bnum2;\r
75                 if (    (!off)  && (size <= count))\r
76                 {\r
77                         iodest = buffer;\r
78                         devread();\r
79                 }\r
80                 else\r
81                 {\r
82                         iodest = iobuf;\r
83                         size -= off;\r
84                         if (size > count)\r
85                                 size = count;\r
86                         devread();\r
87                         bcopy(iodest+off,buffer,size);\r
88                 }\r
89                 buffer += size;\r
90                 count -= size;\r
91                 poff += size;\r
92         }\r
93 }\r
94 \r
95 static int find(char *path)\r
96 {\r
97         char *rest, ch;\r
98         long block, off, loc, ino = ROOTINO;\r
99         struct direct *dp;\r
100 loop:   iodest = iobuf;\r
101         cnt = fs->fs_bsize;\r
102         bnum = fsbtodb(fs,itod(fs,ino)) + boff;\r
103         devread();\r
104         bcopy(&((struct dinode *)iodest)[ino % fs->fs_inopb],\r
105               &inode.i_din,\r
106               sizeof (struct dinode));\r
107         if (!*path)\r
108                 return 1;\r
109         while (*path == '/')\r
110                 path++;\r
111         if (!inode.i_size || ((inode.i_mode&IFMT) != IFDIR))\r
112                 return 0;\r
113         for (rest = path; (ch = *rest) && ch != '/'; rest++) ;\r
114         *rest = 0;\r
115         loc = 0;\r
116         do {\r
117                 if (loc >= inode.i_size)\r
118                         return 0;\r
119                 if (!(off = blkoff(fs, loc))) {\r
120                         block = lblkno(fs, loc);\r
121                         cnt = blksize(fs, &inode, block);\r
122                         bnum = fsbtodb(fs, block_map(block)) + boff;\r
123                         iodest = iobuf;\r
124                         devread();\r
125                 }\r
126                 dp = (struct direct *)(iodest + off);\r
127                 loc += dp->d_reclen;\r
128         } while (!dp->d_ino || strcmp(path, dp->d_name));\r
129         ino = dp->d_ino;\r
130         *(path = rest) = ch;\r
131         goto loop;\r
132 }\r
133 \r
134 static long block_map(long file_block)\r
135 {\r
136         if (file_block < NDADDR)\r
137                 return(inode.i_db[file_block]);\r
138         if ((bnum=fsbtodb(fs, inode.i_ib[0])+boff) != mapblock) {\r
139                 iodest = mapbuf;\r
140                 cnt = fs->fs_bsize;\r
141                 devread();\r
142                 mapblock = bnum;\r
143         }\r
144         return (((long *)mapbuf)[(file_block - NDADDR) % NINDIR(fs)]);\r
145 }\r
146 \r
147 int openrd(char *name)\r
148 {\r
149         char *cp = name;\r
150 \r
151         dosdev = 0x80;                          /* only 1st HD supported yet */\r
152         inode.i_dev = dosdev;\r
153         /***********************************************\\r
154         * Now we know the disk unit and part,                   *\r
155         * Load disk info, (open the device)                             *\r
156         \***********************************************/\r
157         if (devopen()) return 1;\r
158 \r
159         /***********************************************\\r
160         * Load Filesystem info (mount the device)               *\r
161         \***********************************************/\r
162         iodest = (char *)(fs = (struct fs *)fsbuf);\r
163         cnt = SBSIZE;\r
164         bnum = SBLOCK + boff;\r
165         devread();\r
166         /***********************************************\\r
167         * Find the actual FILE on the mounted device    *\r
168         \***********************************************/\r
169         if (!find(cp)) return 1;\r
170         poff = 0;\r
171         name = cp;\r
172         return 0;\r
173 }\r