UefiBootServicesTableLibUnitTestProtocol.c 47 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650
  1. /** @file
  2. Implementation of protocol related services in the UEFI Boot Services table for use in unit tests.
  3. Copyright (c) Microsoft Corporation
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "UefiBootServicesTableLibUnitTestProtocol.h"
  7. STATIC LIST_ENTRY mProtocolDatabase = INITIALIZE_LIST_HEAD_VARIABLE (mProtocolDatabase);
  8. STATIC LIST_ENTRY gHandleList = INITIALIZE_LIST_HEAD_VARIABLE (gHandleList);
  9. STATIC UINT64 gHandleDatabaseKey = 0;
  10. STATIC UINTN mEfiLocateHandleRequest = 0;
  11. //
  12. // Helper Functions
  13. //
  14. /**
  15. Check whether a handle is a valid EFI_HANDLE
  16. @param UserHandle The handle to check
  17. @retval EFI_INVALID_PARAMETER The handle is NULL or not a valid EFI_HANDLE.
  18. @retval EFI_SUCCESS The handle is valid EFI_HANDLE.
  19. **/
  20. EFI_STATUS
  21. UnitTestValidateHandle (
  22. IN EFI_HANDLE UserHandle
  23. )
  24. {
  25. IHANDLE *Handle;
  26. LIST_ENTRY *Link;
  27. if (UserHandle == NULL) {
  28. return EFI_INVALID_PARAMETER;
  29. }
  30. for (Link = gHandleList.BackLink; Link != &gHandleList; Link = Link->BackLink) {
  31. Handle = CR (Link, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
  32. if (Handle == (IHANDLE *)UserHandle) {
  33. return EFI_SUCCESS;
  34. }
  35. }
  36. return EFI_INVALID_PARAMETER;
  37. }
  38. /**
  39. Finds the protocol entry for the requested protocol.
  40. @param Protocol The ID of the protocol
  41. @param Create Create a new entry if not found
  42. @return Protocol entry
  43. **/
  44. PROTOCOL_ENTRY *
  45. UnitTestFindProtocolEntry (
  46. IN EFI_GUID *Protocol,
  47. IN BOOLEAN Create
  48. )
  49. {
  50. LIST_ENTRY *Link;
  51. PROTOCOL_ENTRY *Item;
  52. PROTOCOL_ENTRY *ProtEntry;
  53. //
  54. // Search the database for the matching GUID
  55. //
  56. ProtEntry = NULL;
  57. for (Link = mProtocolDatabase.ForwardLink;
  58. Link != &mProtocolDatabase;
  59. Link = Link->ForwardLink)
  60. {
  61. Item = CR (Link, PROTOCOL_ENTRY, AllEntries, PROTOCOL_ENTRY_SIGNATURE);
  62. if (CompareGuid (&Item->ProtocolID, Protocol)) {
  63. //
  64. // This is the protocol entry
  65. //
  66. ProtEntry = Item;
  67. break;
  68. }
  69. }
  70. //
  71. // If the protocol entry was not found and Create is TRUE, then
  72. // allocate a new entry
  73. //
  74. if ((ProtEntry == NULL) && Create) {
  75. ProtEntry = AllocatePool (sizeof (PROTOCOL_ENTRY));
  76. if (ProtEntry != NULL) {
  77. //
  78. // Initialize new protocol entry structure
  79. //
  80. ProtEntry->Signature = PROTOCOL_ENTRY_SIGNATURE;
  81. CopyGuid ((VOID *)&ProtEntry->ProtocolID, Protocol);
  82. InitializeListHead (&ProtEntry->Protocols);
  83. InitializeListHead (&ProtEntry->Notify);
  84. //
  85. // Add it to protocol database
  86. //
  87. InsertTailList (&mProtocolDatabase, &ProtEntry->AllEntries);
  88. }
  89. }
  90. return ProtEntry;
  91. }
  92. /**
  93. Finds the protocol instance for the requested handle and protocol.
  94. Note: This function doesn't do parameters checking, it's caller's responsibility
  95. to pass in valid parameters.
  96. @param Handle The handle to search the protocol on
  97. @param Protocol GUID of the protocol
  98. @param Interface The interface for the protocol being searched
  99. @return Protocol instance (NULL: Not found)
  100. **/
  101. PROTOCOL_INTERFACE *
  102. UnitTestFindProtocolInterface (
  103. IN IHANDLE *Handle,
  104. IN EFI_GUID *Protocol,
  105. IN VOID *Interface
  106. )
  107. {
  108. PROTOCOL_INTERFACE *Prot;
  109. PROTOCOL_ENTRY *ProtEntry;
  110. LIST_ENTRY *Link;
  111. Prot = NULL;
  112. //
  113. // Lookup the protocol entry for this protocol ID
  114. //
  115. ProtEntry = UnitTestFindProtocolEntry (Protocol, FALSE);
  116. if (ProtEntry != NULL) {
  117. //
  118. // Look at each protocol interface for any matches
  119. //
  120. for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
  121. //
  122. // If this protocol interface matches, remove it
  123. //
  124. Prot = CR (Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
  125. if ((Prot->Interface == Interface) && (Prot->Protocol == ProtEntry)) {
  126. break;
  127. }
  128. Prot = NULL;
  129. }
  130. }
  131. return Prot;
  132. }
  133. /**
  134. Signal event for every protocol in protocol entry.
  135. @param ProtEntry Protocol entry
  136. **/
  137. VOID
  138. UnitTestNotifyProtocolEntry (
  139. IN PROTOCOL_ENTRY *ProtEntry
  140. )
  141. {
  142. PROTOCOL_NOTIFY *ProtNotify;
  143. LIST_ENTRY *Link;
  144. for (Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link = Link->ForwardLink) {
  145. ProtNotify = CR (Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
  146. UnitTestSignalEvent (ProtNotify->Event);
  147. }
  148. }
  149. /**
  150. Routine to get the next Handle, when you are searching for all handles.
  151. @param Position Information about which Handle to seach for.
  152. @param Interface Return the interface structure for the matching
  153. protocol.
  154. @return An pointer to IHANDLE if the next Position is not the end of the list.
  155. Otherwise,NULL is returned.
  156. **/
  157. IHANDLE *
  158. UnitTestGetNextLocateAllHandles (
  159. IN OUT LOCATE_POSITION *Position,
  160. OUT VOID **Interface
  161. )
  162. {
  163. IHANDLE *Handle;
  164. //
  165. // Next handle
  166. //
  167. Position->Position = Position->Position->ForwardLink;
  168. //
  169. // If not at the end of the list, get the handle
  170. //
  171. Handle = NULL;
  172. *Interface = NULL;
  173. if (Position->Position != &gHandleList) {
  174. Handle = CR (Position->Position, IHANDLE, AllHandles, EFI_HANDLE_SIGNATURE);
  175. }
  176. return Handle;
  177. }
  178. /**
  179. Routine to get the next Handle, when you are searching for register protocol
  180. notifies.
  181. @param Position Information about which Handle to seach for.
  182. @param Interface Return the interface structure for the matching
  183. protocol.
  184. @return An pointer to IHANDLE if the next Position is not the end of the list.
  185. Otherwise,NULL is returned.
  186. **/
  187. IHANDLE *
  188. UnitTestGetNextLocateByRegisterNotify (
  189. IN OUT LOCATE_POSITION *Position,
  190. OUT VOID **Interface
  191. )
  192. {
  193. IHANDLE *Handle;
  194. PROTOCOL_NOTIFY *ProtNotify;
  195. PROTOCOL_INTERFACE *Prot;
  196. LIST_ENTRY *Link;
  197. Handle = NULL;
  198. *Interface = NULL;
  199. ProtNotify = Position->SearchKey;
  200. //
  201. // If this is the first request, get the next handle
  202. //
  203. if (ProtNotify != NULL) {
  204. ASSERT (ProtNotify->Signature == PROTOCOL_NOTIFY_SIGNATURE);
  205. Position->SearchKey = NULL;
  206. //
  207. // If not at the end of the list, get the next handle
  208. //
  209. Link = ProtNotify->Position->ForwardLink;
  210. if (Link != &ProtNotify->Protocol->Protocols) {
  211. Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
  212. Handle = Prot->Handle;
  213. *Interface = Prot->Interface;
  214. }
  215. }
  216. return Handle;
  217. }
  218. /**
  219. Routine to get the next Handle, when you are searching for a given protocol.
  220. @param Position Information about which Handle to seach for.
  221. @param Interface Return the interface structure for the matching
  222. protocol.
  223. @return An pointer to IHANDLE if the next Position is not the end of the list.
  224. Otherwise,NULL is returned.
  225. **/
  226. IHANDLE *
  227. UnitTestGetNextLocateByProtocol (
  228. IN OUT LOCATE_POSITION *Position,
  229. OUT VOID **Interface
  230. )
  231. {
  232. IHANDLE *Handle;
  233. LIST_ENTRY *Link;
  234. PROTOCOL_INTERFACE *Prot;
  235. Handle = NULL;
  236. *Interface = NULL;
  237. for ( ; ;) {
  238. //
  239. // Next entry
  240. //
  241. Link = Position->Position->ForwardLink;
  242. Position->Position = Link;
  243. //
  244. // If not at the end, return the handle
  245. //
  246. if (Link == &Position->ProtEntry->Protocols) {
  247. Handle = NULL;
  248. break;
  249. }
  250. //
  251. // Get the handle
  252. //
  253. Prot = CR (Link, PROTOCOL_INTERFACE, ByProtocol, PROTOCOL_INTERFACE_SIGNATURE);
  254. Handle = Prot->Handle;
  255. *Interface = Prot->Interface;
  256. //
  257. // If this handle has not been returned this request, then
  258. // return it now
  259. //
  260. if (Handle->LocateRequest != mEfiLocateHandleRequest) {
  261. Handle->LocateRequest = mEfiLocateHandleRequest;
  262. break;
  263. }
  264. }
  265. return Handle;
  266. }
  267. /**
  268. Attempts to disconnect all drivers that are using the protocol interface being queried.
  269. If failed, reconnect all drivers disconnected.
  270. Note: This function doesn't do parameters checking, it's caller's responsibility
  271. to pass in valid parameters.
  272. @param UserHandle The handle on which the protocol is installed
  273. @param Prot The protocol to disconnect drivers from
  274. @retval EFI_SUCCESS Drivers using the protocol interface are all
  275. disconnected
  276. @retval EFI_ACCESS_DENIED Failed to disconnect one or all of the drivers
  277. **/
  278. EFI_STATUS
  279. UnitTestDisconnectControllersUsingProtocolInterface (
  280. IN EFI_HANDLE UserHandle,
  281. IN PROTOCOL_INTERFACE *Prot
  282. )
  283. {
  284. EFI_STATUS Status;
  285. BOOLEAN ItemFound;
  286. LIST_ENTRY *Link;
  287. OPEN_PROTOCOL_DATA *OpenData;
  288. Status = EFI_SUCCESS;
  289. //
  290. // Attempt to disconnect all drivers from this protocol interface
  291. //
  292. do {
  293. ItemFound = FALSE;
  294. for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
  295. OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
  296. if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
  297. Status = UnitTestDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
  298. if (!EFI_ERROR (Status)) {
  299. ItemFound = TRUE;
  300. }
  301. break;
  302. }
  303. }
  304. } while (ItemFound);
  305. if (!EFI_ERROR (Status)) {
  306. //
  307. // Attempt to remove BY_HANDLE_PROTOCOL and GET_PROTOCOL and TEST_PROTOCOL Open List items
  308. //
  309. for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList;) {
  310. OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
  311. if ((OpenData->Attributes &
  312. (EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL | EFI_OPEN_PROTOCOL_GET_PROTOCOL | EFI_OPEN_PROTOCOL_TEST_PROTOCOL)) != 0)
  313. {
  314. Link = RemoveEntryList (&OpenData->Link);
  315. Prot->OpenListCount--;
  316. FreePool (OpenData);
  317. } else {
  318. Link = Link->ForwardLink;
  319. }
  320. }
  321. }
  322. //
  323. // If there are errors or still has open items in the list, then reconnect all the drivers and return an error
  324. //
  325. if (EFI_ERROR (Status) || (Prot->OpenListCount > 0)) {
  326. UnitTestConnectController (UserHandle, NULL, NULL, TRUE);
  327. Status = EFI_ACCESS_DENIED;
  328. }
  329. return Status;
  330. }
  331. /**
  332. Removes Protocol from the protocol list (but not the handle list).
  333. @param Handle The handle to remove protocol on.
  334. @param Protocol GUID of the protocol to be moved
  335. @param Interface The interface of the protocol
  336. @return Protocol Entry
  337. **/
  338. PROTOCOL_INTERFACE *
  339. UnitTestRemoveInterfaceFromProtocol (
  340. IN IHANDLE *Handle,
  341. IN EFI_GUID *Protocol,
  342. IN VOID *Interface
  343. )
  344. {
  345. PROTOCOL_INTERFACE *Prot;
  346. PROTOCOL_NOTIFY *ProtNotify;
  347. PROTOCOL_ENTRY *ProtEntry;
  348. LIST_ENTRY *Link;
  349. Prot = UnitTestFindProtocolInterface (Handle, Protocol, Interface);
  350. if (Prot != NULL) {
  351. ProtEntry = Prot->Protocol;
  352. //
  353. // If there's a protocol notify location pointing to this entry, back it up one
  354. //
  355. for (Link = ProtEntry->Notify.ForwardLink; Link != &ProtEntry->Notify; Link = Link->ForwardLink) {
  356. ProtNotify = CR (Link, PROTOCOL_NOTIFY, Link, PROTOCOL_NOTIFY_SIGNATURE);
  357. if (ProtNotify->Position == &Prot->ByProtocol) {
  358. ProtNotify->Position = Prot->ByProtocol.BackLink;
  359. }
  360. }
  361. //
  362. // Remove the protocol interface entry
  363. //
  364. RemoveEntryList (&Prot->ByProtocol);
  365. }
  366. return Prot;
  367. }
  368. //
  369. // Boot Services Function Implementation
  370. //
  371. /**
  372. Locate a certain GUID protocol interface in a Handle's protocols.
  373. @param UserHandle The handle to obtain the protocol interface on
  374. @param Protocol The GUID of the protocol
  375. @return The requested protocol interface for the handle
  376. **/
  377. PROTOCOL_INTERFACE *
  378. UnitTestGetProtocolInterface (
  379. IN EFI_HANDLE UserHandle,
  380. IN EFI_GUID *Protocol
  381. )
  382. {
  383. EFI_STATUS Status;
  384. PROTOCOL_ENTRY *ProtEntry;
  385. PROTOCOL_INTERFACE *Prot;
  386. IHANDLE *Handle;
  387. LIST_ENTRY *Link;
  388. Status = UnitTestValidateHandle (UserHandle);
  389. if (EFI_ERROR (Status)) {
  390. return NULL;
  391. }
  392. Handle = (IHANDLE *)UserHandle;
  393. //
  394. // Look at each protocol interface for a match
  395. //
  396. for (Link = Handle->Protocols.ForwardLink; Link != &Handle->Protocols; Link = Link->ForwardLink) {
  397. Prot = CR (Link, PROTOCOL_INTERFACE, Link, PROTOCOL_INTERFACE_SIGNATURE);
  398. ProtEntry = Prot->Protocol;
  399. if (CompareGuid (&ProtEntry->ProtocolID, Protocol)) {
  400. return Prot;
  401. }
  402. }
  403. return NULL;
  404. }
  405. /**
  406. Installs a protocol interface into the boot services environment.
  407. @param UserHandle The handle to install the protocol handler on,
  408. or NULL if a new handle is to be allocated
  409. @param Protocol The protocol to add to the handle
  410. @param InterfaceType Indicates whether Interface is supplied in
  411. native form.
  412. @param Interface The interface for the protocol being added
  413. @param Notify indicates whether notify the notification list
  414. for this protocol
  415. @retval EFI_INVALID_PARAMETER Invalid parameter
  416. @retval EFI_OUT_OF_RESOURCES No enough buffer to allocate
  417. @retval EFI_SUCCESS Protocol interface successfully installed
  418. **/
  419. EFI_STATUS
  420. UnitTestInstallProtocolInterfaceNotify (
  421. IN OUT EFI_HANDLE *UserHandle,
  422. IN EFI_GUID *Protocol,
  423. IN EFI_INTERFACE_TYPE InterfaceType,
  424. IN VOID *Interface,
  425. IN BOOLEAN Notify
  426. )
  427. {
  428. PROTOCOL_INTERFACE *Prot;
  429. PROTOCOL_ENTRY *ProtEntry;
  430. IHANDLE *Handle;
  431. EFI_STATUS Status;
  432. VOID *ExistingInterface;
  433. //
  434. // returns EFI_INVALID_PARAMETER if InterfaceType is invalid.
  435. // Also added check for invalid UserHandle and Protocol pointers.
  436. //
  437. if ((UserHandle == NULL) || (Protocol == NULL)) {
  438. return EFI_INVALID_PARAMETER;
  439. }
  440. if (InterfaceType != EFI_NATIVE_INTERFACE) {
  441. return EFI_INVALID_PARAMETER;
  442. }
  443. //
  444. // Print debug message
  445. //
  446. UT_LOG_INFO ("InstallProtocolInterface: %g %p\n", Protocol, Interface);
  447. Status = EFI_OUT_OF_RESOURCES;
  448. Prot = NULL;
  449. Handle = NULL;
  450. if (*UserHandle != NULL) {
  451. Status = UnitTestHandleProtocol (*UserHandle, Protocol, (VOID **)&ExistingInterface);
  452. if (!EFI_ERROR (Status)) {
  453. return EFI_INVALID_PARAMETER;
  454. }
  455. }
  456. //
  457. // Lookup the Protocol Entry for the requested protocol
  458. //
  459. ProtEntry = UnitTestFindProtocolEntry (Protocol, TRUE);
  460. if (ProtEntry == NULL) {
  461. goto Done;
  462. }
  463. //
  464. // Allocate a new protocol interface structure
  465. //
  466. Prot = AllocateZeroPool (sizeof (PROTOCOL_INTERFACE));
  467. if (Prot == NULL) {
  468. Status = EFI_OUT_OF_RESOURCES;
  469. goto Done;
  470. }
  471. //
  472. // If caller didn't supply a handle, allocate a new one
  473. //
  474. Handle = (IHANDLE *)*UserHandle;
  475. if (Handle == NULL) {
  476. Handle = AllocateZeroPool (sizeof (IHANDLE));
  477. if (Handle == NULL) {
  478. Status = EFI_OUT_OF_RESOURCES;
  479. goto Done;
  480. }
  481. //
  482. // Initialize new handler structure
  483. //
  484. Handle->Signature = EFI_HANDLE_SIGNATURE;
  485. InitializeListHead (&Handle->Protocols);
  486. //
  487. // Initialize the Key to show that the handle has been created/modified
  488. //
  489. gHandleDatabaseKey++;
  490. Handle->Key = gHandleDatabaseKey;
  491. //
  492. // Add this handle to the list global list of all handles
  493. // in the system
  494. //
  495. InsertTailList (&gHandleList, &Handle->AllHandles);
  496. } else {
  497. Status = UnitTestValidateHandle (Handle);
  498. if (EFI_ERROR (Status)) {
  499. DEBUG ((DEBUG_ERROR, "InstallProtocolInterface: input handle at 0x%x is invalid\n", Handle));
  500. goto Done;
  501. }
  502. }
  503. //
  504. // Each interface that is added must be unique
  505. //
  506. ASSERT (UnitTestFindProtocolInterface (Handle, Protocol, Interface) == NULL);
  507. //
  508. // Initialize the protocol interface structure
  509. //
  510. Prot->Signature = PROTOCOL_INTERFACE_SIGNATURE;
  511. Prot->Handle = Handle;
  512. Prot->Protocol = ProtEntry;
  513. Prot->Interface = Interface;
  514. //
  515. // Initialize OpenProtocol Data base
  516. //
  517. InitializeListHead (&Prot->OpenList);
  518. Prot->OpenListCount = 0;
  519. //
  520. // Add this protocol interface to the head of the supported
  521. // protocol list for this handle
  522. //
  523. InsertHeadList (&Handle->Protocols, &Prot->Link);
  524. //
  525. // Add this protocol interface to the tail of the
  526. // protocol entry
  527. //
  528. InsertTailList (&ProtEntry->Protocols, &Prot->ByProtocol);
  529. //
  530. // Notify the notification list for this protocol
  531. //
  532. if (Notify) {
  533. UnitTestNotifyProtocolEntry (ProtEntry);
  534. }
  535. Status = EFI_SUCCESS;
  536. Done:
  537. if (!EFI_ERROR (Status)) {
  538. //
  539. // Return the new handle back to the caller
  540. //
  541. *UserHandle = Handle;
  542. } else {
  543. //
  544. // There was an error, clean up
  545. //
  546. if (Prot != NULL) {
  547. UnitTestFreePool (Prot);
  548. }
  549. DEBUG ((DEBUG_ERROR, "InstallProtocolInterface: %g %p failed with %r\n", Protocol, Interface, Status));
  550. }
  551. return Status;
  552. }
  553. /**
  554. Wrapper function to UnitTestInstallProtocolInterfaceNotify. This is the public API which
  555. Calls the private one which contains a BOOLEAN parameter for notifications
  556. @param UserHandle The handle to install the protocol handler on,
  557. or NULL if a new handle is to be allocated
  558. @param Protocol The protocol to add to the handle
  559. @param InterfaceType Indicates whether Interface is supplied in
  560. native form.
  561. @param Interface The interface for the protocol being added
  562. @return Status code
  563. **/
  564. EFI_STATUS
  565. EFIAPI
  566. UnitTestInstallProtocolInterface (
  567. IN OUT EFI_HANDLE *UserHandle,
  568. IN EFI_GUID *Protocol,
  569. IN EFI_INTERFACE_TYPE InterfaceType,
  570. IN VOID *Interface
  571. )
  572. {
  573. return UnitTestInstallProtocolInterfaceNotify (
  574. UserHandle,
  575. Protocol,
  576. InterfaceType,
  577. Interface,
  578. TRUE
  579. );
  580. }
  581. /**
  582. Reinstall a protocol interface on a device handle. The OldInterface for Protocol is replaced by the NewInterface.
  583. @param UserHandle Handle on which the interface is to be
  584. reinstalled
  585. @param Protocol The numeric ID of the interface
  586. @param OldInterface A pointer to the old interface
  587. @param NewInterface A pointer to the new interface
  588. @retval EFI_SUCCESS The protocol interface was installed
  589. @retval EFI_NOT_FOUND The OldInterface on the handle was not found
  590. @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value
  591. **/
  592. EFI_STATUS
  593. EFIAPI
  594. UnitTestReinstallProtocolInterface (
  595. IN EFI_HANDLE UserHandle,
  596. IN EFI_GUID *Protocol,
  597. IN VOID *OldInterface,
  598. IN VOID *NewInterface
  599. )
  600. {
  601. return EFI_NOT_AVAILABLE_YET;
  602. }
  603. /**
  604. Uninstalls all instances of a protocol:interfacer from a handle.
  605. If the last protocol interface is remove from the handle, the
  606. handle is freed.
  607. @param UserHandle The handle to remove the protocol handler from
  608. @param Protocol The protocol, of protocol:interface, to remove
  609. @param Interface The interface, of protocol:interface, to remove
  610. @retval EFI_INVALID_PARAMETER Protocol is NULL.
  611. @retval EFI_SUCCESS Protocol interface successfully uninstalled.
  612. **/
  613. EFI_STATUS
  614. EFIAPI
  615. UnitTestUninstallProtocolInterface (
  616. IN EFI_HANDLE UserHandle,
  617. IN EFI_GUID *Protocol,
  618. IN VOID *Interface
  619. )
  620. {
  621. EFI_STATUS Status;
  622. IHANDLE *Handle;
  623. PROTOCOL_INTERFACE *Prot;
  624. //
  625. // Check that Protocol is valid
  626. //
  627. if (Protocol == NULL) {
  628. return EFI_INVALID_PARAMETER;
  629. }
  630. //
  631. // Check that UserHandle is a valid handle
  632. //
  633. Status = UnitTestValidateHandle (UserHandle);
  634. if (EFI_ERROR (Status)) {
  635. return Status;
  636. }
  637. //
  638. // Check that Protocol exists on UserHandle, and Interface matches the interface in the database
  639. //
  640. Prot = UnitTestFindProtocolInterface (UserHandle, Protocol, Interface);
  641. if (Prot == NULL) {
  642. Status = EFI_NOT_FOUND;
  643. goto Done;
  644. }
  645. //
  646. // Attempt to disconnect all drivers that are using the protocol interface that is about to be removed
  647. //
  648. Status = UnitTestDisconnectControllersUsingProtocolInterface (
  649. UserHandle,
  650. Prot
  651. );
  652. if (EFI_ERROR (Status)) {
  653. //
  654. // One or more drivers refused to release, so return the error
  655. //
  656. goto Done;
  657. }
  658. //
  659. // Remove the protocol interface from the protocol
  660. //
  661. Status = EFI_NOT_FOUND;
  662. Handle = (IHANDLE *)UserHandle;
  663. Prot = UnitTestRemoveInterfaceFromProtocol (Handle, Protocol, Interface);
  664. if (Prot != NULL) {
  665. //
  666. // Update the Key to show that the handle has been created/modified
  667. //
  668. gHandleDatabaseKey++;
  669. Handle->Key = gHandleDatabaseKey;
  670. //
  671. // Remove the protocol interface from the handle
  672. //
  673. RemoveEntryList (&Prot->Link);
  674. //
  675. // Free the memory
  676. //
  677. Prot->Signature = 0;
  678. FreePool (Prot);
  679. Status = EFI_SUCCESS;
  680. }
  681. //
  682. // If there are no more handlers for the handle, free the handle
  683. //
  684. if (IsListEmpty (&Handle->Protocols)) {
  685. Handle->Signature = 0;
  686. RemoveEntryList (&Handle->AllHandles);
  687. FreePool (Handle);
  688. }
  689. Done:
  690. return Status;
  691. }
  692. /**
  693. Queries a handle to determine if it supports a specified protocol.
  694. @param UserHandle The handle being queried.
  695. @param Protocol The published unique identifier of the protocol.
  696. @param Interface Supplies the address where a pointer to the
  697. corresponding Protocol Interface is returned.
  698. @return The requested protocol interface for the handle
  699. **/
  700. EFI_STATUS
  701. EFIAPI
  702. UnitTestHandleProtocol (
  703. IN EFI_HANDLE UserHandle,
  704. IN EFI_GUID *Protocol,
  705. OUT VOID **Interface
  706. )
  707. {
  708. return UnitTestOpenProtocol (
  709. UserHandle,
  710. Protocol,
  711. Interface,
  712. gImageHandle,
  713. NULL,
  714. EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL
  715. );
  716. }
  717. /**
  718. Add a new protocol notification record for the request protocol.
  719. @param Protocol The requested protocol to add the notify
  720. registration
  721. @param Event The event to signal
  722. @param Registration Returns the registration record
  723. @retval EFI_INVALID_PARAMETER Invalid parameter
  724. @retval EFI_SUCCESS Successfully returned the registration record
  725. that has been added
  726. **/
  727. EFI_STATUS
  728. EFIAPI
  729. UnitTestRegisterProtocolNotify (
  730. IN EFI_GUID *Protocol,
  731. IN EFI_EVENT Event,
  732. OUT VOID **Registration
  733. )
  734. {
  735. return EFI_NOT_AVAILABLE_YET;
  736. }
  737. /**
  738. Locates the requested handle(s) and returns them in Buffer.
  739. @param SearchType The type of search to perform to locate the
  740. handles
  741. @param Protocol The protocol to search for
  742. @param SearchKey Dependant on SearchType
  743. @param BufferSize On input the size of Buffer. On output the
  744. size of data returned.
  745. @param Buffer The buffer to return the results in
  746. @retval EFI_BUFFER_TOO_SMALL Buffer too small, required buffer size is
  747. returned in BufferSize.
  748. @retval EFI_INVALID_PARAMETER Invalid parameter
  749. @retval EFI_SUCCESS Successfully found the requested handle(s) and
  750. returns them in Buffer.
  751. **/
  752. EFI_STATUS
  753. EFIAPI
  754. UnitTestLocateHandle (
  755. IN EFI_LOCATE_SEARCH_TYPE SearchType,
  756. IN EFI_GUID *Protocol OPTIONAL,
  757. IN VOID *SearchKey OPTIONAL,
  758. IN OUT UINTN *BufferSize,
  759. OUT EFI_HANDLE *Buffer
  760. )
  761. {
  762. EFI_STATUS Status;
  763. LOCATE_POSITION Position;
  764. PROTOCOL_NOTIFY *ProtNotify;
  765. UNIT_TEST_GET_NEXT GetNext;
  766. UINTN ResultSize;
  767. IHANDLE *Handle;
  768. IHANDLE **ResultBuffer;
  769. VOID *Interface;
  770. if (BufferSize == NULL) {
  771. return EFI_INVALID_PARAMETER;
  772. }
  773. if ((*BufferSize > 0) && (Buffer == NULL)) {
  774. return EFI_INVALID_PARAMETER;
  775. }
  776. GetNext = NULL;
  777. //
  778. // Set initial position
  779. //
  780. Position.Protocol = Protocol;
  781. Position.SearchKey = SearchKey;
  782. Position.Position = &gHandleList;
  783. ResultSize = 0;
  784. ResultBuffer = (IHANDLE **)Buffer;
  785. Status = EFI_SUCCESS;
  786. //
  787. // Get the search function based on type
  788. //
  789. switch (SearchType) {
  790. case AllHandles:
  791. GetNext = UnitTestGetNextLocateAllHandles;
  792. break;
  793. case ByRegisterNotify:
  794. //
  795. // Must have SearchKey for locate ByRegisterNotify
  796. //
  797. if (SearchKey == NULL) {
  798. Status = EFI_INVALID_PARAMETER;
  799. break;
  800. }
  801. GetNext = UnitTestGetNextLocateByRegisterNotify;
  802. break;
  803. case ByProtocol:
  804. GetNext = UnitTestGetNextLocateByProtocol;
  805. if (Protocol == NULL) {
  806. Status = EFI_INVALID_PARAMETER;
  807. break;
  808. }
  809. //
  810. // Look up the protocol entry and set the head pointer
  811. //
  812. Position.ProtEntry = UnitTestFindProtocolEntry (Protocol, FALSE);
  813. if (Position.ProtEntry == NULL) {
  814. Status = EFI_NOT_FOUND;
  815. break;
  816. }
  817. Position.Position = &Position.ProtEntry->Protocols;
  818. break;
  819. default:
  820. Status = EFI_INVALID_PARAMETER;
  821. break;
  822. }
  823. if (EFI_ERROR (Status)) {
  824. return Status;
  825. }
  826. ASSERT (GetNext != NULL);
  827. //
  828. // Enumerate out the matching handles
  829. //
  830. mEfiLocateHandleRequest += 1;
  831. for ( ; ;) {
  832. //
  833. // Get the next handle. If no more handles, stop
  834. //
  835. Handle = GetNext (&Position, &Interface);
  836. if (NULL == Handle) {
  837. break;
  838. }
  839. //
  840. // Increase the resulting buffer size, and if this handle
  841. // fits return it
  842. //
  843. ResultSize += sizeof (Handle);
  844. if (ResultSize <= *BufferSize) {
  845. *ResultBuffer = Handle;
  846. ResultBuffer += 1;
  847. }
  848. }
  849. //
  850. // If the result is a zero length buffer, then there were no
  851. // matching handles
  852. //
  853. if (ResultSize == 0) {
  854. Status = EFI_NOT_FOUND;
  855. } else {
  856. //
  857. // Return the resulting buffer size. If it's larger than what
  858. // was passed, then set the error code
  859. //
  860. if (ResultSize > *BufferSize) {
  861. Status = EFI_BUFFER_TOO_SMALL;
  862. }
  863. *BufferSize = ResultSize;
  864. if ((SearchType == ByRegisterNotify) && !EFI_ERROR (Status)) {
  865. //
  866. // If this is a search by register notify and a handle was
  867. // returned, update the register notification position
  868. //
  869. ASSERT (SearchKey != NULL);
  870. ProtNotify = SearchKey;
  871. ProtNotify->Position = ProtNotify->Position->ForwardLink;
  872. }
  873. }
  874. return Status;
  875. }
  876. /**
  877. Locates the handle to a device on the device path that best matches the specified protocol.
  878. @param Protocol The protocol to search for.
  879. @param DevicePath On input, a pointer to a pointer to the device
  880. path. On output, the device path pointer is
  881. modified to point to the remaining part of the
  882. devicepath.
  883. @param Device A pointer to the returned device handle.
  884. @retval EFI_SUCCESS The resulting handle was returned.
  885. @retval EFI_NOT_FOUND No handles matched the search.
  886. @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
  887. **/
  888. EFI_STATUS
  889. EFIAPI
  890. UnitTestLocateDevicePath (
  891. IN EFI_GUID *Protocol,
  892. IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath,
  893. OUT EFI_HANDLE *Device
  894. )
  895. {
  896. return EFI_NOT_AVAILABLE_YET;
  897. }
  898. /**
  899. Boot Service called to add, modify, or remove a system configuration table from
  900. the EFI System Table.
  901. @param Guid Pointer to the GUID for the entry to add, update, or
  902. remove
  903. @param Table Pointer to the configuration table for the entry to add,
  904. update, or remove, may be NULL.
  905. @return EFI_SUCCESS Guid, Table pair added, updated, or removed.
  906. @return EFI_INVALID_PARAMETER Input GUID not valid.
  907. @return EFI_NOT_FOUND Attempted to delete non-existant entry
  908. @return EFI_OUT_OF_RESOURCES Not enough memory available
  909. **/
  910. EFI_STATUS
  911. EFIAPI
  912. UnitTestInstallConfigurationTable (
  913. IN EFI_GUID *Guid,
  914. IN VOID *Table
  915. )
  916. {
  917. return EFI_NOT_AVAILABLE_YET;
  918. }
  919. /**
  920. Locates the installed protocol handler for the handle, and
  921. invokes it to obtain the protocol interface. Usage information
  922. is registered in the protocol data base.
  923. @param UserHandle The handle to obtain the protocol interface on
  924. @param Protocol The ID of the protocol
  925. @param Interface The location to return the protocol interface
  926. @param ImageHandle The handle of the Image that is opening the
  927. protocol interface specified by Protocol and
  928. Interface.
  929. @param ControllerHandle The controller handle that is requiring this
  930. interface.
  931. @param Attributes The open mode of the protocol interface
  932. specified by Handle and Protocol.
  933. @retval EFI_INVALID_PARAMETER Protocol is NULL.
  934. @retval EFI_SUCCESS Get the protocol interface.
  935. **/
  936. EFI_STATUS
  937. EFIAPI
  938. UnitTestOpenProtocol (
  939. IN EFI_HANDLE UserHandle,
  940. IN EFI_GUID *Protocol,
  941. OUT VOID **Interface OPTIONAL,
  942. IN EFI_HANDLE ImageHandle,
  943. IN EFI_HANDLE ControllerHandle,
  944. IN UINT32 Attributes
  945. )
  946. {
  947. EFI_STATUS Status;
  948. PROTOCOL_INTERFACE *Prot;
  949. LIST_ENTRY *Link;
  950. OPEN_PROTOCOL_DATA *OpenData;
  951. BOOLEAN ByDriver;
  952. BOOLEAN Exclusive;
  953. BOOLEAN Disconnect;
  954. BOOLEAN ExactMatch;
  955. //
  956. // Check for invalid Protocol
  957. //
  958. if (Protocol == NULL) {
  959. return EFI_INVALID_PARAMETER;
  960. }
  961. //
  962. // Check for invalid Interface
  963. //
  964. if ((Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) && (Interface == NULL)) {
  965. return EFI_INVALID_PARAMETER;
  966. }
  967. //
  968. // Check for invalid UserHandle
  969. //
  970. Status = UnitTestValidateHandle (UserHandle);
  971. if (EFI_ERROR (Status)) {
  972. return Status;
  973. }
  974. //
  975. // Check for invalid Attributes
  976. //
  977. switch (Attributes) {
  978. case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER:
  979. Status = UnitTestValidateHandle (ImageHandle);
  980. if (EFI_ERROR (Status)) {
  981. return Status;
  982. }
  983. Status = UnitTestValidateHandle (ControllerHandle);
  984. if (EFI_ERROR (Status)) {
  985. return Status;
  986. }
  987. if (UserHandle == ControllerHandle) {
  988. return EFI_INVALID_PARAMETER;
  989. }
  990. break;
  991. case EFI_OPEN_PROTOCOL_BY_DRIVER:
  992. case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE:
  993. Status = UnitTestValidateHandle (ImageHandle);
  994. if (EFI_ERROR (Status)) {
  995. return Status;
  996. }
  997. Status = UnitTestValidateHandle (ControllerHandle);
  998. if (EFI_ERROR (Status)) {
  999. return Status;
  1000. }
  1001. break;
  1002. case EFI_OPEN_PROTOCOL_EXCLUSIVE:
  1003. Status = UnitTestValidateHandle (ImageHandle);
  1004. if (EFI_ERROR (Status)) {
  1005. return Status;
  1006. }
  1007. break;
  1008. case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL:
  1009. case EFI_OPEN_PROTOCOL_GET_PROTOCOL:
  1010. case EFI_OPEN_PROTOCOL_TEST_PROTOCOL:
  1011. break;
  1012. default:
  1013. return EFI_INVALID_PARAMETER;
  1014. }
  1015. //
  1016. // Look at each protocol interface for a match
  1017. //
  1018. Prot = UnitTestGetProtocolInterface (UserHandle, Protocol);
  1019. if (Prot == NULL) {
  1020. Status = EFI_UNSUPPORTED;
  1021. goto Done;
  1022. }
  1023. Status = EFI_SUCCESS;
  1024. ByDriver = FALSE;
  1025. Exclusive = FALSE;
  1026. for ( Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
  1027. OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
  1028. ExactMatch = (BOOLEAN)((OpenData->AgentHandle == ImageHandle) &&
  1029. (OpenData->Attributes == Attributes) &&
  1030. (OpenData->ControllerHandle == ControllerHandle));
  1031. if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
  1032. ByDriver = TRUE;
  1033. if (ExactMatch) {
  1034. Status = EFI_ALREADY_STARTED;
  1035. goto Done;
  1036. }
  1037. }
  1038. if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_EXCLUSIVE) != 0) {
  1039. Exclusive = TRUE;
  1040. } else if (ExactMatch) {
  1041. OpenData->OpenCount++;
  1042. Status = EFI_SUCCESS;
  1043. goto Done;
  1044. }
  1045. }
  1046. //
  1047. // ByDriver TRUE -> A driver is managing (UserHandle, Protocol)
  1048. // ByDriver FALSE -> There are no drivers managing (UserHandle, Protocol)
  1049. // Exclusive TRUE -> Something has exclusive access to (UserHandle, Protocol)
  1050. // Exclusive FALSE -> Nothing has exclusive access to (UserHandle, Protocol)
  1051. //
  1052. switch (Attributes) {
  1053. case EFI_OPEN_PROTOCOL_BY_DRIVER:
  1054. if (Exclusive || ByDriver) {
  1055. Status = EFI_ACCESS_DENIED;
  1056. goto Done;
  1057. }
  1058. break;
  1059. case EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE:
  1060. case EFI_OPEN_PROTOCOL_EXCLUSIVE:
  1061. if (Exclusive) {
  1062. Status = EFI_ACCESS_DENIED;
  1063. goto Done;
  1064. }
  1065. if (ByDriver) {
  1066. do {
  1067. Disconnect = FALSE;
  1068. for (Link = Prot->OpenList.ForwardLink; Link != &Prot->OpenList; Link = Link->ForwardLink) {
  1069. OpenData = CR (Link, OPEN_PROTOCOL_DATA, Link, OPEN_PROTOCOL_DATA_SIGNATURE);
  1070. if ((OpenData->Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
  1071. Disconnect = TRUE;
  1072. Status = UnitTestDisconnectController (UserHandle, OpenData->AgentHandle, NULL);
  1073. if (EFI_ERROR (Status)) {
  1074. Status = EFI_ACCESS_DENIED;
  1075. goto Done;
  1076. } else {
  1077. break;
  1078. }
  1079. }
  1080. }
  1081. } while (Disconnect);
  1082. }
  1083. break;
  1084. case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER:
  1085. case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL:
  1086. case EFI_OPEN_PROTOCOL_GET_PROTOCOL:
  1087. case EFI_OPEN_PROTOCOL_TEST_PROTOCOL:
  1088. break;
  1089. }
  1090. if (ImageHandle == NULL) {
  1091. Status = EFI_SUCCESS;
  1092. goto Done;
  1093. }
  1094. //
  1095. // Create new entry
  1096. //
  1097. OpenData = AllocatePool (sizeof (OPEN_PROTOCOL_DATA));
  1098. if (OpenData == NULL) {
  1099. Status = EFI_OUT_OF_RESOURCES;
  1100. } else {
  1101. OpenData->Signature = OPEN_PROTOCOL_DATA_SIGNATURE;
  1102. OpenData->AgentHandle = ImageHandle;
  1103. OpenData->ControllerHandle = ControllerHandle;
  1104. OpenData->Attributes = Attributes;
  1105. OpenData->OpenCount = 1;
  1106. InsertTailList (&Prot->OpenList, &OpenData->Link);
  1107. Prot->OpenListCount++;
  1108. Status = EFI_SUCCESS;
  1109. }
  1110. Done:
  1111. if (Attributes != EFI_OPEN_PROTOCOL_TEST_PROTOCOL) {
  1112. //
  1113. // Keep Interface unmodified in case of any Error
  1114. // except EFI_ALREADY_STARTED and EFI_UNSUPPORTED.
  1115. //
  1116. if (!EFI_ERROR (Status) || (Status == EFI_ALREADY_STARTED)) {
  1117. //
  1118. // According to above logic, if 'Prot' is NULL, then the 'Status' must be
  1119. // EFI_UNSUPPORTED. Here the 'Status' is not EFI_UNSUPPORTED, so 'Prot'
  1120. // must be not NULL.
  1121. //
  1122. // The ASSERT here is for addressing a false positive NULL pointer
  1123. // dereference issue raised from static analysis.
  1124. //
  1125. ASSERT (Prot != NULL);
  1126. //
  1127. // EFI_ALREADY_STARTED is not an error for bus driver.
  1128. // Return the corresponding protocol interface.
  1129. //
  1130. *Interface = Prot->Interface;
  1131. } else if (Status == EFI_UNSUPPORTED) {
  1132. //
  1133. // Return NULL Interface if Unsupported Protocol.
  1134. //
  1135. *Interface = NULL;
  1136. }
  1137. }
  1138. return Status;
  1139. }
  1140. /**
  1141. Closes a protocol on a handle that was opened using OpenProtocol().
  1142. @param UserHandle The handle for the protocol interface that was
  1143. previously opened with OpenProtocol(), and is
  1144. now being closed.
  1145. @param Protocol The published unique identifier of the protocol.
  1146. It is the caller's responsibility to pass in a
  1147. valid GUID.
  1148. @param AgentHandle The handle of the agent that is closing the
  1149. protocol interface.
  1150. @param ControllerHandle If the agent that opened a protocol is a driver
  1151. that follows the EFI Driver Model, then this
  1152. parameter is the controller handle that required
  1153. the protocol interface. If the agent does not
  1154. follow the EFI Driver Model, then this parameter
  1155. is optional and may be NULL.
  1156. @retval EFI_SUCCESS The protocol instance was closed.
  1157. @retval EFI_INVALID_PARAMETER Handle, AgentHandle or ControllerHandle is not a
  1158. valid EFI_HANDLE.
  1159. @retval EFI_NOT_FOUND Can not find the specified protocol or
  1160. AgentHandle.
  1161. **/
  1162. EFI_STATUS
  1163. EFIAPI
  1164. UnitTestCloseProtocol (
  1165. IN EFI_HANDLE UserHandle,
  1166. IN EFI_GUID *Protocol,
  1167. IN EFI_HANDLE AgentHandle,
  1168. IN EFI_HANDLE ControllerHandle
  1169. )
  1170. {
  1171. return EFI_NOT_AVAILABLE_YET;
  1172. }
  1173. /**
  1174. Return information about Opened protocols in the system
  1175. @param UserHandle The handle to close the protocol interface on
  1176. @param Protocol The ID of the protocol
  1177. @param EntryBuffer A pointer to a buffer of open protocol
  1178. information in the form of
  1179. EFI_OPEN_PROTOCOL_INFORMATION_ENTRY structures.
  1180. @param EntryCount Number of EntryBuffer entries
  1181. **/
  1182. EFI_STATUS
  1183. EFIAPI
  1184. UnitTestOpenProtocolInformation (
  1185. IN EFI_HANDLE UserHandle,
  1186. IN EFI_GUID *Protocol,
  1187. OUT EFI_OPEN_PROTOCOL_INFORMATION_ENTRY **EntryBuffer,
  1188. OUT UINTN *EntryCount
  1189. )
  1190. {
  1191. return EFI_NOT_AVAILABLE_YET;
  1192. }
  1193. /**
  1194. Retrieves the list of protocol interface GUIDs that are installed on a handle in a buffer allocated
  1195. from pool.
  1196. @param UserHandle The handle from which to retrieve the list of
  1197. protocol interface GUIDs.
  1198. @param ProtocolBuffer A pointer to the list of protocol interface GUID
  1199. pointers that are installed on Handle.
  1200. @param ProtocolBufferCount A pointer to the number of GUID pointers present
  1201. in ProtocolBuffer.
  1202. @retval EFI_SUCCESS The list of protocol interface GUIDs installed
  1203. on Handle was returned in ProtocolBuffer. The
  1204. number of protocol interface GUIDs was returned
  1205. in ProtocolBufferCount.
  1206. @retval EFI_INVALID_PARAMETER Handle is NULL.
  1207. @retval EFI_INVALID_PARAMETER Handle is not a valid EFI_HANDLE.
  1208. @retval EFI_INVALID_PARAMETER ProtocolBuffer is NULL.
  1209. @retval EFI_INVALID_PARAMETER ProtocolBufferCount is NULL.
  1210. @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
  1211. results.
  1212. **/
  1213. EFI_STATUS
  1214. EFIAPI
  1215. UnitTestProtocolsPerHandle (
  1216. IN EFI_HANDLE UserHandle,
  1217. OUT EFI_GUID ***ProtocolBuffer,
  1218. OUT UINTN *ProtocolBufferCount
  1219. )
  1220. {
  1221. return EFI_NOT_AVAILABLE_YET;
  1222. }
  1223. /**
  1224. Function returns an array of handles that support the requested protocol
  1225. in a buffer allocated from pool. This is a version of UnitTestLocateHandle()
  1226. that allocates a buffer for the caller.
  1227. @param SearchType Specifies which handle(s) are to be returned.
  1228. @param Protocol Provides the protocol to search by. This
  1229. parameter is only valid for SearchType
  1230. ByProtocol.
  1231. @param SearchKey Supplies the search key depending on the
  1232. SearchType.
  1233. @param NumberHandles The number of handles returned in Buffer.
  1234. @param Buffer A pointer to the buffer to return the requested
  1235. array of handles that support Protocol.
  1236. @retval EFI_SUCCESS The result array of handles was returned.
  1237. @retval EFI_NOT_FOUND No handles match the search.
  1238. @retval EFI_OUT_OF_RESOURCES There is not enough pool memory to store the
  1239. matching results.
  1240. @retval EFI_INVALID_PARAMETER One or more parameters are not valid.
  1241. **/
  1242. EFI_STATUS
  1243. EFIAPI
  1244. UnitTestLocateHandleBuffer (
  1245. IN EFI_LOCATE_SEARCH_TYPE SearchType,
  1246. IN EFI_GUID *Protocol OPTIONAL,
  1247. IN VOID *SearchKey OPTIONAL,
  1248. IN OUT UINTN *NumberHandles,
  1249. OUT EFI_HANDLE **Buffer
  1250. )
  1251. {
  1252. EFI_STATUS Status;
  1253. UINTN BufferSize;
  1254. if (NumberHandles == NULL) {
  1255. return EFI_INVALID_PARAMETER;
  1256. }
  1257. if (Buffer == NULL) {
  1258. return EFI_INVALID_PARAMETER;
  1259. }
  1260. BufferSize = 0;
  1261. *NumberHandles = 0;
  1262. *Buffer = NULL;
  1263. Status = UnitTestLocateHandle (
  1264. SearchType,
  1265. Protocol,
  1266. SearchKey,
  1267. &BufferSize,
  1268. *Buffer
  1269. );
  1270. //
  1271. // LocateHandleBuffer() returns incorrect status code if SearchType is
  1272. // invalid.
  1273. //
  1274. // Add code to correctly handle expected errors from UnitTestLocateHandle().
  1275. //
  1276. if (EFI_ERROR (Status) && (Status != EFI_BUFFER_TOO_SMALL)) {
  1277. if (Status != EFI_INVALID_PARAMETER) {
  1278. Status = EFI_NOT_FOUND;
  1279. }
  1280. return Status;
  1281. }
  1282. *Buffer = AllocatePool (BufferSize);
  1283. if (*Buffer == NULL) {
  1284. return EFI_OUT_OF_RESOURCES;
  1285. }
  1286. Status = UnitTestLocateHandle (
  1287. SearchType,
  1288. Protocol,
  1289. SearchKey,
  1290. &BufferSize,
  1291. *Buffer
  1292. );
  1293. *NumberHandles = BufferSize / sizeof (EFI_HANDLE);
  1294. if (EFI_ERROR (Status)) {
  1295. *NumberHandles = 0;
  1296. }
  1297. return Status;
  1298. }
  1299. /**
  1300. Return the first Protocol Interface that matches the Protocol GUID. If
  1301. Registration is passed in, return a Protocol Instance that was just add
  1302. to the system. If Registration is NULL return the first Protocol Interface
  1303. you find.
  1304. @param Protocol The protocol to search for
  1305. @param Registration Optional Registration Key returned from
  1306. RegisterProtocolNotify()
  1307. @param Interface Return the Protocol interface (instance).
  1308. @retval EFI_SUCCESS If a valid Interface is returned
  1309. @retval EFI_INVALID_PARAMETER Invalid parameter
  1310. @retval EFI_NOT_FOUND Protocol interface not found
  1311. **/
  1312. EFI_STATUS
  1313. EFIAPI
  1314. UnitTestLocateProtocol (
  1315. IN EFI_GUID *Protocol,
  1316. IN VOID *Registration OPTIONAL,
  1317. OUT VOID **Interface
  1318. )
  1319. {
  1320. return EFI_NOT_AVAILABLE_YET;
  1321. }
  1322. /**
  1323. Installs a list of protocol interface into the boot services environment.
  1324. This function calls InstallProtocolInterface() in a loop. If any error
  1325. occurs all the protocols added by this function are removed. This is
  1326. basically a lib function to save space.
  1327. @param Handle The handle to install the protocol handlers on,
  1328. or NULL if a new handle is to be allocated
  1329. @param ... EFI_GUID followed by protocol instance. A NULL
  1330. terminates the list. The pairs are the
  1331. arguments to InstallProtocolInterface(). All the
  1332. protocols are added to Handle.
  1333. @retval EFI_SUCCESS All the protocol interface was installed.
  1334. @retval EFI_OUT_OF_RESOURCES There was not enough memory in pool to install all the protocols.
  1335. @retval EFI_ALREADY_STARTED A Device Path Protocol instance was passed in that is already present in
  1336. the handle database.
  1337. @retval EFI_INVALID_PARAMETER Handle is NULL.
  1338. @retval EFI_INVALID_PARAMETER Protocol is already installed on the handle specified by Handle.
  1339. **/
  1340. EFI_STATUS
  1341. EFIAPI
  1342. UnitTestInstallMultipleProtocolInterfaces (
  1343. IN OUT EFI_HANDLE *Handle,
  1344. ...
  1345. )
  1346. {
  1347. return EFI_NOT_AVAILABLE_YET;
  1348. }
  1349. /**
  1350. Uninstalls a list of protocol interface in the boot services environment.
  1351. This function calls UninstallProtocolInterface() in a loop. This is
  1352. basically a lib function to save space.
  1353. @param Handle The handle to uninstall the protocol
  1354. @param ... EFI_GUID followed by protocol instance. A NULL
  1355. terminates the list. The pairs are the
  1356. arguments to UninstallProtocolInterface(). All
  1357. the protocols are added to Handle.
  1358. @return Status code
  1359. **/
  1360. EFI_STATUS
  1361. EFIAPI
  1362. UnitTestUninstallMultipleProtocolInterfaces (
  1363. IN EFI_HANDLE Handle,
  1364. ...
  1365. )
  1366. {
  1367. EFI_STATUS Status;
  1368. VA_LIST Args;
  1369. EFI_GUID *Protocol;
  1370. VOID *Interface;
  1371. UINTN Index;
  1372. VA_START (Args, Handle);
  1373. for (Index = 0, Status = EFI_SUCCESS; !EFI_ERROR (Status); Index++) {
  1374. //
  1375. // If protocol is NULL, then it's the end of the list
  1376. //
  1377. Protocol = VA_ARG (Args, EFI_GUID *);
  1378. if (Protocol == NULL) {
  1379. break;
  1380. }
  1381. Interface = VA_ARG (Args, VOID *);
  1382. //
  1383. // Uninstall it
  1384. //
  1385. Status = UnitTestUninstallProtocolInterface (Handle, Protocol, Interface);
  1386. }
  1387. VA_END (Args);
  1388. //
  1389. // If there was an error, add all the interfaces that were
  1390. // uninstalled without any errors
  1391. //
  1392. if (EFI_ERROR (Status)) {
  1393. //
  1394. // Reset the va_arg back to the first argument.
  1395. //
  1396. VA_START (Args, Handle);
  1397. for ( ; Index > 1; Index--) {
  1398. Protocol = VA_ARG (Args, EFI_GUID *);
  1399. Interface = VA_ARG (Args, VOID *);
  1400. UnitTestInstallProtocolInterface (&Handle, Protocol, EFI_NATIVE_INTERFACE, Interface);
  1401. }
  1402. VA_END (Args);
  1403. Status = EFI_INVALID_PARAMETER;
  1404. }
  1405. return Status;
  1406. }