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 = EFI_SUCCESS; 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 if (!NewBootOptionArray) 390 return EFI_OUT_OF_RESOURCES; 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 FreePool (NewBootOptionArray); 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 527 CHAR16 * 528 LibGetUiString ( 529 IN EFI_HANDLE Handle, 530 IN UI_STRING_TYPE StringType, 531 IN ISO_639_2 *LangCode, 532 IN BOOLEAN ReturnDevicePathStrOnMismatch 533 ) 534 { 535 UI_INTERFACE *Ui; 536 UI_STRING_TYPE Index; 537 UI_STRING_ENTRY *Array; 538 EFI_STATUS Status; 539 540 Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handle, &UiProtocol, (VOID *)&Ui); 541 if (EFI_ERROR(Status)) { 542 return (ReturnDevicePathStrOnMismatch) ? DevicePathToStr(DevicePathFromHandle(Handle)) : NULL; 543 } 544 545 // 546 // Skip the first strings 547 // 548 for (Index = UiDeviceString, Array = Ui->Entry; Index < StringType; Index++, Array++) { 549 while (Array->LangCode) { 550 Array++; 551 } 552 } 553 554 // 555 // Search for the match 556 // 557 while (Array->LangCode) { 558 if (strcmpa (Array->LangCode, LangCode) == 0) { 559 return Array->UiString; 560 } 561 } 562 return (ReturnDevicePathStrOnMismatch) ? DevicePathToStr(DevicePathFromHandle(Handle)) : NULL; 563 } 564