util.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714
  1. /*++
  2. Copyright (c) 2014 Minoca Corp.
  3. This file is licensed under the terms of the GNU General Public License
  4. version 3. Alternative licensing terms are available. Contact
  5. info@minocacorp.com for details. See the LICENSE file at the root of this
  6. project for complete licensing information.
  7. Module Name:
  8. util.c
  9. Abstract:
  10. This module implements miscellaneous functionality for the UEFI core.
  11. Author:
  12. Evan Green 28-Feb-2014
  13. Environment:
  14. Firmware
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include "ueficore.h"
  20. #include <minoca/kernel/hmod.h>
  21. #include <minoca/kernel/kdebug.h>
  22. //
  23. // ---------------------------------------------------------------- Definitions
  24. //
  25. //
  26. // ------------------------------------------------------ Data Type Definitions
  27. //
  28. //
  29. // ----------------------------------------------- Internal Function Prototypes
  30. //
  31. //
  32. // -------------------------------------------------------------------- Globals
  33. //
  34. //
  35. // ------------------------------------------------------------------ Functions
  36. //
  37. EFIAPI
  38. VOID
  39. EfiCoreEmptyCallbackFunction (
  40. EFI_EVENT Event,
  41. VOID *Context
  42. )
  43. /*++
  44. Routine Description:
  45. This routine does nothing but return. It conforms to the event notification
  46. function prototype.
  47. Arguments:
  48. Event - Supplies an unused event.
  49. Context - Supplies an unused context pointer.
  50. Return Value:
  51. None.
  52. --*/
  53. {
  54. return;
  55. }
  56. EFIAPI
  57. VOID
  58. EfiCoreCopyMemory (
  59. VOID *Destination,
  60. VOID *Source,
  61. UINTN Length
  62. )
  63. /*++
  64. Routine Description:
  65. This routine copies the contents of one buffer to another.
  66. Arguments:
  67. Destination - Supplies a pointer to the destination of the copy.
  68. Source - Supplies a pointer to the source of the copy.
  69. Length - Supplies the number of bytes to copy.
  70. Return Value:
  71. None.
  72. --*/
  73. {
  74. ASSERT((Destination != NULL) && (Source != NULL));
  75. while (Length != 0) {
  76. *(INT8 *)Destination = *(INT8 *)Source;
  77. Length -= 1;
  78. Destination += 1;
  79. Source += 1;
  80. }
  81. return;
  82. }
  83. EFIAPI
  84. VOID
  85. EfiCoreSetMemory (
  86. VOID *Buffer,
  87. UINTN Size,
  88. UINT8 Value
  89. )
  90. /*++
  91. Routine Description:
  92. This routine fills a buffer with a specified value.
  93. Arguments:
  94. Buffer - Supplies a pointer to the buffer to fill.
  95. Size - Supplies the size of the buffer in bytes.
  96. Value - Supplies the value to fill the buffer with.
  97. Return Value:
  98. None.
  99. --*/
  100. {
  101. UINT8 *Bytes;
  102. UINTN Index;
  103. Bytes = Buffer;
  104. for (Index = 0; Index < Size; Index += 1) {
  105. Bytes[Index] = Value;
  106. }
  107. return;
  108. }
  109. INTN
  110. EfiCoreCompareMemory (
  111. VOID *FirstBuffer,
  112. VOID *SecondBuffer,
  113. UINTN Length
  114. )
  115. /*++
  116. Routine Description:
  117. This routine compares the contents of two buffers for equality.
  118. Arguments:
  119. FirstBuffer - Supplies a pointer to the first buffer to compare.
  120. SecondBuffer - Supplies a pointer to the second buffer to compare.
  121. Length - Supplies the number of bytes to compare.
  122. Return Value:
  123. 0 if the buffers are identical.
  124. Returns the first mismatched byte as
  125. First[MismatchIndex] - Second[MismatchIndex].
  126. --*/
  127. {
  128. INTN Result;
  129. ASSERT((FirstBuffer != NULL) && (SecondBuffer != NULL));
  130. while (Length != 0) {
  131. if (*(INT8 *)FirstBuffer != *(INT8 *)SecondBuffer) {
  132. Result = (INTN)(UINT8 *)FirstBuffer - (INTN)(UINT8 *)SecondBuffer;
  133. return Result;
  134. }
  135. Length -= 1;
  136. FirstBuffer += 1;
  137. SecondBuffer += 1;
  138. }
  139. return 0;
  140. }
  141. BOOLEAN
  142. EfiCoreCompareGuids (
  143. EFI_GUID *FirstGuid,
  144. EFI_GUID *SecondGuid
  145. )
  146. /*++
  147. Routine Description:
  148. This routine compares two GUIDs.
  149. Arguments:
  150. FirstGuid - Supplies a pointer to the first GUID.
  151. SecondGuid - Supplies a pointer to the second GUID.
  152. Return Value:
  153. TRUE if the GUIDs are equal.
  154. FALSE if the GUIDs are different.
  155. --*/
  156. {
  157. UINT32 *FirstPointer;
  158. UINT32 *SecondPointer;
  159. //
  160. // Compare GUIDs 32 bits at a time.
  161. //
  162. FirstPointer = (UINT32 *)FirstGuid;
  163. SecondPointer = (UINT32 *)SecondGuid;
  164. if ((FirstPointer[0] == SecondPointer[0]) &&
  165. (FirstPointer[1] == SecondPointer[1]) &&
  166. (FirstPointer[2] == SecondPointer[2]) &&
  167. (FirstPointer[3] == SecondPointer[3])) {
  168. return TRUE;
  169. }
  170. return FALSE;
  171. }
  172. VOID *
  173. EfiCoreAllocateBootPool (
  174. UINTN Size
  175. )
  176. /*++
  177. Routine Description:
  178. This routine allocates pool from boot services data.
  179. Arguments:
  180. Size - Supplies the size of the allocation in bytes.
  181. Return Value:
  182. Returns a pointer to the allocation on success.
  183. NULL on allocation failure.
  184. --*/
  185. {
  186. VOID *Allocation;
  187. EFI_STATUS Status;
  188. Status = EfiAllocatePool(EfiBootServicesData, Size, &Allocation);
  189. if (EFI_ERROR(Status)) {
  190. return NULL;
  191. }
  192. return Allocation;
  193. }
  194. VOID *
  195. EfiCoreAllocateRuntimePool (
  196. UINTN Size
  197. )
  198. /*++
  199. Routine Description:
  200. This routine allocates pool from runtime services data.
  201. Arguments:
  202. Size - Supplies the size of the allocation in bytes.
  203. Return Value:
  204. Returns a pointer to the allocation on success.
  205. NULL on allocation failure.
  206. --*/
  207. {
  208. VOID *Allocation;
  209. EFI_STATUS Status;
  210. Status = EfiAllocatePool(EfiRuntimeServicesData, Size, &Allocation);
  211. if (EFI_ERROR(Status)) {
  212. return NULL;
  213. }
  214. return Allocation;
  215. }
  216. INTN
  217. EfiCoreFindHighBitSet64 (
  218. UINT64 Value
  219. )
  220. /*++
  221. Routine Description:
  222. This routine returns the bit position of the highest bit set in a 64-bit
  223. value.
  224. Arguments:
  225. Value - Supplies the input value.
  226. Return Value:
  227. Returns the index of the highest bit set, between 0 and 63. If the value is
  228. zero, then -1 is returned.
  229. --*/
  230. {
  231. if (Value == (UINT32)Value) {
  232. return EfiCoreFindHighBitSet32((UINT32)Value);
  233. }
  234. return EfiCoreFindHighBitSet32((UINT32)(Value >> 32)) + 32;
  235. }
  236. INTN
  237. EfiCoreFindHighBitSet32 (
  238. UINT32 Value
  239. )
  240. /*++
  241. Routine Description:
  242. This routine returns the bit position of the highest bit set in a 32-bit
  243. value.
  244. Arguments:
  245. Value - Supplies the input value.
  246. Return Value:
  247. Returns the index of the highest bit set, between 0 and 31. If the value is
  248. zero, then -1 is returned.
  249. --*/
  250. {
  251. INTN BitIndex;
  252. if (Value == 0) {
  253. return -1;
  254. }
  255. for (BitIndex = 31; BitIndex >= 0; BitIndex -= 1) {
  256. if ((INT32)Value < 0) {
  257. break;
  258. }
  259. Value <<= 1;
  260. }
  261. return BitIndex;
  262. }
  263. VOID
  264. EfiCoreCalculateTableCrc32 (
  265. EFI_TABLE_HEADER *Header
  266. )
  267. /*++
  268. Routine Description:
  269. This routine recalculates the CRC32 of a given EFI table.
  270. Arguments:
  271. Header - Supplies a pointer to the header. The size member will be used to
  272. determine the size of the entire table.
  273. Return Value:
  274. None. The CRC is set in the header.
  275. --*/
  276. {
  277. UINT32 Crc;
  278. Header->CRC32 = 0;
  279. Crc = 0;
  280. //
  281. // This boot service may be "not yet implemented", in which case CRC comes
  282. // back staying zero. This will presumably be filled in correctly and
  283. // reapplied later.
  284. //
  285. EfiCalculateCrc32((UINT8 *)Header, Header->HeaderSize, &Crc);
  286. Header->CRC32 = Crc;
  287. }
  288. EFIAPI
  289. EFI_EVENT
  290. EfiCoreCreateProtocolNotifyEvent (
  291. EFI_GUID *ProtocolGuid,
  292. EFI_TPL NotifyTpl,
  293. EFI_EVENT_NOTIFY NotifyFunction,
  294. VOID *NotifyContext,
  295. VOID **Registration
  296. )
  297. /*++
  298. Routine Description:
  299. This routine creates an event, then registers that event to be notified
  300. whenever the given protocol appears. Finally, it signals the event so that
  301. any pre-existing protocols will be found.
  302. Arguments:
  303. ProtocolGuid - Supplies a pointer to the GUID of the protocol to watch.
  304. NotifyTpl - Supplies the Task Priority Level of the callback function.
  305. NotifyFunction - Supplies a pointer to the function to call when a new
  306. protocol with the given GUID crops up.
  307. NotifyContext - Supplies a pointer to pass into the notify function.
  308. Registration - Supplies a pointer where the registration token for the
  309. event will be returned.
  310. Return Value:
  311. Returns the notification event that was created.
  312. NULL on failure.
  313. --*/
  314. {
  315. EFI_EVENT Event;
  316. EFI_STATUS Status;
  317. ASSERT((ProtocolGuid != NULL) && (NotifyFunction != NULL) &&
  318. (Registration != NULL));
  319. Status = EfiCreateEvent(EVT_NOTIFY_SIGNAL,
  320. NotifyTpl,
  321. NotifyFunction,
  322. NotifyContext,
  323. &Event);
  324. if (EFI_ERROR(Status)) {
  325. ASSERT(FALSE);
  326. return NULL;
  327. }
  328. //
  329. // Register for protocol notifications on the event just created.
  330. //
  331. Status = EfiRegisterProtocolNotify(ProtocolGuid, Event, Registration);
  332. if (EFI_ERROR(Status)) {
  333. ASSERT(FALSE);
  334. EfiCloseEvent(Event);
  335. return NULL;
  336. }
  337. //
  338. // Kick the event so that pre-existing protocol instances will be
  339. // discovered.
  340. //
  341. EfiSignalEvent(Event);
  342. return Event;
  343. }
  344. UINTN
  345. EfiCoreStringLength (
  346. CHAR16 *String
  347. )
  348. /*++
  349. Routine Description:
  350. This routine returns the length of the given string, in characters (not
  351. bytes).
  352. Arguments:
  353. String - Supplies a pointer to the string.
  354. Return Value:
  355. Returns the number of characters in the string.
  356. --*/
  357. {
  358. UINTN Length;
  359. ASSERT(String != NULL);
  360. if (String == NULL) {
  361. return 0;
  362. }
  363. Length = 0;
  364. while (*String != L'\0') {
  365. String += 1;
  366. Length += 1;
  367. }
  368. return Length;
  369. }
  370. VOID
  371. EfiCoreCopyString (
  372. CHAR16 *Destination,
  373. CHAR16 *Source
  374. )
  375. /*++
  376. Routine Description:
  377. This routine copies one string over to another buffer.
  378. Arguments:
  379. Destination - Supplies a pointer to the destination buffer where the
  380. string will be copied to.
  381. Source - Supplies a pointer to the string to copy.
  382. Return Value:
  383. None.
  384. --*/
  385. {
  386. if ((Destination == NULL) || (Source == NULL)) {
  387. ASSERT(FALSE);
  388. return;
  389. }
  390. while (*Source != L'\0') {
  391. *Destination = *Source;
  392. Destination += 1;
  393. Source += 1;
  394. }
  395. *Destination = L'\0';
  396. return;
  397. }
  398. EFI_TPL
  399. EfiCoreGetCurrentTpl (
  400. VOID
  401. )
  402. /*++
  403. Routine Description:
  404. This routine returns the current TPL.
  405. Arguments:
  406. None.
  407. Return Value:
  408. Returns the current TPL.
  409. --*/
  410. {
  411. EFI_TPL Tpl;
  412. Tpl = EfiRaiseTPL(TPL_HIGH_LEVEL);
  413. EfiRestoreTPL(Tpl);
  414. return Tpl;
  415. }
  416. VOID
  417. EfiDebugPrint (
  418. CHAR8 *Format,
  419. ...
  420. )
  421. /*++
  422. Routine Description:
  423. This routine prints to the debugger and console.
  424. Arguments:
  425. Format - Supplies a pointer to the format string.
  426. ... - Supplies the remaining arguments to the format string.
  427. Return Value:
  428. None.
  429. --*/
  430. {
  431. va_list ArgumentList;
  432. CHAR Ascii[128];
  433. ULONG Index;
  434. USHORT Wide[128];
  435. //
  436. // Simply pass the data on to the debugger's print function.
  437. //
  438. va_start(ArgumentList, Format);
  439. KdPrintWithArgumentList(Format, ArgumentList);
  440. va_end(ArgumentList);
  441. if (EfiSystemTable->StdErr != NULL) {
  442. va_start(ArgumentList, Format);
  443. RtlFormatString(Ascii,
  444. sizeof(Ascii) - 1,
  445. CharacterEncodingAscii,
  446. Format,
  447. ArgumentList);
  448. Index = 0;
  449. while (Ascii[Index] != '\0') {
  450. Wide[Index] = Ascii[Index];
  451. Index += 1;
  452. }
  453. Wide[Index] = L'\0';
  454. va_end(ArgumentList);
  455. EfiSystemTable->StdErr->OutputString(EfiSystemTable->StdErr, Wide);
  456. }
  457. return;
  458. }
  459. //
  460. // --------------------------------------------------------- Internal Functions
  461. //