]> git.saurik.com Git - apple/bootx.git/blame_incremental - bootx.tproj/sl.subproj/macho.c
BootX-36.tar.gz
[apple/bootx.git] / bootx.tproj / sl.subproj / macho.c
... / ...
CommitLineData
1/*
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*
23 * macho.c - Functions for decoding a Mach-o Kernel.
24 *
25 * Copyright (c) 1998-2000 Apple Computer, Inc.
26 *
27 * DRI: Josh de Cesare
28 */
29
30#include <mach-o/fat.h>
31#include <mach-o/loader.h>
32#include <mach/machine/thread_status.h>
33
34#include <sl.h>
35
36static long DecodeSegment(long cmdBase);
37static long DecodeUnixThread(long cmdBase);
38static long DecodeSymbolTable(long cmdBase);
39
40static long gPPCOffset;
41
42// Public Functions
43
44long DecodeMachO(void)
45{
46 struct fat_header *fH;
47 struct fat_arch *fA;
48 struct mach_header *mH;
49 long ncmds, cmdBase, cmd, cmdsize, headerBase, headerAddr, headerSize;
50 long cnt, ret;
51
52 // Test for a fat header.
53 fH = (struct fat_header *)kLoadAddr;
54 if (fH->magic == FAT_MAGIC) {
55 fA = (struct fat_arch *)(kLoadAddr + sizeof(struct fat_header));
56 // see if the there is one for PPC.
57 for (cnt = 0; cnt < fH->nfat_arch; cnt++) {
58 if (fA[cnt].cputype == CPU_TYPE_POWERPC) {
59 gPPCOffset = fA[cnt].offset;
60 }
61 }
62 }
63
64 // offset will be the start of the
65 headerBase = kLoadAddr + gPPCOffset;
66 cmdBase = headerBase+ sizeof(struct mach_header);
67
68 mH = (struct mach_header *)(headerBase);
69 if (mH->magic != MH_MAGIC) return -1;
70
71#if 0
72 printf("magic: %x\n", mH->magic);
73 printf("cputype: %x\n", mH->cputype);
74 printf("cpusubtype: %x\n", mH->cpusubtype);
75 printf("filetype: %x\n", mH->filetype);
76 printf("ncmds: %x\n", mH->ncmds);
77 printf("sizeofcmds: %x\n", mH->sizeofcmds);
78 printf("flags: %x\n", mH->flags);
79#endif
80
81 ncmds = mH->ncmds;
82
83 for (cnt = 0; cnt < ncmds; cnt++) {
84 cmd = ((long *)cmdBase)[0];
85 cmdsize = ((long *)cmdBase)[1];
86
87 switch (cmd) {
88
89 case LC_SEGMENT:
90 ret = DecodeSegment(cmdBase);
91 break;
92
93 case LC_UNIXTHREAD:
94 ret = DecodeUnixThread(cmdBase);
95 break;
96
97 case LC_SYMTAB:
98 ret = DecodeSymbolTable(cmdBase);
99 break;
100
101 default:
102 printf("Ignoring cmd type %d.\n", cmd);
103 break;
104 }
105
106 if (ret != 0) return -1;
107
108 cmdBase += cmdsize;
109 }
110
111 // Save the mach-o header.
112 headerSize = cmdBase - headerBase;
113 headerAddr = AllocateKernelMemory(headerSize);
114 bcopy((char *)headerBase, (char *)headerAddr, headerSize);
115
116 // Add the Mach-o header to the memory-map.
117 AllocateMemoryRange("Kernel-__HEADER", headerAddr, headerSize);
118
119 return ret;
120}
121
122// Private Functions
123
124static long DecodeSegment(long cmdBase)
125{
126 struct segment_command *segCmd;
127 char rangeName[32];
128 char *vmaddr, *fileaddr;
129 long vmsize, filesize;
130
131 segCmd = (struct segment_command *)cmdBase;
132
133 vmaddr = (char *)segCmd->vmaddr;
134 vmsize = segCmd->vmsize;
135
136 fileaddr = (char *)(kLoadAddr + gPPCOffset + segCmd->fileoff);
137 filesize = segCmd->filesize;
138
139#if 0
140 printf("segname: %s, vmaddr: %x, vmsize: %x, fileoff: %x, filesize: %x, nsects: %d, flags: %x.\n",
141 segCmd->segname, vmaddr, vmsize, fileaddr, filesize,
142 segCmd->nsects, segCmd->flags);
143#endif
144
145 // Add the Segment to the memory-map.
146 sprintf(rangeName, "Kernel-%s", segCmd->segname);
147 AllocateMemoryRange(rangeName, (long)vmaddr, vmsize);
148
149 // Handle special segments first.
150
151 // If it is the vectors, save them in their special place.
152 if ((strcmp(segCmd->segname, "__VECTORS") == 0) &&
153 ((long)vmaddr < (kVectorAddr + kVectorSize)) &&
154 (vmsize != 0) && (filesize != 0)) {
155
156 // Copy the first part into the save area.
157 bcopy(fileaddr, gVectorSaveAddr,
158 (filesize <= kVectorSize) ? filesize : kVectorSize);
159
160 // Copy the rest into memory.
161 if (filesize > kVectorSize)
162 bcopy(fileaddr + kVectorSize, (char *)kVectorSize,
163 filesize - kVectorSize);
164
165 return 0;
166 }
167
168 // It is nothing special, so do the usual. Only copy sections
169 // that have a filesize. Others are handle by the original bzero.
170 if (filesize != 0) {
171 bcopy(fileaddr, vmaddr, filesize);
172 }
173
174 // Adjust the last address used by the kernel
175 if ((long)vmaddr + vmsize > AllocateKernelMemory(0)) {
176 AllocateKernelMemory((long)vmaddr + vmsize - AllocateKernelMemory(0));
177 }
178
179 return 0;
180}
181
182
183static long DecodeUnixThread(long cmdBase)
184{
185 struct ppc_thread_state *ppcThreadState;
186
187 // The PPC Thread State starts after the thread command stuct plus,
188 // 2 longs for the flaver an num longs.
189 ppcThreadState = (struct ppc_thread_state *)
190 (cmdBase + sizeof(struct thread_command) + 8);
191
192 gKernelEntryPoint = ppcThreadState->srr0;
193
194#if 0
195 printf("gKernelEntryPoint = %x\n", gKernelEntryPoint);
196#endif
197
198 return 0;
199}
200
201
202static long DecodeSymbolTable(long cmdBase)
203{
204 struct symtab_command *symTab, *symTableSave;
205 long tmpAddr, symsSize, totalSize;
206
207 symTab = (struct symtab_command *)cmdBase;
208
209#if 0
210 printf("symoff: %x, nsyms: %x, stroff: %x, strsize: %x\n",
211 symTab->symoff, symTab->nsyms, symTab->stroff, symTab->strsize);
212#endif
213
214 symsSize = symTab->stroff - symTab->symoff;
215 totalSize = symsSize + symTab->strsize;
216
217 gSymbolTableSize = totalSize + sizeof(struct symtab_command);
218 gSymbolTableAddr = AllocateKernelMemory(gSymbolTableSize);
219
220 // Add the SymTab to the memory-map.
221 AllocateMemoryRange("Kernel-__SYMTAB", gSymbolTableAddr, gSymbolTableSize);
222
223 symTableSave = (struct symtab_command *)gSymbolTableAddr;
224 tmpAddr = gSymbolTableAddr + sizeof(struct symtab_command);
225
226 symTableSave->symoff = tmpAddr;
227 symTableSave->nsyms = symTab->nsyms;
228 symTableSave->stroff = tmpAddr + symsSize;
229 symTableSave->strsize = symTab->strsize;
230
231 bcopy((char *)(kLoadAddr + gPPCOffset + symTab->symoff),
232 (char *)tmpAddr, totalSize);
233
234 return 0;
235}