]> git.saurik.com Git - apple/boot.git/blob - i386/boot1u/disk.c
boot-122.tar.gz
[apple/boot.git] / i386 / boot1u / disk.c
1 /*
2 * Copyright (c) 2002-2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 2002-2003 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 2.0 (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
12 * this file.
13 *
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
20 * under the License.
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24
25 #include <string.h>
26 #include "boot1u.h"
27 #include <memory.h>
28 #include <saio_types.h>
29 #include <saio_internal.h>
30 #include <fdisk.h>
31
32 #include "ufs.h"
33
34 /*
35 * trackbuf points to the start of the track cache. Biosread()
36 * will store the sectors read from disk to this memory area.
37 *
38 * biosbuf points to a sector within the track cache, and is
39 * updated by Biosread().
40 */
41 #if 0
42 static const char * const trackbuf = (char *) ptov(BIOS_ADDR);
43 #endif
44 static const char * biosbuf = (char *) ptov(BIOS_ADDR);
45
46 /*
47 * diskinfo unpacking.
48 */
49 #define SPT(di) ((di) & 0xff)
50 #define HEADS(di) ((((di)>>8) & 0xff) + 1)
51 #define SPC(di) (SPT(di) * HEADS(di))
52
53 #define BPS 512 /* sector size of the device */
54 #define N_CACHE_SECS (BIOS_LEN / BPS)
55 #define UFS_FRONT_PORCH 0
56
57 #define ECC_CORRECTED_ERR 0x11
58
59 extern void bios(biosBuf_t *bb);
60
61 static biosBuf_t bb;
62
63 int ebiosread(int dev, long sec, int count)
64 {
65 int i;
66 static struct {
67 unsigned char size;
68 unsigned char reserved;
69 unsigned char numblocks;
70 unsigned char reserved2;
71 unsigned short bufferOffset;
72 unsigned short bufferSegment;
73 unsigned long long startblock;
74 } addrpacket = {0};
75 addrpacket.size = sizeof(addrpacket);
76
77 for (i=0;;) {
78 bb.intno = 0x13;
79 bb.eax.r.h = 0x42;
80 bb.edx.r.l = dev;
81 bb.esi.rr = OFFSET((unsigned)&addrpacket);
82 bb.ds = SEGMENT((unsigned)&addrpacket);
83 addrpacket.reserved = addrpacket.reserved2 = 0;
84 addrpacket.numblocks = count;
85 addrpacket.bufferOffset = OFFSET(ptov(BIOS_ADDR));
86 addrpacket.bufferSegment = SEGMENT(ptov(BIOS_ADDR));
87 addrpacket.startblock = sec;
88 bios(&bb);
89 if ((bb.eax.r.h == 0x00) || (i++ >= 5))
90 break;
91
92 /* reset disk subsystem and try again */
93 bb.eax.r.h = 0x00;
94 bios(&bb);
95 }
96 return bb.eax.r.h;
97 }
98
99 //==========================================================================
100 // Use BIOS INT13 calls to read the sector specified. This function will
101 // also perform read-ahead to cache a few subsequent sector to the sector
102 // cache.
103 //
104 // Return:
105 // 0 on success, or an error code from INT13/F2 or INT13/F42 BIOS call.
106
107 static int Biosread( int biosdev, unsigned int secno )
108 {
109 int rc;
110
111 DEBUG_DISK(("Biosread dev %x sec %d \n", biosdev, secno));
112
113 rc = ebiosread(biosdev, secno, 1);
114 if (rc == ECC_CORRECTED_ERR) {
115 rc = 0;
116 }
117 return rc;
118 }
119
120 //==========================================================================
121
122 static int readBytes( int biosdev, unsigned int blkno,
123 unsigned int byteCount, void * buffer )
124 {
125
126 char * cbuf = (char *) buffer;
127 int error;
128 int copy_len;
129
130 DEBUG_DISK(("%s: dev %x block %x [%d] -> 0x%x...", __FUNCTION__,
131 biosdev, blkno, byteCount, (unsigned)cbuf));
132
133 for ( ; byteCount; cbuf += BPS, blkno++ )
134 {
135 error = Biosread( biosdev, blkno );
136 if ( error )
137 {
138 DEBUG_DISK(("error\n"));
139 return (-1);
140 }
141
142 copy_len = (byteCount > BPS) ? BPS : byteCount;
143 bcopy( biosbuf, cbuf, copy_len );
144 byteCount -= copy_len;
145 }
146
147 DEBUG_DISK(("done\n"));
148
149 return 0;
150 }
151
152 //==========================================================================
153
154 //==========================================================================
155 // Handle seek request from filesystem modules.
156
157 void diskSeek( BVRef bvr, long long position )
158 {
159 bvr->fs_boff = position / BPS;
160 }
161
162 //==========================================================================
163 // Handle read request from filesystem modules.
164
165 int diskRead( BVRef bvr, long addr, long length )
166 {
167 return readBytes( bvr->biosdev,
168 bvr->fs_boff + bvr->part_boff,
169 length,
170 (void *) addr );
171 }
172
173
174 int
175 findUFSPartition(int dev, struct fdisk_part *_fp)
176 {
177 struct disk_blk0 *db;
178 struct fdisk_part *fp;
179 int i, cc;
180 unsigned long offset = 0;
181 unsigned long firstoff = 0;
182 int ext_index = -1;
183
184 db = (struct disk_blk0 *)biosbuf;
185 do {
186 DEBUG_DISK(("reading at offset %d\n", offset));
187 cc = Biosread(dev, offset);
188 if (cc < 0) {
189 return cc;
190 }
191 for (i=0; i<FDISK_NPART; i++) {
192 DEBUG_DISK(("i=%d, offset %ld\n", i, offset));
193 fp = (struct fdisk_part *)&db->parts[i];
194 DEBUG_DISK(("systid %x\n", fp->systid));
195 if (fp->systid == FDISK_UFS) {
196 bcopy(fp, _fp, sizeof(struct fdisk_part));
197 _fp->relsect += offset;
198 DEBUG_DISK(("** found UFS at partition %d\n", i));
199 return 0;
200 } else if (fp->systid == FDISK_DOSEXT ||
201 fp->systid == 0x0F ||
202 fp->systid == 0x85) {
203 ext_index = i;
204 }
205 }
206 if (ext_index != -1) {
207 DEBUG_DISK(("Found ext part at %d\n", ext_index));
208 fp = (struct fdisk_part *)&db->parts[ext_index];
209 ext_index = -1;
210 offset = firstoff + fp->relsect;
211 if (firstoff == 0) {
212 firstoff = fp->relsect;
213 }
214 continue;
215 }
216 break;
217 } while (1);
218 return -1;
219 }
220
221
222 void
223 initUFSBVRef( BVRef bvr, int biosdev, const struct fdisk_part * part)
224 {
225 bvr->biosdev = biosdev;
226 bvr->part_no = 0;
227 bvr->part_boff = part->relsect + UFS_FRONT_PORCH/BPS,
228 bvr->part_type = part->systid;
229 bvr->fs_loadfile = UFSLoadFile;
230 //bvr->fs_getdirentry = UFSGetDirEntry;
231 bvr->description = 0;
232 }
233
234 void putc(int ch)
235 {
236 bb.intno = 0x10;
237 bb.ebx.r.h = 0x00; /* background black */
238 bb.ebx.r.l = 0x0F; /* foreground white */
239 bb.eax.r.h = 0x0e;
240 bb.eax.r.l = ch;
241 bios(&bb);
242 }
243
244 int bgetc(void)
245 {
246 bb.intno = 0x16;
247 bb.eax.r.h = 0x00;
248 bios(&bb);
249 return bb.eax.rr;
250 }
251
252 void delay(int ms)
253 {
254 bb.intno = 0x15;
255 bb.eax.r.h = 0x86;
256 bb.ecx.rr = ms >> 16;
257 bb.edx.rr = ms & 0xFFFF;
258 bios(&bb);
259 }