xref: /DragonStub/lib/misc.c (revision f412fd2a1a248b546b7085648dece8d908077fab)
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 EFIAPI
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 EFIAPI
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 CONST VOID     *Dest,
124     IN CONST 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     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 
242 VOID *
243 LibGetVariableAndSize (
244     IN CHAR16               *Name,
245     IN EFI_GUID             *VendorGuid,
246     OUT UINTN               *VarSize
247     )
248 {
249     EFI_STATUS              Status = EFI_SUCCESS;
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 
283 VOID *
284 LibGetVariable (
285     IN CHAR16               *Name,
286     IN EFI_GUID             *VendorGuid
287     )
288 {
289     UINTN   VarSize;
290 
291     return LibGetVariableAndSize (Name, VendorGuid, &VarSize);
292 }
293 
294 EFI_STATUS
295 LibDeleteVariable (
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 
325 EFI_STATUS
326 LibSetNVVariable (
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 
346 EFI_STATUS
347 LibSetVariable (
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 
367 EFI_STATUS
368 LibInsertToTailOfBootOrder (
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     if (!NewBootOptionArray)
390         return EFI_OUT_OF_RESOURCES;
391 
392     for (Index = 0; Index < ((VarSize/sizeof(UINT16)) - 1); Index++) {
393         NewBootOptionArray[Index] = BootOptionArray[Index];
394     }
395     //
396     // Insert in the tail of the array
397     //
398     NewBootOptionArray[Index] = BootOption;
399 
400     Status = uefi_call_wrapper(
401 		RT->SetVariable,
402 		5,
403                 VarBootOrder, &EfiGlobalVariable,
404                 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
405                 VarSize, (VOID*) NewBootOptionArray
406                 );
407 
408     FreePool (NewBootOptionArray);
409     if (BootOptionArray) {
410         FreePool (BootOptionArray);
411     }
412     return Status;
413 }
414 
415 
416 BOOLEAN
417 ValidMBR(
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 
491 UINT8
492 DecimaltoBCD(
493     IN  UINT8 DecValue
494     )
495 {
496     return RtDecimaltoBCD (DecValue);
497 }
498 
499 
500 UINT8
501 BCDtoDecimal(
502     IN  UINT8 BcdValue
503     )
504 {
505     return RtBCDtoDecimal (BcdValue);
506 }
507 
508 EFI_STATUS
509 LibGetSystemConfigurationTable(
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 
527 CHAR16 *
528 LibGetUiString (
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