misc.c 12 KB

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