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