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