util.c 11 KB

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