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