1/*++ 2 3Copyright (c) 1998 Intel Corporation 4 5Module Name: 6 7 misc.c 8 9Abstract: 10 11 12 13 14Revision History 15 16--*/ 17 18#include "lib.h" 19 20 21// 22// 23// 24 25VOID * 26AllocatePool ( 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 41VOID * 42AllocateZeroPool ( 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 56VOID * 57ReallocatePool ( 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 82VOID 83FreePool ( 84 IN VOID *Buffer 85 ) 86{ 87 uefi_call_wrapper(BS->FreePool, 1, Buffer); 88} 89 90 91 92VOID 93ZeroMem ( 94 IN VOID *Buffer, 95 IN UINTN Size 96 ) 97{ 98 RtZeroMem (Buffer, Size); 99} 100 101VOID 102SetMem ( 103 IN VOID *Buffer, 104 IN UINTN Size, 105 IN UINT8 Value 106 ) 107{ 108 RtSetMem (Buffer, Size, Value); 109} 110 111VOID 112CopyMem ( 113 IN VOID *Dest, 114 IN CONST VOID *Src, 115 IN UINTN len 116 ) 117{ 118 RtCopyMem (Dest, Src, len); 119} 120 121INTN 122CompareMem ( 123 IN CONST VOID *Dest, 124 IN CONST VOID *Src, 125 IN UINTN len 126 ) 127{ 128 return RtCompareMem (Dest, Src, len); 129} 130 131BOOLEAN 132GrowBuffer( 133 IN OUT EFI_STATUS *Status, 134 IN OUT VOID **Buffer, 135 IN UINTN BufferSize 136 ) 137/*++ 138 139Routine 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 145Arguments: 146 147 Status - Current status 148 149 Buffer - Current allocated buffer, or NULL 150 151 BufferSize - Current buffer size needed 152 153Returns: 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 203EFI_MEMORY_DESCRIPTOR * 204LibMemoryMap ( 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 242VOID * 243LibGetVariableAndSize ( 244 IN CHAR16 *Name, 245 IN EFI_GUID *VendorGuid, 246 OUT UINTN *VarSize 247 ) 248{ 249 EFI_STATUS Status; 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 283VOID * 284LibGetVariable ( 285 IN CHAR16 *Name, 286 IN EFI_GUID *VendorGuid 287 ) 288{ 289 UINTN VarSize; 290 291 return LibGetVariableAndSize (Name, VendorGuid, &VarSize); 292} 293 294EFI_STATUS 295LibDeleteVariable ( 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 325EFI_STATUS 326LibSetNVVariable ( 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 346EFI_STATUS 347LibSetVariable ( 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 367EFI_STATUS 368LibInsertToTailOfBootOrder ( 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 390 for (Index = 0; Index < ((VarSize/sizeof(UINT16)) - 1); Index++) { 391 NewBootOptionArray[Index] = BootOptionArray[Index]; 392 } 393 // 394 // Insert in the tail of the array 395 // 396 NewBootOptionArray[Index] = BootOption; 397 398 Status = uefi_call_wrapper( 399 RT->SetVariable, 400 5, 401 VarBootOrder, &EfiGlobalVariable, 402 EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE, 403 VarSize, (VOID*) NewBootOptionArray 404 ); 405 406 if (NewBootOptionArray) { 407 FreePool (NewBootOptionArray); 408 } 409 if (BootOptionArray) { 410 FreePool (BootOptionArray); 411 } 412 return Status; 413} 414 415 416BOOLEAN 417ValidMBR( 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 491UINT8 492DecimaltoBCD( 493 IN UINT8 DecValue 494 ) 495{ 496 return RtDecimaltoBCD (DecValue); 497} 498 499 500UINT8 501BCDtoDecimal( 502 IN UINT8 BcdValue 503 ) 504{ 505 return RtBCDtoDecimal (BcdValue); 506} 507 508EFI_STATUS 509LibGetSystemConfigurationTable( 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 527CHAR16 * 528LibGetUiString ( 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