]> git.saurik.com Git - apple/bootx.git/blob - bootx.tproj/sl.subproj/PEFSupport.c
BootX-34.tar.gz
[apple/bootx.git] / bootx.tproj / sl.subproj / PEFSupport.c
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 File: UnpackPiData.c
24 Written by: Jeffrey Robbin
25 Copyright: © 1994, 1996 by Apple Computer, Inc., all rights reserved.
26
27 Change History (most recent first):
28 <3> 9/20/96 MRN Changed "" to <> on including Types.h, Errors.h and Memory.h
29 that was breaking MW.
30 <2> 9/20/94 TS Dump the globals!
31 <1> 9/6/94 TS first checked in
32
33
34 File: GetSymbolFromPEF.c
35 Written by: Jeffrey Robbin
36 Copyright: © 1994, 1996 by Apple Computer, Inc., all rights reserved.
37
38 Change History (most recent first):
39
40 <6> 9/20/96 MRN Changed <> to "" on including GetSymbolFromPEF.h that was
41 breaking MW.
42 <5> 3/7/96 MRN Minor adjustments to build with the latest version of
43 SuperMarioLatestBuild name revision of MasterInterfaces.
44 <4> 10/13/94 JF Changed CFM error enums-- from 'cfragXXXErr' to 'fragXXX'
45 <3> 10/11/94 TS Move to new CFM error codes
46 <2> 9/16/94 TS Switch to pascal strings in SymbolCompare function
47 <1> 9/6/94 TS first checked in
48
49 */
50
51 typedef unsigned char Boolean;
52 typedef unsigned char *Ptr;
53 typedef char *StringPtr;
54
55 typedef long OSErr;
56
57 typedef unsigned long OSStatus;
58 typedef unsigned long ByteCount;
59 typedef unsigned long LogicalAddress;
60
61 #define nil (void *)0
62 #define false (0)
63 #define true (1)
64 #define noErr (0)
65
66 #include "GetSymbolFromPEF.h"
67 //#include <Types.h>
68 //#include <Errors.h>
69 //#include <Memory.h>
70
71
72 unsigned char PEFGetNextByte (unsigned char** rawBuffer, long* rawBufferRemaining)
73 {
74 *rawBufferRemaining = *rawBufferRemaining - 1;
75 return *(*rawBuffer)++;
76 }
77
78
79 unsigned long PEFGetCount(unsigned char** rawBuffer, long* rawBufferRemaining)
80 {
81 register unsigned char b;
82 register unsigned long value = 0UL;
83
84 /* Scan the count value. All required bytes MUST be present... */
85
86 b = PEFGetNextByte(rawBuffer, rawBufferRemaining);
87 if (!IS_LAST_PICNT_BYTE(b)) { /* if 1st byte is not that last... */
88 value = CONCAT_PICNT(value, b); /* ...init value using 1st byte */
89
90 b = PEFGetNextByte(rawBuffer, rawBufferRemaining);
91 if (!IS_LAST_PICNT_BYTE(b)) { /* if 2nd byte is not the last... */
92 value = CONCAT_PICNT(value, b); /* ...add in 2nd byte */
93
94 b = PEFGetNextByte(rawBuffer, rawBufferRemaining);
95 if (!IS_LAST_PICNT_BYTE(b)) { /* if 3rd byte is not the last... */
96 value = CONCAT_PICNT(value, b); /* ...add in 3rd byte */
97
98 b = PEFGetNextByte(rawBuffer, rawBufferRemaining);
99 if (!IS_LAST_PICNT_BYTE(b)) { /* if 4th byte is not the last... */
100 value = CONCAT_PICNT(value, b); /* ...add in 4th byte */
101
102 /* 5th byte is definitly last! */
103 b = PEFGetNextByte(rawBuffer, rawBufferRemaining);
104 }
105 }
106 }
107 }
108
109 value = CONCAT_PICNT(value, b); /* add in "last" byte (whichever one) */
110
111 return (value);
112 }
113
114
115 void MemSet (unsigned char* theBuffer, long theValue, long theCount)
116 {
117 while (theCount-- > 0)
118 *theBuffer++ = theValue;
119 }
120
121
122 // UnpackPiData expands a compressed section into memory.
123
124 OSErr UnpackPiData (LogicalAddress thePEFPtr,
125 SectionHeaderPtr sectionHeaderPtr,
126 LogicalAddress* theData)
127 {
128 long cntX, cnt, rpt, dcnt, delta;
129 unsigned char op, b;
130 unsigned char* unpackBuffer;
131 unsigned char* originalUnpackBuffer;
132 unsigned char* endUnpackBuffer;
133 unsigned char* oldRawBuffer;
134 long oldRawBufferRemaining;
135 unsigned char* rawBuffer;
136 long rawBufferRemaining;
137
138 // Verify incoming section is packed.
139 if (sectionHeaderPtr->regionKind != kPIDataSection)
140 return (paramErr);
141
142
143 // Allocate memory to unpack into
144 originalUnpackBuffer = (unsigned char*)NewPtrSys(sectionHeaderPtr->initSize);
145 if (originalUnpackBuffer == nil)
146 return memFullErr;
147
148 unpackBuffer = originalUnpackBuffer;
149 endUnpackBuffer = unpackBuffer + sectionHeaderPtr->initSize;
150 rawBuffer = (unsigned char*)((unsigned long)thePEFPtr + sectionHeaderPtr->containerOffset);
151 rawBufferRemaining = sectionHeaderPtr->rawSize;
152
153
154 /* Expand the pidata instructions. EOF will terminate processing through the setjmp */
155 /* on pidData_jmpbuf above... */
156
157 while (rawBufferRemaining > 0) {
158
159 /* The first byte of each instruction contains the opcode and a count. If the count */
160 /* is 0, the count starts in the next byte... */
161
162 /* Pick up the opcode and first count operand... */
163
164 b = PEFGetNextByte(&rawBuffer, &rawBufferRemaining);
165
166 op = PIOP(b);
167 cnt = PICNT(b);
168
169 if (cnt == 0)
170 cnt = PEFGetCount(&rawBuffer, &rawBufferRemaining);
171
172 /* Unpack the data as a function of the opcode... */
173
174 switch (op) {
175 case kZero: /* zero out cnt bytes...*/
176 if (unpackBuffer + cnt > endUnpackBuffer)
177 goto Error;
178 MemSet(unpackBuffer, 0, cnt);
179 unpackBuffer += cnt;
180 break;
181
182 case kBlock: /* copy cnt bytes...*/
183 if (unpackBuffer + cnt > endUnpackBuffer)
184 goto Error;
185 while (--cnt >= 0)
186 *unpackBuffer++ = PEFGetNextByte(&rawBuffer, &rawBufferRemaining);
187 break;
188
189 case kRepeat: /* copy cnt bytes rpt times...*/
190 rpt = PEFGetCount(&rawBuffer, &rawBufferRemaining) + 1;
191
192 if (cnt == 1)
193 {
194 if (unpackBuffer + rpt > endUnpackBuffer)
195 goto Error;
196 b = PEFGetNextByte(&rawBuffer, &rawBufferRemaining);
197 MemSet(unpackBuffer, b, rpt);
198 unpackBuffer += rpt;
199 }
200 else
201 {
202 oldRawBufferRemaining = rawBufferRemaining;
203 oldRawBuffer = rawBuffer;
204 while (--rpt >= 0) {
205 if (unpackBuffer + cnt > endUnpackBuffer)
206 goto Error;
207 rawBufferRemaining = oldRawBufferRemaining;
208 rawBuffer = oldRawBuffer;
209 cntX = cnt;
210 while (--cntX >= 0)
211 *unpackBuffer++ = PEFGetNextByte(&rawBuffer, &rawBufferRemaining);
212 }
213 }
214 break;
215
216 case kRepeatZero: /* copy cnt 0's and dcnt bytes rpt times*/
217 dcnt = PEFGetCount(&rawBuffer, &rawBufferRemaining); /* ...then copy cnt more 0's */
218 rpt = PEFGetCount(&rawBuffer, &rawBufferRemaining);
219
220 goto rptPart1; /* jump into loop to copy 0's first... */
221
222 while (--rpt >= 0) {
223 if (unpackBuffer + dcnt > endUnpackBuffer)
224 goto Error;
225 cntX = dcnt; /* cnt repeating parts follow each other*/
226 while (--cntX >= 0)
227 *unpackBuffer++ = PEFGetNextByte(&rawBuffer, &rawBufferRemaining);
228 rptPart1: /* non-repeating part is always 0's... */
229 if (unpackBuffer + cnt > endUnpackBuffer)
230 goto Error;
231 MemSet(unpackBuffer, 0, cnt);
232 unpackBuffer += cnt;
233 }
234
235 break;
236
237 case kRepeatBlock: /* copy cnt repeating bytes and dcnt */
238 dcnt = PEFGetCount(&rawBuffer, &rawBufferRemaining); /* non-repating bytes rcnt times... */
239 rpt = PEFGetCount(&rawBuffer, &rawBufferRemaining); /* ...then copy cnt repeating bytes */
240
241 oldRawBufferRemaining = rawBufferRemaining;
242 oldRawBuffer = rawBuffer;
243 delta = 0; /* the repeating part and each non-rep */
244
245 goto rptPart2; /* jump into loop to copy rptng part 1st*/
246
247 while (--rpt >= 0) {
248 if (unpackBuffer + dcnt > endUnpackBuffer)
249 goto Error;
250
251 rawBuffer = oldRawBuffer + cnt + delta;
252 rawBufferRemaining = oldRawBufferRemaining - (cnt + delta);
253 cntX = dcnt;
254 while (--cntX >= 0)
255 *unpackBuffer++ = PEFGetNextByte(&rawBuffer, &rawBufferRemaining);
256 delta += dcnt;
257 rptPart2:
258 if (unpackBuffer + cnt > endUnpackBuffer)
259 goto Error;
260 rawBuffer = oldRawBuffer;
261 rawBufferRemaining = oldRawBufferRemaining;
262 cntX = cnt;
263 while (--cntX >= 0)
264 *unpackBuffer++ = PEFGetNextByte(&rawBuffer, &rawBufferRemaining);
265 }
266
267 rawBuffer = oldRawBuffer + cnt + delta;
268 rawBufferRemaining = oldRawBufferRemaining - (cnt + delta);
269 break;
270
271 default:
272 goto Error;
273 } /* switch */
274 } /* for */
275
276 *theData = originalUnpackBuffer;
277
278 return noErr;
279
280 Error:
281 if (unpackBuffer)
282 DisposePtr((Ptr)originalUnpackBuffer);
283
284 *theData = nil;
285
286 return paramErr;
287 }
288
289
290
291
292 // GetSymbolFromPEF will extract from a PEF container the data associated
293 // with a given symbol name. It requires that the PEF file have been previously
294 // loaded into memory.
295
296 OSStatus GetSymbolFromPEF ( StringPtr theSymbolName,
297 LogicalAddress thePEFPtr,
298 LogicalAddress theSymbolPtr,
299 ByteCount theSymbolSize)
300 {
301 ContainerHeaderPtr containerHeaderPtr; // Pointer to the Container Header
302 SectionHeaderPtr loaderSectionPtr; // Pointer to the Loader Section Header
303 SectionHeaderPtr exportSectionPtr; // Pointer to the Section Header with the symbol
304 short currentSection;
305 Boolean foundSection;
306 Boolean foundSymbol;
307 long numExportSymbols;
308 LoaderHeaderPtr loaderHeaderPtr;
309 ExportSymbolEntryPtr exportSymbolEntryPtr;
310 LoaderExportChainEntryPtr exportChainEntryPtr;
311 StringPtr exportSymbolName;
312 LogicalAddress expandedDataPtr;
313 unsigned char* sourceDataPtr;
314 unsigned char* destDataPtr;
315
316
317 containerHeaderPtr = (ContainerHeaderPtr)thePEFPtr;
318
319 // Does the magic cookie match?
320 if (containerHeaderPtr->magicCookie != 'Joy!')
321 return cfragFragmentFormatErr;
322
323 // Is this a known PEF container format?
324 if (containerHeaderPtr->containerID != 'peff')
325 return cfragFragmentFormatErr;
326
327 // Validate parameters
328 if (theSymbolPtr == nil)
329 return paramErr;
330
331
332 // Find the loader section.
333 foundSection = false;
334 for (currentSection = 0; currentSection < containerHeaderPtr->nbrOfSections; currentSection++)
335 {
336 loaderSectionPtr = (SectionHeaderPtr)( (unsigned long)containerHeaderPtr +
337 sizeof(ContainerHeader) +
338 (sizeof(SectionHeader) * currentSection));
339 if (loaderSectionPtr->regionKind == kLoaderSection)
340 {
341 foundSection = true;
342 break;
343 }
344 }
345
346 if (foundSection == false)
347 return cfragNoSectionErr;
348
349 // Get the number of export symbols.
350 loaderHeaderPtr = (LoaderHeaderPtr)((unsigned long)thePEFPtr + loaderSectionPtr->containerOffset);
351 numExportSymbols = loaderHeaderPtr->nbrExportSyms;
352
353 // Start at the first exported symbol.
354 exportSymbolEntryPtr = (ExportSymbolEntryPtr)( (unsigned long)loaderHeaderPtr +
355 loaderHeaderPtr->slotTblOffset +
356 (sizeof(LoaderHashSlotEntry) * (1<<loaderHeaderPtr->hashSlotTblSz)) +
357 (sizeof(LoaderExportChainEntry) * numExportSymbols));
358
359 exportChainEntryPtr = (LoaderExportChainEntryPtr)( (unsigned long)loaderHeaderPtr +
360 loaderHeaderPtr->slotTblOffset +
361 (sizeof(LoaderHashSlotEntry) * (1<<loaderHeaderPtr->hashSlotTblSz)));
362
363 foundSymbol = false;
364 while (numExportSymbols-- > 0)
365 {
366 exportSymbolName = (StringPtr)( (unsigned long)loaderHeaderPtr +
367 loaderHeaderPtr->strTblOffset +
368 (exportSymbolEntryPtr->class_and_name & 0x00FFFFFF));
369 if (SymbolCompare(theSymbolName, exportSymbolName, exportChainEntryPtr->_h._h_h._nameLength))
370 {
371 foundSymbol = true;
372 break;
373 }
374 exportSymbolEntryPtr = (ExportSymbolEntryPtr)(((int)exportSymbolEntryPtr) + 10);
375 exportChainEntryPtr++;
376 }
377
378 if (foundSymbol == false)
379 return cfragNoSymbolErr;
380
381
382 // Found the symbol, so... let's go get the data!
383
384 exportSectionPtr = (SectionHeaderPtr)( (unsigned long)containerHeaderPtr +
385 sizeof(ContainerHeader) +
386 (sizeof(SectionHeader) * exportSymbolEntryPtr->sectionNumber));
387
388 expandedDataPtr = nil;
389
390 switch (exportSectionPtr -> regionKind)
391 {
392 case kPIDataSection:
393
394 // Expand the data! (Not yet... :)
395
396 if (UnpackPiData (thePEFPtr, exportSectionPtr, &expandedDataPtr) != noErr)
397 return cfragFragmentCorruptErr;
398
399 sourceDataPtr = (unsigned char*)((unsigned long)expandedDataPtr +
400 exportSymbolEntryPtr->address);
401 break;
402
403 default:
404 sourceDataPtr = (unsigned char*)((unsigned long)thePEFPtr +
405 exportSectionPtr->containerOffset +
406 exportSymbolEntryPtr->address);
407 break;
408 }
409
410
411 // Copy the data!
412
413 destDataPtr = (unsigned char*)theSymbolPtr;
414
415
416 while (theSymbolSize-- > 0)
417 *destDataPtr++ = *sourceDataPtr++;
418
419
420 // Cleanup any expanded data
421
422 if (expandedDataPtr != nil)
423 DisposePtr((Ptr)expandedDataPtr);
424
425 return noErr;
426 }
427
428
429 //
430 // SymbolCompare
431 //
432 // theExportSymbol is NOT null-terminated, so use theExportSymbolLength.
433 //
434 Boolean SymbolCompare ( StringPtr theLookedForSymbol,
435 StringPtr theExportSymbol,
436 unsigned long theExportSymbolLength)
437 {
438 unsigned char* p1 = (unsigned char*)theLookedForSymbol;
439 unsigned char* p2 = (unsigned char*)theExportSymbol;
440
441 // Same length?
442 // (skip over p string len byte)
443 if ( theExportSymbolLength != *p1++ )
444 return false;
445
446 while ( theExportSymbolLength-- != 0 )
447 {
448 if ( *p1++ != *p2++ )
449 return false;
450 }
451
452 return true;
453 }