2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The 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
22 * @APPLE_LICENSE_HEADER_END@
25 * drivers.c - Driver Loading Functions.
27 * Copyright (c) 2000 Apple Computer, Inc.
34 #include "kernBootStruct.h"
51 #define kXMLTagPList "plist "
52 #define kXMLTagDict "dict"
53 #define kXMLTagKey "key"
54 #define kXMLTagString "string"
55 #define kXMLTagInteger "integer"
56 #define kXMLTagData "data"
57 #define kXMLTagDate "date"
58 #define kXMLTagFalse "false/"
59 #define kXMLTagTrue "true/"
60 #define kXMLTagArray "array"
62 #define kPropCFBundleIdentifier ("CFBundleIdentifier")
63 #define kPropCFBundleExecutable ("CFBundleExecutable")
64 #define kPropOSBundleRequired ("OSBundleRequired")
65 #define kPropOSBundleLibraries ("OSBundleLibraries")
66 #define kPropIOKitPersonalities ("IOKitPersonalities")
67 #define kPropIONameMatch ("IONameMatch")
75 typedef struct Tag Tag
, *TagPtr
;
78 struct Module
*nextModule
;
85 typedef struct Module Module
, *ModulePtr
;
93 typedef struct DriverInfo DriverInfo
, *DriverInfoPtr
;
95 #define kDriverPackageSignature1 'MKXT'
96 #define kDriverPackageSignature2 'MOSX'
98 struct DriversPackage
{
99 unsigned long signature1
;
100 unsigned long signature2
;
101 unsigned long length
;
102 unsigned long alder32
;
103 unsigned long version
;
104 unsigned long numDrivers
;
105 unsigned long reserved1
;
106 unsigned long reserved2
;
108 typedef struct DriversPackage DriversPackage
;
110 static long FileLoadDrivers(char *dirSpec
, long plugin
);
111 static long NetLoadDrivers(char *dirSpec
);
112 static long LoadDriverMKext(char *fileSpec
);
113 static long LoadDriverPList(char *dirSpec
, char *name
);
114 static long LoadMatchedModules(void);
115 static long MatchPersonalities(void);
116 static long MatchLibraries(void);
117 static TagPtr
GetProperty(TagPtr dict
, char *key
);
118 // static ModulePtr FindModule(char *name);
119 static long ParseXML(char *buffer
, ModulePtr
*module, TagPtr
*personalities
);
120 static long ParseNextTag(char *buffer
, TagPtr
*tag
);
121 static long ParseTagList(char *buffer
, TagPtr
*tag
, long type
, long empty
);
122 static long ParseTagKey(char *buffer
, TagPtr
*tag
);
123 static long ParseTagString(char *buffer
, TagPtr
*tag
);
124 static long ParseTagInteger(char *buffer
, TagPtr
*tag
);
125 static long ParseTagData(char *buffer
, TagPtr
*tag
);
126 static long ParseTagDate(char *buffer
, TagPtr
*tag
);
127 static long ParseTagBoolean(char *buffer
, TagPtr
*tag
, long type
);
128 static long GetNextTag(char *buffer
, char **tag
, long *start
);
129 static long FixDataMatchingTag(char *buffer
, char *tag
);
130 static TagPtr
NewTag(void);
131 static void FreeTag(TagPtr tag
);
132 static char *NewSymbol(char *string
);
133 static void FreeSymbol(char *string
);
134 // static void DumpTag(TagPtr tag, long depth);
136 static ModulePtr gModuleHead
, gModuleTail
;
137 static TagPtr gPersonalityHead
, gPersonalityTail
;
138 static char * gExtensionsSpec
;
139 static char * gDriverSpec
;
140 static char * gFileSpec
;
142 //==========================================================================
143 // BootX shim functions.
145 #include <ufs/ufs/dir.h>
147 #define kLoadAddr TFTP_ADDR
148 #define kLoadSize TFTP_LEN
150 #define kPageSize 4096
151 #define RoundPage(x) ((((unsigned)(x)) + kPageSize - 1) & ~(kPageSize - 1))
154 LoadFile( char * fileSpec
)
156 unsigned long count
= TFTP_LEN
;
157 unsigned long addr
= TFTP_ADDR
;
159 if ( gBootDev
== kBootDevNetwork
)
161 if ( nbpTFTPReadFile(fileSpec
, &count
, addr
) != nbpStatusSuccess
)
166 int fd
= open( fileSpec
, 0 );
170 count
= read( fd
, (char *) addr
, count
);
176 static long gImageFirstBootXAddr
;
177 static long gImageLastKernelAddr
;
180 AllocateBootXMemory( long size
)
182 long addr
= gImageFirstBootXAddr
- size
;
184 if ( addr
< gImageLastKernelAddr
) return 0;
188 gImageFirstBootXAddr
= addr
;
194 AllocateKernelMemory( long inSize
)
196 long addr
= gImageLastKernelAddr
;
198 gImageLastKernelAddr
+= RoundPage(inSize
);
200 if ( gImageLastKernelAddr
> gImageFirstBootXAddr
)
201 stop( "AllocateKernelMemory error" );
203 kernBootStruct
->ksize
= gImageLastKernelAddr
- kernBootStruct
->kaddr
;
209 AllocateMemoryRange(char * rangeName
, long start
, long length
, long type
)
211 if ( kernBootStruct
->numBootDrivers
< NDRIVERS
)
213 int num
= kernBootStruct
->numBootDrivers
;
215 kernBootStruct
->driverConfig
[num
].address
= start
;
216 kernBootStruct
->driverConfig
[num
].size
= length
;
217 kernBootStruct
->driverConfig
[num
].type
= type
;
218 kernBootStruct
->numBootDrivers
++;
222 stop( "AllocateMemoryRange error" );
227 // Map BootX file types to UFS file types defined in ufs/ufs/dir.h.
230 kUnknownFileType
= DT_UNKNOWN
,
231 kFlatFileType
= DT_REG
,
232 kDirectoryFileType
= DT_DIR
,
233 kLinkFileType
= DT_LNK
237 GetFileInfo( char * dirSpec
, char * name
, long * flags
, long * time
)
239 struct dirstuff
* dir
;
240 struct direct
* entry
= 0;
242 dir
= opendir(dirSpec
);
245 while (( entry
= readdir(dir
) ))
247 if ( strcmp( entry
->d_name
, name
) == 0 )
249 *flags
= entry
->d_type
;
256 return ( entry
) ? 0 : -1;
259 // Map BootX types to boot counterparts.
261 #define gBootFileType gBootDev
263 kNetworkDeviceType
= kBootDevNetwork
,
264 kBlockDeviceType
= kBootDevHardDisk
267 static struct dirstuff
*
268 OpenDir( char * dirSpec
)
270 return opendir(dirSpec
);
274 CloseDir( struct dirstuff
* dirStuff
)
280 GetDirEntry( struct dirstuff
* dir
, long * dirIndex
, char ** name
,
281 long * flags
, long * time
)
285 struct direct
* entry
= readdir(dir
);
289 *name
= entry
->d_name
;
290 *flags
= entry
->d_type
;
301 gExtensionsSpec
= (char *) malloc( 4096 );
302 gDriverSpec
= (char *) malloc( 4096 );
303 gFileSpec
= (char *) malloc( 4096 );
305 if ( !gExtensionsSpec
|| !gDriverSpec
|| !gFileSpec
)
306 stop( "InitDriverSupport error" );
308 gImageLastKernelAddr
= RoundPage( kernBootStruct
->kaddr
+
309 kernBootStruct
->ksize
);
311 gImageFirstBootXAddr
= ( KERNEL_ADDR
+ KERNEL_LEN
);
317 Alder32( unsigned char * buffer
, long length
)
320 unsigned long result
, lowHalf
, highHalf
;
325 for ( cnt
= 0; cnt
< length
; cnt
++ )
327 if ((cnt
% 5000) == 0)
333 lowHalf
+= buffer
[cnt
];
340 result
= (highHalf
<< 16) | lowHalf
;
345 //==========================================================================
348 long LoadDrivers( char * dirSpec
)
350 if ( InitDriverSupport() != 0 )
353 if ( gBootFileType
== kNetworkDeviceType
)
355 NetLoadDrivers(dirSpec
);
357 else /* if ( gBootFileType == kBlockDeviceType ) */
359 strcpy(gExtensionsSpec
, dirSpec
);
360 strcat(gExtensionsSpec
, "System/Library/");
361 FileLoadDrivers(gExtensionsSpec
, 0);
370 MatchPersonalities();
374 LoadMatchedModules();
379 //==========================================================================
383 FileLoadDrivers( char * dirSpec
, long plugin
)
385 long ret
, length
, index
, flags
, time
;
387 struct dirstuff
* dir
;
393 ret
= GetFileInfo(dirSpec
, "Extensions.mkext", &flags
, &time
);
394 if ((ret
== 0) && (flags
== kFlatFileType
))
396 ret
= GetFileInfo(dirSpec
, "Extensions", &flags
, &time2
);
397 if ((ret
!= 0) || (flags
== kDirectoryFileType
) || (time
> time2
))
399 sprintf(gDriverSpec
, "%sExtensions.mkext", dirSpec
);
400 verbose("LoadDrivers: Loading from [%s]\n", gDriverSpec
);
401 if (LoadDriverMKext(gDriverSpec
) == 0) return 0;
405 strcat(dirSpec
, "Extensions");
408 verbose("LoadDrivers: Loading from [%s]\n", dirSpec
);
411 dir
= OpenDir( dirSpec
);
415 // INTEL modification
416 ret
= GetDirEntry(dir
, &index
, &name
, &flags
, &time
);
417 if (ret
== -1) break;
419 // Make sure this is a directory.
420 if (flags
!= kDirectoryFileType
) continue;
422 // Make sure this is a kext.
423 length
= strlen(name
);
424 if (strcmp(name
+ length
- 5, ".kext")) continue;
427 sprintf(gDriverSpec
, "%s/%s/Contents/PlugIns", dirSpec
, name
);
429 ret
= LoadDriverPList(dirSpec
, name
);
432 // printf("LoadDrivers: failed\n");
436 ret
= FileLoadDrivers(gDriverSpec
, 1);
440 if ( dir
) CloseDir( dir
);
445 //==========================================================================
449 NetLoadDrivers( char * dirSpec
)
456 // Get the name of the kernel
457 cnt
= strlen(gBootFile
);
459 if ((gBootFile
[cnt
] == '\\') || (gBootFile
[cnt
] == ',')) {
466 // INTEL modification
467 sprintf(gDriverSpec
, "%s%s.mkext", dirSpec
, kernBootStruct
->bootFile
);
469 verbose("NetLoadDrivers: Loading from [%s]\n", gDriverSpec
);
474 if (LoadDriverMKext(gDriverSpec
) == 0) break;
476 if (tries
== -1) return -1;
481 //==========================================================================
485 LoadDriverMKext( char * fileSpec
)
487 long driversAddr
, driversLength
;
489 DriversPackage
* package
= (DriversPackage
*)kLoadAddr
;
491 #define GetPackageElement(e) bswap32(package-> ## e)
494 if (LoadFile(fileSpec
) == -1) return -1;
497 if (( GetPackageElement(signature1
) != kDriverPackageSignature1
) ||
498 ( GetPackageElement(signature2
) != kDriverPackageSignature2
) ||
499 ( GetPackageElement(length
) > kLoadSize
) ||
500 ( GetPackageElement(alder32
) !=
501 Alder32((char *)&package
->version
, GetPackageElement(length
) - 0x10) ) )
506 // Make space for the MKext.
507 driversLength
= GetPackageElement(length
);
508 driversAddr
= AllocateKernelMemory(driversLength
);
511 memcpy((void *)driversAddr
, (void *)kLoadAddr
, driversLength
);
513 // Add the MKext to the memory map.
514 sprintf(segName
, "DriversPackage-%lx", driversAddr
);
515 AllocateMemoryRange(segName
, driversAddr
, driversLength
,
516 kBootDriverTypeMKEXT
);
521 //==========================================================================
525 LoadDriverPList( char * dirSpec
, char * name
)
527 long length
, driverPathLength
;
529 TagPtr personalities
;
531 char * tmpDriverPath
= 0;
535 // Save the driver path.
537 sprintf(gFileSpec
, "%s/%s/Contents/MacOS/", dirSpec
, name
);
538 driverPathLength
= strlen(gFileSpec
);
540 tmpDriverPath
= malloc(driverPathLength
+ 1);
541 if (tmpDriverPath
== 0) break;
543 strcpy(tmpDriverPath
, gFileSpec
);
545 // Construct the file spec to the plist, then load it.
547 sprintf(gFileSpec
, "%s/%s/Contents/Info.plist", dirSpec
, name
);
549 length
= LoadFile(gFileSpec
);
550 if (length
== -1) break;
552 buffer
= malloc(length
+ 1);
553 if (buffer
== 0) break;
555 strncpy(buffer
, (char *)kLoadAddr
, length
);
559 ret
= ParseXML(buffer
, &module, &personalities
);
562 // Allocate memory for the driver path and the plist.
564 module->driverPath
= AllocateBootXMemory(driverPathLength
+ 1);
565 module->plistAddr
= AllocateBootXMemory(length
+ 1);
567 if ((module->driverPath
== 0) || (module->plistAddr
== 0))
570 // Save the driver path in the module.
572 strcpy(module->driverPath
, tmpDriverPath
);
574 // Add the plist to the module.
576 strncpy(module->plistAddr
, (char *)kLoadAddr
, length
);
577 module->plistLength
= length
+ 1;
579 // Add the module to the end of the module list.
581 if (gModuleHead
== 0)
582 gModuleHead
= module;
584 gModuleTail
->nextModule
= module;
585 gModuleTail
= module;
587 // Add the persionalities to the personality list.
589 if (personalities
) personalities
= personalities
->tag
;
590 while (personalities
!= 0)
592 if (gPersonalityHead
== 0)
593 gPersonalityHead
= personalities
->tag
;
595 gPersonalityTail
->tagNext
= personalities
->tag
;
597 gPersonalityTail
= personalities
->tag
;
598 personalities
= personalities
->tagNext
;
605 if ( buffer
) free( buffer
);
606 if ( tmpDriverPath
) free( tmpDriverPath
);
611 //==========================================================================
612 // LoadMatchedModules
615 LoadMatchedModules( void )
619 char *fileName
, segName
[32];
620 DriverInfoPtr driver
;
621 long length
, driverAddr
, driverLength
;
623 module = gModuleHead
;
627 if (module->willLoad
)
629 prop
= GetProperty(module->dict
, kPropCFBundleExecutable
);
632 fileName
= prop
->string
;
633 sprintf(gFileSpec
, "%s%s", module->driverPath
, fileName
);
634 length
= LoadFile(gFileSpec
);
641 // Make make in the image area.
642 driverLength
= sizeof(DriverInfo
) + module->plistLength
+ length
;
643 driverAddr
= AllocateKernelMemory(driverLength
);
645 // Set up the DriverInfo.
646 driver
= (DriverInfoPtr
)driverAddr
;
647 driver
->plistAddr
= (char *)(driverAddr
+ sizeof(DriverInfo
));
648 driver
->plistLength
= module->plistLength
;
651 driver
->moduleAddr
= (void *)(driverAddr
+ sizeof(DriverInfo
) +
652 module->plistLength
);
653 driver
->moduleLength
= length
;
657 driver
->moduleAddr
= 0;
658 driver
->moduleLength
= 0;
661 // Save the plist and module.
662 strcpy(driver
->plistAddr
, module->plistAddr
);
665 memcpy(driver
->moduleAddr
, (void *)kLoadAddr
, driver
->moduleLength
);
668 // Add an entry to the memory map.
669 sprintf(segName
, "Driver-%lx", (unsigned long)driver
);
670 AllocateMemoryRange(segName
, driverAddr
, driverLength
,
671 kBootDriverTypeKEXT
);
674 module = module->nextModule
;
680 //==========================================================================
681 // MatchPersonalities
684 MatchPersonalities( void )
686 #warning IONameMatch support not implemented
690 //==========================================================================
694 MatchLibraries( void )
697 ModulePtr
module, module2
;
702 module = gModuleHead
;
706 if (module->willLoad
== 1)
708 prop
= GetProperty(module->dict
, kPropOSBundleLibraries
);
714 module2
= gModuleHead
;
717 prop2
= GetProperty(module2
->dict
, kPropCFBundleIdentifier
);
718 if ((prop2
!= 0) && (!strcmp(prop
->string
, prop2
->string
)))
720 if (module2
->willLoad
== 0) module2
->willLoad
= 1;
723 module2
= module2
->nextModule
;
725 prop
= prop
->tagNext
;
728 module->willLoad
= 2;
731 module = module->nextModule
;
739 //==========================================================================
743 GetProperty( TagPtr dict
, char * key
)
747 if (dict
->type
!= kTagTypeDict
) return 0;
754 tagList
= tag
->tagNext
;
756 if ((tag
->type
!= kTagTypeKey
) || (tag
->string
== 0)) continue;
758 if (!strcmp(tag
->string
, key
)) return tag
->tag
;
764 //==========================================================================
769 FindModule( char * name
)
774 module = gModuleHead
;
778 prop
= GetProperty(module->dict
, kPropCFBundleIdentifier
);
779 if ((prop
!= 0) && !strcmp(name
, prop
->string
)) break;
780 module = module->nextModule
;
787 //==========================================================================
791 ParseXML( char * buffer
, ModulePtr
* module, TagPtr
* personalities
)
794 TagPtr moduleDict
, required
;
801 length
= ParseNextTag(buffer
+ pos
, &moduleDict
);
802 if (length
== -1) break;
806 if (moduleDict
== 0) continue;
807 if (moduleDict
->type
== kTagTypeDict
) break;
812 if (length
== -1) return -1;
814 required
= GetProperty(moduleDict
, kPropOSBundleRequired
);
815 if ( (required
== 0) ||
816 (required
->type
!= kTagTypeString
) ||
817 !strcmp(required
->string
, "Safe Boot"))
823 tmpModule
= AllocateBootXMemory(sizeof(Module
));
829 tmpModule
->dict
= moduleDict
;
831 // For now, load any module that has OSBundleRequired != "Safe Boot".
833 tmpModule
->willLoad
= 1;
837 // Get the personalities.
839 *personalities
= GetProperty(moduleDict
, kPropIOKitPersonalities
);
844 //==========================================================================
848 ParseNextTag( char * buffer
, TagPtr
* tag
)
853 length
= GetNextTag(buffer
, &tagName
, 0);
854 if (length
== -1) return -1;
857 if (!strncmp(tagName
, kXMLTagPList
, 6))
861 else if (!strcmp(tagName
, kXMLTagDict
))
863 length
= ParseTagList(buffer
+ pos
, tag
, kTagTypeDict
, 0);
865 else if (!strcmp(tagName
, kXMLTagDict
"/"))
867 length
= ParseTagList(buffer
+ pos
, tag
, kTagTypeDict
, 1);
869 else if (!strcmp(tagName
, kXMLTagKey
))
871 length
= ParseTagKey(buffer
+ pos
, tag
);
873 else if (!strcmp(tagName
, kXMLTagString
))
875 length
= ParseTagString(buffer
+ pos
, tag
);
877 else if (!strcmp(tagName
, kXMLTagInteger
))
879 length
= ParseTagInteger(buffer
+ pos
, tag
);
881 else if (!strcmp(tagName
, kXMLTagData
))
883 length
= ParseTagData(buffer
+ pos
, tag
);
885 else if (!strcmp(tagName
, kXMLTagDate
))
887 length
= ParseTagDate(buffer
+ pos
, tag
);
889 else if (!strcmp(tagName
, kXMLTagFalse
))
891 length
= ParseTagBoolean(buffer
+ pos
, tag
, kTagTypeFalse
);
893 else if (!strcmp(tagName
, kXMLTagTrue
))
895 length
= ParseTagBoolean(buffer
+ pos
, tag
, kTagTypeTrue
);
897 else if (!strcmp(tagName
, kXMLTagArray
))
899 length
= ParseTagList(buffer
+ pos
, tag
, kTagTypeArray
, 0);
901 else if (!strcmp(tagName
, kXMLTagArray
"/"))
903 length
= ParseTagList(buffer
+ pos
, tag
, kTagTypeArray
, 1);
911 if (length
== -1) return -1;
916 //==========================================================================
920 ParseTagList( char * buffer
, TagPtr
* tag
, long type
, long empty
)
923 TagPtr tagList
, tmpTag
;
932 length
= ParseNextTag(buffer
+ pos
, &tmpTag
);
933 if (length
== -1) break;
937 if (tmpTag
== 0) break;
938 tmpTag
->tagNext
= tagList
;
958 tmpTag
->tag
= tagList
;
966 //==========================================================================
970 ParseTagKey( char * buffer
, TagPtr
* tag
)
972 long length
, length2
;
974 TagPtr tmpTag
, subTag
;
976 length
= FixDataMatchingTag(buffer
, kXMLTagKey
);
977 if (length
== -1) return -1;
979 length2
= ParseNextTag(buffer
+ length
, &subTag
);
980 if (length2
== -1) return -1;
989 string
= NewSymbol(buffer
);
997 tmpTag
->type
= kTagTypeKey
;
998 tmpTag
->string
= string
;
999 tmpTag
->tag
= subTag
;
1000 tmpTag
->tagNext
= 0;
1004 return length
+ length2
;
1007 //==========================================================================
1011 ParseTagString( char * buffer
, TagPtr
* tag
)
1017 length
= FixDataMatchingTag(buffer
, kXMLTagString
);
1018 if (length
== -1) return -1;
1021 if (tmpTag
== 0) return -1;
1023 string
= NewSymbol(buffer
);
1030 tmpTag
->type
= kTagTypeString
;
1031 tmpTag
->string
= string
;
1033 tmpTag
->tagNext
= 0;
1040 //==========================================================================
1044 ParseTagInteger( char * buffer
, TagPtr
* tag
)
1046 long length
, integer
;
1049 length
= FixDataMatchingTag(buffer
, kXMLTagInteger
);
1050 if (length
== -1) return -1;
1053 if (tmpTag
== 0) return -1;
1057 tmpTag
->type
= kTagTypeInteger
;
1058 tmpTag
->string
= (char *)integer
;
1060 tmpTag
->tagNext
= 0;
1067 //==========================================================================
1071 ParseTagData( char * buffer
, TagPtr
* tag
)
1076 length
= FixDataMatchingTag(buffer
, kXMLTagData
);
1077 if (length
== -1) return -1;
1080 if (tmpTag
== 0) return -1;
1082 tmpTag
->type
= kTagTypeData
;
1085 tmpTag
->tagNext
= 0;
1092 //==========================================================================
1096 ParseTagDate( char * buffer
, TagPtr
* tag
)
1101 length
= FixDataMatchingTag(buffer
, kXMLTagDate
);
1102 if (length
== -1) return -1;
1105 if (tmpTag
== 0) return -1;
1107 tmpTag
->type
= kTagTypeDate
;
1110 tmpTag
->tagNext
= 0;
1117 //==========================================================================
1121 ParseTagBoolean( char * buffer
, TagPtr
* tag
, long type
)
1126 if (tmpTag
== 0) return -1;
1128 tmpTag
->type
= type
;
1131 tmpTag
->tagNext
= 0;
1138 //==========================================================================
1142 GetNextTag( char * buffer
, char ** tag
, long * start
)
1146 if (tag
== 0) return -1;
1148 // Find the start of the tag.
1150 while ((buffer
[cnt
] != '\0') && (buffer
[cnt
] != '<')) cnt
++;
1151 if (buffer
[cnt
] == '\0') return -1;
1153 // Find the end of the tag.
1155 while ((buffer
[cnt2
] != '\0') && (buffer
[cnt2
] != '>')) cnt2
++;
1156 if (buffer
[cnt2
] == '\0') return -1;
1158 // Fix the tag data.
1159 *tag
= buffer
+ cnt
+ 1;
1160 buffer
[cnt2
] = '\0';
1161 if (start
) *start
= cnt
;
1166 //==========================================================================
1167 // FixDataMatchingTag
1170 FixDataMatchingTag( char * buffer
, char * tag
)
1172 long length
, start
, stop
;
1178 length
= GetNextTag(buffer
+ start
, &endTag
, &stop
);
1179 if (length
== -1) return -1;
1181 if ((*endTag
== '/') && !strcmp(endTag
+ 1, tag
)) break;
1185 buffer
[start
+ stop
] = '\0';
1187 return start
+ length
;
1190 //==========================================================================
1193 #define kTagsPerBlock (0x1000)
1195 static TagPtr gTagsFree
;
1205 tag
= (TagPtr
)AllocateBootXMemory(kTagsPerBlock
* sizeof(Tag
));
1206 if (tag
== 0) return 0;
1208 // Initalize the new tags.
1209 for (cnt
= 0; cnt
< kTagsPerBlock
; cnt
++)
1211 tag
[cnt
].type
= kTagTypeNone
;
1212 tag
[cnt
].string
= 0;
1214 tag
[cnt
].tagNext
= tag
+ cnt
+ 1;
1216 tag
[kTagsPerBlock
- 1].tagNext
= 0;
1222 gTagsFree
= tag
->tagNext
;
1227 //==========================================================================
1231 FreeTag( TagPtr tag
)
1234 if (tag
== 0) return;
1236 if (tag
->string
) FreeSymbol(tag
->string
);
1239 FreeTag(tag
->tagNext
);
1241 // Clear and free the tag.
1242 tag
->type
= kTagTypeNone
;
1245 tag
->tagNext
= gTagsFree
;
1249 //==========================================================================
1255 struct Symbol
*next
;
1258 typedef struct Symbol Symbol
, *SymbolPtr
;
1260 static SymbolPtr
FindSymbol(char * string
, SymbolPtr
* prevSymbol
);
1262 static SymbolPtr gSymbolsHead
;
1264 //==========================================================================
1268 NewSymbol( char * string
)
1272 // Look for string in the list of symbols.
1273 symbol
= FindSymbol(string
, 0);
1275 // Add the new symbol.
1278 symbol
= AllocateBootXMemory(sizeof(Symbol
) + strlen(string
));
1279 if (symbol
== 0) return 0;
1281 // Set the symbol's data.
1282 symbol
->refCount
= 0;
1283 strcpy(symbol
->string
, string
);
1285 // Add the symbol to the list.
1286 symbol
->next
= gSymbolsHead
;
1287 gSymbolsHead
= symbol
;
1290 // Update the refCount and return the string.
1292 return symbol
->string
;
1295 //==========================================================================
1299 FreeSymbol( char * string
)
1302 SymbolPtr symbol
, prev
;
1304 // Look for string in the list of symbols.
1305 symbol
= FindSymbol(string
, &prev
);
1306 if (symbol
== 0) return;
1308 // Update the refCount.
1311 if (symbol
->refCount
!= 0) return;
1313 // Remove the symbol from the list.
1314 if (prev
!= 0) prev
->next
= symbol
->next
;
1315 else gSymbolsHead
= symbol
->next
;
1317 // Free the symbol's memory.
1322 //==========================================================================
1326 FindSymbol( char * string
, SymbolPtr
* prevSymbol
)
1328 SymbolPtr symbol
, prev
;
1330 symbol
= gSymbolsHead
;
1335 if (!strcmp(symbol
->string
, string
)) break;
1338 symbol
= symbol
->next
;
1341 if ((symbol
!= 0) && (prevSymbol
!= 0)) *prevSymbol
= prev
;