]> git.saurik.com Git - apple/bootx.git/blame - bootx.tproj/fs.subproj/fs.c
BootX-81.tar.gz
[apple/bootx.git] / bootx.tproj / fs.subproj / fs.c
CommitLineData
04fee52e 1/*
873b6fa6 2 * Copyright (c) 2000-2007 Apple Inc. All rights reserved.
04fee52e 3 *
873b6fa6 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
04fee52e 5 *
873b6fa6
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
04fee52e 14 *
873b6fa6
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
04fee52e
A
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
873b6fa6
A
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
04fee52e 25 *
873b6fa6 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
04fee52e 27 */
873b6fa6 28
04fee52e
A
29/*
30 * fs.c - Generic access to the file system modules.
31 *
8be739c0 32 * Copyright (c) 1999-2004 Apple Computer, Inc.
04fee52e
A
33 *
34 * DRI: Josh de Cesare
35 */
36
37#include <sl.h>
873b6fa6 38#include "md5.h"
04fee52e
A
39
40typedef long (* FSLoadFile)(CICell ih, char *filePath);
8be739c0
A
41typedef long (* FSReadFile)(CICell ih, char *filePath,
42 void *base, unsigned long offset,
43 unsigned long length);
04fee52e 44typedef long (* FSGetDirEntry)(CICell ih, char *dirPath,
873b6fa6 45 unsigned long *dirIndex, char **name,
04fee52e 46 long *flags, long *time);
8be739c0 47typedef long (* FSGetUUID)(CICell ih, char *uuidStr);
04fee52e
A
48
49#define kPartNet (0)
50#define kPartHFS (1)
51#define kPartUFS (2)
52#define kPartExt2 (3)
53
54struct PartInfo {
55 long partType;
56 CICell partIH;
57 FSLoadFile loadFile;
8be739c0 58 FSReadFile readFile;
04fee52e 59 FSGetDirEntry getDirEntry;
8be739c0 60 FSGetUUID getUUID;
04fee52e
A
61 char partName[1024];
62};
63typedef struct PartInfo PartInfo, *PartInfoPtr;
64
65#define kNumPartInfos (16)
66static PartInfo gParts[kNumPartInfos];
b1faa321 67static char gMakeDirSpec[1024];
04fee52e
A
68
69// Private function prototypes
70long LookupPartition(char *devSpec);
71
72
73// Public functions
74
75long LoadFile(char *fileSpec)
76{
77 char devSpec[256];
78 char *filePath;
79 FSLoadFile loadFile;
80 long ret, length, partIndex;
81
82 ret = ConvertFileSpec(fileSpec, devSpec, &filePath);
83 if ((ret == -1) || (filePath == NULL)) return -1;
84
85 // Get the partition index for devSpec.
86 partIndex = LookupPartition(devSpec);
87 if (partIndex == -1) return -1;
88
89 loadFile = gParts[partIndex].loadFile;
90 length = loadFile(gParts[partIndex].partIH, filePath);
91
92// if (length == 0) return -1;
93
94 return length;
95}
96
8be739c0
A
97long LoadThinFatFile(char *fileSpec, void **binary)
98{
99 char devSpec[256];
100 char *filePath;
101 FSLoadFile loadFile;
102 FSReadFile readFile;
103 long ret, length, length2, partIndex;
104
105 ret = ConvertFileSpec(fileSpec, devSpec, &filePath);
106 if ((ret == -1) || (filePath == NULL)) return -1;
107
108 // Get the partition index for devSpec.
109 partIndex = LookupPartition(devSpec);
110 if (partIndex == -1) return -1;
111
112 *binary = (void *)kLoadAddr;
113
114 readFile = gParts[partIndex].readFile;
115
116 if (readFile != NULL) {
117 // Read the first 4096 bytes (fat header)
118 length = readFile(gParts[partIndex].partIH, filePath, *binary, 0, 0x1000);
119 if (length > 0) {
120 if (ThinFatBinary(binary, &length) == 0) {
121 // We found a fat binary; read only the thin part
122 length = readFile(gParts[partIndex].partIH, filePath,
123 (void *)kLoadAddr, (unsigned long)(*binary) - kLoadAddr, length);
124 *binary = (void *)kLoadAddr;
125 } else {
126 // Not a fat binary; read the rest of the file
127 length2 = readFile(gParts[partIndex].partIH, filePath, (void *)(kLoadAddr + length), length, 0);
128 if (length2 == -1) return -1;
129 length += length2;
130 }
131 }
132 } else {
133 loadFile = gParts[partIndex].loadFile;
134 length = loadFile(gParts[partIndex].partIH, filePath);
135 if (length > 0) {
136 ThinFatBinary(binary, &length);
137 }
138 }
139
140 return length;
141}
142
143long GetFSUUID(char *spec, char *uuidStr)
144{
145 long rval = -1, partIndex;
146 FSGetUUID getUUID;
147 char devSpec[256];
148
149 do {
150 if(ConvertFileSpec(spec, devSpec, NULL)) break;
151
152 // Get the partition index
153 partIndex = LookupPartition(devSpec);
154 if (partIndex == -1) break;
155
156 getUUID = gParts[partIndex].getUUID;
157 if(getUUID)
158 rval = getUUID(gParts[partIndex].partIH, uuidStr);
159 } while(0);
160
161 return rval;
162}
163
164
165// from our uuid/namespace.h (UFS and HFS uuids can live in the same space?)
873b6fa6 166static unsigned char kFSUUIDNamespaceSHA1[] = {0xB3,0xE2,0x0F,0x39,0xF2,0x92,0x11,0xD6,0x97,0xA4,0x00,0x30,0x65,0x43,0xEC,0xAC};
8be739c0
A
167
168// filesystem-specific getUUID functions call this shared string generator
169long CreateUUIDString(uint8_t uubytes[], int nbytes, char *uuidStr)
170{
171 unsigned fmtbase, fmtidx, i;
172 uint8_t uuidfmt[] = { 4, 2, 2, 2, 6 };
173 char *p = uuidStr;
174 MD5_CTX md5c;
175 uint8_t mdresult[16];
176
177 bzero(mdresult, sizeof(mdresult));
178
179 // just like AppleFileSystemDriver
180 MD5Init(&md5c);
181 MD5Update(&md5c, kFSUUIDNamespaceSHA1, sizeof(kFSUUIDNamespaceSHA1));
182 MD5Update(&md5c, uubytes, nbytes);
183 MD5Final(mdresult, &md5c);
184
185 // this UUID has been made version 3 style (i.e. via namespace)
186 // see "-uuid-urn-" IETF draft (which otherwise copies byte for byte)
187 mdresult[6] = 0x30 | ( mdresult[6] & 0x0F );
188 mdresult[8] = 0x80 | ( mdresult[8] & 0x3F );
189
190
191 // generate the text: e.g. 5EB1869F-C4FA-3502-BDEB-3B8ED5D87292
192 i = 0; fmtbase = 0;
193 for(fmtidx = 0; fmtidx < sizeof(uuidfmt); fmtidx++) {
194 for(i=0; i < uuidfmt[fmtidx]; i++) {
195 uint8_t byte = mdresult[fmtbase+i];
196 char nib;
197
198 nib = byte >> 4;
199 *p = nib + '0'; // 0x4 -> '4'
200 if(*p > '9') *p = (nib - 9 + ('A'-1)); // 0xB -> 'B'
201 p++;
202
203 nib = byte & 0xf;
204 *p = nib + '0'; // 0x4 -> '4'
205 if(*p > '9') *p = (nib - 9 + ('A'-1)); // 0xB -> 'B'
206 p++;
207
208 }
209 fmtbase += i;
210 if(fmtidx < sizeof(uuidfmt)-1)
211 *(p++) = '-';
212 else
213 *p = '\0';
214 }
215
216 return 0;
217}
218
04fee52e
A
219long GetFileInfo(char *dirSpec, char *name, long *flags, long *time)
220{
873b6fa6
A
221 long ret;
222 unsigned long index = 0;
04fee52e 223 char *curName;
b1faa321
A
224
225 if (!dirSpec) {
226 long idx, len;
227
228 len = strlen(name);
229
230 for (idx = len; idx && (name[idx] != '\\'); idx--) {}
231 idx++;
232 strncpy(gMakeDirSpec, name, idx);
233 name += idx;
234 dirSpec = gMakeDirSpec;
235 }
04fee52e
A
236
237 while (1) {
238 ret = GetDirEntry(dirSpec, &index, &curName, flags, time);
239 if (ret == -1) break;
240
241 if (!strcmp(name, curName)) break;
242 }
243
244 return ret;
245}
246
873b6fa6 247long GetDirEntry(char *dirSpec, unsigned long *dirIndex, char **name,
04fee52e
A
248 long *flags, long *time)
249{
250 char devSpec[256];
251 char *dirPath;
252 FSGetDirEntry getDirEntry;
253 long ret, partIndex;
254
255 ret = ConvertFileSpec(dirSpec, devSpec, &dirPath);
256 if ((ret == -1) || (dirPath == NULL)) return -1;
257
258 // Get the partition index for devSpec.
259 partIndex = LookupPartition(devSpec);
260 if (partIndex == -1) return -1;
261
262 getDirEntry = gParts[partIndex].getDirEntry;
263 ret = getDirEntry(gParts[partIndex].partIH, dirPath,
264 dirIndex, name, flags, time);
265
266 return ret;
267}
268
269long DumpDir(char *dirSpec)
270{
873b6fa6
A
271 long ret, flags, time;
272 unsigned long index = 0;
04fee52e
A
273 char *name;
274
275 printf("DumpDir on [%s]\n", dirSpec);
276
277 while (1) {
278 ret = GetDirEntry(dirSpec, &index, &name, &flags, &time);
279 if (ret == -1) break;
280
281 printf("%x %x [%s]\n", flags, time, name);
282 }
283
284 return 0;
285}
286
287
288// Private functions
289
290long LookupPartition(char *devSpec)
291{
292 CICell partIH;
293 long partIndex, partType;
294 long deviceType;
295
296 // See if the devSpec has already been opened.
297 for (partIndex = 0; partIndex < kNumPartInfos; partIndex++) {
298 if (!strcmp(gParts[partIndex].partName, devSpec)) break;
299 }
300
301 // If it has not been opened, do so now.
302 if (partIndex == kNumPartInfos) {
303 // Find a free slot.
304 for (partIndex = 0; partIndex < kNumPartInfos; partIndex++) {
305 if (gParts[partIndex].partIH == 0) break;
306 }
307 // No free slots, so return error.
308 if (partIndex == kNumPartInfos) return -1;
309
310 deviceType = GetDeviceType(devSpec);
311 switch (deviceType) {
312 case kNetworkDeviceType :
313 partIH = NetInitPartition(devSpec);
314 if (partIH == 0) return -1;
315 partType = kPartNet;
316 break;
317
318 case kBlockDeviceType :
319 printf("Opening partition [%s]...\n", devSpec);
320 partIH = Open(devSpec);
321 if (partIH == 0) {
322 printf("Failed to open partition [%s].\n", devSpec);
323 return -1;
324 }
325
326 // Find out what kind of partition it is.
327 if (HFSInitPartition(partIH) != -1) partType = kPartHFS;
328 else if (UFSInitPartition(partIH) != -1) partType = kPartUFS;
329 else if (Ext2InitPartition(partIH) != -1) partType = kPartExt2;
330 else return -1;
331 break;
332
333 default :
334 return -1;
335 }
336
337 gParts[partIndex].partIH = partIH;
338 gParts[partIndex].partType = partType;
339 strcpy(gParts[partIndex].partName, devSpec);
340
341 switch (partType) {
342 case kPartNet:
343 gParts[partIndex].loadFile = NetLoadFile;
8be739c0 344 gParts[partIndex].readFile = NULL;
04fee52e 345 gParts[partIndex].getDirEntry = NetGetDirEntry;
8be739c0 346 gParts[partIndex].getUUID = NULL;
04fee52e
A
347 break;
348
349 case kPartHFS:
350 gParts[partIndex].loadFile = HFSLoadFile;
8be739c0 351 gParts[partIndex].readFile = HFSReadFile;
04fee52e 352 gParts[partIndex].getDirEntry = HFSGetDirEntry;
8be739c0 353 gParts[partIndex].getUUID = HFSGetUUID;
04fee52e
A
354 break;
355
356 case kPartUFS:
357 gParts[partIndex].loadFile = UFSLoadFile;
8be739c0 358 gParts[partIndex].readFile = UFSReadFile;
04fee52e 359 gParts[partIndex].getDirEntry = UFSGetDirEntry;
8be739c0 360 gParts[partIndex].getUUID = UFSGetUUID;
04fee52e
A
361 break;
362
363 case kPartExt2:
364 gParts[partIndex].loadFile = Ext2LoadFile;
8be739c0 365 gParts[partIndex].readFile = NULL;
04fee52e 366 gParts[partIndex].getDirEntry = Ext2GetDirEntry;
8be739c0
A
367 gParts[partIndex].getUUID = NULL;
368 // Ext2GetUUID exists, but there's no kernel support
04fee52e
A
369 break;
370 }
371 }
372
373 return partIndex;
374}