]> git.proxmox.com Git - efi-boot-shim.git/blame - gnu-efi/lib/misc.c
New upstream version 15.5
[efi-boot-shim.git] / gnu-efi / lib / misc.c
CommitLineData
031e5cce
SM
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
8529e0f7 101VOID EFIAPI
031e5cce
SM
102SetMem (
103 IN VOID *Buffer,
104 IN UINTN Size,
105 IN UINT8 Value
106 )
107{
108 RtSetMem (Buffer, Size, Value);
109}
110
8529e0f7 111VOID EFIAPI
031e5cce
SM
112CopyMem (
113 IN VOID *Dest,
8529e0f7 114 IN VOID *Src,
031e5cce
SM
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#define strcmp(s1, s2) __builtin_strcmp(s1, s2)
527
528CHAR16 *
529LibGetUiString (
530 IN EFI_HANDLE Handle,
531 IN UI_STRING_TYPE StringType,
532 IN ISO_639_2 *LangCode,
533 IN BOOLEAN ReturnDevicePathStrOnMismatch
534 )
535{
536 UI_INTERFACE *Ui;
537 UI_STRING_TYPE Index;
538 UI_STRING_ENTRY *Array;
539 EFI_STATUS Status;
540
541 Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handle, &UiProtocol, (VOID *)&Ui);
542 if (EFI_ERROR(Status)) {
543 return (ReturnDevicePathStrOnMismatch) ? DevicePathToStr(DevicePathFromHandle(Handle)) : NULL;
544 }
545
546 //
547 // Skip the first strings
548 //
549 for (Index = UiDeviceString, Array = Ui->Entry; Index < StringType; Index++, Array++) {
550 while (Array->LangCode) {
551 Array++;
552 }
553 }
554
555 //
556 // Search for the match
557 //
558 while (Array->LangCode) {
559 if (strcmp(Array->LangCode, LangCode) == 0) {
560 return Array->UiString;
561 }
562 }
563 return (ReturnDevicePathStrOnMismatch) ? DevicePathToStr(DevicePathFromHandle(Handle)) : NULL;
564}