]> git.saurik.com Git - apple/bootx.git/blobdiff - bootx.tproj/fs.subproj/fs.c
BootX-74.1.tar.gz
[apple/bootx.git] / bootx.tproj / fs.subproj / fs.c
index a58553b64a8325a846028a3cb585a61760fa8308..98f5e79aad2508e3e68eebb0df8bf8b83c21874e 100644 (file)
@@ -3,39 +3,41 @@
  *
  * @APPLE_LICENSE_HEADER_START@
  * 
- * Copyright (c) 1999-2003 Apple Computer, Inc.  All Rights Reserved.
+ * The contents of this file constitute Original Code as defined in and
+ * are subject to the Apple Public Source License Version 1.1 (the
+ * "License").  You may not use this file except in compliance with the
+ * License.  Please obtain a copy of the License at
+ * http://www.apple.com/publicsource and read it before using this file.
  * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
+ * This Original Code and all software distributed under the License are
+ * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
+ * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
+ * License for the specific language governing rights and limitations
+ * under the License.
  * 
  * @APPLE_LICENSE_HEADER_END@
  */
 /*
  *  fs.c - Generic access to the file system modules.
  *
- *  Copyright (c) 1999-2000 Apple Computer, Inc.
+ *  Copyright (c) 1999-2004 Apple Computer, Inc.
  *
  *  DRI: Josh de Cesare
  */
 
 #include <sl.h>
+#include <sys/md5.h>
 
 typedef long (* FSLoadFile)(CICell ih, char *filePath);
+typedef long (* FSReadFile)(CICell ih, char *filePath,
+                           void *base, unsigned long offset,
+                           unsigned long length);
 typedef long (* FSGetDirEntry)(CICell ih, char *dirPath,
                               long *dirIndex, char **name,
                               long *flags, long *time);
+typedef long (* FSGetUUID)(CICell ih, char *uuidStr);
 
 #define kPartNet     (0)
 #define kPartHFS     (1)
@@ -46,7 +48,9 @@ struct PartInfo {
   long            partType;
   CICell          partIH;
   FSLoadFile      loadFile;
+  FSReadFile      readFile;
   FSGetDirEntry   getDirEntry;
+  FSGetUUID       getUUID;
   char            partName[1024];
 };
 typedef struct PartInfo PartInfo, *PartInfoPtr;
@@ -83,6 +87,128 @@ long LoadFile(char *fileSpec)
   return length;
 }
 
