]> git.proxmox.com Git - efi-boot-shim.git/blob - gnu-efi/lib/misc.c
Update upstream source from tag 'upstream/15.5'
[efi-boot-shim.git] / gnu-efi / 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 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;
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
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
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 #define strcmp(s1, s2) __builtin_strcmp(s1, s2)
527
528 CHAR16 *
529 LibGetUiString (
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 }