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