misc.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562
  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
  74. SetMem (
  75. IN VOID *Buffer,
  76. IN UINTN Size,
  77. IN UINT8 Value
  78. )
  79. {
  80. RtSetMem (Buffer, Size, Value);
  81. }
  82. VOID
  83. CopyMem (
  84. IN VOID *Dest,
  85. IN CONST 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. Buffer = NULL;
  166. BufferSize = sizeof(EFI_MEMORY_DESCRIPTOR);
  167. //
  168. // Call the real function
  169. //
  170. while (GrowBuffer (&Status, (VOID **) &Buffer, BufferSize)) {
  171. Status = uefi_call_wrapper(BS->GetMemoryMap, 5, &BufferSize, Buffer, MapKey, DescriptorSize, DescriptorVersion);
  172. }
  173. //
  174. // Convert buffer size to NoEntries
  175. //
  176. if (!EFI_ERROR(Status)) {
  177. *NoEntries = BufferSize / *DescriptorSize;
  178. }
  179. return Buffer;
  180. }
  181. VOID *
  182. LibGetVariableAndSize (
  183. IN CHAR16 *Name,
  184. IN EFI_GUID *VendorGuid,
  185. OUT UINTN *VarSize
  186. )
  187. {
  188. EFI_STATUS Status;
  189. VOID *Buffer;
  190. UINTN BufferSize;
  191. //
  192. // Initialize for GrowBuffer loop
  193. //
  194. Buffer = NULL;
  195. BufferSize = 100;
  196. //
  197. // Call the real function
  198. //
  199. while (GrowBuffer (&Status, &Buffer, BufferSize)) {
  200. Status = uefi_call_wrapper(
  201. RT->GetVariable,
  202. 5,
  203. Name,
  204. VendorGuid,
  205. NULL,
  206. &BufferSize,
  207. Buffer
  208. );
  209. }
  210. if (Buffer) {
  211. *VarSize = BufferSize;
  212. } else {
  213. *VarSize = 0;
  214. }
  215. return Buffer;
  216. }
  217. VOID *
  218. LibGetVariable (
  219. IN CHAR16 *Name,
  220. IN EFI_GUID *VendorGuid
  221. )
  222. {
  223. UINTN VarSize;
  224. return LibGetVariableAndSize (Name, VendorGuid, &VarSize);
  225. }
  226. EFI_STATUS
  227. LibDeleteVariable (
  228. IN CHAR16 *VarName,
  229. IN EFI_GUID *VarGuid
  230. )
  231. {
  232. VOID *VarBuf;
  233. EFI_STATUS Status;
  234. VarBuf = LibGetVariable(VarName,VarGuid);
  235. Status = EFI_NOT_FOUND;
  236. if (VarBuf) {
  237. //
  238. // Delete variable from Storage
  239. //
  240. Status = uefi_call_wrapper(
  241. RT->SetVariable,
  242. 5,
  243. VarName, VarGuid,
  244. EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
  245. 0, NULL
  246. );
  247. ASSERT (!EFI_ERROR(Status));
  248. FreePool(VarBuf);
  249. }
  250. return (Status);
  251. }
  252. EFI_STATUS
  253. LibSetNVVariable (
  254. IN CHAR16 *VarName,
  255. IN EFI_GUID *VarGuid,
  256. IN UINTN DataSize,
  257. IN VOID *Data
  258. )
  259. {
  260. EFI_STATUS Status;
  261. Status = uefi_call_wrapper(
  262. RT->SetVariable,
  263. 5,
  264. VarName, VarGuid,
  265. EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
  266. DataSize, Data
  267. );
  268. ASSERT (!EFI_ERROR(Status));
  269. return (Status);
  270. }
  271. EFI_STATUS
  272. LibSetVariable (
  273. IN CHAR16 *VarName,
  274. IN EFI_GUID *VarGuid,
  275. IN UINTN DataSize,
  276. IN VOID *Data
  277. )
  278. {
  279. EFI_STATUS Status;
  280. Status = uefi_call_wrapper(
  281. RT->SetVariable,
  282. 5,
  283. VarName, VarGuid,
  284. EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
  285. DataSize, Data
  286. );
  287. ASSERT (!EFI_ERROR(Status));
  288. return (Status);
  289. }
  290. EFI_STATUS
  291. LibInsertToTailOfBootOrder (
  292. IN UINT16 BootOption,
  293. IN BOOLEAN OnlyInsertIfEmpty
  294. )
  295. {
  296. UINT16 *BootOptionArray;
  297. UINT16 *NewBootOptionArray;
  298. UINTN VarSize;
  299. UINTN Index;
  300. EFI_STATUS Status;
  301. BootOptionArray = LibGetVariableAndSize (VarBootOrder, &EfiGlobalVariable, &VarSize);
  302. if (VarSize != 0 && OnlyInsertIfEmpty) {
  303. if (BootOptionArray) {
  304. FreePool (BootOptionArray);
  305. }
  306. return EFI_UNSUPPORTED;
  307. }
  308. VarSize += sizeof(UINT16);
  309. NewBootOptionArray = AllocatePool (VarSize);
  310. for (Index = 0; Index < ((VarSize/sizeof(UINT16)) - 1); Index++) {
  311. NewBootOptionArray[Index] = BootOptionArray[Index];
  312. }
  313. //
  314. // Insert in the tail of the array
  315. //
  316. NewBootOptionArray[Index] = BootOption;
  317. Status = uefi_call_wrapper(
  318. RT->SetVariable,
  319. 5,
  320. VarBootOrder, &EfiGlobalVariable,
  321. EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
  322. VarSize, (VOID*) NewBootOptionArray
  323. );
  324. if (NewBootOptionArray) {
  325. FreePool (NewBootOptionArray);
  326. }
  327. if (BootOptionArray) {
  328. FreePool (BootOptionArray);
  329. }
  330. return Status;
  331. }
  332. BOOLEAN
  333. ValidMBR(
  334. IN MASTER_BOOT_RECORD *Mbr,
  335. IN EFI_BLOCK_IO *BlkIo
  336. )
  337. {
  338. UINT32 StartingLBA, EndingLBA;
  339. UINT32 NewEndingLBA;
  340. INTN i, j;
  341. BOOLEAN ValidMbr;
  342. if (Mbr->Signature != MBR_SIGNATURE) {
  343. //
  344. // The BPB also has this signature, so it can not be used alone.
  345. //
  346. return FALSE;
  347. }
  348. ValidMbr = FALSE;
  349. for (i=0; i<MAX_MBR_PARTITIONS; i++) {
  350. if ( Mbr->Partition[i].OSIndicator == 0x00 || EXTRACT_UINT32(Mbr->Partition[i].SizeInLBA) == 0 ) {
  351. continue;
  352. }
  353. ValidMbr = TRUE;
  354. StartingLBA = EXTRACT_UINT32(Mbr->Partition[i].StartingLBA);
  355. EndingLBA = StartingLBA + EXTRACT_UINT32(Mbr->Partition[i].SizeInLBA) - 1;
  356. if (EndingLBA > BlkIo->Media->LastBlock) {
  357. //
  358. // Compatability Errata:
  359. // Some systems try to hide drive space with thier INT 13h driver
  360. // This does not hide space from the OS driver. This means the MBR
  361. // that gets created from DOS is smaller than the MBR created from
  362. // a real OS (NT & Win98). This leads to BlkIo->LastBlock being
  363. // wrong on some systems FDISKed by the OS.
  364. //
  365. //
  366. if (BlkIo->Media->LastBlock < MIN_MBR_DEVICE_SIZE) {
  367. //
  368. // If this is a very small device then trust the BlkIo->LastBlock
  369. //
  370. return FALSE;
  371. }
  372. if (EndingLBA > (BlkIo->Media->LastBlock + MBR_ERRATA_PAD)) {
  373. return FALSE;
  374. }
  375. }
  376. for (j=i+1; j<MAX_MBR_PARTITIONS; j++) {
  377. if (Mbr->Partition[j].OSIndicator == 0x00 || EXTRACT_UINT32(Mbr->Partition[j].SizeInLBA) == 0) {
  378. continue;
  379. }
  380. if ( EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) >= StartingLBA &&
  381. EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) <= EndingLBA ) {
  382. //
  383. // The Start of this region overlaps with the i'th region
  384. //
  385. return FALSE;
  386. }
  387. NewEndingLBA = EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) + EXTRACT_UINT32(Mbr->Partition[j].SizeInLBA) - 1;
  388. if ( NewEndingLBA >= StartingLBA && NewEndingLBA <= EndingLBA ) {
  389. //
  390. // The End of this region overlaps with the i'th region
  391. //
  392. return FALSE;
  393. }
  394. }
  395. }
  396. //
  397. // Non of the regions overlapped so MBR is O.K.
  398. //
  399. return ValidMbr;
  400. }
  401. UINT8
  402. DecimaltoBCD(
  403. IN UINT8 DecValue
  404. )
  405. {
  406. return RtDecimaltoBCD (DecValue);
  407. }
  408. UINT8
  409. BCDtoDecimal(
  410. IN UINT8 BcdValue
  411. )
  412. {
  413. return RtBCDtoDecimal (BcdValue);
  414. }
  415. EFI_STATUS
  416. LibGetSystemConfigurationTable(
  417. IN EFI_GUID *TableGuid,
  418. IN OUT VOID **Table
  419. )
  420. {
  421. UINTN Index;
  422. for(Index=0;Index<ST->NumberOfTableEntries;Index++) {
  423. if (CompareGuid(TableGuid,&(ST->ConfigurationTable[Index].VendorGuid))==0) {
  424. *Table = ST->ConfigurationTable[Index].VendorTable;
  425. return EFI_SUCCESS;
  426. }
  427. }
  428. return EFI_NOT_FOUND;
  429. }
  430. CHAR16 *
  431. LibGetUiString (
  432. IN EFI_HANDLE Handle,
  433. IN UI_STRING_TYPE StringType,
  434. IN ISO_639_2 *LangCode,
  435. IN BOOLEAN ReturnDevicePathStrOnMismatch
  436. )
  437. {
  438. UI_INTERFACE *Ui;
  439. UI_STRING_TYPE Index;
  440. UI_STRING_ENTRY *Array;
  441. EFI_STATUS Status;
  442. Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handle, &UiProtocol, (VOID *)&Ui);
  443. if (EFI_ERROR(Status)) {
  444. return (ReturnDevicePathStrOnMismatch) ? DevicePathToStr(DevicePathFromHandle(Handle)) : NULL;
  445. }
  446. //
  447. // Skip the first strings
  448. //
  449. for (Index = UiDeviceString, Array = Ui->Entry; Index < StringType; Index++, Array++) {
  450. while (Array->LangCode) {
  451. Array++;
  452. }
  453. }
  454. //
  455. // Search for the match
  456. //
  457. while (Array->LangCode) {
  458. if (strcmpa (Array->LangCode, LangCode) == 0) {
  459. return Array->UiString;
  460. }
  461. }
  462. return (ReturnDevicePathStrOnMismatch) ? DevicePathToStr(DevicePathFromHandle(Handle)) : NULL;
  463. }