]> git.saurik.com Git - apple/bootx.git/blobdiff - bootx.tproj/sl.subproj/macho.c
BootX-81.tar.gz
[apple/bootx.git] / bootx.tproj / sl.subproj / macho.c
index b2ef134687f1a2aa6c6cb7957e04368836c2e24b..333cbe135638f2018b8621438a47e3a4a8678b46 100644 (file)
 /*
  *  macho.c - Functions for decoding a Mach-o Kernel.
  *
- *  Copyright (c) 1998-2000 Apple Computer, Inc.
+ *  Copyright (c) 1998-2003 Apple Computer, Inc.
  *
  *  DRI: Josh de Cesare
  */
 
+#define __srr0 srr0                    // so we can build in both (conformant/not) worlds
 #include <mach-o/fat.h>
 #include <mach-o/loader.h>
 #include <mach/machine/thread_status.h>
@@ -37,33 +38,56 @@ static long DecodeSegment(long cmdBase);
 static long DecodeUnixThread(long cmdBase);
 static long DecodeSymbolTable(long cmdBase);
 
-static long gPPCOffset;
+static unsigned long gPPCAddress;
 
 // Public Functions
 
-long DecodeMachO(void)
+long ThinFatBinaryMachO(void **binary, unsigned long *length)
 {
-  struct fat_header  *fH;
-  struct fat_arch    *fA;
-  struct mach_header *mH;
-  long   ncmds, cmdBase, cmd, cmdsize, headerBase, headerAddr, headerSize;
-  long   cnt, ret;
-  
-  // Test for a fat header.
-  fH = (struct fat_header *)kLoadAddr;
-  if (fH->magic == FAT_MAGIC) {
-    fA = (struct fat_arch *)(kLoadAddr + sizeof(struct fat_header));
-    // see if the there is one for PPC.
-    for (cnt = 0; cnt < fH->nfat_arch; cnt++) {
-      if (fA[cnt].cputype == CPU_TYPE_POWERPC) {
-       gPPCOffset = fA[cnt].offset;
-      }
+  unsigned long nfat, swapped, size = 0;
+  struct fat_header *fhp = (struct fat_header *)*binary;
+  struct fat_arch   *fap =
+    (struct fat_arch *)((unsigned long)*binary + sizeof(struct fat_header));
+  
+  if (fhp->magic == FAT_MAGIC) {
+    nfat = fhp->nfat_arch;
+    swapped = 0;
+  } else if (fhp->magic == FAT_CIGAM) {
+    nfat = NXSwapInt(fhp->nfat_arch);
+    swapped = 1;
+  } else {
+    return -1;
+  }
+  
+  for (; nfat > 0; nfat--, fap++) {
+    if (swapped) {
+      fap->cputype = NXSwapInt(fap->cputype);
+      fap->offset = NXSwapInt(fap->offset);
+      fap->size = NXSwapInt(fap->size);
+    }
+    
+    if (fap->cputype == CPU_TYPE_POWERPC) {
+      *binary = (void *) ((unsigned long)*binary + fap->offset);
+      size = fap->size;
+      break;
     }
   }
   
-  // offset will be the start of the 
-  headerBase = kLoadAddr + gPPCOffset;
-  cmdBase = headerBase+ sizeof(struct mach_header);
+  if (length != 0) *length = size;
+  
+  return 0;
+}
+
+long DecodeMachO(void *binary)
+{
+  struct mach_header *mH;
+  long   ncmds, cmdBase, cmd, cmdsize, headerBase, headerAddr, headerSize;
+  long   cnt, ret = 0;
+  
+  gPPCAddress = (unsigned long)binary;
+  
+  headerBase = gPPCAddress;
+  cmdBase = headerBase + sizeof(struct mach_header);
   
   mH = (struct mach_header *)(headerBase);
   if (mH->magic != MH_MAGIC) return -1;
@@ -133,7 +157,7 @@ static long DecodeSegment(long cmdBase)
   vmaddr = (char *)segCmd->vmaddr;
   vmsize = segCmd->vmsize;
   
-  fileaddr = (char *)(kLoadAddr + gPPCOffset + segCmd->fileoff);
+  fileaddr = (char *)(gPPCAddress + segCmd->fileoff);
   filesize = segCmd->filesize;
   
 #if 0
@@ -145,6 +169,9 @@ static long DecodeSegment(long cmdBase)
   // Add the Segment to the memory-map.
   sprintf(rangeName, "Kernel-%s", segCmd->segname);
   AllocateMemoryRange(rangeName, (long)vmaddr, vmsize);
+
+  if (vmsize && (strcmp(segCmd->segname, "__PRELINK") == 0))
+    gHaveKernelCache = 1;
   
   // Handle special segments first.
   
@@ -182,11 +209,11 @@ static long DecodeSegment(long cmdBase)
 
 static long DecodeUnixThread(long cmdBase)
 {
-  struct ppc_thread_state *ppcThreadState;
+  ppc_thread_state_t *ppcThreadState;
   
   // The PPC Thread State starts after the thread command stuct plus,
   // 2 longs for the flaver an num longs.
-  ppcThreadState = (struct ppc_thread_state *)
+  ppcThreadState = (ppc_thread_state_t *)
     (cmdBase + sizeof(struct thread_command) + 8);
   
   gKernelEntryPoint = ppcThreadState->srr0;
@@ -228,7 +255,7 @@ static long DecodeSymbolTable(long cmdBase)
   symTableSave->stroff = tmpAddr + symsSize;
   symTableSave->strsize = symTab->strsize;
   
-  bcopy((char *)(kLoadAddr + gPPCOffset + symTab->symoff),
+  bcopy((char *)(gPPCAddress + symTab->symoff),
        (char *)tmpAddr, totalSize);
   
   return 0;