]> git.saurik.com Git - apple/boot.git/blob - i386/boot1u/disk.c
cd8b4cd35e74b0f4810358fdfdb2e51ad2232e4d
[apple/boot.git] / i386 / boot1u / disk.c
1 /*
2 * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * Portions Copyright (c) 2002 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.2 (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 //#undef DEBUG_DISK
60 //#define DEBUG_DISK(x) printf x
61
62 extern void bios(biosBuf_t *bb);
63
64 static biosBuf_t bb;
65 int ebiosread(int dev, long sec, int count)
66 {
67 int i;
68 static struct {
69 unsigned char size;
70 unsigned char reserved;
71 unsigned char numblocks;
72 unsigned char reserved2;
73 unsigned short bufferOffset;
74 unsigned short bufferSegment;
75 unsigned long long startblock;
76 } addrpacket = {0};
77 addrpacket.size = sizeof(addrpacket);
78
79 for (i=0;;) {
80 bb.intno = 0x13;
81 bb.eax.r.h = 0x42;
82 bb.edx.r.l = dev;
83 bb.esi.rr = OFFSET((unsigned)&addrpacket);
84 bb.ds = SEGMENT((unsigned)&addrpacket);
85 addrpacket.reserved = addrpacket.reserved2 = 0;
86 addrpacket.numblocks = count;
87 addrpacket.bufferOffset = OFFSET(ptov(BIOS_ADDR));
88 addrpacket.bufferSegment = SEGMENT(ptov(BIOS_ADDR));
89 addrpacket.startblock = sec;
90 bios(&bb);
91 if ((bb.eax.r.h == 0x00) || (i++ >= 5))
92 break;
93
94 /* reset disk subsystem and try again */
95 bb.eax.r.h = 0x00;
96 bios(&bb);
97 }
98 return bb.eax.r.h;
99 }
100
101 //==========================================================================
102 // Use BIOS INT13 calls to read the sector specified. This function will
103 // also perform read-ahead to cache a few subsequent sector to the sector
104 // cache.
105 //
106 // Return:
107 // 0 on success, or an error code from INT13/F2 or INT13/F42 BIOS call.
108
109 static int Biosread( int biosdev, unsigned int secno )
110 {
111 int rc;
112
113 DEBUG_DISK(("Biosread dev %x sec %d \n", biosdev, secno));
114
115 rc = ebiosread(biosdev, secno, 1);
116 if (rc == ECC_CORRECTED_ERR) {
117 rc = 0;
118 }
119 return rc;
120 }
121
122 //==========================================================================
123
124 static int readBytes( int biosdev, unsigned int blkno,
125 unsigned int byteCount, void * buffer )
126 {
127
128 char * cbuf = (char *) buffer;
129 int error;
130 int copy_len;
131
132 DEBUG_DISK(("%s: dev %x block %x [%d] -> 0x%x...", __FUNCTION__,
133 biosdev, blkno, byteCount, (unsigned)cbuf));
134
135 for ( ; byteCount; cbuf += BPS, blkno++ )
136 {
137 error = Biosread( biosdev, blkno );
138 if ( error )
139 {
140 DEBUG_DISK(("error\n"));
141 return (-1);
142 }
143
144 copy_len = (byteCount > BPS) ? BPS : byteCount;
145 bcopy( biosbuf, cbuf, copy_len );
146 byteCount -= copy_len;
147 }
148
149 DEBUG_DISK(("done\n"));
150
151 return 0;
152 }
153
154 //==========================================================================
155
156 //==========================================================================
157 // Handle seek request from filesystem modules.
158
159 void diskSeek( BVRef bvr, long long position )
160 {
161 bvr->fs_boff = position / BPS;
162 }
163
164 //==========================================================================
165 // Handle read request from filesystem modules.
166
167 int diskRead( BVRef bvr, long addr, long length )
168 {
169 return readBytes( bvr->biosdev,
170 bvr->fs_boff + bvr->part_boff,
171 length,
172 (void *) addr );
173 }
174
175 int
176 findUFSPartition(int dev, struct fdisk_part *_fp)
177 {
178 struct disk_blk0 *db;
179 struct fdisk_part *fp;
180 int i, cc;
181 unsigned long offset = 0;
182
183 db = (struct disk_blk0 *)biosbuf;
184 for (i=0; i<FDISK_NPART; i++) {
185 DEBUG_DISK(("i=%d, %ld\n", i, offset));
186 if (i==0) {
187 DEBUG_DISK(("reading\n"));
188 cc = Biosread(dev, offset);
189 if (cc < 0) {
190 return cc;
191 }
192 }
193 fp = (struct fdisk_part *)&db->parts[i];
194 DEBUG_DISK(("systid %x\n", fp->systid));
195 if (fp->systid == 0xA8) {
196 bcopy(fp, _fp, sizeof(struct fdisk_part));
197 _fp->relsect += offset;
198 DEBUG_DISK(("found %d\n", i));
199 return 0;
200 } else if (fp->systid == 0x05 ||
201 fp->systid == 0x0F ||
202 fp->systid == 0x85) {
203 offset += fp->relsect;
204 i = -1;
205 continue;
206 }
207 }
208 return -1;
209 }
210
211
212 void
213 initUFSBVRef( BVRef bvr, int biosdev, const struct fdisk_part * part)
214 {
215 bvr->biosdev = biosdev;
216 bvr->part_no = 0;
217 bvr->part_boff = part->relsect + UFS_FRONT_PORCH/BPS,
218 bvr->part_type = part->systid;
219 bvr->fs_loadfile = UFSLoadFile;
220 bvr->fs_getdirentry = UFSGetDirEntry;
221 bvr->description = 0;
222 }
223
224 void putc(int ch)
225 {
226 bb.intno = 0x10;
227 bb.ebx.r.h = 0x00; /* background black */
228 bb.ebx.r.l = 0x0F; /* foreground white */
229 bb.eax.r.h = 0x0e;
230 bb.eax.r.l = ch;
231 bios(&bb);
232 }
233
234 int bgetc(void)
235 {
236 bb.intno = 0x16;
237 bb.eax.r.h = 0x00;
238 bios(&bb);
239 return bb.eax.rr;
240 }
241
242 void delay(int ms)
243 {
244 bb.intno = 0x15;
245 bb.eax.r.h = 0x86;
246 bb.ecx.rr = ms >> 16;
247 bb.edx.rr = ms & 0xFFFF;
248 bios(&bb);
249 }