+long LoadThinFatFile(char *fileSpec, void **binary)
+{
+  char       devSpec[256];
+  char       *filePath;
+  FSLoadFile loadFile;
+  FSReadFile readFile;
+  long       ret, length, length2, partIndex;
+  
+  ret = ConvertFileSpec(fileSpec, devSpec, &filePath);
+  if ((ret == -1) || (filePath == NULL)) return -1;
+  
+  // Get the partition index for devSpec.
+  partIndex = LookupPartition(devSpec);
+  if (partIndex == -1) return -1;
+  
+  *binary = (void *)kLoadAddr;
+  
+  readFile = gParts[partIndex].readFile;
+  
+  if (readFile != NULL) {
+    // Read the first 4096 bytes (fat header)
+    length = readFile(gParts[partIndex].partIH, filePath, *binary, 0, 0x1000);
+    if (length > 0) {
+      if (ThinFatBinary(binary, &length) == 0) {
+        // We found a fat binary; read only the thin part
+        length = readFile(gParts[partIndex].partIH, filePath,
+                          (void *)kLoadAddr, (unsigned long)(*binary) - kLoadAddr, length);
+        *binary = (void *)kLoadAddr;
+      } else {
+        // Not a fat binary; read the rest of the file
+        length2 = readFile(gParts[partIndex].partIH, filePath, (void *)(kLoadAddr + length), length, 0);
+        if (length2 == -1) return -1;
+        length += length2;
+      }
+    }
+  } else {
+    loadFile = gParts[partIndex].loadFile;
+    length = loadFile(gParts[partIndex].partIH, filePath);
+    if (length > 0) {
+      ThinFatBinary(binary, &length);
+    }
+  }
+  
+  return length;
+}
+
+long GetFSUUID(char *spec, char *uuidStr)
+{
+  long       rval = -1, partIndex;
+  FSGetUUID  getUUID;
+  char       devSpec[256];
+  
+  do {
+    if(ConvertFileSpec(spec, devSpec, NULL))  break;
+    
+    // Get the partition index
+    partIndex = LookupPartition(devSpec);
+    if (partIndex == -1)  break;
+    
+    getUUID = gParts[partIndex].getUUID;
+    if(getUUID)
+      rval = getUUID(gParts[partIndex].partIH, uuidStr);
+  } while(0);
+
+  return rval;
+}
+
+
+// from our uuid/namespace.h (UFS and HFS uuids can live in the same space?)
+static char kFSUUIDNamespaceSHA1[] = {0xB3,0xE2,0x0F,0x39,0xF2,0x92,0x11,0xD6,0x97,0xA4,0x00,0x30,0x65,0x43,0xEC,0xAC};
+
+// filesystem-specific getUUID functions call this shared string generator
+long CreateUUIDString(uint8_t uubytes[], int nbytes, char *uuidStr)
+{
+  unsigned  fmtbase, fmtidx, i;
+  uint8_t   uuidfmt[] = { 4, 2, 2, 2, 6 };
+  char     *p = uuidStr;
+  MD5_CTX   md5c;
+  uint8_t   mdresult[16];
+
+  bzero(mdresult, sizeof(mdresult));
+
+  // just like AppleFileSystemDriver
+  MD5Init(&md5c);
+  MD5Update(&md5c, kFSUUIDNamespaceSHA1, sizeof(kFSUUIDNamespaceSHA1));
+  MD5Update(&md5c, uubytes, nbytes);
+  MD5Final(mdresult, &md5c);
+
+  // this UUID has been made version 3 style (i.e. via namespace) 
+  // see "-uuid-urn-" IETF draft (which otherwise copies byte for byte)
+  mdresult[6] = 0x30 | ( mdresult[6] & 0x0F );
+  mdresult[8] = 0x80 | ( mdresult[8] & 0x3F );
+
+
+  // generate the text: e.g. 5EB1869F-C4FA-3502-BDEB-3B8ED5D87292
+  i = 0; fmtbase = 0;
+  for(fmtidx = 0; fmtidx < sizeof(uuidfmt); fmtidx++) {
+    for(i=0; i < uuidfmt[fmtidx]; i++) {
+      uint8_t byte = mdresult[fmtbase+i];
+      char nib;
+
+      nib = byte >> 4;
+      *p = nib + '0';  // 0x4 -> '4'
+      if(*p > '9')  *p = (nib - 9 + ('A'-1));  // 0xB -> 'B'
+      p++;
+
+      nib = byte & 0xf;
+      *p = nib + '0';  // 0x4 -> '4'
+      if(*p > '9')  *p = (nib - 9 + ('A'-1));  // 0xB -> 'B'
+      p++;
+
+    }
+    fmtbase += i;
+    if(fmtidx < sizeof(uuidfmt)-1)
+      *(p++) = '-';
+    else
+      *p = '\0';
+  }
+
+  return 0;
+}
+
 long GetFileInfo(char *dirSpec, char *name, long *flags, long *time)
 {
   long ret, index = 0;
@@ -206,22 +332,31 @@ long LookupPartition(char *devSpec)
     switch (partType) {
     case kPartNet:
       gParts[partIndex].loadFile      = NetLoadFile;
+      gParts[partIndex].readFile      = NULL;
       gParts[partIndex].getDirEntry   = NetGetDirEntry;
+      gParts[partIndex].getUUID       = NULL;
       break;
       
     case kPartHFS:
       gParts[partIndex].loadFile      = HFSLoadFile;
+      gParts[partIndex].readFile      = HFSReadFile;
       gParts[partIndex].getDirEntry   = HFSGetDirEntry;
+      gParts[partIndex].getUUID       = HFSGetUUID;
       break;
       
     case kPartUFS:
       gParts[partIndex].loadFile      = UFSLoadFile;
+      gParts[partIndex].readFile      = UFSReadFile;
       gParts[partIndex].getDirEntry   = UFSGetDirEntry;
+      gParts[partIndex].getUUID       = UFSGetUUID;
       break;
       
     case kPartExt2:
       gParts[partIndex].loadFile      = Ext2LoadFile;
+      gParts[partIndex].readFile      = NULL;
       gParts[partIndex].getDirEntry   = Ext2GetDirEntry;
+      gParts[partIndex].getUUID       = NULL;
+      // Ext2GetUUID exists, but there's no kernel support
       break;
     }
   }