ThunkProtocolList.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. /** @file
  2. Emulator Thunk to abstract OS services from pure EFI code
  3. Copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>
  4. Copyright (c) 2011 - 2019, Intel Corporation. All rights reserved.<BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include <Uefi.h>
  8. #include <Library/BaseLib.h>
  9. #include <Library/BaseMemoryLib.h>
  10. #include <Library/DebugLib.h>
  11. #include <Library/MemoryAllocationLib.h>
  12. #include <Protocol/EmuIoThunk.h>
  13. #define EMU_IO_THUNK_PROTOCOL_DATA_SIGNATURE SIGNATURE_32('E','m','u','T')
  14. typedef struct {
  15. UINTN Signature;
  16. EMU_IO_THUNK_PROTOCOL Data;
  17. BOOLEAN EmuBusDriver;
  18. LIST_ENTRY Link;
  19. } EMU_IO_THUNK_PROTOCOL_DATA;
  20. LIST_ENTRY mThunkList = INITIALIZE_LIST_HEAD_VARIABLE (mThunkList);
  21. EFI_STATUS
  22. EFIAPI
  23. AddThunkProtocol (
  24. IN EMU_IO_THUNK_PROTOCOL *ThunkIo,
  25. IN CHAR16 *ConfigString,
  26. IN BOOLEAN EmuBusDriver
  27. )
  28. {
  29. UINTN Size;
  30. CHAR16 *StartString;
  31. CHAR16 *SubString;
  32. UINTN Instance;
  33. EMU_IO_THUNK_PROTOCOL_DATA *Private;
  34. if (ThunkIo == NULL) {
  35. return EFI_INVALID_PARAMETER;
  36. }
  37. Instance = 0;
  38. Size = StrSize (ConfigString);
  39. StartString = AllocatePool (Size);
  40. if (StartString == NULL) {
  41. return EFI_OUT_OF_RESOURCES;
  42. }
  43. StrCpyS (StartString, Size / sizeof (CHAR16), ConfigString);
  44. while (*StartString != '\0') {
  45. //
  46. // Find the end of the sub string
  47. //
  48. SubString = StartString;
  49. while (*SubString != '\0' && *SubString != '!') {
  50. SubString++;
  51. }
  52. if (*SubString == '!') {
  53. //
  54. // Replace token with '\0' to make sub strings. If this is the end
  55. // of the string SubString will already point to NULL.
  56. //
  57. *SubString = '\0';
  58. SubString++;
  59. }
  60. Private = AllocatePool (sizeof (EMU_IO_THUNK_PROTOCOL_DATA));
  61. if (Private == NULL) {
  62. return EFI_OUT_OF_RESOURCES;
  63. }
  64. Private->Signature = EMU_IO_THUNK_PROTOCOL_DATA_SIGNATURE;
  65. Private->EmuBusDriver = EmuBusDriver;
  66. CopyMem (&Private->Data, ThunkIo, sizeof (EMU_IO_THUNK_PROTOCOL));
  67. Private->Data.Instance = (UINT16)Instance++;
  68. Private->Data.ConfigString = StartString;
  69. InsertTailList (&mThunkList, &Private->Link);
  70. //
  71. // Parse Next sub string. This will point to '\0' if we are at the end.
  72. //
  73. StartString = SubString;
  74. }
  75. return EFI_SUCCESS;
  76. }
  77. EFI_STATUS
  78. EFIAPI
  79. GetNextThunkProtocol (
  80. IN BOOLEAN EmuBusDriver,
  81. OUT EMU_IO_THUNK_PROTOCOL **Instance OPTIONAL
  82. )
  83. {
  84. LIST_ENTRY *Link;
  85. EMU_IO_THUNK_PROTOCOL_DATA *Private;
  86. if (mThunkList.ForwardLink == &mThunkList) {
  87. // Skip parsing an empty list
  88. return EFI_NOT_FOUND;
  89. }
  90. for (Link = mThunkList.ForwardLink; Link != &mThunkList; Link = Link->ForwardLink) {
  91. Private = CR (Link, EMU_IO_THUNK_PROTOCOL_DATA, Link, EMU_IO_THUNK_PROTOCOL_DATA_SIGNATURE);
  92. if (EmuBusDriver & !Private->EmuBusDriver) {
  93. continue;
  94. } else if (*Instance == NULL) {
  95. // Find 1st match in list
  96. *Instance = &Private->Data;
  97. return EFI_SUCCESS;
  98. } else if (*Instance == &Private->Data) {
  99. // Matched previous call so look for valid next entry
  100. Link = Link->ForwardLink;
  101. if (Link == &mThunkList) {
  102. return EFI_NOT_FOUND;
  103. }
  104. Private = CR (Link, EMU_IO_THUNK_PROTOCOL_DATA, Link, EMU_IO_THUNK_PROTOCOL_DATA_SIGNATURE);
  105. *Instance = &Private->Data;
  106. return EFI_SUCCESS;
  107. }
  108. }
  109. return EFI_NOT_FOUND;
  110. }