drv0.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. /*
  2. * Copyright (C) 2013 David Decotigny <decot@googlers.com>
  3. *
  4. * Sample EFI shell session, together with drv0_use.efi:
  5. *
  6. * # Loading first instance:
  7. *
  8. * fs0:\> load drv0.efi
  9. * Driver instance loaded successfully.
  10. * load: Image fs0:\drv0.efi loaded at 2FD7C000 - Success
  11. *
  12. * # Testing 1st instance:
  13. *
  14. * fs0:\> drv0_use.efi
  15. * Playing with driver instance 0...
  16. * Hello Sample UEFI Driver!
  17. * Hello was called 1 time(s).
  18. *
  19. * fs0:\> drv0_use.efi
  20. * Playing with driver instance 0...
  21. * Hello Sample UEFI Driver!
  22. * Hello was called 2 time(s).
  23. *
  24. * # Loading another instance:
  25. *
  26. * fs0:\> load drv0.efi
  27. * Driver instance loaded successfully.
  28. * load: Image fs0:\drv0.efi loaded at 2FD6D000 - Success
  29. *
  30. * # Using both instances:
  31. *
  32. * fs0:\> drv0_use.efi
  33. * Playing with driver instance 0...
  34. * Hello Sample UEFI Driver!
  35. * Hello was called 3 time(s).
  36. * Playing with driver instance 1...
  37. * Hello Sample UEFI Driver!
  38. * Hello was called 1 time(s).
  39. *
  40. * fs0:\> drv0_use.efi
  41. * Playing with driver instance 0...
  42. * Hello Sample UEFI Driver!
  43. * Hello was called 4 time(s).
  44. * Playing with driver instance 1...
  45. * Hello Sample UEFI Driver!
  46. * Hello was called 2 time(s).
  47. *
  48. * # Removing 1st instance:
  49. *
  50. * fs0:\> dh
  51. * Handle dump
  52. * 1: Image(DxeCore)
  53. * [...]
  54. * 79: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi)
  55. * 7A: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi)
  56. *
  57. * fs0:\> unload 79
  58. * 79: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi)
  59. * Unload driver image (y/n)? y
  60. * Driver instance unloaded.
  61. * unload: Success
  62. *
  63. * # Only 2nd instance remaining:
  64. *
  65. * fs0:\> drv0_use.efi
  66. * Playing with driver instance 0...
  67. * Hello Sample UEFI Driver!
  68. * Hello was called 3 time(s).
  69. *
  70. * # Removing 2nd/last instance:
  71. *
  72. * fs0:\> dh
  73. * Handle dump
  74. * 1: Image(DxeCore)
  75. * [...]
  76. * 79: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi)
  77. *
  78. * fs0:\> unload 79
  79. * 79: Image(\/drv0.efi) ImageDevPath (..A,0x800,0x17F7DF)/\/drv0.efi)
  80. * Unload driver image (y/n)? y
  81. * Driver instance unloaded.
  82. * unload: Success
  83. *
  84. * # Expect error: no other drv0 instance left
  85. *
  86. * fs0:\> drv0_use.efi
  87. * Error looking up handles for proto: 14
  88. */
  89. #include <efi.h>
  90. #include <efilib.h>
  91. #include "drv0.h"
  92. static const EFI_GUID GnuEfiAppsDrv0ProtocolGuid
  93. = GNU_EFI_APPS_DRV0_PROTOCOL_GUID;
  94. static struct {
  95. GNU_EFI_APPS_DRV0_PROTOCOL Proto;
  96. UINTN Counter;
  97. } InternalGnuEfiAppsDrv0ProtocolData;
  98. static
  99. EFI_STATUS
  100. EFI_FUNCTION
  101. Drv0SayHello(
  102. IN const CHAR16 *HelloWho
  103. )
  104. {
  105. if (! HelloWho)
  106. return EFI_INVALID_PARAMETER;
  107. Print(L"Hello %s!\n", HelloWho);
  108. InternalGnuEfiAppsDrv0ProtocolData.Counter ++;
  109. return EFI_SUCCESS;
  110. }
  111. static
  112. EFI_STATUS
  113. EFI_FUNCTION
  114. Drv0GetNumberOfHello(
  115. OUT UINTN *NumberOfHello
  116. )
  117. {
  118. if (! NumberOfHello)
  119. return EFI_INVALID_PARAMETER;
  120. *NumberOfHello = InternalGnuEfiAppsDrv0ProtocolData.Counter;
  121. return EFI_SUCCESS;
  122. }
  123. static
  124. EFI_STATUS
  125. EFI_FUNCTION
  126. Drv0Unload(IN EFI_HANDLE ImageHandle)
  127. {
  128. LibUninstallProtocolInterfaces(ImageHandle,
  129. &GnuEfiAppsDrv0ProtocolGuid,
  130. &InternalGnuEfiAppsDrv0ProtocolData.Proto,
  131. NULL);
  132. Print(L"Driver instance unloaded.\n", ImageHandle);
  133. return EFI_SUCCESS;
  134. }
  135. EFI_STATUS
  136. efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SysTab)
  137. {
  138. EFI_STATUS Status;
  139. EFI_LOADED_IMAGE *LoadedImage = NULL;
  140. InitializeLib(ImageHandle, SysTab);
  141. /* Initialize global protocol definition + data */
  142. InternalGnuEfiAppsDrv0ProtocolData.Proto.SayHello
  143. = (GNU_EFI_APPS_DRV0_SAY_HELLO) Drv0SayHello;
  144. InternalGnuEfiAppsDrv0ProtocolData.Proto.GetNumberOfHello
  145. = (GNU_EFI_APPS_DRV0_GET_NUMBER_OF_HELLO) Drv0GetNumberOfHello;
  146. InternalGnuEfiAppsDrv0ProtocolData.Counter = 0;
  147. /* Grab handle to this image: we'll attach our proto instance to it */
  148. Status = uefi_call_wrapper(BS->OpenProtocol, 6,
  149. ImageHandle, &LoadedImageProtocol,
  150. (void**)&LoadedImage, ImageHandle,
  151. NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
  152. if (EFI_ERROR(Status)) {
  153. Print(L"Could not open loaded image protocol: %d\n", Status);
  154. return Status;
  155. }
  156. /* Attach our proto to the current driver image */
  157. Status = LibInstallProtocolInterfaces(
  158. &ImageHandle, &GnuEfiAppsDrv0ProtocolGuid,
  159. &InternalGnuEfiAppsDrv0ProtocolData.Proto, NULL);
  160. if (EFI_ERROR(Status)) {
  161. Print(L"Error registering driver instance: %d\n", Status);
  162. return Status;
  163. }
  164. /* Register Unload callback, used to unregister current protocol
  165. * instance from system */
  166. LoadedImage->Unload = (EFI_IMAGE_UNLOAD)Drv0Unload;
  167. Print(L"Driver instance loaded successfully.\n");
  168. return EFI_SUCCESS; /* at this point, this instance stays resident
  169. * until image is unloaded, eg. with shell's unload,
  170. * ExitBootServices() */
  171. }