]> git.saurik.com Git - apple/bootx.git/blob - bootx.tproj/sl.subproj/macho.c
BootX-59.tar.gz
[apple/bootx.git] / bootx.tproj / sl.subproj / macho.c
1 /*
2 * Copyright (c) 2000 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 * macho.c - Functions for decoding a Mach-o Kernel.
27 *
28 * Copyright (c) 1998-2003 Apple Computer, Inc.
29 *
30 * DRI: Josh de Cesare
31 */
32
33 #include <mach-o/fat.h>
34 #include <mach-o/loader.h>
35 #include <mach/machine/thread_status.h>
36
37 #include <sl.h>
38
39 static long DecodeSegment(long cmdBase);
40 static long DecodeUnixThread(long cmdBase);
41 static long DecodeSymbolTable(long cmdBase);
42
43 static unsigned long gPPCAddress;
44
45 // Public Functions
46
47 long ThinFatBinaryMachO(void **binary, unsigned long *length)
48 {
49 unsigned long nfat, swapped, size;
50 struct fat_header *fhp = (struct fat_header *)*binary;
51 struct fat_arch *fap =
52 (struct fat_arch *)((unsigned long)*binary + sizeof(struct fat_header));
53
54 if (fhp->magic == FAT_MAGIC) {
55 nfat = fhp->nfat_arch;
56 swapped = 0;
57 } else if (fhp->magic == FAT_CIGAM) {
58 nfat = NXSwapInt(fhp->nfat_arch);
59 swapped = 1;
60 } else {
61 return -1;
62 }
63
64 for (; nfat > 0; nfat--, fap++) {
65 if (swapped) {
66 fap->cputype = NXSwapInt(fap->cputype);
67 fap->offset = NXSwapInt(fap->offset);
68 fap->size = NXSwapInt(fap->size);
69 }
70
71 if (fap->cputype == CPU_TYPE_POWERPC) {
72 *binary = (void *) ((unsigned long)*binary + fap->offset);
73 size = fap->size;
74 break;
75 }
76 }
77
78 if (length != 0) *length = size;
79
80 return 0;
81 }
82
83 long DecodeMachO(void *binary)
84 {
85 struct mach_header *mH;
86 long ncmds, cmdBase, cmd, cmdsize, headerBase, headerAddr, headerSize;
87 long cnt, ret;
88
89 gPPCAddress = (unsigned long)binary;
90
91 headerBase = gPPCAddress;
92 cmdBase = headerBase + sizeof(struct mach_header);
93
94 mH = (struct mach_header *)(headerBase);
95 if (mH->magic != MH_MAGIC) return -1;
96
97 #if 0
98 printf("magic: %x\n", mH->magic);
99 printf("cputype: %x\n", mH->cputype);
100 printf("cpusubtype: %x\n", mH->cpusubtype);
101 printf("filetype: %x\n", mH->filetype);
102 printf("ncmds: %x\n", mH->ncmds);
103 printf("sizeofcmds: %x\n", mH->sizeofcmds);
104 printf("flags: %x\n", mH->flags);
105 #endif
106
107 ncmds = mH->ncmds;
108
109 for (cnt = 0; cnt < ncmds; cnt++) {
110 cmd = ((long *)cmdBase)[0];
111 cmdsize = ((long *)cmdBase)[1];
112
113 switch (cmd) {
114
115 case LC_SEGMENT:
116 ret = DecodeSegment(cmdBase);
117 break;
118
119 case LC_UNIXTHREAD:
120 ret = DecodeUnixThread(cmdBase);
121 break;
122
123 case LC_SYMTAB:
124 ret = DecodeSymbolTable(cmdBase);
125 break;
126
127 default:
128 printf("Ignoring cmd type %d.\n", cmd);
129 break;
130 }
131
132 if (ret != 0) return -1;
133
134 cmdBase += cmdsize;
135 }
136
137 // Save the mach-o header.
138 headerSize = cmdBase - headerBase;
139 headerAddr = AllocateKernelMemory(headerSize);
140 bcopy((char *)headerBase, (char *)headerAddr, headerSize);
141
142 // Add the Mach-o header to the memory-map.
143 AllocateMemoryRange("Kernel-__HEADER", headerAddr, headerSize);
144
145 return ret;
146 }
147
148 // Private Functions
149
150 static long DecodeSegment(long cmdBase)
151 {
152 struct segment_command *segCmd;
153 char rangeName[32];
154 char *vmaddr, *fileaddr;
155 long vmsize, filesize;
156
157 segCmd = (struct segment_command *)cmdBase;
158
159 vmaddr = (char *)segCmd->vmaddr;
160 vmsize = segCmd->vmsize;
161
162 fileaddr = (char *)(gPPCAddress + segCmd->fileoff);
163 filesize = segCmd->filesize;
164
165 #if 0
166 printf("segname: %s, vmaddr: %x, vmsize: %x, fileoff: %x, filesize: %x, nsects: %d, flags: %x.\n",
167 segCmd->segname, vmaddr, vmsize, fileaddr, filesize,
168 segCmd->nsects, segCmd->flags);
169 #endif
170
171 // Add the Segment to the memory-map.
172 sprintf(rangeName, "Kernel-%s", segCmd->segname);
173 AllocateMemoryRange(rangeName, (long)vmaddr, vmsize);
174
175 if (vmsize && (strcmp(segCmd->segname, "__PRELINK") == 0))
176 gHaveKernelCache = 1;
177
178 // Handle special segments first.
179
180 // If it is the vectors, save them in their special place.
181 if ((strcmp(segCmd->segname, "__VECTORS") == 0) &&
182 ((long)vmaddr < (kVectorAddr + kVectorSize)) &&
183 (vmsize != 0) && (filesize != 0)) {
184
185 // Copy the first part into the save area.
186 bcopy(fileaddr, gVectorSaveAddr,
187 (filesize <= kVectorSize) ? filesize : kVectorSize);
188
189 // Copy the rest into memory.
190 if (filesize > kVectorSize)
191 bcopy(fileaddr + kVectorSize, (char *)kVectorSize,
192 filesize - kVectorSize);
193
194 return 0;
195 }
196
197 // It is nothing special, so do the usual. Only copy sections
198 // that have a filesize. Others are handle by the original bzero.
199 if (filesize != 0) {
200 bcopy(fileaddr, vmaddr, filesize);
201 }
202
203 // Adjust the last address used by the kernel
204 if ((long)vmaddr + vmsize > AllocateKernelMemory(0)) {
205 AllocateKernelMemory((long)vmaddr + vmsize - AllocateKernelMemory(0));
206 }
207
208 return 0;
209 }
210
211
212 static long DecodeUnixThread(long cmdBase)
213 {
214 struct ppc_thread_state *ppcThreadState;
215
216 // The PPC Thread State starts after the thread command stuct plus,
217 // 2 longs for the flaver an num longs.
218 ppcThreadState = (struct ppc_thread_state *)
219 (cmdBase + sizeof(struct thread_command) + 8);
220
221 gKernelEntryPoint = ppcThreadState->srr0;
222
223 #if 0
224 printf("gKernelEntryPoint = %x\n", gKernelEntryPoint);
225 #endif
226
227 return 0;
228 }
229
230
231 static long DecodeSymbolTable(long cmdBase)
232 {
233 struct symtab_command *symTab, *symTableSave;
234 long tmpAddr, symsSize, totalSize;
235
236 symTab = (struct symtab_command *)cmdBase;
237
238 #if 0
239 printf("symoff: %x, nsyms: %x, stroff: %x, strsize: %x\n",
240 symTab->symoff, symTab->nsyms, symTab->stroff, symTab->strsize);
241 #endif
242
243 symsSize = symTab->stroff - symTab->symoff;
244 totalSize = symsSize + symTab->strsize;
245
246 gSymbolTableSize = totalSize + sizeof(struct symtab_command);
247 gSymbolTableAddr = AllocateKernelMemory(gSymbolTableSize);
248
249 // Add the SymTab to the memory-map.
250 AllocateMemoryRange("Kernel-__SYMTAB", gSymbolTableAddr, gSymbolTableSize);
251
252 symTableSave = (struct symtab_command *)gSymbolTableAddr;
253 tmpAddr = gSymbolTableAddr + sizeof(struct symtab_command);
254
255 symTableSave->symoff = tmpAddr;
256 symTableSave->nsyms = symTab->nsyms;
257 symTableSave->stroff = tmpAddr + symsSize;
258 symTableSave->strsize = symTab->strsize;
259
260 bcopy((char *)(gPPCAddress + symTab->symoff),
261 (char *)tmpAddr, totalSize);
262
263 return 0;
264 }