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