misc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563
  1. /*++
  2. Copyright (c) 1998 Intel Corporation
  3. Module Name:
  4. misc.c
  5. Abstract:
  6. Revision History
  7. --*/
  8. #include "lib.h"
  9. //
  10. //
  11. //
  12. VOID *
  13. AllocatePool (
  14. IN UINTN Size
  15. )
  16. {
  17. EFI_STATUS Status;
  18. VOID *p;
  19. Status = uefi_call_wrapper(BS->AllocatePool, 3, PoolAllocationType, Size, &p);
  20. if (EFI_ERROR(Status)) {
  21. DEBUG((D_ERROR, "AllocatePool: out of pool %x\n", Status));
  22. p = NULL;
  23. }
  24. return p;
  25. }
  26. VOID *
  27. AllocateZeroPool (
  28. IN UINTN Size
  29. )
  30. {
  31. VOID *p;
  32. p = AllocatePool (Size);
  33. if (p) {
  34. ZeroMem (p, Size);
  35. }
  36. return p;
  37. }
  38. VOID *
  39. ReallocatePool (
  40. IN VOID *OldPool,
  41. IN UINTN OldSize,
  42. IN UINTN NewSize
  43. )
  44. {
  45. VOID *NewPool;
  46. NewPool = NULL;
  47. if (NewSize) {
  48. NewPool = AllocatePool (NewSize);
  49. }
  50. if (OldPool) {
  51. if (NewPool) {
  52. CopyMem (NewPool, OldPool, OldSize < NewSize ? OldSize : NewSize);
  53. }
  54. FreePool (OldPool);
  55. }
  56. return NewPool;
  57. }
  58. VOID
  59. FreePool (
  60. IN VOID *Buffer
  61. )
  62. {
  63. uefi_call_wrapper(BS->FreePool, 1, Buffer);
  64. }
  65. VOID
  66. ZeroMem (
  67. IN VOID *Buffer,
  68. IN UINTN Size
  69. )
  70. {
  71. RtZeroMem (Buffer, Size);
  72. }
  73. VOID EFIAPI
  74. SetMem (
  75. IN VOID *Buffer,
  76. IN UINTN Size,
  77. IN UINT8 Value
  78. )
  79. {
  80. RtSetMem (Buffer, Size, Value);
  81. }
  82. VOID EFIAPI
  83. CopyMem (
  84. IN VOID *Dest,
  85. IN VOID *Src,
  86. IN UINTN len
  87. )
  88. {
  89. RtCopyMem (Dest, Src, len);
  90. }
  91. INTN
  92. CompareMem (
  93. IN CONST VOID *Dest,
  94. IN CONST VOID *Src,
  95. IN UINTN len
  96. )
  97. {
  98. return RtCompareMem (Dest, Src, len);
  99. }
  100. BOOLEAN
  101. GrowBuffer(
  102. IN OUT EFI_STATUS *Status,
  103. IN OUT VOID **Buffer,
  104. IN UINTN BufferSize
  105. )
  106. /*++
  107. Routine Description:
  108. Helper function called as part of the code needed
  109. to allocate the proper sized buffer for various
  110. EFI interfaces.
  111. Arguments:
  112. Status - Current status
  113. Buffer - Current allocated buffer, or NULL
  114. BufferSize - Current buffer size needed
  115. Returns:
  116. TRUE - if the buffer was reallocated and the caller
  117. should try the API again.
  118. --*/
  119. {
  120. BOOLEAN TryAgain;
  121. //
  122. // If this is an initial request, buffer will be null with a new buffer size
  123. //
  124. if (!*Buffer && BufferSize) {
  125. *Status = EFI_BUFFER_TOO_SMALL;
  126. }
  127. //
  128. // If the status code is "buffer too small", resize the buffer
  129. //
  130. TryAgain = FALSE;
  131. if (*Status == EFI_BUFFER_TOO_SMALL) {
  132. if (*Buffer) {
  133. FreePool (*Buffer);
  134. }
  135. *Buffer = AllocatePool (BufferSize);
  136. if (*Buffer) {
  137. TryAgain = TRUE;
  138. } else {
  139. *Status = EFI_OUT_OF_RESOURCES;
  140. }
  141. }
  142. //
  143. // If there's an error, free the buffer
  144. //
  145. if (!TryAgain && EFI_ERROR(*Status) && *Buffer) {
  146. FreePool (*Buffer);
  147. *Buffer = NULL;
  148. }
  149. return TryAgain;
  150. }
  151. EFI_MEMORY_DESCRIPTOR *
  152. LibMemoryMap (
  153. OUT UINTN *NoEntries,
  154. OUT UINTN *MapKey,
  155. OUT UINTN *DescriptorSize,
  156. OUT UINT32 *DescriptorVersion
  157. )
  158. {
  159. EFI_STATUS Status;
  160. EFI_MEMORY_DESCRIPTOR *Buffer;
  161. UINTN BufferSize;
  162. //
  163. // Initialize for GrowBuffer loop
  164. //
  165. Status = EFI_SUCCESS;
  166. Buffer = NULL;
  167. BufferSize = sizeof(EFI_MEMORY_DESCRIPTOR);
  168. //
  169. // Call the real function
  170. //
  171. while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
  172. Status = uefi_call_wrapper(BS->GetMemoryMap, 5, &BufferSize, Buffer, MapKey, DescriptorSize, DescriptorVersion);
  173. }
  174. //
  175. // Convert buffer size to NoEntries
  176. //
  177. if (!EFI_ERROR(Status)) {
  178. *NoEntries = BufferSize / *DescriptorSize;
  179. }
  180. return Buffer;
  181. }
  182. VOID *
  183. LibGetVariableAndSize (
  184. IN CHAR16 *Name,
  185. IN EFI_GUID *VendorGuid,
  186. OUT UINTN *VarSize
  187. )
  188. {
  189. EFI_STATUS Status = EFI_SUCCESS;
  190. VOID *Buffer;
  191. UINTN BufferSize;
  192. //
  193. // Initialize for GrowBuffer loop
  194. //
  195. Buffer = NULL;
  196. BufferSize = 100;
  197. //
  198. // Call the real function
  199. //
  200. while (GrowBuffer (&Status, &Buffer, BufferSize)) {
  201. Status = uefi_call_wrapper(
  202. RT->GetVariable,
  203. 5,
  204. Name,
  205. VendorGuid,
  206. NULL,
  207. &BufferSize,
  208. Buffer
  209. );
  210. }
  211. if (Buffer) {
  212. *VarSize = BufferSize;
  213. } else {
  214. *VarSize = 0;
  215. }
  216. return Buffer;
  217. }
  218. VOID *
  219. LibGetVariable (
  220. IN CHAR16 *Name,
  221. IN EFI_GUID *VendorGuid
  222. )
  223. {
  224. UINTN VarSize;
  225. return LibGetVariableAndSize (Name, VendorGuid, &VarSize);
  226. }
  227. EFI_STATUS
  228. LibDeleteVariable (
  229. IN CHAR16 *VarName,
  230. IN EFI_GUID *VarGuid
  231. )
  232. {
  233. VOID *VarBuf;
  234. EFI_STATUS Status;
  235. VarBuf = LibGetVariable(VarName,VarGuid);
  236. Status = EFI_NOT_FOUND;
  237. if (VarBuf) {
  238. //
  239. // Delete variable from Storage
  240. //
  241. Status = uefi_call_wrapper(
  242. RT->SetVariable,
  243. 5,
  244. VarName, VarGuid,
  245. EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
  246. 0, NULL
  247. );
  248. ASSERT (!EFI_ERROR(Status));
  249. FreePool(VarBuf);
  250. }
  251. return (Status);
  252. }
  253. EFI_STATUS
  254. LibSetNVVariable (
  255. IN CHAR16 *VarName,
  256. IN EFI_GUID *VarGuid,
  257. IN UINTN DataSize,
  258. IN VOID *Data
  259. )
  260. {
  261. EFI_STATUS Status;
  262. Status = uefi_call_wrapper(
  263. RT->SetVariable,
  264. 5,
  265. VarName, VarGuid,
  266. EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
  267. DataSize, Data
  268. );
  269. ASSERT (!EFI_ERROR(Status));
  270. return (Status);
  271. }
  272. EFI_STATUS
  273. LibSetVariable (
  274. IN CHAR16 *VarName,
  275. IN EFI_GUID *VarGuid,
  276. IN UINTN DataSize,
  277. IN VOID *Data
  278. )
  279. {
  280. EFI_STATUS Status;
  281. Status = uefi_call_wrapper(
  282. RT->SetVariable,
  283. 5,
  284. VarName, VarGuid,
  285. EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
  286. DataSize, Data
  287. );
  288. ASSERT (!EFI_ERROR(Status));
  289. return (Status);
  290. }
  291. EFI_STATUS
  292. LibInsertToTailOfBootOrder (
  293. IN UINT16 BootOption,
  294. IN BOOLEAN OnlyInsertIfEmpty
  295. )
  296. {
  297. UINT16 *BootOptionArray;
  298. UINT16 *NewBootOptionArray;
  299. UINTN VarSize;
  300. UINTN Index;
  301. EFI_STATUS Status;
  302. BootOptionArray = LibGetVariableAndSize (VarBootOrder, &EfiGlobalVariable, &VarSize);
  303. if (VarSize != 0 && OnlyInsertIfEmpty) {
  304. if (BootOptionArray) {
  305. FreePool (BootOptionArray);
  306. }
  307. return EFI_UNSUPPORTED;
  308. }
  309. VarSize += sizeof(UINT16);
  310. NewBootOptionArray = AllocatePool (VarSize);
  311. if (!NewBootOptionArray)
  312. return EFI_OUT_OF_RESOURCES;
  313. for (Index = 0; Index < ((VarSize/sizeof(UINT16)) - 1); Index++) {
  314. NewBootOptionArray[Index] = BootOptionArray[Index];
  315. }
  316. //
  317. // Insert in the tail of the array
  318. //
  319. NewBootOptionArray[Index] = BootOption;
  320. Status = uefi_call_wrapper(
  321. RT->SetVariable,
  322. 5,
  323. VarBootOrder, &EfiGlobalVariable,
  324. EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
  325. VarSize, (VOID*) NewBootOptionArray
  326. );
  327. FreePool (NewBootOptionArray);
  328. if (BootOptionArray) {
  329. FreePool (BootOptionArray);
  330. }
  331. return Status;
  332. }
  333. BOOLEAN
  334. ValidMBR(
  335. IN MASTER_BOOT_RECORD *Mbr,
  336. IN EFI_BLOCK_IO *BlkIo
  337. )
  338. {
  339. UINT32 StartingLBA, EndingLBA;
  340. UINT32 NewEndingLBA;
  341. INTN i, j;
  342. BOOLEAN ValidMbr;
  343. if (Mbr->Signature != MBR_SIGNATURE) {
  344. //
  345. // The BPB also has this signature, so it can not be used alone.
  346. //
  347. return FALSE;
  348. }
  349. ValidMbr = FALSE;
  350. for (i=0; i<MAX_MBR_PARTITIONS; i++) {
  351. if ( Mbr->Partition[i].OSIndicator == 0x00 || EXTRACT_UINT32(Mbr->Partition[i].SizeInLBA) == 0 ) {
  352. continue;
  353. }
  354. ValidMbr = TRUE;
  355. StartingLBA = EXTRACT_UINT32(Mbr->Partition[i].StartingLBA);
  356. EndingLBA = StartingLBA + EXTRACT_UINT32(Mbr->Partition[i].SizeInLBA) - 1;
  357. if (EndingLBA > BlkIo->Media->LastBlock) {
  358. //
  359. // Compatability Errata:
  360. // Some systems try to hide drive space with thier INT 13h driver
  361. // This does not hide space from the OS driver. This means the MBR
  362. // that gets created from DOS is smaller than the MBR created from
  363. // a real OS (NT & Win98). This leads to BlkIo->LastBlock being
  364. // wrong on some systems FDISKed by the OS.
  365. //
  366. //
  367. if (BlkIo->Media->LastBlock < MIN_MBR_DEVICE_SIZE) {
  368. //
  369. // If this is a very small device then trust the BlkIo->LastBlock
  370. //
  371. return FALSE;
  372. }
  373. if (EndingLBA > (BlkIo->Media->LastBlock + MBR_ERRATA_PAD)) {
  374. return FALSE;
  375. }
  376. }
  377. for (j=i+1; j<MAX_MBR_PARTITIONS; j++) {
  378. if (Mbr->Partition[j].OSIndicator == 0x00 || EXTRACT_UINT32(Mbr->Partition[j].SizeInLBA) == 0) {
  379. continue;
  380. }
  381. if ( EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) >= StartingLBA &&
  382. EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) <= EndingLBA ) {
  383. //
  384. // The Start of this region overlaps with the i'th region
  385. //
  386. return FALSE;
  387. }
  388. NewEndingLBA = EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) + EXTRACT_UINT32(Mbr->Partition[j].SizeInLBA) - 1;
  389. if ( NewEndingLBA >= StartingLBA && NewEndingLBA <= EndingLBA ) {
  390. //
  391. // The End of this region overlaps with the i'th region
  392. //
  393. return FALSE;
  394. }
  395. }
  396. }
  397. //
  398. // Non of the regions overlapped so MBR is O.K.
  399. //
  400. return ValidMbr;
  401. }
  402. UINT8
  403. DecimaltoBCD(
  404. IN UINT8 DecValue
  405. )
  406. {
  407. return RtDecimaltoBCD (DecValue);
  408. }
  409. UINT8
  410. BCDtoDecimal(
  411. IN UINT8 BcdValue
  412. )
  413. {
  414. return RtBCDtoDecimal (BcdValue);
  415. }
  416. EFI_STATUS
  417. LibGetSystemConfigurationTable(
  418. IN EFI_GUID *TableGuid,
  419. IN OUT VOID **Table
  420. )
  421. {
  422. UINTN Index;
  423. for(Index=0;Index<ST->NumberOfTableEntries;Index++) {
  424. if (CompareGuid(TableGuid,&(ST->ConfigurationTable[Index].VendorGuid))==0) {
  425. *Table = ST->ConfigurationTable[Index].VendorTable;
  426. return EFI_SUCCESS;
  427. }
  428. }
  429. return EFI_NOT_FOUND;
  430. }
  431. CHAR16 *
  432. LibGetUiString (
  433. IN EFI_HANDLE Handle,
  434. IN UI_STRING_TYPE StringType,
  435. IN ISO_639_2 *LangCode,
  436. IN BOOLEAN ReturnDevicePathStrOnMismatch
  437. )
  438. {
  439. UI_INTERFACE *Ui;
  440. UI_STRING_TYPE Index;
  441. UI_STRING_ENTRY *Array;
  442. EFI_STATUS Status;
  443. Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handle, &UiProtocol, (VOID *)&Ui);
  444. if (EFI_ERROR(Status)) {
  445. return (ReturnDevicePathStrOnMismatch) ? DevicePathToStr(DevicePathFromHandle(Handle)) : NULL;
  446. }
  447. //
  448. // Skip the first strings
  449. //
  450. for (Index = UiDeviceString, Array = Ui->Entry; Index < StringType; Index++, Array++) {
  451. while (Array->LangCode) {
  452. Array++;
  453. }
  454. }
  455. //
  456. // Search for the match
  457. //
  458. while (Array->LangCode) {
  459. if (strcmpa (Array->LangCode, LangCode) == 0) {
  460. return Array->UiString;
  461. }
  462. }
  463. return (ReturnDevicePathStrOnMismatch) ? DevicePathToStr(DevicePathFromHandle(Handle)) : NULL;
  464. }