misc.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  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 VOID *Src,
  86. IN UINTN len
  87. )
  88. {
  89. RtCopyMem (Dest, Src, len);
  90. }
  91. INTN
  92. CompareMem (
  93. IN VOID *Dest,
  94. IN 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. LibInsertToTailOfBootOrder (
  254. IN UINT16 BootOption,
  255. IN BOOLEAN OnlyInsertIfEmpty
  256. )
  257. {
  258. UINT16 *BootOptionArray;
  259. UINT16 *NewBootOptionArray;
  260. UINTN VarSize;
  261. UINTN Index;
  262. EFI_STATUS Status;
  263. BootOptionArray = LibGetVariableAndSize (VarBootOrder, &EfiGlobalVariable, &VarSize);
  264. if (VarSize != 0 && OnlyInsertIfEmpty) {
  265. if (BootOptionArray) {
  266. FreePool (BootOptionArray);
  267. }
  268. return EFI_UNSUPPORTED;
  269. }
  270. VarSize += sizeof(UINT16);
  271. NewBootOptionArray = AllocatePool (VarSize);
  272. for (Index = 0; Index < ((VarSize/sizeof(UINT16)) - 1); Index++) {
  273. NewBootOptionArray[Index] = BootOptionArray[Index];
  274. }
  275. //
  276. // Insert in the tail of the array
  277. //
  278. NewBootOptionArray[Index] = BootOption;
  279. Status = uefi_call_wrapper(
  280. RT->SetVariable,
  281. 5,
  282. VarBootOrder, &EfiGlobalVariable,
  283. EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_NON_VOLATILE,
  284. VarSize, (VOID*) NewBootOptionArray
  285. );
  286. if (NewBootOptionArray) {
  287. FreePool (NewBootOptionArray);
  288. }
  289. if (BootOptionArray) {
  290. FreePool (BootOptionArray);
  291. }
  292. return Status;
  293. }
  294. BOOLEAN
  295. ValidMBR(
  296. IN MASTER_BOOT_RECORD *Mbr,
  297. IN EFI_BLOCK_IO *BlkIo
  298. )
  299. {
  300. UINT32 StartingLBA, EndingLBA;
  301. UINT32 NewEndingLBA;
  302. INTN i, j;
  303. BOOLEAN ValidMbr;
  304. if (Mbr->Signature != MBR_SIGNATURE) {
  305. //
  306. // The BPB also has this signature, so it can not be used alone.
  307. //
  308. return FALSE;
  309. }
  310. ValidMbr = FALSE;
  311. for (i=0; i<MAX_MBR_PARTITIONS; i++) {
  312. if ( Mbr->Partition[i].OSIndicator == 0x00 || EXTRACT_UINT32(Mbr->Partition[i].SizeInLBA) == 0 ) {
  313. continue;
  314. }
  315. ValidMbr = TRUE;
  316. StartingLBA = EXTRACT_UINT32(Mbr->Partition[i].StartingLBA);
  317. EndingLBA = StartingLBA + EXTRACT_UINT32(Mbr->Partition[i].SizeInLBA) - 1;
  318. if (EndingLBA > BlkIo->Media->LastBlock) {
  319. //
  320. // Compatability Errata:
  321. // Some systems try to hide drive space with thier INT 13h driver
  322. // This does not hide space from the OS driver. This means the MBR
  323. // that gets created from DOS is smaller than the MBR created from
  324. // a real OS (NT & Win98). This leads to BlkIo->LastBlock being
  325. // wrong on some systems FDISKed by the OS.
  326. //
  327. //
  328. if (BlkIo->Media->LastBlock < MIN_MBR_DEVICE_SIZE) {
  329. //
  330. // If this is a very small device then trust the BlkIo->LastBlock
  331. //
  332. return FALSE;
  333. }
  334. if (EndingLBA > (BlkIo->Media->LastBlock + MBR_ERRATA_PAD)) {
  335. return FALSE;
  336. }
  337. }
  338. for (j=i+1; j<MAX_MBR_PARTITIONS; j++) {
  339. if (Mbr->Partition[j].OSIndicator == 0x00 || EXTRACT_UINT32(Mbr->Partition[j].SizeInLBA) == 0) {
  340. continue;
  341. }
  342. if ( EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) >= StartingLBA &&
  343. EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) <= EndingLBA ) {
  344. //
  345. // The Start of this region overlaps with the i'th region
  346. //
  347. return FALSE;
  348. }
  349. NewEndingLBA = EXTRACT_UINT32(Mbr->Partition[j].StartingLBA) + EXTRACT_UINT32(Mbr->Partition[j].SizeInLBA) - 1;
  350. if ( NewEndingLBA >= StartingLBA && NewEndingLBA <= EndingLBA ) {
  351. //
  352. // The End of this region overlaps with the i'th region
  353. //
  354. return FALSE;
  355. }
  356. }
  357. }
  358. //
  359. // Non of the regions overlapped so MBR is O.K.
  360. //
  361. return ValidMbr;
  362. }
  363. UINT8
  364. DecimaltoBCD(
  365. IN UINT8 DecValue
  366. )
  367. {
  368. return RtDecimaltoBCD (DecValue);
  369. }
  370. UINT8
  371. BCDtoDecimal(
  372. IN UINT8 BcdValue
  373. )
  374. {
  375. return RtBCDtoDecimal (BcdValue);
  376. }
  377. EFI_STATUS
  378. LibGetSystemConfigurationTable(
  379. IN EFI_GUID *TableGuid,
  380. IN OUT VOID **Table
  381. )
  382. {
  383. UINTN Index;
  384. for(Index=0;Index<ST->NumberOfTableEntries;Index++) {
  385. if (CompareGuid(TableGuid,&(ST->ConfigurationTable[Index].VendorGuid))==0) {
  386. *Table = ST->ConfigurationTable[Index].VendorTable;
  387. return EFI_SUCCESS;
  388. }
  389. }
  390. return EFI_NOT_FOUND;
  391. }
  392. CHAR16 *
  393. LibGetUiString (
  394. IN EFI_HANDLE Handle,
  395. IN UI_STRING_TYPE StringType,
  396. IN ISO_639_2 *LangCode,
  397. IN BOOLEAN ReturnDevicePathStrOnMismatch
  398. )
  399. {
  400. UI_INTERFACE *Ui;
  401. UI_STRING_TYPE Index;
  402. UI_STRING_ENTRY *Array;
  403. EFI_STATUS Status;
  404. Status = uefi_call_wrapper(BS->HandleProtocol, 3, Handle, &UiProtocol, (VOID *)&Ui);
  405. if (EFI_ERROR(Status)) {
  406. return (ReturnDevicePathStrOnMismatch) ? DevicePathToStr(DevicePathFromHandle(Handle)) : NULL;
  407. }
  408. //
  409. // Skip the first strings
  410. //
  411. for (Index = UiDeviceString, Array = Ui->Entry; Index < StringType; Index++, Array++) {
  412. while (Array->LangCode) {
  413. Array++;
  414. }
  415. }
  416. //
  417. // Search for the match
  418. //
  419. while (Array->LangCode) {
  420. if (strcmpa (Array->LangCode, LangCode) == 0) {
  421. return Array->UiString;
  422. }
  423. }
  424. return (ReturnDevicePathStrOnMismatch) ? DevicePathToStr(DevicePathFromHandle(Handle)) : NULL;
  425. }