]> git.saurik.com Git - apple/boot.git/blame - i386/libsaio/load.c
boot-111.tar.gz
[apple/boot.git] / i386 / libsaio / load.c
CommitLineData
14c7c974 1/*
f083c6c3 2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
14c7c974
A
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
f083c6c3
A
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.
14c7c974
A
14 *
15 * The Original Code and all software distributed under the License are
f083c6c3 16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14c7c974
A
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
f083c6c3
A
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.
14c7c974
A
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25/*
f083c6c3
A
26 * load.c - Functions for decoding a Mach-o Kernel.
27 *
28 * Copyright (c) 1998-2003 Apple Computer, Inc.
29 *
14c7c974
A
30 */
31
14c7c974 32#include <mach-o/fat.h>
f083c6c3
A
33#include <mach-o/loader.h>
34#include <mach/machine/thread_status.h>
14c7c974 35
f083c6c3 36#include <sl.h>
75b89a82 37
f083c6c3
A
38static long DecodeSegment(long cmdBase, unsigned int*load_addr, unsigned int *load_size);
39static long DecodeUnixThread(long cmdBase, unsigned int *entry);
14c7c974 40
14c7c974 41
f083c6c3
A
42static unsigned long gBinaryAddress;
43BOOL gHaveKernelCache;
75b89a82 44
f083c6c3 45// Public Functions
14c7c974 46
f083c6c3 47long ThinFatFile(void **binary, unsigned long *length)
14c7c974 48{
f083c6c3
A
49 unsigned long nfat, swapped, size = 0;
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);
14c7c974 69 }
75b89a82 70
f083c6c3
A
71 if (fap->cputype == CPU_TYPE_I386) {
72 *binary = (void *) ((unsigned long)*binary + fap->offset);
73 size = fap->size;
74 break;
14c7c974 75 }
f083c6c3
A
76 }
77
78 if (length != 0) *length = size;
79
80 return 0;
14c7c974
A
81}
82
f083c6c3 83long DecodeMachO(void *binary, entry_t *rentry, char **raddr, int *rsize)
14c7c974 84{
f083c6c3
A
85 struct mach_header *mH;
86 unsigned long ncmds, cmdBase, cmd, cmdsize;
87 // long headerBase, headerAddr, headerSize;
88 unsigned int vmaddr = ~0;
89 unsigned int vmend = 0;
90 unsigned long cnt;
91 long ret = -1;
92 unsigned int entry;
93
94 gBinaryAddress = (unsigned long)binary;
95
96 // headerBase = gBinaryAddress;
97 cmdBase = (unsigned long)gBinaryAddress + sizeof(struct mach_header);
98
99 mH = (struct mach_header *)(gBinaryAddress);
100 if (mH->magic != MH_MAGIC) {
101 error("Mach-O file has bad magic number\n");
102 return -1;
103 }
104
105#if NOTDEF
106 printf("magic: %x\n", (unsigned)mH->magic);
107 printf("cputype: %x\n", (unsigned)mH->cputype);
108 printf("cpusubtype: %x\n", (unsigned)mH->cpusubtype);
109 printf("filetype: %x\n", (unsigned)mH->filetype);
110 printf("ncmds: %x\n", (unsigned)mH->ncmds);
111 printf("sizeofcmds: %x\n", (unsigned)mH->sizeofcmds);
112 printf("flags: %x\n", (unsigned)mH->flags);
113 getc();
14c7c974 114#endif
f083c6c3
A
115
116 ncmds = mH->ncmds;
117
118 for (cnt = 0; cnt < ncmds; cnt++) {
119 cmd = ((long *)cmdBase)[0];
120 cmdsize = ((long *)cmdBase)[1];
121 unsigned int load_addr;
122 unsigned int load_size;
123
124 switch (cmd) {
125
126 case LC_SEGMENT:
127 ret = DecodeSegment(cmdBase, &load_addr, &load_size);
128 if (ret == 0 && load_size != 0) {
129 vmaddr = min(vmaddr, load_addr);
130 vmend = max(vmend, load_addr + load_size);
131 }
132 break;
133
134 case LC_UNIXTHREAD:
135 ret = DecodeUnixThread(cmdBase, &entry);
136 break;
137
138 default:
139#if NOTDEF
140 printf("Ignoring cmd type %d.\n", (unsigned)cmd);
14c7c974 141#endif
f083c6c3 142 break;
75b89a82 143 }
f083c6c3
A
144
145 if (ret != 0) return -1;
146
147 cmdBase += cmdsize;
148 }
149
150 *rentry = (entry_t)( (unsigned long) entry & 0x3fffffff );
151 *rsize = vmend - vmaddr;
152 *raddr = (char *)vmaddr;
153
154 return ret;
14c7c974
A
155}
156
f083c6c3 157// Private Functions
14c7c974 158
f083c6c3 159static long DecodeSegment(long cmdBase, unsigned int *load_addr, unsigned int *load_size)
14c7c974 160{
f083c6c3
A
161 struct segment_command *segCmd;
162 unsigned long vmaddr, fileaddr;
163 long vmsize, filesize;
75b89a82 164
f083c6c3
A
165 segCmd = (struct segment_command *)cmdBase;
166
167 vmaddr = (segCmd->vmaddr & 0x3fffffff);
168 vmsize = segCmd->vmsize;
169
170 fileaddr = (gBinaryAddress + segCmd->fileoff);
171 filesize = segCmd->filesize;
172
173 if (filesize == 0) {
174 *load_addr = ~0;
175 *load_size = 0;
176 return 0;
177 }
178
179#if NOTDEF
180 printf("segname: %s, vmaddr: %x, vmsize: %x, fileoff: %x, filesize: %x, nsects: %d, flags: %x.\n",
181 segCmd->segname, (unsigned)vmaddr, (unsigned)vmsize, (unsigned)fileaddr, (unsigned)filesize,
182 (unsigned) segCmd->nsects, (unsigned)segCmd->flags);
183 getc();
14c7c974 184#endif
f083c6c3
A
185
186 if (vmaddr < KERNEL_ADDR ||
187 (vmaddr + vmsize) > (KERNEL_ADDR + KERNEL_LEN)) {
188 stop("Kernel overflows available space");
189 }
190
191 if (vmsize && (strcmp(segCmd->segname, "__PRELINK") == 0)) {
192 gHaveKernelCache = 1;
193 }
194
195 // Copy from file load area.
196 bcopy((char *)fileaddr, (char *)vmaddr, filesize);
197
198 // Zero space at the end of the segment.
199 bzero((char *)(vmaddr + filesize), vmsize - filesize);
14c7c974 200
f083c6c3
A
201 *load_addr = vmaddr;
202 *load_size = vmsize;
47b0a8bd 203
f083c6c3
A
204 return 0;
205}
14c7c974 206
14c7c974 207
f083c6c3
A
208static long DecodeUnixThread(long cmdBase, unsigned int *entry)
209{
210 i386_thread_state_t *i386ThreadState;
211
212 i386ThreadState = (i386_thread_state_t *)
213 (cmdBase + sizeof(struct thread_command) + 8);
214
215 *entry = i386ThreadState->eip;
216
217 return 0;
14c7c974 218}
f083c6c3 219