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