misc.c revision 1.1.1.2 1 /* $NetBSD: misc.c,v 1.1.1.2 2018/08/16 18:17:47 jmcneill 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 CONST VOID *Src,
117 IN UINTN len
118 )
119 {
120 RtCopyMem (Dest, Src, len);
121 }
122
123 INTN
124 CompareMem (
125 IN CONST VOID *Dest,
126 IN CONST 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 Status = EFI_SUCCESS;
222 Buffer = NULL;
223 BufferSize = sizeof(EFI_MEMORY_DESCRIPTOR);
224
225 //
226 // Call the real function
227 //
228
229 while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
230 Status = uefi_call_wrapper(BS->GetMemoryMap, 5, &BufferSize, Buffer, MapKey, DescriptorSize, DescriptorVersion);
231 }
232
233 //
234 // Convert buffer size to NoEntries
235 //
236
237 if (!EFI_ERROR(Status)) {
238 *NoEntries = BufferSize / *DescriptorSize;
239 }
240
241 return Buffer;
242 }
243
244 VOID *
245 LibGetVariableAndSize (
246 IN CHAR16 *Name,
247 IN EFI_GUID *VendorGuid,
248 OUT UINTN *VarSize
249 )
250 {
251 EFI_STATUS Status;
252 VOID *Buffer;
253 UINTN BufferSize;
254
255 //
256 // Initialize for GrowBuffer loop
257 //
258
259 Buffer = NULL;
260 BufferSize = 100;
261
262 //
263 // Call the real function
264 //
265
266 while (GrowBuffer (&Status, &Buffer, BufferSize)) {
267 Status = uefi_call_wrapper(
268 RT->GetVariable,
269 5,
270 Name,
271 VendorGuid,
272 NULL,
273 &BufferSize,
274 Buffer
275 );
276 }
277 if (Buffer) {
278 *VarSize = BufferSize;
279 } else {
280 *VarSize = 0;
281 }
282 return Buffer;
283 }
284
285 VOID *
286 LibGetVariable (
287 IN CHAR16 *Name,
288 IN EFI_GUID *VendorGuid
289 )
290 {
291 UINTN VarSize;
292
293 return LibGetVariableAndSize (Name, VendorGuid, &VarSize);
294 }
295
296 EFI_STATUS
297 LibDeleteVariable (
298 IN CHAR16 *VarName,
299 IN EFI_GUID *VarGuid
300 )
301 {
302 VOID *VarBuf;
303 EFI_STATUS Status;
304
305 VarBuf = LibGetVariable(VarName,VarGuid);
306
307 Status = EFI_NOT_FOUND;
308
309 if (VarBuf) {
310 //
311 // Delete variable from Storage
312 //
313 Status = uefi_call_wrapper(
314 RT->SetVariable,
315 5,
316 VarName, VarGuid,
317 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
318 0, NULL
319 );
320 ASSERT (!EFI_ERROR(Status));
321 FreePool(VarBuf);
322 }
323
324 return (Status);
325 }
326
327 EFI_STATUS
328 LibSetNVVariable (
329 IN CHAR16 *VarName,
330 IN EFI_GUID *VarGuid,
331 IN UINTN DataSize,
332 IN VOID *Data
333 )
334 {
335 EFI_STATUS Status;
336
337 Status = uefi_call_wrapper(
338 RT->SetVariable,
339 5,
340 VarName, VarGuid,
341 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
342 DataSize, Data
343 );
344 ASSERT (!EFI_ERROR(Status));
345 return (Status);
346 }
347
348 EFI_STATUS
349 LibSetVariable (
350 IN CHAR16 *VarName,
351 IN EFI_GUID *VarGuid,
352 IN UINTN DataSize,
353 IN VOID *Data
354 )
355 {
356 EFI_STATUS Status;
357
358 Status = uefi_call_wrapper(
359 RT->SetVariable,
360 5,
361 VarName, VarGuid,
362 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
363 DataSize, Data
364 );
365 ASSERT (!EFI_ERROR(Status));
366 return (Status);
367 }
368
369 EFI_STATUS
370 LibInsertToTailOfBootOrder (
371 IN UINT16 BootOption,
372 IN BOOLEAN OnlyInsertIfEmpty
373 )
374 {
375 UINT16 *BootOptionArray;
376 UINT16 *NewBootOptionArray;
377 UINTN VarSize;
378 UINTN Index;
379 EFI_STATUS Status;
380
381 BootOptionArray = LibGetVariableAndSize (VarBootOrder, &EfiGlobalVariable, &VarSize);
382 if (VarSize != 0 && OnlyInsertIfEmpty) {
383 if (BootOptionArray) {
384 FreePool (BootOptionArray);
385 }
386 return EFI_UNSUPPORTED;
387 }
388
389 VarSize += sizeof(UINT16);
390 NewBootOptionArray = AllocatePool (VarSize);
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 if (NewBootOptionArray) {
409 FreePool (NewBootOptionArray);
410 }
411 if (BootOptionArray) {
412 FreePool (BootOptionArray);
413 }
414 return Status;
415 }
416
417
418 BOOLEAN
419 ValidMBR(
420 IN MASTER_BOOT_RECORD *Mbr,
421 IN EFI_BLOCK_IO *BlkIo
422 )
423 {
424 UINT32 StartingLBA, EndingLBA;
425 UINT32 NewEndingLBA;
426 INTN i, j;
427 BOOLEAN ValidMbr;
428
429 if (Mbr->Signature != MBR_SIGNATURE) {
430 //
431 // The BPB also has this signature, so it can not be used alone.
432 //
433 return FALSE;
434 }
435
436 ValidMbr = FALSE;
437 for (i=0; i<MAX_MBR_PARTITIONS; i++) {
438 if ( Mbr->Partition[i].OSIndicator == 0x00 || EXTRACT_UINT32(Mbr->Partition[i].SizeInLBA) == 0 ) {
439 continue;
440 }
441 ValidMbr = TRUE;
442 StartingLBA = EXTRACT_UINT32(Mbr->Partition[i].StartingLBA);
443 EndingLBA = StartingLBA + EXTRACT_UINT32(Mbr->Partition[i].SizeInLBA) - 1;
444 if (EndingLBA > BlkIo->Media->LastBlock) {
445 //
446 // Compatability Errata:
447 // Some systems try to hide drive space with thier INT 13h driver
448 // This does not hide space from the OS driver. This means the MBR
449 // that gets created from DOS is smaller than the MBR created from
450 // a real OS (NT & Win98). This leads to BlkIo->LastBlock being
451 // wrong on some systems FDISKed by the OS.
452 //
453 //
454 if (BlkIo->Media->LastBlock < MIN_MBR_DEVICE_SIZE) {
455 //
456 // If this is a very small device then trust the BlkIo->LastBlock
457 //
458 return FALSE;
459 }
460
461 if (EndingLBA > (BlkIo->Media->LastBlock + MBR_ERRATA_PAD)) {
462 return FALSE;
463 }
464
465 }
466 for (j=i+1; j<MAX_MBR_PARTITIONS; j++) {
467 if (Mbr->Partition[j].OSIndicator == 0x00 || EXTRACT_UINT32(Mbr->Partition[j].SizeInLBA) == 0) {
468 continue;
469 }
470 if ( EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) >= StartingLBA &&
471 EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) <= EndingLBA ) {
472 //
473 // The Start of this region overlaps with the i'th region
474 //
475 return FALSE;
476 }
477 NewEndingLBA = EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) + EXTRACT_UINT32(Mbr->Partition[j].SizeInLBA) - 1;
478 if ( NewEndingLBA >= StartingLBA && NewEndingLBA <= EndingLBA ) {
479 //
480 // The End of this region overlaps with the i'th region
481 //
482 return FALSE;
483 }
484 }
485 }
486 //
487 // Non of the regions overlapped so MBR is O.K.
488 //
489 return ValidMbr;
490 }
491
492
493 UINT8
494 DecimaltoBCD(
495 IN UINT8 DecValue
496 )
497 {
498 return RtDecimaltoBCD (DecValue);
499 }
500
501
502 UINT8
503 BCDtoDecimal(
504 IN UINT8 BcdValue
505 )
506 {
507 return RtBCDtoDecimal (BcdValue);
508 }
509
510 EFI_STATUS
511 LibGetSystemConfigurationTable(
512 IN EFI_GUID *TableGuid,
513 IN OUT VOID **Table
514 )
515
516 {
517 UINTN Index;
518
519 for(Index=0;Index<ST->NumberOfTableEntries;Index++) {
520 if (CompareGuid(TableGuid,&(ST->ConfigurationTable[Index].VendorGuid))==0) {
521 *Table = ST->ConfigurationTable[Index].VendorTable;
522 return EFI_SUCCESS;
523 }
524 }
525 return EFI_NOT_FOUND;
526 }
527
528
529 CHAR16 *
530 LibGetUiString (
531 IN EFI_HANDLE Handle,
532 IN UI_STRING_TYPE StringType,
533 IN ISO_639_2 *LangCode,
534 IN BOOLEAN ReturnDevicePathStrOnMismatch
535 )
536 {
537 UI_INTERFACE *Ui;
538 UI_STRING_TYPE Index;
539 UI_STRING_ENTRY *Array;
540 EFI_STATUS Status;
541
542 Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handle, &UiProtocol, (VOID *)&Ui);
543 if (EFI_ERROR(Status)) {
544 return (ReturnDevicePathStrOnMismatch) ? DevicePathToStr(DevicePathFromHandle(Handle)) : NULL;
545 }
546
547 //
548 // Skip the first strings
549 //
550 for (Index = UiDeviceString, Array = Ui->Entry; Index < StringType; Index++, Array++) {
551 while (Array->LangCode) {
552 Array++;
553 }
554 }
555
556 //
557 // Search for the match
558 //
559 while (Array->LangCode) {
560 if (strcmpa (Array->LangCode, LangCode) == 0) {
561 return Array->UiString;
562 }
563 }
564 return (ReturnDevicePathStrOnMismatch) ? DevicePathToStr(DevicePathFromHandle(Handle)) : NULL;
565 }
566