]>
git.saurik.com Git - apple/bootx.git/blob - bootx.tproj/sl.subproj/macho.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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.
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
20 * @APPLE_LICENSE_HEADER_END@
23 * macho.c - Functions for decoding a Mach-o Kernel.
25 * Copyright (c) 1998-2000 Apple Computer, Inc.
30 #include <mach-o/fat.h>
31 #include <mach-o/loader.h>
32 #include <mach/machine/thread_status.h>
36 static long DecodeSegment(long cmdBase
);
37 static long DecodeUnixThread(long cmdBase
);
38 static long DecodeSymbolTable(long cmdBase
);
40 static long gPPCOffset
;
44 long DecodeMachO(void)
46 struct fat_header
*fH
;
48 struct mach_header
*mH
;
49 long ncmds
, cmdBase
, cmd
, cmdsize
, headerBase
, headerAddr
, headerSize
;
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
;
64 // offset will be the start of the
65 headerBase
= kLoadAddr
+ gPPCOffset
;
66 cmdBase
= headerBase
+ sizeof(struct mach_header
);
68 mH
= (struct mach_header
*)(headerBase
);
69 if (mH
->magic
!= MH_MAGIC
) return -1;
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
);
83 for (cnt
= 0; cnt
< ncmds
; cnt
++) {
84 cmd
= ((long *)cmdBase
)[0];
85 cmdsize
= ((long *)cmdBase
)[1];
90 ret
= DecodeSegment(cmdBase
);
94 ret
= DecodeUnixThread(cmdBase
);
98 ret
= DecodeSymbolTable(cmdBase
);
102 printf("Ignoring cmd type %d.\n", cmd
);
106 if (ret
!= 0) return -1;
111 // Save the mach-o header.
112 headerSize
= cmdBase
- headerBase
;
113 headerAddr
= AllocateKernelMemory(headerSize
);
114 bcopy((char *)headerBase
, (char *)headerAddr
, headerSize
);
116 // Add the Mach-o header to the memory-map.
117 AllocateMemoryRange("Kernel-__HEADER", headerAddr
, headerSize
);
124 static long DecodeSegment(long cmdBase
)
126 struct segment_command
*segCmd
;
128 char *vmaddr
, *fileaddr
;
129 long vmsize
, filesize
;
131 segCmd
= (struct segment_command
*)cmdBase
;
133 vmaddr
= (char *)segCmd
->vmaddr
;
134 vmsize
= segCmd
->vmsize
;
136 fileaddr
= (char *)(kLoadAddr
+ gPPCOffset
+ segCmd
->fileoff
);
137 filesize
= segCmd
->filesize
;
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
);
145 // Add the Segment to the memory-map.
146 sprintf(rangeName
, "Kernel-%s", segCmd
->segname
);
147 AllocateMemoryRange(rangeName
, (long)vmaddr
, vmsize
);
149 // Handle special segments first.
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)) {
156 // Copy the first part into the save area.
157 bcopy(fileaddr
, gVectorSaveAddr
,
158 (filesize
<= kVectorSize
) ? filesize
: kVectorSize
);
160 // Copy the rest into memory.
161 if (filesize
> kVectorSize
)
162 bcopy(fileaddr
+ kVectorSize
, (char *)kVectorSize
,
163 filesize
- kVectorSize
);
168 // It is nothing special, so do the usual. Only copy sections
169 // that have a filesize. Others are handle by the original bzero.
171 bcopy(fileaddr
, vmaddr
, filesize
);
174 // Adjust the last address used by the kernel
175 if ((long)vmaddr
+ vmsize
> AllocateKernelMemory(0)) {
176 AllocateKernelMemory((long)vmaddr
+ vmsize
- AllocateKernelMemory(0));
183 static long DecodeUnixThread(long cmdBase
)
185 struct ppc_thread_state
*ppcThreadState
;
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);
192 gKernelEntryPoint
= ppcThreadState
->srr0
;
195 printf("gKernelEntryPoint = %x\n", gKernelEntryPoint
);
202 static long DecodeSymbolTable(long cmdBase
)
204 struct symtab_command
*symTab
, *symTableSave
;
205 long tmpAddr
, symsSize
, totalSize
;
207 symTab
= (struct symtab_command
*)cmdBase
;
210 printf("symoff: %x, nsyms: %x, stroff: %x, strsize: %x\n",
211 symTab
->symoff
, symTab
->nsyms
, symTab
->stroff
, symTab
->strsize
);
214 symsSize
= symTab
->stroff
- symTab
->symoff
;
215 totalSize
= symsSize
+ symTab
->strsize
;
217 gSymbolTableSize
= totalSize
+ sizeof(struct symtab_command
);
218 gSymbolTableAddr
= AllocateKernelMemory(gSymbolTableSize
);
220 // Add the SymTab to the memory-map.
221 AllocateMemoryRange("Kernel-__SYMTAB", gSymbolTableAddr
, gSymbolTableSize
);
223 symTableSave
= (struct symtab_command
*)gSymbolTableAddr
;
224 tmpAddr
= gSymbolTableAddr
+ sizeof(struct symtab_command
);
226 symTableSave
->symoff
= tmpAddr
;
227 symTableSave
->nsyms
= symTab
->nsyms
;
228 symTableSave
->stroff
= tmpAddr
+ symsSize
;
229 symTableSave
->strsize
= symTab
->strsize
;
231 bcopy((char *)(kLoadAddr
+ gPPCOffset
+ symTab
->symoff
),
232 (char *)tmpAddr
, totalSize
);