dispatch.c 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797
  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. dispatch.c
  9. Abstract:
  10. This module implements the driver dispatcher.
  11. Author:
  12. Evan Green 12-Mar-2014
  13. Environment:
  14. Firmware
  15. --*/
  16. //
  17. // ------------------------------------------------------------------- Includes
  18. //
  19. #include "ueficore.h"
  20. #include "fwvolp.h"
  21. //
  22. // ---------------------------------------------------------------- Definitions
  23. //
  24. #define EFI_CORE_DRIVER_ENTRY_MAGIC 0x76697244 // 'virD'
  25. //
  26. // ------------------------------------------------------ Data Type Definitions
  27. //
  28. typedef struct _EFI_KNOWN_HANDLE {
  29. LIST_ENTRY ListEntry;
  30. EFI_HANDLE Handle;
  31. EFI_GUID NameGuid;
  32. } EFI_KNOWN_HANDLE, *PEFI_KNOWN_HANDLE;
  33. typedef struct _EFI_CORE_DRIVER_ENTRY {
  34. UINTN Magic;
  35. LIST_ENTRY DriverListEntry;
  36. LIST_ENTRY SchedulerListEntry;
  37. EFI_HANDLE VolumeHandle;
  38. EFI_GUID FileName;
  39. EFI_DEVICE_PATH_PROTOCOL *FileDevicePath;
  40. EFI_FIRMWARE_VOLUME2_PROTOCOL *Volume;
  41. EFI_HANDLE ImageHandle;
  42. BOOLEAN IsFirmwareVolumeImage;
  43. BOOLEAN Untrusted;
  44. BOOLEAN Initialized;
  45. BOOLEAN Scheduled;
  46. BOOLEAN Dependent;
  47. } EFI_CORE_DRIVER_ENTRY, *PEFI_CORE_DRIVER_ENTRY;
  48. typedef struct _EFI_FIRMWARE_VOLUME_FILE_DEVICE_PATH {
  49. MEDIA_FW_VOL_FILEPATH_DEVICE_PATH File;
  50. EFI_DEVICE_PATH_PROTOCOL End;
  51. } EFI_FIRMWARE_VOLUME_FILE_DEVICE_PATH, *PEFI_FIRMWARE_VOLUME_FILE_DEVICE_PATH;
  52. //
  53. // ----------------------------------------------- Internal Function Prototypes
  54. //
  55. EFIAPI
  56. VOID
  57. EfipFirmwareVolumeEventProtocolNotify (
  58. EFI_EVENT Event,
  59. VOID *Context
  60. );
  61. BOOLEAN
  62. EfipFirmwareVolumeHasBeenProcessed (
  63. EFI_HANDLE Handle
  64. );
  65. PEFI_KNOWN_HANDLE
  66. EfipMarkFirmwareVolumeProcessed (
  67. EFI_HANDLE Handle
  68. );
  69. EFI_STATUS
  70. EfipCoreAddDriverToList (
  71. EFI_FIRMWARE_VOLUME2_PROTOCOL *Volume,
  72. EFI_HANDLE VolumeHandle,
  73. EFI_GUID *DriverName,
  74. EFI_FV_FILETYPE Type
  75. );
  76. EFI_DEVICE_PATH_PROTOCOL *
  77. EfipCoreConvertFirmwareVolumeFileToDevicePath (
  78. EFI_FIRMWARE_VOLUME2_PROTOCOL *Volume,
  79. EFI_HANDLE VolumeHandle,
  80. EFI_GUID *DriverName
  81. );
  82. VOID
  83. EfipCoreInsertOnScheduledQueue (
  84. PEFI_CORE_DRIVER_ENTRY DriverEntry
  85. );
  86. //
  87. // -------------------------------------------------------------------- Globals
  88. //
  89. //
  90. // Store the list of known firmware volume handles.
  91. //
  92. LIST_ENTRY EfiFirmwareVolumeList;
  93. //
  94. // Define the variables used to register for firmware volume arrivals.
  95. //
  96. EFI_EVENT EfiFirmwareVolumeEvent;
  97. VOID *EfiFirmwareVolumeEventRegistration;
  98. //
  99. // Define the list of file types supported by the dispatcher.
  100. //
  101. EFI_FV_FILETYPE EfiDispatcherFileTypes[] = {
  102. EFI_FV_FILETYPE_DRIVER,
  103. EFI_FV_FILETYPE_COMBINED_PEIM_DRIVER,
  104. };
  105. EFI_LOCK EfiDispatcherLock;
  106. LIST_ENTRY EfiDiscoveredList;
  107. LIST_ENTRY EfiScheduledQueue;
  108. BOOLEAN EfiDispatcherRunning;
  109. //
  110. // ------------------------------------------------------------------ Functions
  111. //
  112. VOID
  113. EfiCoreInitializeDispatcher (
  114. VOID
  115. )
  116. /*++
  117. Routine Description:
  118. This routine initializes the driver dispatcher.
  119. Arguments:
  120. None.
  121. Return Value:
  122. None.
  123. --*/
  124. {
  125. INITIALIZE_LIST_HEAD(&EfiFirmwareVolumeList);
  126. INITIALIZE_LIST_HEAD(&EfiDiscoveredList);
  127. INITIALIZE_LIST_HEAD(&EfiScheduledQueue);
  128. EfiCoreInitializeLock(&EfiDispatcherLock, TPL_HIGH_LEVEL);
  129. EfiFirmwareVolumeEvent = EfiCoreCreateProtocolNotifyEvent(
  130. &EfiFirmwareVolume2ProtocolGuid,
  131. TPL_CALLBACK,
  132. EfipFirmwareVolumeEventProtocolNotify,
  133. NULL,
  134. &EfiFirmwareVolumeEventRegistration);
  135. ASSERT(EfiFirmwareVolumeEvent != NULL);
  136. return;
  137. }
  138. EFIAPI
  139. EFI_STATUS
  140. EfiCoreDispatcher (
  141. VOID
  142. )
  143. /*++
  144. Routine Description:
  145. This routine runs the driver dispatcher. It drains the scheduled queue
  146. loading and starting drivers until there are no more drivers to run.
  147. Arguments:
  148. None.
  149. Return Value:
  150. EFI_SUCCESS if one or more drivers were loaded.
  151. EFI_NOT_FOUND if no drivers were loaded.
  152. EFI_ALREADY_STARTED if the dispatcher is already running.
  153. --*/
  154. {
  155. PLIST_ENTRY CurrentEntry;
  156. PEFI_CORE_DRIVER_ENTRY DriverEntry;
  157. BOOLEAN ReadyToRun;
  158. EFI_STATUS ReturnStatus;
  159. EFI_STATUS Status;
  160. if (EfiDispatcherRunning != FALSE) {
  161. return EFI_ALREADY_STARTED;
  162. }
  163. EfiDispatcherRunning = TRUE;
  164. ReturnStatus = EFI_NOT_FOUND;
  165. do {
  166. //
  167. // Drain the scheduled queue.
  168. //
  169. while (LIST_EMPTY(&EfiScheduledQueue) == FALSE) {
  170. DriverEntry = LIST_VALUE(EfiScheduledQueue.Next,
  171. EFI_CORE_DRIVER_ENTRY,
  172. SchedulerListEntry);
  173. ASSERT(DriverEntry->Magic == EFI_CORE_DRIVER_ENTRY_MAGIC);
  174. //
  175. // Load the driver into memory if needed.
  176. //
  177. if ((DriverEntry->ImageHandle == NULL) &&
  178. (DriverEntry->IsFirmwareVolumeImage == FALSE)) {
  179. Status = EfiCoreLoadImage(FALSE,
  180. EfiFirmwareImageHandle,
  181. DriverEntry->FileDevicePath,
  182. NULL,
  183. 0,
  184. &(DriverEntry->ImageHandle));
  185. if (EFI_ERROR(Status)) {
  186. RtlDebugPrint("Warning: Driver failed load with status "
  187. "0x%x.\n",
  188. Status);
  189. EfiCoreAcquireLock(&EfiDispatcherLock);
  190. if (Status == EFI_SECURITY_VIOLATION) {
  191. DriverEntry->Untrusted = TRUE;
  192. } else {
  193. DriverEntry->Initialized = TRUE;
  194. }
  195. DriverEntry->Scheduled = FALSE;
  196. LIST_REMOVE(&(DriverEntry->SchedulerListEntry));
  197. EfiCoreReleaseLock(&EfiDispatcherLock);
  198. //
  199. // Don't try to start this image, it failed to load.
  200. //
  201. continue;
  202. }
  203. }
  204. EfiCoreAcquireLock(&EfiDispatcherLock);
  205. DriverEntry->Scheduled = FALSE;
  206. DriverEntry->Initialized = TRUE;
  207. LIST_REMOVE(&(DriverEntry->SchedulerListEntry));
  208. EfiCoreReleaseLock(&EfiDispatcherLock);
  209. if (DriverEntry->IsFirmwareVolumeImage == FALSE) {
  210. ASSERT(DriverEntry->ImageHandle != NULL);
  211. Status = EfiCoreStartImage(DriverEntry->ImageHandle,
  212. NULL,
  213. NULL);
  214. if (EFI_ERROR(Status)) {
  215. RtlDebugPrint("Warning: Driver start failed with "
  216. "status 0x%x.\n",
  217. Status);
  218. }
  219. }
  220. ReturnStatus = EFI_SUCCESS;
  221. }
  222. //
  223. // Search the discovered list for items to place on the scheduled
  224. // queue.
  225. //
  226. ReadyToRun = FALSE;
  227. CurrentEntry = EfiDiscoveredList.Next;
  228. while (CurrentEntry != &EfiDiscoveredList) {
  229. DriverEntry = LIST_VALUE(CurrentEntry,
  230. EFI_CORE_DRIVER_ENTRY,
  231. DriverListEntry);
  232. CurrentEntry = CurrentEntry->Next;
  233. if (DriverEntry->Dependent != FALSE) {
  234. EfipCoreInsertOnScheduledQueue(DriverEntry);
  235. ReadyToRun = TRUE;
  236. }
  237. }
  238. } while (ReadyToRun != FALSE);
  239. EfiDispatcherRunning = FALSE;
  240. return ReturnStatus;
  241. }
  242. //
  243. // --------------------------------------------------------- Internal Functions
  244. //
  245. EFIAPI
  246. VOID
  247. EfipFirmwareVolumeEventProtocolNotify (
  248. EFI_EVENT Event,
  249. VOID *Context
  250. )
  251. /*++
  252. Routine Description:
  253. This routine is called when a new firmware volume protocol appears in the
  254. system.
  255. Arguments:
  256. Event - Supplies a pointer to the event that fired.
  257. Context - Supplies an unused context pointer.
  258. Return Value:
  259. None.
  260. --*/
  261. {
  262. EFI_FV_FILE_ATTRIBUTES Attributes;
  263. UINTN BufferSize;
  264. EFI_DEVICE_PATH_PROTOCOL *DevicePath;
  265. UINTN FileTypeCount;
  266. EFI_STATUS GetNextFileStatus;
  267. UINTN Index;
  268. UINTN Key;
  269. PEFI_KNOWN_HANDLE KnownHandle;
  270. EFI_GUID NameGuid;
  271. UINTN Size;
  272. EFI_STATUS Status;
  273. EFI_FV_FILETYPE Type;
  274. EFI_FIRMWARE_VOLUME2_PROTOCOL *Volume;
  275. EFI_HANDLE VolumeHandle;
  276. //
  277. // Loop through all the new firmware volumes.
  278. //
  279. while (TRUE) {
  280. BufferSize = sizeof(EFI_HANDLE);
  281. Status = EfiCoreLocateHandle(ByRegisterNotify,
  282. NULL,
  283. EfiFirmwareVolumeEventRegistration,
  284. &BufferSize,
  285. &VolumeHandle);
  286. if (EFI_ERROR(Status)) {
  287. break;
  288. }
  289. if (EfipFirmwareVolumeHasBeenProcessed(VolumeHandle) != FALSE) {
  290. continue;
  291. }
  292. KnownHandle = EfipMarkFirmwareVolumeProcessed(VolumeHandle);
  293. if (KnownHandle == NULL) {
  294. continue;
  295. }
  296. Status = EfiCoreHandleProtocol(VolumeHandle,
  297. &EfiFirmwareVolume2ProtocolGuid,
  298. (VOID **)&Volume);
  299. if ((EFI_ERROR(Status)) || (Volume == NULL)) {
  300. ASSERT(FALSE);
  301. continue;
  302. }
  303. Status = EfiCoreHandleProtocol(VolumeHandle,
  304. &EfiDevicePathProtocolGuid,
  305. (VOID **)&DevicePath);
  306. if (EFI_ERROR(Status)) {
  307. continue;
  308. }
  309. //
  310. // Discover drivers in the firmware volume and add them to the
  311. // discovered driver list.
  312. //
  313. FileTypeCount = sizeof(EfiDispatcherFileTypes) /
  314. sizeof(EfiDispatcherFileTypes[0]);
  315. for (Index = 0; Index < FileTypeCount; Index += 1) {
  316. Key = 0;
  317. while (TRUE) {
  318. Type = EfiDispatcherFileTypes[Index];
  319. GetNextFileStatus = Volume->GetNextFile(Volume,
  320. &Key,
  321. &Type,
  322. &NameGuid,
  323. &Attributes,
  324. &Size);
  325. if (EFI_ERROR(GetNextFileStatus)) {
  326. break;
  327. }
  328. EfipCoreAddDriverToList(Volume, VolumeHandle, &NameGuid, Type);
  329. }
  330. }
  331. }
  332. return;
  333. }
  334. BOOLEAN
  335. EfipFirmwareVolumeHasBeenProcessed (
  336. EFI_HANDLE Handle
  337. )
  338. /*++
  339. Routine Description:
  340. This routine determines if the given firmware volume has been processed.
  341. Arguments:
  342. Handle - Supplies the handle to the volume.
  343. Return Value:
  344. TRUE if the handle has been processed.
  345. FALSE if the handle has not been processed.
  346. --*/
  347. {
  348. PLIST_ENTRY CurrentEntry;
  349. PEFI_KNOWN_HANDLE KnownHandle;
  350. CurrentEntry = EfiFirmwareVolumeList.Next;
  351. while (CurrentEntry != &EfiFirmwareVolumeList) {
  352. KnownHandle = LIST_VALUE(CurrentEntry, EFI_KNOWN_HANDLE, ListEntry);
  353. if (KnownHandle->Handle == Handle) {
  354. return TRUE;
  355. }
  356. CurrentEntry = CurrentEntry->Next;
  357. }
  358. return FALSE;
  359. }
  360. PEFI_KNOWN_HANDLE
  361. EfipMarkFirmwareVolumeProcessed (
  362. EFI_HANDLE Handle
  363. )
  364. /*++
  365. Routine Description:
  366. This routine marks a firmware volume handle as having been processed. This
  367. function adds entries on the firmware volume list if the new entry is
  368. different from the one in the handle list by checking the firmware volume
  369. image GUID. Items are never removed/free from the firmware volume list.
  370. Arguments:
  371. Handle - Supplies the handle to the volume.
  372. Return Value:
  373. Returns a pointer to the new known handle structure.
  374. NULL if a firmware volume with the same GUID was already processed.
  375. --*/
  376. {
  377. EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *BlockIo;
  378. EFI_FV_BLOCK_MAP_ENTRY *BlockMap;
  379. PLIST_ENTRY CurrentEntry;
  380. UINT32 ExtHeaderOffset;
  381. UINTN Index;
  382. PEFI_KNOWN_HANDLE KnownHandle;
  383. EFI_LBA LbaIndex;
  384. UINTN LbaOffset;
  385. EFI_GUID NameGuid;
  386. BOOLEAN NameGuidFound;
  387. EFI_STATUS Status;
  388. EFI_FIRMWARE_VOLUME_HEADER *VolumeHeader;
  389. NameGuidFound = FALSE;
  390. //
  391. // Get the firmware volume block protocol on the handle. Going rogue.
  392. //
  393. Status = EfiCoreHandleProtocol(Handle,
  394. &EfiFirmwareVolumeBlockProtocolGuid,
  395. (VOID **)&BlockIo);
  396. if (!EFI_ERROR(Status)) {
  397. //
  398. // Get the full volume header using the block I/O protocol.
  399. //
  400. ASSERT(BlockIo != NULL);
  401. Status = EfiFvGetVolumeHeader(BlockIo, &VolumeHeader);
  402. if (!EFI_ERROR(Status)) {
  403. ASSERT(VolumeHeader != NULL);
  404. if ((EfiFvVerifyHeaderChecksum(VolumeHeader) != FALSE) &&
  405. (VolumeHeader->ExtHeaderOffset != 0)) {
  406. ExtHeaderOffset = VolumeHeader->ExtHeaderOffset;
  407. BlockMap = VolumeHeader->BlockMap;
  408. LbaIndex = 0;
  409. LbaOffset = 0;
  410. //
  411. // Find the LBA index and offset for the volume extension
  412. // header using the block map.
  413. //
  414. while ((BlockMap->BlockCount != 0) ||
  415. (BlockMap->BlockLength != 0)) {
  416. for (Index = 0;
  417. Index < BlockMap->BlockCount;
  418. Index += 1) {
  419. if (ExtHeaderOffset < BlockMap->BlockLength) {
  420. break;
  421. }
  422. ExtHeaderOffset -= BlockMap->BlockLength;
  423. LbaIndex += 1;
  424. }
  425. if (Index < BlockMap->BlockCount) {
  426. LbaOffset = ExtHeaderOffset;
  427. break;
  428. }
  429. BlockMap += 1;
  430. }
  431. Status = EfiFvReadData(BlockIo,
  432. &LbaIndex,
  433. &LbaOffset,
  434. sizeof(NameGuid),
  435. (UINT8 *)&NameGuid);
  436. if (!EFI_ERROR(Status)) {
  437. NameGuidFound = TRUE;
  438. }
  439. }
  440. EfiCoreFreePool(VolumeHeader);
  441. }
  442. }
  443. //
  444. // If a name GUID for this volume was found, compare it with all the other
  445. // known volumes.
  446. //
  447. if (NameGuidFound != FALSE) {
  448. CurrentEntry = EfiFirmwareVolumeList.Next;
  449. while (CurrentEntry != &EfiFirmwareVolumeList) {
  450. KnownHandle = LIST_VALUE(CurrentEntry, EFI_KNOWN_HANDLE, ListEntry);
  451. if (EfiCoreCompareGuids(&NameGuid, &(KnownHandle->NameGuid)) !=
  452. FALSE) {
  453. RtlDebugPrint("Found two firmware volumes with the same GUID. "
  454. "Skipping one!\n");
  455. return NULL;
  456. }
  457. }
  458. }
  459. KnownHandle = EfiCoreAllocateBootPool(sizeof(EFI_KNOWN_HANDLE));
  460. if (KnownHandle == NULL) {
  461. ASSERT(FALSE);
  462. return NULL;
  463. }
  464. EfiCoreSetMemory(KnownHandle, sizeof(EFI_KNOWN_HANDLE), 0);
  465. KnownHandle->Handle = Handle;
  466. if (NameGuidFound != FALSE) {
  467. EfiCoreCopyMemory(&(KnownHandle->NameGuid),
  468. &NameGuid,
  469. sizeof(EFI_GUID));
  470. }
  471. INSERT_BEFORE(&(KnownHandle->ListEntry), &EfiFirmwareVolumeList);
  472. return KnownHandle;
  473. }
  474. EFI_STATUS
  475. EfipCoreAddDriverToList (
  476. EFI_FIRMWARE_VOLUME2_PROTOCOL *Volume,
  477. EFI_HANDLE VolumeHandle,
  478. EFI_GUID *DriverName,
  479. EFI_FV_FILETYPE Type
  480. )
  481. /*++
  482. Routine Description:
  483. This routine adds a driver entry to the discovered list.
  484. Arguments:
  485. Volume - Supplies a pointer to the firmware volume.
  486. VolumeHandle - Supplies the firmware volume handle.
  487. DriverName - Supplies a pointer to the GUID of the driver's name.
  488. Type - Supplies the file type.
  489. Return Value:
  490. EFI_SUCCESS on success.
  491. EFI_ALREADY_STARTED if the driver has already been started.
  492. --*/
  493. {
  494. EFI_CORE_DRIVER_ENTRY *DriverEntry;
  495. DriverEntry = EfiCoreAllocateBootPool(sizeof(EFI_CORE_DRIVER_ENTRY));
  496. if (DriverEntry == NULL) {
  497. return EFI_OUT_OF_RESOURCES;
  498. }
  499. EfiCoreSetMemory(DriverEntry, sizeof(EFI_CORE_DRIVER_ENTRY), 0);
  500. if (Type == EFI_FV_FILETYPE_FIRMWARE_VOLUME_IMAGE) {
  501. DriverEntry->IsFirmwareVolumeImage = TRUE;
  502. }
  503. DriverEntry->Magic = EFI_CORE_DRIVER_ENTRY_MAGIC;
  504. EfiCoreCopyMemory(&(DriverEntry->FileName), DriverName, sizeof(EFI_GUID));
  505. DriverEntry->VolumeHandle = VolumeHandle;
  506. DriverEntry->Volume = Volume;
  507. DriverEntry->FileDevicePath =
  508. EfipCoreConvertFirmwareVolumeFileToDevicePath(Volume,
  509. VolumeHandle,
  510. DriverName);
  511. DriverEntry->Dependent = TRUE;
  512. EfiCoreAcquireLock(&EfiDispatcherLock);
  513. INSERT_BEFORE(&(DriverEntry->DriverListEntry), &EfiDiscoveredList);
  514. EfiCoreReleaseLock(&EfiDispatcherLock);
  515. return EFI_SUCCESS;
  516. }
  517. EFI_DEVICE_PATH_PROTOCOL *
  518. EfipCoreConvertFirmwareVolumeFileToDevicePath (
  519. EFI_FIRMWARE_VOLUME2_PROTOCOL *Volume,
  520. EFI_HANDLE VolumeHandle,
  521. EFI_GUID *DriverName
  522. )
  523. /*++
  524. Routine Description:
  525. This routine converts a firmware volume and driver name into an EFI
  526. device path.
  527. Arguments:
  528. Volume - Supplies a pointer to the firmware volume.
  529. VolumeHandle - Supplies the firmware volume handle.
  530. DriverName - Supplies a pointer to the GUID of the driver's name.
  531. Return Value:
  532. Returns a pointer to the file device path.
  533. --*/
  534. {
  535. EFI_DEVICE_PATH_PROTOCOL *FileDevicePath;
  536. EFI_FIRMWARE_VOLUME_FILE_DEVICE_PATH FileNameDevicePath;
  537. EFI_STATUS Status;
  538. EFI_DEVICE_PATH_PROTOCOL *VolumeDevicePath;
  539. Status = EfiCoreHandleProtocol(VolumeHandle,
  540. &EfiDevicePathProtocolGuid,
  541. (VOID **)&VolumeDevicePath);
  542. if (EFI_ERROR(Status)) {
  543. return NULL;
  544. }
  545. //
  546. // Build a device path to the file in the volume.
  547. //
  548. EfiCoreInitializeFirmwareVolumeDevicePathNode(&(FileNameDevicePath.File),
  549. DriverName);
  550. EfiCoreSetDevicePathEndNode(&(FileNameDevicePath.End));
  551. FileDevicePath = EfiCoreAppendDevicePath(
  552. VolumeDevicePath,
  553. (EFI_DEVICE_PATH_PROTOCOL *)&FileNameDevicePath);
  554. return FileDevicePath;
  555. }
  556. VOID
  557. EfipCoreInsertOnScheduledQueue (
  558. PEFI_CORE_DRIVER_ENTRY DriverEntry
  559. )
  560. /*++
  561. Routine Description:
  562. This routine inserts a driver entry onto the scheduled queue.
  563. Arguments:
  564. DriverEntry - Supplies a pointer to the driver entry to schedule.
  565. Return Value:
  566. None.
  567. --*/
  568. {
  569. EfiCoreAcquireLock(&EfiDispatcherLock);
  570. DriverEntry->Dependent = FALSE;
  571. DriverEntry->Scheduled = TRUE;
  572. INSERT_BEFORE(&(DriverEntry->SchedulerListEntry), &EfiScheduledQueue);
  573. EfiCoreReleaseLock(&EfiDispatcherLock);
  574. return;
  575. }