Imported Upstream version 3.0
[platform/upstream/gnu-efi.git] / lib / misc.c
1 /*++
2
3 Copyright (c) 1998  Intel Corporation
4
5 Module Name:
6
7     misc.c
8
9 Abstract:
10
11
12
13
14 Revision History
15
16 --*/
17
18 #include "lib.h"
19
20
21 //
22 //
23 //
24
25 VOID *
26 AllocatePool (
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
41 VOID *
42 AllocateZeroPool (
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
56 VOID *
57 ReallocatePool (
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
82 VOID
83 FreePool (
84     IN VOID                 *Buffer
85     )
86 {
87     uefi_call_wrapper(BS->FreePool, 1, Buffer);
88 }
89
90
91
92 VOID
93 ZeroMem (
94     IN VOID     *Buffer,
95     IN UINTN    Size
96     )
97 {
98     RtZeroMem (Buffer, Size);
99 }
100
101 VOID
102 SetMem (
103     IN VOID     *Buffer,
104     IN UINTN    Size,
105     IN UINT8    Value    
106     )
107 {
108     RtSetMem (Buffer, Size, Value);
109 }
110
111 VOID
112 CopyMem (
113     IN VOID     *Dest,
114     IN VOID     *Src,
115     IN UINTN    len
116     )
117 {
118     RtCopyMem (Dest, Src, len);
119 }
120
121 INTN
122 CompareMem (
123     IN VOID     *Dest,
124     IN VOID     *Src,
125     IN UINTN    len
126     )
127 {
128     return RtCompareMem (Dest, Src, len);
129 }
130
131 BOOLEAN
132 GrowBuffer(
133     IN OUT EFI_STATUS   *Status,
134     IN OUT VOID         **Buffer,
135     IN UINTN            BufferSize
136     )
137 /*++
138
139 Routine 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
145 Arguments:
146
147     Status      - Current status
148
149     Buffer      - Current allocated buffer, or NULL
150
151     BufferSize  - Current buffer size needed
152     
153 Returns:
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
203 EFI_MEMORY_DESCRIPTOR *
204 LibMemoryMap (
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     Buffer = NULL;
220     BufferSize = sizeof(EFI_MEMORY_DESCRIPTOR);
221
222     //
223     // Call the real function
224     //
225
226     while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
227         Status = uefi_call_wrapper(BS->GetMemoryMap, 5, &BufferSize, Buffer, MapKey, DescriptorSize, DescriptorVersion);
228     }
229
230     //
231     // Convert buffer size to NoEntries
232     //
233
234     if (!EFI_ERROR(Status)) {
235         *NoEntries = BufferSize / *DescriptorSize;
236     }
237
238     return Buffer;
239 }
240
241 VOID *
242 LibGetVariableAndSize (
243     IN CHAR16               *Name,
244     IN EFI_GUID             *VendorGuid,
245     OUT UINTN               *VarSize
246     )
247 {
248     EFI_STATUS              Status;
249     VOID                    *Buffer;
250     UINTN                   BufferSize;
251
252     //
253     // Initialize for GrowBuffer loop
254     //
255
256     Buffer = NULL;
257     BufferSize = 100;
258
259     //
260     // Call the real function
261     //
262
263     while (GrowBuffer (&Status, &Buffer, BufferSize)) {
264         Status = uefi_call_wrapper(
265                     RT->GetVariable,
266                         5,
267                     Name,
268                     VendorGuid,
269                     NULL,
270                     &BufferSize,
271                     Buffer
272                     );
273     }
274     if (Buffer) {
275         *VarSize = BufferSize;
276     } else {
277         *VarSize = 0;
278     }
279     return Buffer;
280 }
281     
282 VOID *
283 LibGetVariable (
284     IN CHAR16               *Name,
285     IN EFI_GUID             *VendorGuid
286     )
287 {
288     UINTN   VarSize;
289
290     return LibGetVariableAndSize (Name, VendorGuid, &VarSize);
291 }
292
293 EFI_STATUS
294 LibDeleteVariable (
295     IN CHAR16   *VarName,
296     IN EFI_GUID *VarGuid
297     )
298 {
299     VOID        *VarBuf;
300     EFI_STATUS  Status;
301
302     VarBuf = LibGetVariable(VarName,VarGuid);
303
304     Status = EFI_NOT_FOUND;
305
306     if (VarBuf) {
307         //
308         // Delete variable from Storage
309         //
310         Status = uefi_call_wrapper(
311                     RT->SetVariable,
312                         5,
313                     VarName, VarGuid,
314                     EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
315                     0, NULL
316                  );
317         ASSERT (!EFI_ERROR(Status));
318         FreePool(VarBuf);
319     }
320
321     return (Status);
322 }
323
324 EFI_STATUS
325 LibInsertToTailOfBootOrder (
326     IN  UINT16  BootOption,
327     IN  BOOLEAN OnlyInsertIfEmpty
328     )
329 {
330     UINT16      *BootOptionArray;
331     UINT16      *NewBootOptionArray;
332     UINTN       VarSize;
333     UINTN       Index;
334     EFI_STATUS  Status;
335
336     BootOptionArray = LibGetVariableAndSize (VarBootOrder, &EfiGlobalVariable, &VarSize);    
337     if (VarSize != 0 && OnlyInsertIfEmpty) {
338         if (BootOptionArray) {
339             FreePool (BootOptionArray);
340         }
341         return EFI_UNSUPPORTED;
342     }
343
344     VarSize += sizeof(UINT16);
345     NewBootOptionArray = AllocatePool (VarSize);
346     
347     for (Index = 0; Index < ((VarSize/sizeof(UINT16)) - 1); Index++) {
348         NewBootOptionArray[Index] = BootOptionArray[Index];
349     }
350     //
351     // Insert in the tail of the array
352     //
353     NewBootOptionArray[Index] = BootOption;
354
355     Status = uefi_call_wrapper(
356                 RT->SetVariable,
357                 5,
358                 VarBootOrder, &EfiGlobalVariable,
359                 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
360                 VarSize, (VOID*) NewBootOptionArray
361                 );
362
363     if (NewBootOptionArray) {
364         FreePool (NewBootOptionArray);
365     }
366     if (BootOptionArray) {
367         FreePool (BootOptionArray);
368     }
369     return Status;
370 }
371
372
373 BOOLEAN
374 ValidMBR(
375     IN  MASTER_BOOT_RECORD  *Mbr,
376     IN  EFI_BLOCK_IO        *BlkIo
377     )
378 {
379     UINT32      StartingLBA, EndingLBA;
380     UINT32      NewEndingLBA;
381     INTN        i, j;
382     BOOLEAN     ValidMbr;
383
384     if (Mbr->Signature != MBR_SIGNATURE) {
385         //
386         // The BPB also has this signature, so it can not be used alone.
387         //
388         return FALSE;
389     } 
390
391     ValidMbr = FALSE;
392     for (i=0; i<MAX_MBR_PARTITIONS; i++) {
393         if ( Mbr->Partition[i].OSIndicator == 0x00 || EXTRACT_UINT32(Mbr->Partition[i].SizeInLBA) == 0 ) {
394             continue;
395         }
396         ValidMbr = TRUE;
397         StartingLBA = EXTRACT_UINT32(Mbr->Partition[i].StartingLBA);
398         EndingLBA = StartingLBA + EXTRACT_UINT32(Mbr->Partition[i].SizeInLBA) - 1;
399         if (EndingLBA > BlkIo->Media->LastBlock) {
400             //
401             // Compatability Errata:
402             //  Some systems try to hide drive space with thier INT 13h driver
403             //  This does not hide space from the OS driver. This means the MBR
404             //  that gets created from DOS is smaller than the MBR created from 
405             //  a real OS (NT & Win98). This leads to BlkIo->LastBlock being 
406             //  wrong on some systems FDISKed by the OS.
407             //
408             //
409             if (BlkIo->Media->LastBlock < MIN_MBR_DEVICE_SIZE) {
410                 //
411                 // If this is a very small device then trust the BlkIo->LastBlock
412                 //
413                 return FALSE;
414             }
415
416             if (EndingLBA > (BlkIo->Media->LastBlock + MBR_ERRATA_PAD)) {
417                 return FALSE;
418             }
419
420         }
421         for (j=i+1; j<MAX_MBR_PARTITIONS; j++) {
422             if (Mbr->Partition[j].OSIndicator == 0x00 || EXTRACT_UINT32(Mbr->Partition[j].SizeInLBA) == 0) {
423                 continue;
424             }
425             if (   EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) >= StartingLBA && 
426                    EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) <= EndingLBA       ) {
427                 //
428                 // The Start of this region overlaps with the i'th region
429                 //
430                 return FALSE;
431             } 
432             NewEndingLBA = EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) + EXTRACT_UINT32(Mbr->Partition[j].SizeInLBA) - 1;
433             if ( NewEndingLBA >= StartingLBA && NewEndingLBA <= EndingLBA ) {
434                 //
435                 // The End of this region overlaps with the i'th region
436                 //
437                 return FALSE;
438             }
439         }
440     }
441     //
442     // Non of the regions overlapped so MBR is O.K.
443     //
444     return ValidMbr;
445
446    
447
448 UINT8
449 DecimaltoBCD(
450     IN  UINT8 DecValue
451     )
452 {
453     return RtDecimaltoBCD (DecValue);
454 }
455
456
457 UINT8
458 BCDtoDecimal(
459     IN  UINT8 BcdValue
460     )
461 {
462     return RtBCDtoDecimal (BcdValue);
463 }
464
465 EFI_STATUS
466 LibGetSystemConfigurationTable(
467     IN EFI_GUID *TableGuid,
468     IN OUT VOID **Table
469     )
470
471 {
472     UINTN Index;
473
474     for(Index=0;Index<ST->NumberOfTableEntries;Index++) {
475         if (CompareGuid(TableGuid,&(ST->ConfigurationTable[Index].VendorGuid))==0) {
476             *Table = ST->ConfigurationTable[Index].VendorTable;
477             return EFI_SUCCESS;
478         }
479     }
480     return EFI_NOT_FOUND;
481 }
482
483
484 CHAR16 *
485 LibGetUiString (
486     IN  EFI_HANDLE      Handle,
487     IN  UI_STRING_TYPE  StringType,
488     IN  ISO_639_2       *LangCode,
489     IN  BOOLEAN         ReturnDevicePathStrOnMismatch
490     )
491 {
492     UI_INTERFACE    *Ui;
493     UI_STRING_TYPE  Index;
494     UI_STRING_ENTRY *Array;
495     EFI_STATUS      Status;
496     
497     Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handle, &UiProtocol, (VOID *)&Ui);
498     if (EFI_ERROR(Status)) {
499         return (ReturnDevicePathStrOnMismatch) ? DevicePathToStr(DevicePathFromHandle(Handle)) : NULL;
500     }
501
502     //
503     // Skip the first strings
504     //
505     for (Index = UiDeviceString, Array = Ui->Entry; Index < StringType; Index++, Array++) {
506         while (Array->LangCode) {
507             Array++;
508         }
509     }
510
511     //
512     // Search for the match
513     //
514     while (Array->LangCode) {
515         if (strcmpa (Array->LangCode, LangCode) == 0) {
516             return Array->UiString; 
517         }
518     }
519     return (ReturnDevicePathStrOnMismatch) ? DevicePathToStr(DevicePathFromHandle(Handle)) : NULL;
520 }