Ext4Dxe.c 35 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847
  1. /** @file
  2. Driver entry point
  3. Copyright (c) 2021 - 2023 Pedro Falcato All rights reserved.
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "Ext4Dxe.h"
  7. GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mExt4DriverNameTable[] = {
  8. {
  9. "eng;en",
  10. L"Ext4 File System Driver"
  11. },
  12. {
  13. NULL,
  14. NULL
  15. }
  16. };
  17. GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mExt4ControllerNameTable[] = {
  18. {
  19. "eng;en",
  20. L"Ext4 File System"
  21. },
  22. {
  23. NULL,
  24. NULL
  25. }
  26. };
  27. // Needed by gExt4ComponentName*
  28. /**
  29. Retrieves a Unicode string that is the user-readable name of the EFI Driver.
  30. @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
  31. @param[in] Language A pointer to a three-character ISO 639-2 language identifier.
  32. This is the language of the driver name that that the caller
  33. is requesting, and it must match one of the languages specified
  34. in SupportedLanguages. The number of languages supported by a
  35. driver is up to the driver writer.
  36. @param[out] DriverName A pointer to the Unicode string to return. This Unicode string
  37. is the name of the driver specified by This in the language
  38. specified by Language.
  39. @retval EFI_SUCCESS The Unicode string for the Driver specified by This
  40. and the language specified by Language was returned
  41. in DriverName.
  42. @retval EFI_INVALID_PARAMETER Language is NULL.
  43. @retval EFI_INVALID_PARAMETER DriverName is NULL.
  44. @retval EFI_UNSUPPORTED The driver specified by This does not support the
  45. language specified by Language.
  46. **/
  47. EFI_STATUS
  48. EFIAPI
  49. Ext4ComponentNameGetDriverName (
  50. IN EFI_COMPONENT_NAME_PROTOCOL *This,
  51. IN CHAR8 *Language,
  52. OUT CHAR16 **DriverName
  53. );
  54. /**
  55. Retrieves a Unicode string that is the user readable name of the controller
  56. that is being managed by an EFI Driver.
  57. @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
  58. @param[in] ControllerHandle The handle of a controller that the driver specified by
  59. This is managing. This handle specifies the controller
  60. whose name is to be returned.
  61. @param[in] ChildHandle The handle of the child controller to retrieve the name
  62. of. This is an optional parameter that may be NULL. It
  63. will be NULL for device drivers. It will also be NULL
  64. for a bus drivers that wish to retrieve the name of the
  65. bus controller. It will not be NULL for a bus driver
  66. that wishes to retrieve the name of a child controller.
  67. @param[in] Language A pointer to a three character ISO 639-2 language
  68. identifier. This is the language of the controller name
  69. that the caller is requesting, and it must match one
  70. of the languages specified in SupportedLanguages. The
  71. number of languages supported by a driver is up to the
  72. driver writer.
  73. @param[out] ControllerName A pointer to the Unicode string to return. This Unicode
  74. string is the name of the controller specified by
  75. ControllerHandle and ChildHandle in the language specified
  76. by Language, from the point of view of the driver specified
  77. by This.
  78. @retval EFI_SUCCESS The Unicode string for the user-readable name in the
  79. language specified by Language for the driver
  80. specified by This was returned in DriverName.
  81. @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
  82. @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.
  83. @retval EFI_INVALID_PARAMETER Language is NULL.
  84. @retval EFI_INVALID_PARAMETER ControllerName is NULL.
  85. @retval EFI_UNSUPPORTED The driver specified by This is not currently managing
  86. the controller specified by ControllerHandle and
  87. ChildHandle.
  88. @retval EFI_UNSUPPORTED The driver specified by This does not support the
  89. language specified by Language.
  90. **/
  91. EFI_STATUS
  92. EFIAPI
  93. Ext4ComponentNameGetControllerName (
  94. IN EFI_COMPONENT_NAME_PROTOCOL *This,
  95. IN EFI_HANDLE ControllerHandle,
  96. IN EFI_HANDLE ChildHandle OPTIONAL,
  97. IN CHAR8 *Language,
  98. OUT CHAR16 **ControllerName
  99. );
  100. extern EFI_COMPONENT_NAME_PROTOCOL gExt4ComponentName;
  101. GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gExt4ComponentName = {
  102. Ext4ComponentNameGetDriverName,
  103. Ext4ComponentNameGetControllerName,
  104. "eng"
  105. };
  106. //
  107. // EFI Component Name 2 Protocol
  108. //
  109. GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gExt4ComponentName2 = {
  110. (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)Ext4ComponentNameGetDriverName,
  111. (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)Ext4ComponentNameGetControllerName,
  112. "en"
  113. };
  114. // Needed by gExt4BindingProtocol
  115. /**
  116. Tests to see if this driver supports a given controller. If a child device is provided,
  117. it further tests to see if this driver supports creating a handle for the specified child device.
  118. This function checks to see if the driver specified by This supports the device specified by
  119. ControllerHandle. Drivers will typically use the device path attached to
  120. ControllerHandle and/or the services from the bus I/O abstraction attached to
  121. ControllerHandle to determine if the driver supports ControllerHandle. This function
  122. may be called many times during platform initialization. In order to reduce boot times, the tests
  123. performed by this function must be very small, and take as little time as possible to execute. This
  124. function must not change the state of any hardware devices, and this function must be aware that the
  125. device specified by ControllerHandle may already be managed by the same driver or a
  126. different driver. This function must match its calls to AllocatePages() with FreePages(),
  127. AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
  128. Because ControllerHandle may have been previously started by the same driver, if a protocol is
  129. already in the opened state, then it must not be closed with CloseProtocol(). This is required
  130. to guarantee the state of ControllerHandle is not modified by this function.
  131. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  132. @param[in] ControllerHandle The handle of the controller to test. This handle
  133. must support a protocol interface that supplies
  134. an I/O abstraction to the driver.
  135. @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
  136. parameter is ignored by device drivers, and is optional for bus
  137. drivers. For bus drivers, if this parameter is not NULL, then
  138. the bus driver must determine if the bus controller specified
  139. by ControllerHandle and the child controller specified
  140. by RemainingDevicePath are both supported by this
  141. bus driver.
  142. @retval EFI_SUCCESS The device specified by ControllerHandle and
  143. RemainingDevicePath is supported by the driver specified by This.
  144. @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
  145. RemainingDevicePath is already being managed by the driver
  146. specified by This.
  147. @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
  148. RemainingDevicePath is already being managed by a different
  149. driver or an application that requires exclusive access.
  150. Currently not implemented.
  151. @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
  152. RemainingDevicePath is not supported by the driver specified by This.
  153. **/
  154. EFI_STATUS
  155. EFIAPI
  156. Ext4IsBindingSupported (
  157. IN EFI_DRIVER_BINDING_PROTOCOL *BindingProtocol,
  158. IN EFI_HANDLE ControllerHandle,
  159. IN EFI_DEVICE_PATH *RemainingDevicePath OPTIONAL
  160. );
  161. /**
  162. Starts a device controller or a bus controller.
  163. The Start() function is designed to be invoked from the EFI boot service ConnectController().
  164. As a result, much of the error checking on the parameters to Start() has been moved into this
  165. common boot service. It is legal to call Start() from other locations,
  166. but the following calling restrictions must be followed, or the system behavior will not be deterministic.
  167. 1. ControllerHandle must be a valid EFI_HANDLE.
  168. 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
  169. EFI_DEVICE_PATH_PROTOCOL.
  170. 3. Prior to calling Start(), the Supported() function for the driver specified by This must
  171. have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
  172. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  173. @param[in] ControllerHandle The handle of the controller to start. This handle
  174. must support a protocol interface that supplies
  175. an I/O abstraction to the driver.
  176. @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
  177. parameter is ignored by device drivers, and is optional for bus
  178. drivers. For a bus driver, if this parameter is NULL, then handles
  179. for all the children of Controller are created by this driver.
  180. If this parameter is not NULL and the first Device Path Node is
  181. not the End of Device Path Node, then only the handle for the
  182. child device specified by the first Device Path Node of
  183. RemainingDevicePath is created by this driver.
  184. If the first Device Path Node of RemainingDevicePath is
  185. the End of Device Path Node, no child handle is created by this
  186. driver.
  187. @retval EFI_SUCCESS The device was started.
  188. @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
  189. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
  190. @retval Others The driver failded to start the device.
  191. **/
  192. EFI_STATUS
  193. EFIAPI
  194. Ext4Bind (
  195. IN EFI_DRIVER_BINDING_PROTOCOL *BindingProtocol,
  196. IN EFI_HANDLE ControllerHandle,
  197. IN EFI_DEVICE_PATH *RemainingDevicePath OPTIONAL
  198. );
  199. /**
  200. Stops a device controller or a bus controller.
  201. The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
  202. As a result, much of the error checking on the parameters to Stop() has been moved
  203. into this common boot service. It is legal to call Stop() from other locations,
  204. but the following calling restrictions must be followed, or the system behavior will not be deterministic.
  205. 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
  206. same driver's Start() function.
  207. 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
  208. EFI_HANDLE. In addition, all of these handles must have been created in this driver's
  209. Start() function, and the Start() function must have called OpenProtocol() on
  210. ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
  211. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  212. @param[in] ControllerHandle A handle to the device being stopped. The handle must
  213. support a bus specific I/O protocol for the driver
  214. to use to stop the device.
  215. @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
  216. @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
  217. if NumberOfChildren is 0.
  218. @retval EFI_SUCCESS The device was stopped.
  219. @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
  220. **/
  221. EFI_STATUS
  222. EFIAPI
  223. Ext4Stop (
  224. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  225. IN EFI_HANDLE ControllerHandle,
  226. IN UINTN NumberOfChildren,
  227. IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
  228. );
  229. EFI_DRIVER_BINDING_PROTOCOL gExt4BindingProtocol =
  230. {
  231. .Supported = Ext4IsBindingSupported,
  232. .Start = Ext4Bind,
  233. .Stop = Ext4Stop,
  234. .Version = EXT4_DRIVER_VERSION,
  235. .ImageHandle = NULL,
  236. .DriverBindingHandle = NULL
  237. };
  238. /**
  239. Retrieves a Unicode string that is the user readable name of the controller
  240. that is being managed by an EFI Driver.
  241. @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
  242. @param[in] ControllerHandle The handle of a controller that the driver specified by
  243. This is managing. This handle specifies the controller
  244. whose name is to be returned.
  245. @param[in] ChildHandle The handle of the child controller to retrieve the name
  246. of. This is an optional parameter that may be NULL. It
  247. will be NULL for device drivers. It will also be NULL
  248. for a bus drivers that wish to retrieve the name of the
  249. bus controller. It will not be NULL for a bus driver
  250. that wishes to retrieve the name of a child controller.
  251. @param[in] Language A pointer to a three character ISO 639-2 language
  252. identifier. This is the language of the controller name
  253. that the caller is requesting, and it must match one
  254. of the languages specified in SupportedLanguages. The
  255. number of languages supported by a driver is up to the
  256. driver writer.
  257. @param[out] ControllerName A pointer to the Unicode string to return. This Unicode
  258. string is the name of the controller specified by
  259. ControllerHandle and ChildHandle in the language specified
  260. by Language, from the point of view of the driver specified
  261. by This.
  262. @retval EFI_SUCCESS The Unicode string for the user-readable name in the
  263. language specified by Language for the driver
  264. specified by This was returned in DriverName.
  265. @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
  266. @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.
  267. @retval EFI_INVALID_PARAMETER Language is NULL.
  268. @retval EFI_INVALID_PARAMETER ControllerName is NULL.
  269. @retval EFI_UNSUPPORTED The driver specified by This is not currently managing
  270. the controller specified by ControllerHandle and
  271. ChildHandle.
  272. @retval EFI_UNSUPPORTED The driver specified by This does not support the
  273. language specified by Language.
  274. **/
  275. EFI_STATUS
  276. EFIAPI
  277. Ext4ComponentNameGetControllerName (
  278. IN EFI_COMPONENT_NAME_PROTOCOL *This,
  279. IN EFI_HANDLE ControllerHandle,
  280. IN EFI_HANDLE ChildHandle OPTIONAL,
  281. IN CHAR8 *Language,
  282. OUT CHAR16 **ControllerName
  283. )
  284. {
  285. EFI_STATUS Status;
  286. if (ChildHandle != NULL) {
  287. return EFI_UNSUPPORTED;
  288. }
  289. // Test if the driver manages ControllHandle
  290. Status = EfiTestManagedDevice (
  291. ControllerHandle,
  292. gExt4BindingProtocol.DriverBindingHandle,
  293. &gEfiDiskIoProtocolGuid
  294. );
  295. if (EFI_ERROR (Status)) {
  296. return Status;
  297. }
  298. return LookupUnicodeString2 (
  299. Language,
  300. This->SupportedLanguages,
  301. mExt4ControllerNameTable,
  302. ControllerName,
  303. (BOOLEAN)(This == &gExt4ComponentName)
  304. );
  305. }
  306. /**
  307. Retrieves a Unicode string that is the user-readable name of the EFI Driver.
  308. @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.
  309. @param[in] Language A pointer to a three-character ISO 639-2 language identifier.
  310. This is the language of the driver name that that the caller
  311. is requesting, and it must match one of the languages specified
  312. in SupportedLanguages. The number of languages supported by a
  313. driver is up to the driver writer.
  314. @param[out] DriverName A pointer to the Unicode string to return. This Unicode string
  315. is the name of the driver specified by This in the language
  316. specified by Language.
  317. @retval EFI_SUCCESS The Unicode string for the Driver specified by This
  318. and the language specified by Language was returned
  319. in DriverName.
  320. @retval EFI_INVALID_PARAMETER Language is NULL.
  321. @retval EFI_INVALID_PARAMETER DriverName is NULL.
  322. @retval EFI_UNSUPPORTED The driver specified by This does not support the
  323. language specified by Language.
  324. **/
  325. EFI_STATUS
  326. EFIAPI
  327. Ext4ComponentNameGetDriverName (
  328. IN EFI_COMPONENT_NAME_PROTOCOL *This,
  329. IN CHAR8 *Language,
  330. OUT CHAR16 **DriverName
  331. )
  332. {
  333. return LookupUnicodeString2 (
  334. Language,
  335. This->SupportedLanguages,
  336. mExt4DriverNameTable,
  337. DriverName,
  338. (BOOLEAN)(This == &gExt4ComponentName)
  339. );
  340. }
  341. /**
  342. Stops a device controller or a bus controller.
  343. The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
  344. As a result, much of the error checking on the parameters to Stop() has been moved
  345. into this common boot service. It is legal to call Stop() from other locations,
  346. but the following calling restrictions must be followed, or the system behavior will not be deterministic.
  347. 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
  348. same driver's Start() function.
  349. 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
  350. EFI_HANDLE. In addition, all of these handles must have been created in this driver's
  351. Start() function, and the Start() function must have called OpenProtocol() on
  352. ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
  353. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  354. @param[in] ControllerHandle A handle to the device being stopped. The handle must
  355. support a bus specific I/O protocol for the driver
  356. to use to stop the device.
  357. @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
  358. @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
  359. if NumberOfChildren is 0.
  360. @retval EFI_SUCCESS The device was stopped.
  361. @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
  362. **/
  363. EFI_STATUS
  364. EFIAPI
  365. Ext4Stop (
  366. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  367. IN EFI_HANDLE ControllerHandle,
  368. IN UINTN NumberOfChildren,
  369. IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
  370. )
  371. {
  372. EFI_STATUS Status;
  373. EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *Sfs;
  374. EXT4_PARTITION *Partition;
  375. BOOLEAN HasDiskIo2;
  376. Status = gBS->OpenProtocol (
  377. ControllerHandle,
  378. &gEfiSimpleFileSystemProtocolGuid,
  379. (VOID **)&Sfs,
  380. This->DriverBindingHandle,
  381. ControllerHandle,
  382. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  383. );
  384. if (EFI_ERROR (Status)) {
  385. return Status;
  386. }
  387. Partition = (EXT4_PARTITION *)Sfs;
  388. HasDiskIo2 = EXT4_DISK_IO2 (Partition) != NULL;
  389. Status = Ext4UnmountAndFreePartition (Partition);
  390. if (EFI_ERROR (Status)) {
  391. return Status;
  392. }
  393. Status = gBS->UninstallMultipleProtocolInterfaces (
  394. ControllerHandle,
  395. &gEfiSimpleFileSystemProtocolGuid,
  396. &Partition->Interface,
  397. NULL
  398. );
  399. if (EFI_ERROR (Status)) {
  400. return Status;
  401. }
  402. // Close all open protocols (DiskIo, DiskIo2, BlockIo)
  403. Status = gBS->CloseProtocol (
  404. ControllerHandle,
  405. &gEfiDiskIoProtocolGuid,
  406. This->DriverBindingHandle,
  407. ControllerHandle
  408. );
  409. if (EFI_ERROR (Status)) {
  410. return Status;
  411. }
  412. Status = gBS->CloseProtocol (
  413. ControllerHandle,
  414. &gEfiBlockIoProtocolGuid,
  415. This->DriverBindingHandle,
  416. ControllerHandle
  417. );
  418. if (EFI_ERROR (Status)) {
  419. return Status;
  420. }
  421. if (HasDiskIo2) {
  422. Status = gBS->CloseProtocol (
  423. ControllerHandle,
  424. &gEfiDiskIo2ProtocolGuid,
  425. This->DriverBindingHandle,
  426. ControllerHandle
  427. );
  428. if (EFI_ERROR (Status)) {
  429. return Status;
  430. }
  431. }
  432. return Status;
  433. }
  434. /**
  435. Ext4Dxe Driver's entry point.
  436. Called at load time.
  437. @param[in] ImageHandle Handle to the image.
  438. @param[in] SystemTable Pointer to the EFI_SYSTEM_TABLE.
  439. @return Result of the load.
  440. **/
  441. EFI_STATUS
  442. EFIAPI
  443. Ext4EntryPoint (
  444. IN EFI_HANDLE ImageHandle,
  445. IN EFI_SYSTEM_TABLE *SystemTable
  446. )
  447. {
  448. return EfiLibInstallAllDriverProtocols2 (
  449. ImageHandle,
  450. SystemTable,
  451. &gExt4BindingProtocol,
  452. ImageHandle,
  453. &gExt4ComponentName,
  454. &gExt4ComponentName2,
  455. NULL,
  456. NULL,
  457. NULL,
  458. NULL
  459. );
  460. }
  461. /**
  462. Ext4Dxe Driver's unload callback.
  463. Called at unload time.
  464. @param[in] ImageHandle Handle to the image.
  465. @return Result of the unload.
  466. **/
  467. EFI_STATUS
  468. EFIAPI
  469. Ext4Unload (
  470. IN EFI_HANDLE ImageHandle
  471. )
  472. {
  473. EFI_STATUS Status;
  474. EFI_HANDLE *DeviceHandleBuffer;
  475. UINTN DeviceHandleCount;
  476. UINTN Index;
  477. EFI_HANDLE Handle;
  478. Status = gBS->LocateHandleBuffer (
  479. AllHandles,
  480. NULL,
  481. NULL,
  482. &DeviceHandleCount,
  483. &DeviceHandleBuffer
  484. );
  485. if (EFI_ERROR (Status)) {
  486. return Status;
  487. }
  488. for (Index = 0; Index < DeviceHandleCount; Index++) {
  489. Handle = DeviceHandleBuffer[Index];
  490. Status = EfiTestManagedDevice (Handle, ImageHandle, &gEfiDiskIoProtocolGuid);
  491. if (Status == EFI_SUCCESS) {
  492. Status = gBS->DisconnectController (Handle, ImageHandle, NULL);
  493. if (EFI_ERROR (Status)) {
  494. break;
  495. }
  496. }
  497. }
  498. FreePool (DeviceHandleBuffer);
  499. Status = EfiLibUninstallAllDriverProtocols2 (
  500. &gExt4BindingProtocol,
  501. &gExt4ComponentName,
  502. &gExt4ComponentName2,
  503. NULL,
  504. NULL,
  505. NULL,
  506. NULL
  507. );
  508. return Status;
  509. }
  510. /**
  511. Tests to see if this driver supports a given controller. If a child device is provided,
  512. it further tests to see if this driver supports creating a handle for the specified child device.
  513. This function checks to see if the driver specified by This supports the device specified by
  514. ControllerHandle. Drivers will typically use the device path attached to
  515. ControllerHandle and/or the services from the bus I/O abstraction attached to
  516. ControllerHandle to determine if the driver supports ControllerHandle. This function
  517. may be called many times during platform initialization. In order to reduce boot times, the tests
  518. performed by this function must be very small, and take as little time as possible to execute. This
  519. function must not change the state of any hardware devices, and this function must be aware that the
  520. device specified by ControllerHandle may already be managed by the same driver or a
  521. different driver. This function must match its calls to AllocatePages() with FreePages(),
  522. AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
  523. Because ControllerHandle may have been previously started by the same driver, if a protocol is
  524. already in the opened state, then it must not be closed with CloseProtocol(). This is required
  525. to guarantee the state of ControllerHandle is not modified by this function.
  526. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  527. @param[in] ControllerHandle The handle of the controller to test. This handle
  528. must support a protocol interface that supplies
  529. an I/O abstraction to the driver.
  530. @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
  531. parameter is ignored by device drivers, and is optional for bus
  532. drivers. For bus drivers, if this parameter is not NULL, then
  533. the bus driver must determine if the bus controller specified
  534. by ControllerHandle and the child controller specified
  535. by RemainingDevicePath are both supported by this
  536. bus driver.
  537. @retval EFI_SUCCESS The device specified by ControllerHandle and
  538. RemainingDevicePath is supported by the driver specified by This.
  539. @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
  540. RemainingDevicePath is already being managed by the driver
  541. specified by This.
  542. @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
  543. RemainingDevicePath is already being managed by a different
  544. driver or an application that requires exclusive access.
  545. @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
  546. RemainingDevicePath is not supported by the driver specified by This.
  547. **/
  548. EFI_STATUS
  549. EFIAPI
  550. Ext4IsBindingSupported (
  551. IN EFI_DRIVER_BINDING_PROTOCOL *BindingProtocol,
  552. IN EFI_HANDLE ControllerHandle,
  553. IN EFI_DEVICE_PATH *RemainingDevicePath OPTIONAL
  554. )
  555. {
  556. EFI_STATUS Status;
  557. EFI_DISK_IO_PROTOCOL *DiskIo;
  558. EFI_BLOCK_IO_PROTOCOL *BlockIo;
  559. DiskIo = NULL;
  560. BlockIo = NULL;
  561. //
  562. // Open the IO Abstraction(s) needed to perform the supported test
  563. //
  564. Status = gBS->OpenProtocol (
  565. ControllerHandle,
  566. &gEfiDiskIoProtocolGuid,
  567. (VOID **)&DiskIo,
  568. BindingProtocol->DriverBindingHandle,
  569. ControllerHandle,
  570. EFI_OPEN_PROTOCOL_BY_DRIVER
  571. );
  572. if (EFI_ERROR (Status)) {
  573. return Status;
  574. }
  575. //
  576. // Open the IO Abstraction(s) needed to perform the supported test
  577. //
  578. Status = gBS->OpenProtocol (
  579. ControllerHandle,
  580. &gEfiBlockIoProtocolGuid,
  581. (VOID **)&BlockIo,
  582. BindingProtocol->DriverBindingHandle,
  583. ControllerHandle,
  584. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  585. );
  586. if (!EFI_ERROR (Status)) {
  587. if (!Ext4SuperblockCheckMagic (DiskIo, BlockIo)) {
  588. Status = EFI_UNSUPPORTED;
  589. }
  590. }
  591. //
  592. // Close the I/O Abstraction(s) used to perform the supported test
  593. //
  594. if (DiskIo != NULL) {
  595. gBS->CloseProtocol (
  596. ControllerHandle,
  597. &gEfiDiskIoProtocolGuid,
  598. BindingProtocol->DriverBindingHandle,
  599. ControllerHandle
  600. );
  601. }
  602. if (BlockIo != NULL) {
  603. gBS->CloseProtocol (
  604. ControllerHandle,
  605. &gEfiBlockIoProtocolGuid,
  606. BindingProtocol->DriverBindingHandle,
  607. ControllerHandle
  608. );
  609. }
  610. return Status;
  611. }
  612. /**
  613. Starts a device controller or a bus controller.
  614. The Start() function is designed to be invoked from the EFI boot service ConnectController().
  615. As a result, much of the error checking on the parameters to Start() has been moved into this
  616. common boot service. It is legal to call Start() from other locations,
  617. but the following calling restrictions must be followed, or the system behavior will not be deterministic.
  618. 1. ControllerHandle must be a valid EFI_HANDLE.
  619. 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
  620. EFI_DEVICE_PATH_PROTOCOL.
  621. 3. Prior to calling Start(), the Supported() function for the driver specified by This must
  622. have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
  623. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  624. @param[in] ControllerHandle The handle of the controller to start. This handle
  625. must support a protocol interface that supplies
  626. an I/O abstraction to the driver.
  627. @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
  628. parameter is ignored by device drivers, and is optional for bus
  629. drivers. For a bus driver, if this parameter is NULL, then handles
  630. for all the children of Controller are created by this driver.
  631. If this parameter is not NULL and the first Device Path Node is
  632. not the End of Device Path Node, then only the handle for the
  633. child device specified by the first Device Path Node of
  634. RemainingDevicePath is created by this driver.
  635. If the first Device Path Node of RemainingDevicePath is
  636. the End of Device Path Node, no child handle is created by this
  637. driver.
  638. @retval EFI_SUCCESS The device was started.
  639. @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
  640. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
  641. @retval Others The driver failded to start the device.
  642. **/
  643. EFI_STATUS
  644. EFIAPI
  645. Ext4Bind (
  646. IN EFI_DRIVER_BINDING_PROTOCOL *BindingProtocol,
  647. IN EFI_HANDLE ControllerHandle,
  648. IN EFI_DEVICE_PATH *RemainingDevicePath OPTIONAL
  649. )
  650. {
  651. EFI_DISK_IO_PROTOCOL *DiskIo;
  652. EFI_DISK_IO2_PROTOCOL *DiskIo2;
  653. EFI_BLOCK_IO_PROTOCOL *BlockIo;
  654. EFI_STATUS Status;
  655. DiskIo2 = NULL;
  656. BlockIo = NULL;
  657. DiskIo = NULL;
  658. // Note: We initialize collation here since this is called in BDS, when we are likely
  659. // to have the Unicode Collation protocols available.
  660. Status = Ext4InitialiseUnicodeCollation (BindingProtocol->ImageHandle);
  661. if (EFI_ERROR (Status)) {
  662. // Lets throw a loud error into the log
  663. // It is very unlikely something like this may fire out of the blue. Chances are either
  664. // the platform configuration is wrong, or we are.
  665. DEBUG ((DEBUG_ERROR, "[ext4] Error: Unicode Collation not available - failure to Start() - error %r\n", Status));
  666. goto Error;
  667. }
  668. Status = gBS->OpenProtocol (
  669. ControllerHandle,
  670. &gEfiDiskIoProtocolGuid,
  671. (VOID **)&DiskIo,
  672. BindingProtocol->ImageHandle,
  673. ControllerHandle,
  674. EFI_OPEN_PROTOCOL_BY_DRIVER
  675. );
  676. if (EFI_ERROR (Status)) {
  677. goto Error;
  678. }
  679. DEBUG ((DEBUG_INFO, "[ext4] Controller supports DISK_IO\n"));
  680. Status = gBS->OpenProtocol (
  681. ControllerHandle,
  682. &gEfiDiskIo2ProtocolGuid,
  683. (VOID **)&DiskIo2,
  684. BindingProtocol->ImageHandle,
  685. ControllerHandle,
  686. EFI_OPEN_PROTOCOL_BY_DRIVER
  687. );
  688. // It's okay to not support DISK_IO2
  689. if (DiskIo2 != NULL) {
  690. DEBUG ((DEBUG_INFO, "[ext4] Controller supports DISK_IO2\n"));
  691. }
  692. Status = gBS->OpenProtocol (
  693. ControllerHandle,
  694. &gEfiBlockIoProtocolGuid,
  695. (VOID **)&BlockIo,
  696. BindingProtocol->ImageHandle,
  697. ControllerHandle,
  698. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  699. );
  700. if (EFI_ERROR (Status)) {
  701. goto Error;
  702. }
  703. Status = Ext4OpenPartition (ControllerHandle, DiskIo, DiskIo2, BlockIo);
  704. if (EFI_ERROR (Status)) {
  705. DEBUG ((DEBUG_ERROR, "[ext4] Error mounting: %r\n", Status));
  706. // Falls through to Error
  707. } else {
  708. return Status;
  709. }
  710. Error:
  711. if (DiskIo) {
  712. gBS->CloseProtocol (
  713. ControllerHandle,
  714. &gEfiDiskIoProtocolGuid,
  715. BindingProtocol->ImageHandle,
  716. ControllerHandle
  717. );
  718. }
  719. if (DiskIo2) {
  720. gBS->CloseProtocol (
  721. ControllerHandle,
  722. &gEfiDiskIo2ProtocolGuid,
  723. BindingProtocol->ImageHandle,
  724. ControllerHandle
  725. );
  726. }
  727. if (BlockIo) {
  728. gBS->CloseProtocol (
  729. ControllerHandle,
  730. &gEfiBlockIoProtocolGuid,
  731. BindingProtocol->ImageHandle,
  732. ControllerHandle
  733. );
  734. }
  735. return Status;
  736. }