1## @file
2# This file is used to parse a strings file and create or add to a string database
3# file.
4#
5# Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
6# SPDX-License-Identifier: BSD-2-Clause-Patent
7
8##
9# Import Modules
10#
11from __future__ import absolute_import
12import re
13import Common.EdkLogger as EdkLogger
14from Common.BuildToolError import *
15from .UniClassObject import *
16from io import BytesIO
17from struct import pack, unpack
18from Common.LongFilePathSupport import OpenLongFilePath as open
19
20##
21# Static definitions
22#
23EFI_HII_SIBT_END = '0x00'
24EFI_HII_SIBT_STRING_SCSU = '0x10'
25EFI_HII_SIBT_STRING_SCSU_FONT = '0x11'
26EFI_HII_SIBT_STRINGS_SCSU = '0x12'
27EFI_HII_SIBT_STRINGS_SCSU_FONT = '0x13'
28EFI_HII_SIBT_STRING_UCS2 = '0x14'
29EFI_HII_SIBT_STRING_UCS2_FONT = '0x15'
30EFI_HII_SIBT_STRINGS_UCS2 = '0x16'
31EFI_HII_SIBT_STRINGS_UCS2_FONT = '0x17'
32EFI_HII_SIBT_DUPLICATE = '0x20'
33EFI_HII_SIBT_SKIP2 = '0x21'
34EFI_HII_SIBT_SKIP1 = '0x22'
35EFI_HII_SIBT_EXT1 = '0x30'
36EFI_HII_SIBT_EXT2 = '0x31'
37EFI_HII_SIBT_EXT4 = '0x32'
38EFI_HII_SIBT_FONT = '0x40'
39
40EFI_HII_PACKAGE_STRINGS = '0x04'
41EFI_HII_PACKAGE_FORM = '0x02'
42
43StringPackageType = EFI_HII_PACKAGE_STRINGS
44StringPackageForm = EFI_HII_PACKAGE_FORM
45StringBlockType = EFI_HII_SIBT_STRING_UCS2
46StringSkipType = EFI_HII_SIBT_SKIP2
47
48HexHeader = '0x'
49
50COMMENT = '// '
51DEFINE_STR = '#define'
52COMMENT_DEFINE_STR = COMMENT + DEFINE_STR
53NOT_REFERENCED = 'not referenced'
54COMMENT_NOT_REFERENCED = ' ' + COMMENT + NOT_REFERENCED
55CHAR_ARRAY_DEFIN = 'unsigned char'
56COMMON_FILE_NAME = 'Strings'
57STRING_TOKEN = re.compile('STRING_TOKEN *\(([A-Z0-9_]+) *\)', re.MULTILINE | re.UNICODE)
58
59EFI_HII_ARRAY_SIZE_LENGTH = 4
60EFI_HII_PACKAGE_HEADER_LENGTH = 4
61EFI_HII_HDR_SIZE_LENGTH = 4
62EFI_HII_STRING_OFFSET_LENGTH = 4
63EFI_STRING_ID = 1
64EFI_STRING_ID_LENGTH = 2
65EFI_HII_LANGUAGE_WINDOW = 0
66EFI_HII_LANGUAGE_WINDOW_LENGTH = 2
67EFI_HII_LANGUAGE_WINDOW_NUMBER = 16
68EFI_HII_STRING_PACKAGE_HDR_LENGTH = EFI_HII_PACKAGE_HEADER_LENGTH + EFI_HII_HDR_SIZE_LENGTH + EFI_HII_STRING_OFFSET_LENGTH + EFI_HII_LANGUAGE_WINDOW_LENGTH * EFI_HII_LANGUAGE_WINDOW_NUMBER + EFI_STRING_ID_LENGTH
69
70H_C_FILE_HEADER = ['//', \
71                   '//  DO NOT EDIT -- auto-generated file', \
72                   '//', \
73                   '//  This file is generated by the StrGather utility', \
74                   '//']
75LANGUAGE_NAME_STRING_NAME = '$LANGUAGE_NAME'
76PRINTABLE_LANGUAGE_NAME_STRING_NAME = '$PRINTABLE_LANGUAGE_NAME'
77
78## Convert a dec number to a hex string
79#
80# Convert a dec number to a formatted hex string in length digit
81# The digit is set to default 8
82# The hex string starts with "0x"
83# DecToHexStr(1000) is '0x000003E8'
84# DecToHexStr(1000, 6) is '0x0003E8'
85#
86# @param Dec:    The number in dec format
87# @param Digit:  The needed digit of hex string
88#
89# @retval:       The formatted hex string
90#
91def DecToHexStr(Dec, Digit = 8):
92    return '0x{0:0{1}X}'.format(Dec, Digit)
93
94## Convert a dec number to a hex list
95#
96# Convert a dec number to a formatted hex list in size digit
97# The digit is set to default 8
98# DecToHexList(1000) is ['0xE8', '0x03', '0x00', '0x00']
99# DecToHexList(1000, 6) is ['0xE8', '0x03', '0x00']
100#
101# @param Dec:    The number in dec format
102# @param Digit:  The needed digit of hex list
103#
104# @retval:       A list for formatted hex string
105#
106def DecToHexList(Dec, Digit = 8):
107    Hex = '{0:0{1}X}'.format(Dec, Digit)
108    return ["0x" + Hex[Bit:Bit + 2] for Bit in range(Digit - 2, -1, -2)]
109
110## Convert a acsii string to a hex list
111#
112# Convert a acsii string to a formatted hex list
113# AscToHexList('en-US') is ['0x65', '0x6E', '0x2D', '0x55', '0x53']
114#
115# @param Ascii:  The acsii string
116#
117# @retval:       A list for formatted hex string
118#
119def AscToHexList(Ascii):
120    try:
121        return ['0x{0:02X}'.format(Item) for Item in Ascii]
122    except:
123        return ['0x{0:02X}'.format(ord(Item)) for Item in Ascii]
124
125## Create content of .h file
126#
127# Create content of .h file
128#
129# @param BaseName:        The basename of strings
130# @param UniObjectClass   A UniObjectClass instance
131# @param IsCompatibleMode Compatible mode
132# @param UniGenCFlag      UniString is generated into AutoGen C file when it is set to True
133#
134# @retval Str:           A string of .h file content
135#
136def CreateHFileContent(BaseName, UniObjectClass, IsCompatibleMode, UniGenCFlag):
137    Str = []
138    ValueStartPtr = 60
139    Line = COMMENT_DEFINE_STR + ' ' + LANGUAGE_NAME_STRING_NAME + ' ' * (ValueStartPtr - len(DEFINE_STR + LANGUAGE_NAME_STRING_NAME)) + DecToHexStr(0, 4) + COMMENT_NOT_REFERENCED
140    Str = WriteLine(Str, Line)
141    Line = COMMENT_DEFINE_STR + ' ' + PRINTABLE_LANGUAGE_NAME_STRING_NAME + ' ' * (ValueStartPtr - len(DEFINE_STR + PRINTABLE_LANGUAGE_NAME_STRING_NAME)) + DecToHexStr(1, 4) + COMMENT_NOT_REFERENCED
142    Str = WriteLine(Str, Line)
143    UnusedStr = ''
144
145    #Group the referred/Unused STRING token together.
146    for Index in range(2, len(UniObjectClass.OrderedStringList[UniObjectClass.LanguageDef[0][0]])):
147        StringItem = UniObjectClass.OrderedStringList[UniObjectClass.LanguageDef[0][0]][Index]
148        Name = StringItem.StringName
149        Token = StringItem.Token
150        Referenced = StringItem.Referenced
151        if Name is not None:
152            Line = ''
153            if Referenced == True:
154                if (ValueStartPtr - len(DEFINE_STR + Name)) <= 0:
155                    Line = DEFINE_STR + ' ' + Name + ' ' + DecToHexStr(Token, 4)
156                else:
157                    Line = DEFINE_STR + ' ' + Name + ' ' * (ValueStartPtr - len(DEFINE_STR + Name)) + DecToHexStr(Token, 4)
158                Str = WriteLine(Str, Line)
159            else:
160                if (ValueStartPtr - len(DEFINE_STR + Name)) <= 0:
161                    Line = COMMENT_DEFINE_STR + ' ' + Name + ' ' + DecToHexStr(Token, 4) + COMMENT_NOT_REFERENCED
162                else:
163                    Line = COMMENT_DEFINE_STR + ' ' + Name + ' ' * (ValueStartPtr - len(DEFINE_STR + Name)) + DecToHexStr(Token, 4) + COMMENT_NOT_REFERENCED
164                UnusedStr = WriteLine(UnusedStr, Line)
165
166    Str.extend( UnusedStr)
167
168    Str = WriteLine(Str, '')
169    if IsCompatibleMode or UniGenCFlag:
170        Str = WriteLine(Str, 'extern unsigned char ' + BaseName + 'Strings[];')
171    return "".join(Str)
172
173## Create a complete .h file
174#
175# Create a complet .h file with file header and file content
176#
177# @param BaseName:        The basename of strings
178# @param UniObjectClass   A UniObjectClass instance
179# @param IsCompatibleMode Compatible mode
180# @param UniGenCFlag      UniString is generated into AutoGen C file when it is set to True
181#
182# @retval Str:           A string of complete .h file
183#
184def CreateHFile(BaseName, UniObjectClass, IsCompatibleMode, UniGenCFlag):
185    HFile = WriteLine('', CreateHFileContent(BaseName, UniObjectClass, IsCompatibleMode, UniGenCFlag))
186
187    return "".join(HFile)
188
189## Create a buffer to store all items in an array
190#
191# @param BinBuffer   Buffer to contain Binary data.
192# @param Array:      The array need to be formatted
193#
194def CreateBinBuffer(BinBuffer, Array):
195    for Item in Array:
196        BinBuffer.write(pack("B", int(Item, 16)))
197
198## Create a formatted string all items in an array
199#
200# Use ',' to join each item in an array, and break an new line when reaching the width (default is 16)
201#
202# @param Array:      The array need to be formatted
203# @param Width:      The line length, the default value is set to 16
204#
205# @retval ArrayItem: A string for all formatted array items
206#
207def CreateArrayItem(Array, Width = 16):
208    MaxLength = Width
209    Index = 0
210    Line = '  '
211    ArrayItem = []
212
213    for Item in Array:
214        if Index < MaxLength:
215            Line = Line + Item + ',  '
216            Index = Index + 1
217        else:
218            ArrayItem = WriteLine(ArrayItem, Line)
219            Line = '  ' + Item + ',  '
220            Index = 1
221    ArrayItem = Write(ArrayItem, Line.rstrip())
222
223    return "".join(ArrayItem)
224
225## CreateCFileStringValue
226#
227# Create a line with string value
228#
229# @param Value:  Value of the string
230#
231# @retval Str:   A formatted string with string value
232#
233
234def CreateCFileStringValue(Value):
235    Value = [StringBlockType] + Value
236    Str = WriteLine('', CreateArrayItem(Value))
237
238    return "".join(Str)
239
240## GetFilteredLanguage
241#
242# apply get best language rules to the UNI language code list
243#
244# @param UniLanguageList:  language code definition list in *.UNI file
245# @param LanguageFilterList:  language code filter list of RFC4646 format in DSC file
246#
247# @retval UniLanguageListFiltered:   the filtered language code
248#
249def GetFilteredLanguage(UniLanguageList, LanguageFilterList):
250    UniLanguageListFiltered = []
251    # if filter list is empty, then consider there is no filter
252    if LanguageFilterList == []:
253        UniLanguageListFiltered = UniLanguageList
254        return UniLanguageListFiltered
255    for Language in LanguageFilterList:
256        # first check for exact match
257        if Language in UniLanguageList:
258            if Language not in UniLanguageListFiltered:
259                UniLanguageListFiltered.append(Language)
260        # find the first one with the same/equivalent primary tag
261        else:
262            if Language.find('-') != -1:
263                PrimaryTag = Language[0:Language.find('-')].lower()
264            else:
265                PrimaryTag = Language
266
267            if len(PrimaryTag) == 3:
268                PrimaryTag = LangConvTable.get(PrimaryTag)
269
270            for UniLanguage in UniLanguageList:
271                if UniLanguage.find('-') != -1:
272                    UniLanguagePrimaryTag = UniLanguage[0:UniLanguage.find('-')].lower()
273                else:
274                    UniLanguagePrimaryTag = UniLanguage
275
276                if len(UniLanguagePrimaryTag) == 3:
277                    UniLanguagePrimaryTag = LangConvTable.get(UniLanguagePrimaryTag)
278
279                if PrimaryTag == UniLanguagePrimaryTag:
280                    if UniLanguage not in UniLanguageListFiltered:
281                        UniLanguageListFiltered.append(UniLanguage)
282                    break
283            else:
284                # Here is rule 3 for "get best language"
285                # If tag is not listed in the Unicode file, the default ("en") tag should be used for that language
286                # for better processing, find the one that best suit for it.
287                DefaultTag = 'en'
288                if DefaultTag not in UniLanguageListFiltered:
289                    # check whether language code with primary code equivalent with DefaultTag already in the list, if so, use that
290                    for UniLanguage in UniLanguageList:
291                        if UniLanguage.startswith('en-') or UniLanguage.startswith('eng-'):
292                            if UniLanguage not in UniLanguageListFiltered:
293                                UniLanguageListFiltered.append(UniLanguage)
294                            break
295                    else:
296                        UniLanguageListFiltered.append(DefaultTag)
297    return  UniLanguageListFiltered
298
299
300## Create content of .c file
301#
302# Create content of .c file
303#
304# @param BaseName:        The basename of strings
305# @param UniObjectClass   A UniObjectClass instance
306# @param IsCompatibleMode Compatible mode
307# @param UniBinBuffer     UniBinBuffer to contain UniBinary data.
308# @param FilterInfo       Platform language filter information
309#
310# @retval Str:           A string of .c file content
311#
312def CreateCFileContent(BaseName, UniObjectClass, IsCompatibleMode, UniBinBuffer, FilterInfo):
313    #
314    # Init array length
315    #
316    TotalLength = EFI_HII_ARRAY_SIZE_LENGTH
317    Str = ''
318    Offset = 0
319
320    EDK2Module = FilterInfo[0]
321    if EDK2Module:
322        LanguageFilterList = FilterInfo[1]
323    else:
324        # EDK module is using ISO639-2 format filter, convert to the RFC4646 format
325        LanguageFilterList = [LangConvTable.get(F.lower()) for F in FilterInfo[1]]
326
327    UniLanguageList = []
328    for IndexI in range(len(UniObjectClass.LanguageDef)):
329        UniLanguageList += [UniObjectClass.LanguageDef[IndexI][0]]
330
331    UniLanguageListFiltered = GetFilteredLanguage(UniLanguageList, LanguageFilterList)
332
333
334    #
335    # Create lines for each language's strings
336    #
337    for IndexI in range(len(UniObjectClass.LanguageDef)):
338        Language = UniObjectClass.LanguageDef[IndexI][0]
339        if Language not in UniLanguageListFiltered:
340            continue
341
342        StringBuffer = BytesIO()
343        StrStringValue = ''
344        ArrayLength = 0
345        NumberOfUseOtherLangDef = 0
346        Index = 0
347        for IndexJ in range(1, len(UniObjectClass.OrderedStringList[UniObjectClass.LanguageDef[IndexI][0]])):
348            Item = UniObjectClass.OrderedStringListByToken[Language][IndexJ]
349
350            Name = Item.StringName
351            Value = Item.StringValueByteList
352            Referenced = Item.Referenced
353            Token = Item.Token
354            UseOtherLangDef = Item.UseOtherLangDef
355
356            if UseOtherLangDef != '' and Referenced:
357                NumberOfUseOtherLangDef = NumberOfUseOtherLangDef + 1
358                Index = Index + 1
359            else:
360                if NumberOfUseOtherLangDef > 0:
361                    StrStringValue = WriteLine(StrStringValue, CreateArrayItem([StringSkipType] + DecToHexList(NumberOfUseOtherLangDef, 4)))
362                    CreateBinBuffer (StringBuffer, ([StringSkipType] + DecToHexList(NumberOfUseOtherLangDef, 4)))
363                    NumberOfUseOtherLangDef = 0
364                    ArrayLength = ArrayLength + 3
365                if Referenced and Item.Token > 0:
366                    Index = Index + 1
367                    StrStringValue = WriteLine(StrStringValue, "// %s: %s:%s" % (DecToHexStr(Index, 4), Name, DecToHexStr(Token, 4)))
368                    StrStringValue = Write(StrStringValue, CreateCFileStringValue(Value))
369                    CreateBinBuffer (StringBuffer, [StringBlockType] + Value)
370                    ArrayLength = ArrayLength + Item.Length + 1 # 1 is for the length of string type
371
372        #
373        # EFI_HII_PACKAGE_HEADER
374        #
375        Offset = EFI_HII_STRING_PACKAGE_HDR_LENGTH + len(Language) + 1
376        ArrayLength = Offset + ArrayLength + 1
377
378        #
379        # Create PACKAGE HEADER
380        #
381        Str = WriteLine(Str, '// PACKAGE HEADER\n')
382        TotalLength = TotalLength + ArrayLength
383
384        List = DecToHexList(ArrayLength, 6) + \
385               [StringPackageType] + \
386               DecToHexList(Offset) + \
387               DecToHexList(Offset) + \
388               DecToHexList(EFI_HII_LANGUAGE_WINDOW, EFI_HII_LANGUAGE_WINDOW_LENGTH * 2) * EFI_HII_LANGUAGE_WINDOW_NUMBER + \
389               DecToHexList(EFI_STRING_ID, 4) + \
390               AscToHexList(Language) + \
391               DecToHexList(0, 2)
392        Str = WriteLine(Str, CreateArrayItem(List, 16) + '\n')
393
394        #
395        # Create PACKAGE DATA
396        #
397        Str = WriteLine(Str, '// PACKAGE DATA\n')
398        Str = Write(Str, StrStringValue)
399
400        #
401        # Add an EFI_HII_SIBT_END at last
402        #
403        Str = WriteLine(Str, '  ' + EFI_HII_SIBT_END + ",")
404
405        #
406        # Create binary UNI string
407        #
408        if UniBinBuffer:
409            CreateBinBuffer (UniBinBuffer, List)
410            UniBinBuffer.write (StringBuffer.getvalue())
411            UniBinBuffer.write (pack("B", int(EFI_HII_SIBT_END, 16)))
412        StringBuffer.close()
413
414    #
415    # Create line for string variable name
416    # "unsigned char $(BaseName)Strings[] = {"
417    #
418    AllStr = WriteLine('', CHAR_ARRAY_DEFIN + ' ' + BaseName + COMMON_FILE_NAME + '[] = {\n')
419
420    if IsCompatibleMode:
421        #
422        # Create FRAMEWORK_EFI_HII_PACK_HEADER in compatible mode
423        #
424        AllStr = WriteLine(AllStr, '// FRAMEWORK PACKAGE HEADER Length')
425        AllStr = WriteLine(AllStr, CreateArrayItem(DecToHexList(TotalLength + 2)) + '\n')
426        AllStr = WriteLine(AllStr, '// FRAMEWORK PACKAGE HEADER Type')
427        AllStr = WriteLine(AllStr, CreateArrayItem(DecToHexList(2, 4)) + '\n')
428    else:
429        #
430        # Create whole array length in UEFI mode
431        #
432        AllStr = WriteLine(AllStr, '// STRGATHER_OUTPUT_HEADER')
433        AllStr = WriteLine(AllStr, CreateArrayItem(DecToHexList(TotalLength)) + '\n')
434
435    #
436    # Join package data
437    #
438    AllStr = Write(AllStr, Str)
439
440    return "".join(AllStr)
441
442## Create end of .c file
443#
444# Create end of .c file
445#
446# @retval Str:           A string of .h file end
447#
448def CreateCFileEnd():
449    Str = Write('', '};')
450    return Str
451
452## Create a .c file
453#
454# Create a complete .c file
455#
456# @param BaseName:        The basename of strings
457# @param UniObjectClass   A UniObjectClass instance
458# @param IsCompatibleMode Compatible Mode
459# @param FilterInfo       Platform language filter information
460#
461# @retval CFile:          A string of complete .c file
462#
463def CreateCFile(BaseName, UniObjectClass, IsCompatibleMode, FilterInfo):
464    CFile = ''
465    CFile = WriteLine(CFile, CreateCFileContent(BaseName, UniObjectClass, IsCompatibleMode, None, FilterInfo))
466    CFile = WriteLine(CFile, CreateCFileEnd())
467    return "".join(CFile)
468
469## GetFileList
470#
471# Get a list for all files
472#
473# @param IncludeList:  A list of all path to be searched
474# @param SkipList:     A list of all types of file could be skipped
475#
476# @retval FileList:    A list of all files found
477#
478def GetFileList(SourceFileList, IncludeList, SkipList):
479    if IncludeList is None:
480        EdkLogger.error("UnicodeStringGather", AUTOGEN_ERROR, "Include path for unicode file is not defined")
481
482    FileList = []
483    if SkipList is None:
484        SkipList = []
485
486    for File in SourceFileList:
487        for Dir in IncludeList:
488            if not os.path.exists(Dir):
489                continue
490            File = os.path.join(Dir, File.Path)
491            #
492            # Ignore Dir
493            #
494            if os.path.isfile(File) != True:
495                continue
496            #
497            # Ignore file listed in skip list
498            #
499            IsSkip = False
500            for Skip in SkipList:
501                if os.path.splitext(File)[1].upper() == Skip.upper():
502                    EdkLogger.verbose("Skipped %s for string token uses search" % File)
503                    IsSkip = True
504                    break
505
506            if not IsSkip:
507                FileList.append(File)
508
509            break
510
511    return FileList
512
513## SearchString
514#
515# Search whether all string defined in UniObjectClass are referenced
516# All string used should be set to Referenced
517#
518# @param UniObjectClass:  Input UniObjectClass
519# @param FileList:        Search path list
520# @param IsCompatibleMode Compatible Mode
521#
522# @retval UniObjectClass: UniObjectClass after searched
523#
524def SearchString(UniObjectClass, FileList, IsCompatibleMode):
525    if FileList == []:
526        return UniObjectClass
527
528    for File in FileList:
529        if os.path.isfile(File):
530            Lines = open(File, 'r')
531            for Line in Lines:
532                for StrName in STRING_TOKEN.findall(Line):
533                    EdkLogger.debug(EdkLogger.DEBUG_5, "Found string identifier: " + StrName)
534                    UniObjectClass.SetStringReferenced(StrName)
535
536    UniObjectClass.ReToken()
537
538    return UniObjectClass
539
540## GetStringFiles
541#
542# This function is used for UEFI2.1 spec
543#
544#
545def GetStringFiles(UniFilList, SourceFileList, IncludeList, IncludePathList, SkipList, BaseName, IsCompatibleMode = False, ShellMode = False, UniGenCFlag = True, UniGenBinBuffer = None, FilterInfo = [True, []]):
546    if len(UniFilList) > 0:
547        if ShellMode:
548            #
549            # support ISO 639-2 codes in .UNI files of EDK Shell
550            #
551            Uni = UniFileClassObject(sorted(UniFilList, key=lambda x: x.File), True, IncludePathList)
552        else:
553            Uni = UniFileClassObject(sorted(UniFilList, key=lambda x: x.File), IsCompatibleMode, IncludePathList)
554    else:
555        EdkLogger.error("UnicodeStringGather", AUTOGEN_ERROR, 'No unicode files given')
556
557    FileList = GetFileList(SourceFileList, IncludeList, SkipList)
558
559    Uni = SearchString(Uni, sorted (FileList), IsCompatibleMode)
560
561    HFile = CreateHFile(BaseName, Uni, IsCompatibleMode, UniGenCFlag)
562    CFile = None
563    if IsCompatibleMode or UniGenCFlag:
564        CFile = CreateCFile(BaseName, Uni, IsCompatibleMode, FilterInfo)
565    if UniGenBinBuffer:
566        CreateCFileContent(BaseName, Uni, IsCompatibleMode, UniGenBinBuffer, FilterInfo)
567
568    return HFile, CFile
569
570#
571# Write an item
572#
573def Write(Target, Item):
574    if isinstance(Target,str):
575        Target = [Target]
576    if not Target:
577        Target = []
578    if isinstance(Item,list):
579        Target.extend(Item)
580    else:
581        Target.append(Item)
582    return Target
583
584#
585# Write an item with a break line
586#
587def WriteLine(Target, Item):
588    if isinstance(Target,str):
589        Target = [Target]
590    if not Target:
591        Target = []
592    if isinstance(Item, list):
593        Target.extend(Item)
594    else:
595        Target.append(Item)
596    Target.append('\n')
597    return Target
598
599# This acts like the main() function for the script, unless it is 'import'ed into another
600# script.
601if __name__ == '__main__':
602    EdkLogger.info('start')
603
604    UniFileList = [
605                   r'C:\\Edk\\Strings2.uni',
606                   r'C:\\Edk\\Strings.uni'
607    ]
608
609    SrcFileList = []
610    for Root, Dirs, Files in os.walk('C:\\Edk'):
611        for File in Files:
612            SrcFileList.append(File)
613
614    IncludeList = [
615                   r'C:\\Edk'
616    ]
617
618    SkipList = ['.inf', '.uni']
619    BaseName = 'DriverSample'
620    (h, c) = GetStringFiles(UniFileList, SrcFileList, IncludeList, SkipList, BaseName, True)
621    hfile = open('unistring.h', 'w')
622    cfile = open('unistring.c', 'w')
623    hfile.write(h)
624    cfile.write(c)
625
626    EdkLogger.info('end')
627