misc.c revision 1.1.1.1 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