]> git.saurik.com Git - apple/boot.git/blob - i386/libsaio/xml.c
boot-111.tar.gz
[apple/boot.git] / i386 / libsaio / xml.c
1 /*
2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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.
14 *
15 * The Original Code and all software distributed under the License are
16 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
17 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
18 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
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.
22 *
23 * @APPLE_LICENSE_HEADER_END@
24 */
25
26 #include "bootstruct.h"
27 #include "libsaio.h"
28 #include "sl.h"
29 #include "xml.h"
30
31 struct Module {
32 struct Module *nextModule;
33 long willLoad;
34 TagPtr dict;
35 char *plistAddr;
36 long plistLength;
37 char *driverPath;
38 };
39 typedef struct Module Module, *ModulePtr;
40
41 struct DriverInfo {
42 char *plistAddr;
43 long plistLength;
44 void *moduleAddr;
45 long moduleLength;
46 };
47 typedef struct DriverInfo DriverInfo, *DriverInfoPtr;
48
49 #define kDriverPackageSignature1 'MKXT'
50 #define kDriverPackageSignature2 'MOSX'
51
52 struct DriversPackage {
53 unsigned long signature1;
54 unsigned long signature2;
55 unsigned long length;
56 unsigned long alder32;
57 unsigned long version;
58 unsigned long numDrivers;
59 unsigned long reserved1;
60 unsigned long reserved2;
61 };
62 typedef struct DriversPackage DriversPackage;
63
64 enum {
65 kCFBundleType2,
66 kCFBundleType3
67 };
68
69
70 #define USEMALLOC 1
71 #define DOFREE 1
72
73 static long ParseTagList(char *buffer, TagPtr *tag, long type, long empty);
74 static long ParseTagKey(char *buffer, TagPtr *tag);
75 static long ParseTagString(char *buffer, TagPtr *tag);
76 static long ParseTagInteger(char *buffer, TagPtr *tag);
77 static long ParseTagData(char *buffer, TagPtr *tag);
78 static long ParseTagDate(char *buffer, TagPtr *tag);
79 static long ParseTagBoolean(char *buffer, TagPtr *tag, long type);
80 static long GetNextTag(char *buffer, char **tag, long *start);
81 static long FixDataMatchingTag(char *buffer, char *tag);
82 static TagPtr NewTag(void);
83 static char *NewSymbol(char *string);
84 #if DOFREE
85 static void FreeSymbol(char *string);
86 #endif
87
88
89 //==========================================================================
90 // XMLGetProperty
91
92 TagPtr
93 XMLGetProperty( TagPtr dict, const char * key )
94 {
95 TagPtr tagList, tag;
96
97 if (dict->type != kTagTypeDict) return 0;
98
99 tag = 0;
100 tagList = dict->tag;
101 while (tagList)
102 {
103 tag = tagList;
104 tagList = tag->tagNext;
105
106 if ((tag->type != kTagTypeKey) || (tag->string == 0)) continue;
107
108 if (!strcmp(tag->string, key)) return tag->tag;
109 }
110
111 return 0;
112 }
113
114
115 //==========================================================================
116 // XMLParseFile
117 // Expects to see one dictionary in the XML file.
118 // Puts the first dictionary it finds in the
119 // tag pointer and returns 0, or returns -1 if not found.
120 //
121 long
122 XMLParseFile( char * buffer, TagPtr * dict )
123 {
124 long length, pos;
125 TagPtr tag;
126 pos = 0;
127
128 while (1)
129 {
130 length = XMLParseNextTag(buffer + pos, &tag);
131 if (length == -1) break;
132
133 pos += length;
134
135 if (tag == 0) continue;
136 if (tag->type == kTagTypeDict) break;
137
138 XMLFreeTag(tag);
139 }
140 if (length < 0) {
141 return -1;
142 }
143 *dict = tag;
144 return 0;
145 }
146
147 //==========================================================================
148 // ParseNextTag
149
150 long
151 XMLParseNextTag( char * buffer, TagPtr * tag )
152 {
153 long length, pos;
154 char * tagName;
155
156 length = GetNextTag(buffer, &tagName, 0);
157 if (length == -1) return -1;
158
159 pos = length;
160 if (!strncmp(tagName, kXMLTagPList, 6))
161 {
162 length = 0;
163 }
164 else if (!strcmp(tagName, kXMLTagDict))
165 {
166 length = ParseTagList(buffer + pos, tag, kTagTypeDict, 0);
167 }
168 else if (!strcmp(tagName, kXMLTagDict "/"))
169 {
170 length = ParseTagList(buffer + pos, tag, kTagTypeDict, 1);
171 }
172 else if (!strcmp(tagName, kXMLTagKey))
173 {
174 length = ParseTagKey(buffer + pos, tag);
175 }
176 else if (!strcmp(tagName, kXMLTagString))
177 {
178 length = ParseTagString(buffer + pos, tag);
179 }
180 else if (!strcmp(tagName, kXMLTagInteger))
181 {
182 length = ParseTagInteger(buffer + pos, tag);
183 }
184 else if (!strcmp(tagName, kXMLTagData))
185 {
186 length = ParseTagData(buffer + pos, tag);
187 }
188 else if (!strcmp(tagName, kXMLTagDate))
189 {
190 length = ParseTagDate(buffer + pos, tag);
191 }
192 else if (!strcmp(tagName, kXMLTagFalse))
193 {
194 length = ParseTagBoolean(buffer + pos, tag, kTagTypeFalse);
195 }
196 else if (!strcmp(tagName, kXMLTagTrue))
197 {
198 length = ParseTagBoolean(buffer + pos, tag, kTagTypeTrue);
199 }
200 else if (!strcmp(tagName, kXMLTagArray))
201 {
202 length = ParseTagList(buffer + pos, tag, kTagTypeArray, 0);
203 }
204 else if (!strcmp(tagName, kXMLTagArray "/"))
205 {
206 length = ParseTagList(buffer + pos, tag, kTagTypeArray, 1);
207 }
208 else
209 {
210 *tag = 0;
211 length = 0;
212 }
213
214 if (length == -1) return -1;
215
216 return pos + length;
217 }
218
219 //==========================================================================
220 // ParseTagList
221
222 static long
223 ParseTagList( char * buffer, TagPtr * tag, long type, long empty )
224 {
225 long length, pos;
226 TagPtr tagList, tmpTag;
227
228 tagList = 0;
229 pos = 0;
230
231 if (!empty)
232 {
233 while (1)
234 {
235 length = XMLParseNextTag(buffer + pos, &tmpTag);
236 if (length == -1) break;
237
238 pos += length;
239
240 if (tmpTag == 0) break;
241 tmpTag->tagNext = tagList;
242 tagList = tmpTag;
243 }
244
245 if (length == -1)
246 {
247 XMLFreeTag(tagList);
248 return -1;
249 }
250 }
251
252 tmpTag = NewTag();
253 if (tmpTag == 0)
254 {
255 XMLFreeTag(tagList);
256 return -1;
257 }
258
259 tmpTag->type = type;
260 tmpTag->string = 0;
261 tmpTag->tag = tagList;
262 tmpTag->tagNext = 0;
263
264 *tag = tmpTag;
265
266 return pos;
267 }
268
269 //==========================================================================
270 // ParseTagKey
271
272 static long
273 ParseTagKey( char * buffer, TagPtr * tag )
274 {
275 long length, length2;
276 char *string;
277 TagPtr tmpTag, subTag;
278
279 length = FixDataMatchingTag(buffer, kXMLTagKey);
280 if (length == -1) return -1;
281
282 length2 = XMLParseNextTag(buffer + length, &subTag);
283 if (length2 == -1) return -1;
284
285 tmpTag = NewTag();
286 if (tmpTag == 0)
287 {
288 XMLFreeTag(subTag);
289 return -1;
290 }
291
292 string = NewSymbol(buffer);
293 if (string == 0)
294 {
295 XMLFreeTag(subTag);
296 XMLFreeTag(tmpTag);
297 return -1;
298 }
299
300 tmpTag->type = kTagTypeKey;
301 tmpTag->string = string;
302 tmpTag->tag = subTag;
303 tmpTag->tagNext = 0;
304
305 *tag = tmpTag;
306
307 return length + length2;
308 }
309
310 //==========================================================================
311 // ParseTagString
312
313 static long
314 ParseTagString( char * buffer, TagPtr * tag )
315 {
316 long length;
317 char * string;
318 TagPtr tmpTag;
319
320 length = FixDataMatchingTag(buffer, kXMLTagString);
321 if (length == -1) return -1;
322
323 tmpTag = NewTag();
324 if (tmpTag == 0) return -1;
325
326 string = NewSymbol(buffer);
327 if (string == 0)
328 {
329 XMLFreeTag(tmpTag);
330 return -1;
331 }
332
333 tmpTag->type = kTagTypeString;
334 tmpTag->string = string;
335 tmpTag->tag = 0;
336 tmpTag->tagNext = 0;
337
338 *tag = tmpTag;
339 return length;
340 }
341
342 //==========================================================================
343 // ParseTagInteger
344
345 static long
346 ParseTagInteger( char * buffer, TagPtr * tag )
347 {
348 long length, integer;
349 TagPtr tmpTag;
350
351 length = FixDataMatchingTag(buffer, kXMLTagInteger);
352 if (length == -1) return -1;
353
354 tmpTag = NewTag();
355 if (tmpTag == 0) return -1;
356
357 integer = 0;
358
359 tmpTag->type = kTagTypeInteger;
360 tmpTag->string = (char *)integer;
361 tmpTag->tag = 0;
362 tmpTag->tagNext = 0;
363
364 *tag = tmpTag;
365
366 return length;
367 }
368
369 //==========================================================================
370 // ParseTagData
371
372 static long
373 ParseTagData( char * buffer, TagPtr * tag )
374 {
375 long length;
376 TagPtr tmpTag;
377
378 length = FixDataMatchingTag(buffer, kXMLTagData);
379 if (length == -1) return -1;
380
381 tmpTag = NewTag();
382 if (tmpTag == 0) return -1;
383
384 tmpTag->type = kTagTypeData;
385 tmpTag->string = 0;
386 tmpTag->tag = 0;
387 tmpTag->tagNext = 0;
388
389 *tag = tmpTag;
390
391 return length;
392 }
393
394 //==========================================================================
395 // ParseTagDate
396
397 static long
398 ParseTagDate( char * buffer, TagPtr * tag )
399 {
400 long length;
401 TagPtr tmpTag;
402
403 length = FixDataMatchingTag(buffer, kXMLTagDate);
404 if (length == -1) return -1;
405
406 tmpTag = NewTag();
407 if (tmpTag == 0) return -1;
408
409 tmpTag->type = kTagTypeDate;
410 tmpTag->string = 0;
411 tmpTag->tag = 0;
412 tmpTag->tagNext = 0;
413
414 *tag = tmpTag;
415
416 return length;
417 }
418
419 //==========================================================================
420 // ParseTagBoolean
421
422 static long
423 ParseTagBoolean( char * buffer, TagPtr * tag, long type )
424 {
425 TagPtr tmpTag;
426
427 tmpTag = NewTag();
428 if (tmpTag == 0) return -1;
429
430 tmpTag->type = type;
431 tmpTag->string = 0;
432 tmpTag->tag = 0;
433 tmpTag->tagNext = 0;
434
435 *tag = tmpTag;
436
437 return 0;
438 }
439
440 //==========================================================================
441 // GetNextTag
442
443 static long
444 GetNextTag( char * buffer, char ** tag, long * start )
445 {
446 long cnt, cnt2;
447
448 if (tag == 0) return -1;
449
450 // Find the start of the tag.
451 cnt = 0;
452 while ((buffer[cnt] != '\0') && (buffer[cnt] != '<')) cnt++;
453 if (buffer[cnt] == '\0') return -1;
454
455 // Find the end of the tag.
456 cnt2 = cnt + 1;
457 while ((buffer[cnt2] != '\0') && (buffer[cnt2] != '>')) cnt2++;
458 if (buffer[cnt2] == '\0') return -1;
459
460 // Fix the tag data.
461 *tag = buffer + cnt + 1;
462 buffer[cnt2] = '\0';
463 if (start) *start = cnt;
464
465 return cnt2 + 1;
466 }
467
468 //==========================================================================
469 // FixDataMatchingTag
470 // Modifies 'buffer' to add a '\0' at the end of the tag matching 'tag'.
471 // Returns the length of the data found, counting the end tag,
472 // or -1 if the end tag was not found.
473
474 static long
475 FixDataMatchingTag( char * buffer, char * tag )
476 {
477 long length, start, stop;
478 char * endTag;
479
480 start = 0;
481 while (1)
482 {
483 length = GetNextTag(buffer + start, &endTag, &stop);
484 if (length == -1) return -1;
485
486 if ((*endTag == '/') && !strcmp(endTag + 1, tag)) break;
487 start += length;
488 }
489
490 buffer[start + stop] = '\0';
491
492 return start + length;
493 }
494
495 //==========================================================================
496 // NewTag
497
498 #define kTagsPerBlock (0x1000)
499
500 static TagPtr gTagsFree;
501
502 static TagPtr
503 NewTag( void )
504 {
505 long cnt;
506 TagPtr tag;
507
508 if (gTagsFree == 0)
509 {
510 #if USEMALLOC
511 tag = (TagPtr)malloc(kTagsPerBlock * sizeof(Tag));
512 #else
513 tag = (TagPtr)AllocateBootXMemory(kTagsPerBlock * sizeof(Tag));
514 #endif
515 if (tag == 0) return 0;
516
517 // Initalize the new tags.
518 for (cnt = 0; cnt < kTagsPerBlock; cnt++)
519 {
520 tag[cnt].type = kTagTypeNone;
521 tag[cnt].string = 0;
522 tag[cnt].tag = 0;
523 tag[cnt].tagNext = tag + cnt + 1;
524 }
525 tag[kTagsPerBlock - 1].tagNext = 0;
526
527 gTagsFree = tag;
528 }
529
530 tag = gTagsFree;
531 gTagsFree = tag->tagNext;
532
533 return tag;
534 }
535
536 //==========================================================================
537 // XMLFreeTag
538
539 void
540 XMLFreeTag( TagPtr tag )
541 {
542 #if DOFREE
543 if (tag == 0) return;
544
545 if (tag->string) FreeSymbol(tag->string);
546
547 XMLFreeTag(tag->tag);
548 XMLFreeTag(tag->tagNext);
549
550 // Clear and free the tag.
551 tag->type = kTagTypeNone;
552 tag->string = 0;
553 tag->tag = 0;
554 tag->tagNext = gTagsFree;
555 gTagsFree = tag;
556 #else
557 return;
558 #endif
559 }
560
561 //==========================================================================
562 // Symbol object.
563
564 struct Symbol
565 {
566 long refCount;
567 struct Symbol *next;
568 char string[];
569 };
570 typedef struct Symbol Symbol, *SymbolPtr;
571
572 static SymbolPtr FindSymbol(char * string, SymbolPtr * prevSymbol);
573
574 static SymbolPtr gSymbolsHead;
575
576 //==========================================================================
577 // NewSymbol
578
579 static char *
580 NewSymbol( char * string )
581 {
582 static SymbolPtr lastGuy = 0;
583 SymbolPtr symbol;
584
585 // Look for string in the list of symbols.
586 symbol = FindSymbol(string, 0);
587
588 // Add the new symbol.
589 if (symbol == 0)
590 {
591 #if USEMALLOC
592 symbol = (SymbolPtr)malloc(sizeof(Symbol) + 1 + strlen(string));
593 #else
594 symbol = (SymbolPtr)AllocateBootXMemory(sizeof(Symbol) + 1 + strlen(string));
595 #endif
596 if (symbol == 0) //return 0;
597 stop("NULL symbol!");
598
599 // Set the symbol's data.
600 symbol->refCount = 0;
601 strcpy(symbol->string, string);
602
603 // Add the symbol to the list.
604 symbol->next = gSymbolsHead;
605 gSymbolsHead = symbol;
606 }
607
608 // Update the refCount and return the string.
609 symbol->refCount++;
610
611 if (lastGuy && lastGuy->next != 0) stop("last guy not last!");
612 return symbol->string;
613 }
614
615 //==========================================================================
616 // FreeSymbol
617
618 #if DOFREE
619 static void
620 FreeSymbol( char * string )
621 {
622 SymbolPtr symbol, prev;
623
624 // Look for string in the list of symbols.
625 symbol = FindSymbol(string, &prev);
626 if (symbol == 0) return;
627
628 // Update the refCount.
629 symbol->refCount--;
630
631 if (symbol->refCount != 0) return;
632
633 // Remove the symbol from the list.
634 if (prev != 0) prev->next = symbol->next;
635 else gSymbolsHead = symbol->next;
636
637 // Free the symbol's memory.
638 free(symbol);
639 }
640 #endif
641
642 //==========================================================================
643 // FindSymbol
644
645 static SymbolPtr
646 FindSymbol( char * string, SymbolPtr * prevSymbol )
647 {
648 SymbolPtr symbol, prev;
649
650 symbol = gSymbolsHead;
651 prev = 0;
652
653 while (symbol != 0) {
654 if (!strcmp(symbol->string, string)) break;
655
656 prev = symbol;
657 symbol = symbol->next;
658 }
659
660 if ((symbol != 0) && (prevSymbol != 0)) *prevSymbol = prev;
661
662 return symbol;
663 }