1/*++
2
3Copyright (c) 1998  Intel Corporation
4
5Module Name:
6
7    misc.c
8
9Abstract:
10
11
12
13
14Revision History
15
16--*/
17
18#include "lib.h"
19
20
21//
22//
23//
24
25VOID *
26AllocatePool (
27    IN UINTN                Size
28    )
29{
30    EFI_STATUS              Status;
31    VOID                    *p;
32
33    Status = uefi_call_wrapper(BS->AllocatePool, 3, PoolAllocationType, Size, &p);
34    if (EFI_ERROR(Status)) {
35        DEBUG((D_ERROR, "AllocatePool: out of pool  %x\n", Status));
36        p = NULL;
37    }
38    return p;
39}
40
41VOID *
42AllocateZeroPool (
43    IN UINTN                Size
44    )
45{
46    VOID                    *p;
47
48    p = AllocatePool (Size);
49    if (p) {
50        ZeroMem (p, Size);
51    }
52
53    return p;
54}
55
56VOID *
57ReallocatePool (
58    IN VOID                 *OldPool,
59    IN UINTN                OldSize,
60    IN UINTN                NewSize
61    )
62{
63    VOID                    *NewPool;
64
65    NewPool = NULL;
66    if (NewSize) {
67        NewPool = AllocatePool (NewSize);
68    }
69
70    if (OldPool) {
71        if (NewPool) {
72            CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);
73        }
74
75        FreePool (OldPool);
76    }
77
78    return NewPool;
79}
80
81
82VOID
83FreePool (
84    IN VOID                 *Buffer
85    )
86{
87    uefi_call_wrapper(BS->FreePool, 1, Buffer);
88}
89
90
91
92VOID
93ZeroMem (
94    IN VOID     *Buffer,
95    IN UINTN    Size
96    )
97{
98    RtZeroMem (Buffer, Size);
99}
100
101VOID
102SetMem (
103    IN VOID     *Buffer,
104    IN UINTN    Size,
105    IN UINT8    Value
106    )
107{
108    RtSetMem (Buffer, Size, Value);
109}
110
111VOID
112CopyMem (
113    IN VOID     *Dest,
114    IN CONST VOID     *Src,
115    IN UINTN    len
116    )
117{
118    RtCopyMem (Dest, Src, len);
119}
120
121INTN
122CompareMem (
123    IN CONST VOID     *Dest,
124    IN CONST VOID     *Src,
125    IN UINTN    len
126    )
127{
128    return RtCompareMem (Dest, Src, len);
129}
130
131BOOLEAN
132GrowBuffer(
133    IN OUT EFI_STATUS   *Status,
134    IN OUT VOID         **Buffer,
135    IN UINTN            BufferSize
136    )
137/*++
138
139Routine Description:
140
141    Helper function called as part of the code needed
142    to allocate the proper sized buffer for various
143    EFI interfaces.
144
145Arguments:
146
147    Status      - Current status
148
149    Buffer      - Current allocated buffer, or NULL
150
151    BufferSize  - Current buffer size needed
152
153Returns:
154
155    TRUE - if the buffer was reallocated and the caller
156    should try the API again.
157
158--*/
159{
160    BOOLEAN         TryAgain;
161
162    //
163    // If this is an initial request, buffer will be null with a new buffer size
164    //
165
166    if (!*Buffer && BufferSize) {
167        *Status = EFI_BUFFER_TOO_SMALL;
168    }
169
170    //
171    // If the status code is "buffer too small", resize the buffer
172    //
173
174    TryAgain = FALSE;
175    if (*Status == EFI_BUFFER_TOO_SMALL) {
176
177        if (*Buffer) {
178            FreePool (*Buffer);
179        }
180
181        *Buffer = AllocatePool (BufferSize);
182
183        if (*Buffer) {
184            TryAgain = TRUE;
185        } else {
186            *Status = EFI_OUT_OF_RESOURCES;
187        }
188    }
189
190    //
191    // If there's an error, free the buffer
192    //
193
194    if (!TryAgain && EFI_ERROR(*Status) && *Buffer) {
195        FreePool (*Buffer);
196        *Buffer = NULL;
197    }
198
199    return TryAgain;
200}
201
202
203EFI_MEMORY_DESCRIPTOR *
204LibMemoryMap (
205    OUT UINTN               *NoEntries,
206    OUT UINTN               *MapKey,
207    OUT UINTN               *DescriptorSize,
208    OUT UINT32              *DescriptorVersion
209    )
210{
211    EFI_STATUS              Status;
212    EFI_MEMORY_DESCRIPTOR   *Buffer;
213    UINTN                   BufferSize;
214
215    //
216    // Initialize for GrowBuffer loop
217    //
218
219    Status = EFI_SUCCESS;
220    Buffer = NULL;
221    BufferSize = sizeof(EFI_MEMORY_DESCRIPTOR);
222
223    //
224    // Call the real function
225    //
226
227    while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
228        Status = uefi_call_wrapper(BS->GetMemoryMap, 5, &BufferSize, Buffer, MapKey, DescriptorSize, DescriptorVersion);
229    }
230
231    //
232    // Convert buffer size to NoEntries
233    //
234
235    if (!EFI_ERROR(Status)) {
236        *NoEntries = BufferSize / *DescriptorSize;
237    }
238
239    return Buffer;
240}
241
242VOID *
243LibGetVariableAndSize (
244    IN CHAR16               *Name,
245    IN EFI_GUID             *VendorGuid,
246    OUT UINTN               *VarSize
247    )
248{
249    EFI_STATUS              Status;
250    VOID                    *Buffer;
251    UINTN                   BufferSize;
252
253    //
254    // Initialize for GrowBuffer loop
255    //
256
257    Buffer = NULL;
258    BufferSize = 100;
259
260    //
261    // Call the real function
262    //
263
264    while (GrowBuffer (&Status, &Buffer, BufferSize)) {
265        Status = uefi_call_wrapper(
266		    RT->GetVariable,
267			5,
268                    Name,
269                    VendorGuid,
270                    NULL,
271                    &BufferSize,
272                    Buffer
273                    );
274    }
275    if (Buffer) {
276        *VarSize = BufferSize;
277    } else {
278        *VarSize = 0;
279    }
280    return Buffer;
281}
282
283VOID *
284LibGetVariable (
285    IN CHAR16               *Name,
286    IN EFI_GUID             *VendorGuid
287    )
288{
289    UINTN   VarSize;
290
291    return LibGetVariableAndSize (Name, VendorGuid, &VarSize);
292}
293
294EFI_STATUS
295LibDeleteVariable (
296    IN CHAR16   *VarName,
297    IN EFI_GUID *VarGuid
298    )
299{
300    VOID        *VarBuf;
301    EFI_STATUS  Status;
302
303    VarBuf = LibGetVariable(VarName,VarGuid);
304
305    Status = EFI_NOT_FOUND;
306
307    if (VarBuf) {
308        //
309        // Delete variable from Storage
310        //
311        Status = uefi_call_wrapper(
312		    RT->SetVariable,
313			5,
314                    VarName, VarGuid,
315                    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
316                    0, NULL
317                 );
318        ASSERT (!EFI_ERROR(Status));
319        FreePool(VarBuf);
320    }
321
322    return (Status);
323}
324
325EFI_STATUS
326LibSetNVVariable (
327    IN CHAR16   *VarName,
328    IN EFI_GUID *VarGuid,
329    IN UINTN	 DataSize,
330    IN VOID     *Data
331    )
332{
333    EFI_STATUS  Status;
334
335    Status = uefi_call_wrapper(
336	    RT->SetVariable,
337	    5,
338	    VarName, VarGuid,
339	    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
340	    DataSize, Data
341	    );
342    ASSERT (!EFI_ERROR(Status));
343    return (Status);
344}
345
346EFI_STATUS
347LibSetVariable (
348    IN CHAR16   *VarName,
349    IN EFI_GUID *VarGuid,
350    IN UINTN	 DataSize,
351    IN VOID     *Data
352    )
353{
354    EFI_STATUS  Status;
355
356    Status = uefi_call_wrapper(
357	    RT->SetVariable,
358	    5,
359	    VarName, VarGuid,
360	    EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
361	    DataSize, Data
362	    );
363    ASSERT (!EFI_ERROR(Status));
364    return (Status);
365}
366
367EFI_STATUS
368LibInsertToTailOfBootOrder (
369    IN  UINT16  BootOption,
370    IN  BOOLEAN OnlyInsertIfEmpty
371    )
372{
373    UINT16      *BootOptionArray;
374    UINT16      *NewBootOptionArray;
375    UINTN       VarSize;
376    UINTN       Index;
377    EFI_STATUS  Status;
378
379    BootOptionArray = LibGetVariableAndSize (VarBootOrder, &EfiGlobalVariable, &VarSize);
380    if (VarSize != 0 && OnlyInsertIfEmpty) {
381        if (BootOptionArray) {
382            FreePool (BootOptionArray);
383        }
384        return EFI_UNSUPPORTED;
385    }
386
387    VarSize += sizeof(UINT16);
388    NewBootOptionArray = AllocatePool (VarSize);
389
390    for (Index = 0; Index < ((VarSize/sizeof(UINT16)) - 1); Index++) {
391        NewBootOptionArray[Index] = BootOptionArray[Index];
392    }
393    //
394    // Insert in the tail of the array
395    //
396    NewBootOptionArray[Index] = BootOption;
397
398    Status = uefi_call_wrapper(
399		RT->SetVariable,
400		5,
401                VarBootOrder, &EfiGlobalVariable,
402                EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
403                VarSize, (VOID*) NewBootOptionArray
404                );
405
406    if (NewBootOptionArray) {
407        FreePool (NewBootOptionArray);
408    }
409    if (BootOptionArray) {
410        FreePool (BootOptionArray);
411    }
412    return Status;
413}
414
415
416BOOLEAN
417ValidMBR(
418    IN  MASTER_BOOT_RECORD  *Mbr,
419    IN  EFI_BLOCK_IO        *BlkIo
420    )
421{
422    UINT32      StartingLBA, EndingLBA;
423    UINT32      NewEndingLBA;
424    INTN        i, j;
425    BOOLEAN     ValidMbr;
426
427    if (Mbr->Signature != MBR_SIGNATURE) {
428        //
429        // The BPB also has this signature, so it can not be used alone.
430        //
431        return FALSE;
432    }
433
434    ValidMbr = FALSE;
435    for (i=0; i<MAX_MBR_PARTITIONS; i++) {
436        if ( Mbr->Partition[i].OSIndicator == 0x00 || EXTRACT_UINT32(Mbr->Partition[i].SizeInLBA) == 0 ) {
437            continue;
438        }
439        ValidMbr = TRUE;
440        StartingLBA = EXTRACT_UINT32(Mbr->Partition[i].StartingLBA);
441        EndingLBA = StartingLBA + EXTRACT_UINT32(Mbr->Partition[i].SizeInLBA) - 1;
442        if (EndingLBA > BlkIo->Media->LastBlock) {
443            //
444            // Compatability Errata:
445            //  Some systems try to hide drive space with thier INT 13h driver
446            //  This does not hide space from the OS driver. This means the MBR
447            //  that gets created from DOS is smaller than the MBR created from
448            //  a real OS (NT & Win98). This leads to BlkIo->LastBlock being
449            //  wrong on some systems FDISKed by the OS.
450            //
451            //
452            if (BlkIo->Media->LastBlock < MIN_MBR_DEVICE_SIZE) {
453                //
454                // If this is a very small device then trust the BlkIo->LastBlock
455                //
456                return FALSE;
457            }
458
459            if (EndingLBA > (BlkIo->Media->LastBlock + MBR_ERRATA_PAD)) {
460                return FALSE;
461            }
462
463        }
464        for (j=i+1; j<MAX_MBR_PARTITIONS; j++) {
465            if (Mbr->Partition[j].OSIndicator == 0x00 || EXTRACT_UINT32(Mbr->Partition[j].SizeInLBA) == 0) {
466                continue;
467            }
468            if (   EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) >= StartingLBA &&
469                   EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) <= EndingLBA       ) {
470                //
471                // The Start of this region overlaps with the i'th region
472                //
473                return FALSE;
474            }
475            NewEndingLBA = EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) + EXTRACT_UINT32(Mbr->Partition[j].SizeInLBA) - 1;
476            if ( NewEndingLBA >= StartingLBA && NewEndingLBA <= EndingLBA ) {
477                //
478                // The End of this region overlaps with the i'th region
479                //
480                return FALSE;
481            }
482        }
483    }
484    //
485    // Non of the regions overlapped so MBR is O.K.
486    //
487    return ValidMbr;
488}
489
490
491UINT8
492DecimaltoBCD(
493    IN  UINT8 DecValue
494    )
495{
496    return RtDecimaltoBCD (DecValue);
497}
498
499
500UINT8
501BCDtoDecimal(
502    IN  UINT8 BcdValue
503    )
504{
505    return RtBCDtoDecimal (BcdValue);
506}
507
508EFI_STATUS
509LibGetSystemConfigurationTable(
510    IN EFI_GUID *TableGuid,
511    IN OUT VOID **Table
512    )
513
514{
515    UINTN Index;
516
517    for(Index=0;Index<ST->NumberOfTableEntries;Index++) {
518        if (CompareGuid(TableGuid,&(ST->ConfigurationTable[Index].VendorGuid))==0) {
519            *Table = ST->ConfigurationTable[Index].VendorTable;
520            return EFI_SUCCESS;
521        }
522    }
523    return EFI_NOT_FOUND;
524}
525
526
527CHAR16 *
528LibGetUiString (
529    IN  EFI_HANDLE      Handle,
530    IN  UI_STRING_TYPE  StringType,
531    IN  ISO_639_2       *LangCode,
532    IN  BOOLEAN         ReturnDevicePathStrOnMismatch
533    )
534{
535    UI_INTERFACE    *Ui;
536    UI_STRING_TYPE  Index;
537    UI_STRING_ENTRY *Array;
538    EFI_STATUS      Status;
539
540    Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handle, &UiProtocol, (VOID *)&Ui);
541    if (EFI_ERROR(Status)) {
542        return (ReturnDevicePathStrOnMismatch) ? DevicePathToStr(DevicePathFromHandle(Handle)) : NULL;
543    }
544
545    //
546    // Skip the first strings
547    //
548    for (Index = UiDeviceString, Array = Ui->Entry; Index < StringType; Index++, Array++) {
549        while (Array->LangCode) {
550            Array++;
551        }
552    }
553
554    //
555    // Search for the match
556    //
557    while (Array->LangCode) {
558        if (strcmpa (Array->LangCode, LangCode) == 0) {
559            return Array->UiString;
560        }
561    }
562    return (ReturnDevicePathStrOnMismatch) ? DevicePathToStr(DevicePathFromHandle(Handle)) : NULL;
563}
564