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