VirtioBlk.c 39 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338
  1. /** @file
  2. This driver produces Block I/O Protocol instances for virtio-blk devices.
  3. The implementation is basic:
  4. - No attach/detach (ie. removable media).
  5. - Although the non-blocking interfaces of EFI_BLOCK_IO2_PROTOCOL could be a
  6. good match for multiple in-flight virtio-blk requests, we stick to
  7. synchronous requests and EFI_BLOCK_IO_PROTOCOL for now.
  8. Copyright (C) 2012, Red Hat, Inc.
  9. Copyright (c) 2012 - 2018, Intel Corporation. All rights reserved.<BR>
  10. Copyright (c) 2017, AMD Inc, All rights reserved.<BR>
  11. SPDX-License-Identifier: BSD-2-Clause-Patent
  12. **/
  13. #include <IndustryStandard/VirtioBlk.h>
  14. #include <Library/BaseMemoryLib.h>
  15. #include <Library/DebugLib.h>
  16. #include <Library/MemoryAllocationLib.h>
  17. #include <Library/UefiBootServicesTableLib.h>
  18. #include <Library/UefiLib.h>
  19. #include <Library/VirtioLib.h>
  20. #include "VirtioBlk.h"
  21. /**
  22. Convenience macros to read and write region 0 IO space elements of the
  23. virtio-blk device, for configuration purposes.
  24. The following macros make it possible to specify only the "core parameters"
  25. for such accesses and to derive the rest. By the time VIRTIO_CFG_WRITE()
  26. returns, the transaction will have been completed.
  27. @param[in] Dev Pointer to the VBLK_DEV structure whose VirtIo space
  28. we're accessing. Dev->VirtIo must be valid.
  29. @param[in] Field A field name from VBLK_HDR, identifying the virtio-blk
  30. configuration item to access.
  31. @param[in] Value (VIRTIO_CFG_WRITE() only.) The value to write to the
  32. selected configuration item.
  33. @param[out] Pointer (VIRTIO_CFG_READ() only.) The object to receive the
  34. value read from the configuration item. Its type must be
  35. one of UINT8, UINT16, UINT32, UINT64.
  36. @return Status code returned by Virtio->WriteDevice() /
  37. Virtio->ReadDevice().
  38. **/
  39. #define VIRTIO_CFG_WRITE(Dev, Field, Value) ((Dev)->VirtIo->WriteDevice ( \
  40. (Dev)->VirtIo, \
  41. OFFSET_OF_VBLK (Field), \
  42. SIZE_OF_VBLK (Field), \
  43. (Value) \
  44. ))
  45. #define VIRTIO_CFG_READ(Dev, Field, Pointer) ((Dev)->VirtIo->ReadDevice ( \
  46. (Dev)->VirtIo, \
  47. OFFSET_OF_VBLK (Field), \
  48. SIZE_OF_VBLK (Field), \
  49. sizeof *(Pointer), \
  50. (Pointer) \
  51. ))
  52. //
  53. // UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol
  54. // Driver Writer's Guide for UEFI 2.3.1 v1.01,
  55. // 24.2 Block I/O Protocol Implementations
  56. //
  57. EFI_STATUS
  58. EFIAPI
  59. VirtioBlkReset (
  60. IN EFI_BLOCK_IO_PROTOCOL *This,
  61. IN BOOLEAN ExtendedVerification
  62. )
  63. {
  64. //
  65. // If we managed to initialize and install the driver, then the device is
  66. // working correctly.
  67. //
  68. return EFI_SUCCESS;
  69. }
  70. /**
  71. Verify correctness of the read/write (not flush) request submitted to the
  72. EFI_BLOCK_IO_PROTOCOL instance.
  73. This function provides most verification steps described in:
  74. UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
  75. Protocol,
  76. - EFI_BLOCK_IO_PROTOCOL.ReadBlocks()
  77. - EFI_BLOCK_IO_PROTOCOL.WriteBlocks()
  78. Driver Writer's Guide for UEFI 2.3.1 v1.01,
  79. - 24.2.2. ReadBlocks() and ReadBlocksEx() Implementation
  80. - 24.2.3 WriteBlocks() and WriteBlockEx() Implementation
  81. Request sizes are limited to 1 GB (checked). This is not a practical
  82. limitation, just conformance to virtio-0.9.5, 2.3.2 Descriptor Table: "no
  83. descriptor chain may be more than 2^32 bytes long in total".
  84. Some Media characteristics are hardcoded in VirtioBlkInit() below (like
  85. non-removable media, no restriction on buffer alignment etc); we rely on
  86. those here without explicit mention.
  87. @param[in] Media The EFI_BLOCK_IO_MEDIA characteristics for
  88. this driver instance, extracted from the
  89. underlying virtio-blk device at initialization
  90. time. We validate the request against this set
  91. of attributes.
  92. @param[in] Lba Logical Block Address: number of logical
  93. blocks to skip from the beginning of the
  94. device.
  95. @param[in] PositiveBufferSize Size of buffer to transfer, in bytes. The
  96. caller is responsible to ensure this parameter
  97. is positive.
  98. @param[in] RequestIsWrite TRUE iff data transfer goes from guest to
  99. device.
  100. @@return Validation result to be forwarded outwards by
  101. ReadBlocks() and WriteBlocks, as required by
  102. the specs above.
  103. **/
  104. STATIC
  105. EFI_STATUS
  106. EFIAPI
  107. VerifyReadWriteRequest (
  108. IN EFI_BLOCK_IO_MEDIA *Media,
  109. IN EFI_LBA Lba,
  110. IN UINTN PositiveBufferSize,
  111. IN BOOLEAN RequestIsWrite
  112. )
  113. {
  114. UINTN BlockCount;
  115. ASSERT (PositiveBufferSize > 0);
  116. if ((PositiveBufferSize > SIZE_1GB) ||
  117. (PositiveBufferSize % Media->BlockSize > 0))
  118. {
  119. return EFI_BAD_BUFFER_SIZE;
  120. }
  121. BlockCount = PositiveBufferSize / Media->BlockSize;
  122. //
  123. // Avoid unsigned wraparound on either side in the second comparison.
  124. //
  125. if ((Lba > Media->LastBlock) || (BlockCount - 1 > Media->LastBlock - Lba)) {
  126. return EFI_INVALID_PARAMETER;
  127. }
  128. if (RequestIsWrite && Media->ReadOnly) {
  129. return EFI_WRITE_PROTECTED;
  130. }
  131. return EFI_SUCCESS;
  132. }
  133. /**
  134. Format a read / write / flush request as three consecutive virtio
  135. descriptors, push them to the host, and poll for the response.
  136. This is the main workhorse function. Two use cases are supported, read/write
  137. and flush. The function may only be called after the request parameters have
  138. been verified by
  139. - specific checks in ReadBlocks() / WriteBlocks() / FlushBlocks(), and
  140. - VerifyReadWriteRequest() (for read/write only).
  141. Parameters handled commonly:
  142. @param[in] Dev The virtio-blk device the request is targeted
  143. at.
  144. Flush request:
  145. @param[in] Lba Must be zero.
  146. @param[in] BufferSize Must be zero.
  147. @param[in out] Buffer Ignored by the function.
  148. @param[in] RequestIsWrite Must be TRUE.
  149. Read/Write request:
  150. @param[in] Lba Logical Block Address: number of logical blocks
  151. to skip from the beginning of the device.
  152. @param[in] BufferSize Size of buffer to transfer, in bytes. The caller
  153. is responsible to ensure this parameter is
  154. positive.
  155. @param[in out] Buffer The guest side area to read data from the device
  156. into, or write data to the device from.
  157. @param[in] RequestIsWrite TRUE iff data transfer goes from guest to
  158. device.
  159. Return values are common to both use cases, and are appropriate to be
  160. forwarded by the EFI_BLOCK_IO_PROTOCOL functions (ReadBlocks(),
  161. WriteBlocks(), FlushBlocks()).
  162. @retval EFI_SUCCESS Transfer complete.
  163. @retval EFI_DEVICE_ERROR Failed to notify host side via VirtIo write, or
  164. unable to parse host response, or host response
  165. is not VIRTIO_BLK_S_OK or failed to map Buffer
  166. for a bus master operation.
  167. **/
  168. STATIC
  169. EFI_STATUS
  170. EFIAPI
  171. SynchronousRequest (
  172. IN VBLK_DEV *Dev,
  173. IN EFI_LBA Lba,
  174. IN UINTN BufferSize,
  175. IN OUT volatile VOID *Buffer,
  176. IN BOOLEAN RequestIsWrite
  177. )
  178. {
  179. UINT32 BlockSize;
  180. volatile VIRTIO_BLK_REQ Request;
  181. volatile UINT8 *HostStatus;
  182. VOID *HostStatusBuffer;
  183. DESC_INDICES Indices;
  184. VOID *RequestMapping;
  185. VOID *StatusMapping;
  186. VOID *BufferMapping;
  187. EFI_PHYSICAL_ADDRESS BufferDeviceAddress;
  188. EFI_PHYSICAL_ADDRESS HostStatusDeviceAddress;
  189. EFI_PHYSICAL_ADDRESS RequestDeviceAddress;
  190. EFI_STATUS Status;
  191. EFI_STATUS UnmapStatus;
  192. BlockSize = Dev->BlockIoMedia.BlockSize;
  193. //
  194. // Set BufferMapping and BufferDeviceAddress to suppress incorrect
  195. // compiler/analyzer warnings.
  196. //
  197. BufferMapping = NULL;
  198. BufferDeviceAddress = 0;
  199. //
  200. // ensured by VirtioBlkInit()
  201. //
  202. ASSERT (BlockSize > 0);
  203. ASSERT (BlockSize % 512 == 0);
  204. //
  205. // ensured by contract above, plus VerifyReadWriteRequest()
  206. //
  207. ASSERT (BufferSize % BlockSize == 0);
  208. //
  209. // Prepare virtio-blk request header, setting zero size for flush.
  210. // IO Priority is homogeneously 0.
  211. //
  212. Request.Type = RequestIsWrite ?
  213. (BufferSize == 0 ? VIRTIO_BLK_T_FLUSH : VIRTIO_BLK_T_OUT) :
  214. VIRTIO_BLK_T_IN;
  215. Request.IoPrio = 0;
  216. Request.Sector = MultU64x32 (Lba, BlockSize / 512);
  217. //
  218. // Host status is bi-directional (we preset with a value and expect the
  219. // device to update it). Allocate a host status buffer which can be mapped
  220. // to access equally by both processor and the device.
  221. //
  222. Status = Dev->VirtIo->AllocateSharedPages (
  223. Dev->VirtIo,
  224. EFI_SIZE_TO_PAGES (sizeof *HostStatus),
  225. &HostStatusBuffer
  226. );
  227. if (EFI_ERROR (Status)) {
  228. return EFI_DEVICE_ERROR;
  229. }
  230. HostStatus = HostStatusBuffer;
  231. //
  232. // Map virtio-blk request header (must be done after request header is
  233. // populated)
  234. //
  235. Status = VirtioMapAllBytesInSharedBuffer (
  236. Dev->VirtIo,
  237. VirtioOperationBusMasterRead,
  238. (VOID *)&Request,
  239. sizeof Request,
  240. &RequestDeviceAddress,
  241. &RequestMapping
  242. );
  243. if (EFI_ERROR (Status)) {
  244. Status = EFI_DEVICE_ERROR;
  245. goto FreeHostStatusBuffer;
  246. }
  247. //
  248. // Map data buffer
  249. //
  250. if (BufferSize > 0) {
  251. Status = VirtioMapAllBytesInSharedBuffer (
  252. Dev->VirtIo,
  253. (RequestIsWrite ?
  254. VirtioOperationBusMasterRead :
  255. VirtioOperationBusMasterWrite),
  256. (VOID *)Buffer,
  257. BufferSize,
  258. &BufferDeviceAddress,
  259. &BufferMapping
  260. );
  261. if (EFI_ERROR (Status)) {
  262. Status = EFI_DEVICE_ERROR;
  263. goto UnmapRequestBuffer;
  264. }
  265. }
  266. //
  267. // preset a host status for ourselves that we do not accept as success
  268. //
  269. *HostStatus = VIRTIO_BLK_S_IOERR;
  270. //
  271. // Map the Status Buffer with VirtioOperationBusMasterCommonBuffer so that
  272. // both processor and device can access it.
  273. //
  274. Status = VirtioMapAllBytesInSharedBuffer (
  275. Dev->VirtIo,
  276. VirtioOperationBusMasterCommonBuffer,
  277. HostStatusBuffer,
  278. sizeof *HostStatus,
  279. &HostStatusDeviceAddress,
  280. &StatusMapping
  281. );
  282. if (EFI_ERROR (Status)) {
  283. Status = EFI_DEVICE_ERROR;
  284. goto UnmapDataBuffer;
  285. }
  286. VirtioPrepare (&Dev->Ring, &Indices);
  287. //
  288. // ensured by VirtioBlkInit() -- this predicate, in combination with the
  289. // lock-step progress, ensures we don't have to track free descriptors.
  290. //
  291. ASSERT (Dev->Ring.QueueSize >= 3);
  292. //
  293. // virtio-blk header in first desc
  294. //
  295. VirtioAppendDesc (
  296. &Dev->Ring,
  297. RequestDeviceAddress,
  298. sizeof Request,
  299. VRING_DESC_F_NEXT,
  300. &Indices
  301. );
  302. //
  303. // data buffer for read/write in second desc
  304. //
  305. if (BufferSize > 0) {
  306. //
  307. // From virtio-0.9.5, 2.3.2 Descriptor Table:
  308. // "no descriptor chain may be more than 2^32 bytes long in total".
  309. //
  310. // The predicate is ensured by the call contract above (for flush), or
  311. // VerifyReadWriteRequest() (for read/write). It also implies that
  312. // converting BufferSize to UINT32 will not truncate it.
  313. //
  314. ASSERT (BufferSize <= SIZE_1GB);
  315. //
  316. // VRING_DESC_F_WRITE is interpreted from the host's point of view.
  317. //
  318. VirtioAppendDesc (
  319. &Dev->Ring,
  320. BufferDeviceAddress,
  321. (UINT32)BufferSize,
  322. VRING_DESC_F_NEXT | (RequestIsWrite ? 0 : VRING_DESC_F_WRITE),
  323. &Indices
  324. );
  325. }
  326. //
  327. // host status in last (second or third) desc
  328. //
  329. VirtioAppendDesc (
  330. &Dev->Ring,
  331. HostStatusDeviceAddress,
  332. sizeof *HostStatus,
  333. VRING_DESC_F_WRITE,
  334. &Indices
  335. );
  336. //
  337. // virtio-blk's only virtqueue is #0, called "requestq" (see Appendix D).
  338. //
  339. if ((VirtioFlush (
  340. Dev->VirtIo,
  341. 0,
  342. &Dev->Ring,
  343. &Indices,
  344. NULL
  345. ) == EFI_SUCCESS) &&
  346. (*HostStatus == VIRTIO_BLK_S_OK))
  347. {
  348. Status = EFI_SUCCESS;
  349. } else {
  350. Status = EFI_DEVICE_ERROR;
  351. }
  352. Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, StatusMapping);
  353. UnmapDataBuffer:
  354. if (BufferSize > 0) {
  355. UnmapStatus = Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, BufferMapping);
  356. if (EFI_ERROR (UnmapStatus) && !RequestIsWrite && !EFI_ERROR (Status)) {
  357. //
  358. // Data from the bus master may not reach the caller; fail the request.
  359. //
  360. Status = EFI_DEVICE_ERROR;
  361. }
  362. }
  363. UnmapRequestBuffer:
  364. Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, RequestMapping);
  365. FreeHostStatusBuffer:
  366. Dev->VirtIo->FreeSharedPages (
  367. Dev->VirtIo,
  368. EFI_SIZE_TO_PAGES (sizeof *HostStatus),
  369. HostStatusBuffer
  370. );
  371. return Status;
  372. }
  373. /**
  374. ReadBlocks() operation for virtio-blk.
  375. See
  376. - UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
  377. Protocol, EFI_BLOCK_IO_PROTOCOL.ReadBlocks().
  378. - Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.2. ReadBlocks() and
  379. ReadBlocksEx() Implementation.
  380. Parameter checks and conformant return values are implemented in
  381. VerifyReadWriteRequest() and SynchronousRequest().
  382. A zero BufferSize doesn't seem to be prohibited, so do nothing in that case,
  383. successfully.
  384. **/
  385. EFI_STATUS
  386. EFIAPI
  387. VirtioBlkReadBlocks (
  388. IN EFI_BLOCK_IO_PROTOCOL *This,
  389. IN UINT32 MediaId,
  390. IN EFI_LBA Lba,
  391. IN UINTN BufferSize,
  392. OUT VOID *Buffer
  393. )
  394. {
  395. VBLK_DEV *Dev;
  396. EFI_STATUS Status;
  397. if (BufferSize == 0) {
  398. return EFI_SUCCESS;
  399. }
  400. Dev = VIRTIO_BLK_FROM_BLOCK_IO (This);
  401. Status = VerifyReadWriteRequest (
  402. &Dev->BlockIoMedia,
  403. Lba,
  404. BufferSize,
  405. FALSE // RequestIsWrite
  406. );
  407. if (EFI_ERROR (Status)) {
  408. return Status;
  409. }
  410. return SynchronousRequest (
  411. Dev,
  412. Lba,
  413. BufferSize,
  414. Buffer,
  415. FALSE // RequestIsWrite
  416. );
  417. }
  418. /**
  419. WriteBlocks() operation for virtio-blk.
  420. See
  421. - UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
  422. Protocol, EFI_BLOCK_IO_PROTOCOL.WriteBlocks().
  423. - Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.3 WriteBlocks() and
  424. WriteBlockEx() Implementation.
  425. Parameter checks and conformant return values are implemented in
  426. VerifyReadWriteRequest() and SynchronousRequest().
  427. A zero BufferSize doesn't seem to be prohibited, so do nothing in that case,
  428. successfully.
  429. **/
  430. EFI_STATUS
  431. EFIAPI
  432. VirtioBlkWriteBlocks (
  433. IN EFI_BLOCK_IO_PROTOCOL *This,
  434. IN UINT32 MediaId,
  435. IN EFI_LBA Lba,
  436. IN UINTN BufferSize,
  437. IN VOID *Buffer
  438. )
  439. {
  440. VBLK_DEV *Dev;
  441. EFI_STATUS Status;
  442. if (BufferSize == 0) {
  443. return EFI_SUCCESS;
  444. }
  445. Dev = VIRTIO_BLK_FROM_BLOCK_IO (This);
  446. Status = VerifyReadWriteRequest (
  447. &Dev->BlockIoMedia,
  448. Lba,
  449. BufferSize,
  450. TRUE // RequestIsWrite
  451. );
  452. if (EFI_ERROR (Status)) {
  453. return Status;
  454. }
  455. return SynchronousRequest (
  456. Dev,
  457. Lba,
  458. BufferSize,
  459. Buffer,
  460. TRUE // RequestIsWrite
  461. );
  462. }
  463. /**
  464. FlushBlocks() operation for virtio-blk.
  465. See
  466. - UEFI Spec 2.3.1 + Errata C, 12.8 EFI Block I/O Protocol, 12.8 EFI Block I/O
  467. Protocol, EFI_BLOCK_IO_PROTOCOL.FlushBlocks().
  468. - Driver Writer's Guide for UEFI 2.3.1 v1.01, 24.2.4 FlushBlocks() and
  469. FlushBlocksEx() Implementation.
  470. If the underlying virtio-blk device doesn't support flushing (ie.
  471. write-caching), then this function should not be called by higher layers,
  472. according to EFI_BLOCK_IO_MEDIA characteristics set in VirtioBlkInit().
  473. Should they do nonetheless, we do nothing, successfully.
  474. **/
  475. EFI_STATUS
  476. EFIAPI
  477. VirtioBlkFlushBlocks (
  478. IN EFI_BLOCK_IO_PROTOCOL *This
  479. )
  480. {
  481. VBLK_DEV *Dev;
  482. Dev = VIRTIO_BLK_FROM_BLOCK_IO (This);
  483. return Dev->BlockIoMedia.WriteCaching ?
  484. SynchronousRequest (
  485. Dev,
  486. 0, // Lba
  487. 0, // BufferSize
  488. NULL, // Buffer
  489. TRUE // RequestIsWrite
  490. ) :
  491. EFI_SUCCESS;
  492. }
  493. /**
  494. Device probe function for this driver.
  495. The DXE core calls this function for any given device in order to see if the
  496. driver can drive the device.
  497. Specs relevant in the general sense:
  498. - UEFI Spec 2.3.1 + Errata C:
  499. - 6.3 Protocol Handler Services -- for accessing the underlying device
  500. - 10.1 EFI Driver Binding Protocol -- for exporting ourselves
  501. - Driver Writer's Guide for UEFI 2.3.1 v1.01:
  502. - 5.1.3.4 OpenProtocol() and CloseProtocol() -- for accessing the
  503. underlying device
  504. - 9 Driver Binding Protocol -- for exporting ourselves
  505. @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
  506. incorporating this driver (independently of
  507. any device).
  508. @param[in] DeviceHandle The device to probe.
  509. @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
  510. @retval EFI_SUCCESS The driver supports the device being probed.
  511. @retval EFI_UNSUPPORTED Based on virtio-blk discovery, we do not support
  512. the device.
  513. @return Error codes from the OpenProtocol() boot service or
  514. the VirtIo protocol.
  515. **/
  516. EFI_STATUS
  517. EFIAPI
  518. VirtioBlkDriverBindingSupported (
  519. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  520. IN EFI_HANDLE DeviceHandle,
  521. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
  522. )
  523. {
  524. EFI_STATUS Status;
  525. VIRTIO_DEVICE_PROTOCOL *VirtIo;
  526. //
  527. // Attempt to open the device with the VirtIo set of interfaces. On success,
  528. // the protocol is "instantiated" for the VirtIo device. Covers duplicate
  529. // open attempts (EFI_ALREADY_STARTED).
  530. //
  531. Status = gBS->OpenProtocol (
  532. DeviceHandle, // candidate device
  533. &gVirtioDeviceProtocolGuid, // for generic VirtIo access
  534. (VOID **)&VirtIo, // handle to instantiate
  535. This->DriverBindingHandle, // requestor driver identity
  536. DeviceHandle, // ControllerHandle, according to
  537. // the UEFI Driver Model
  538. EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive VirtIo access to
  539. // the device; to be released
  540. );
  541. if (EFI_ERROR (Status)) {
  542. return Status;
  543. }
  544. if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_BLOCK_DEVICE) {
  545. Status = EFI_UNSUPPORTED;
  546. }
  547. //
  548. // We needed VirtIo access only transitorily, to see whether we support the
  549. // device or not.
  550. //
  551. gBS->CloseProtocol (
  552. DeviceHandle,
  553. &gVirtioDeviceProtocolGuid,
  554. This->DriverBindingHandle,
  555. DeviceHandle
  556. );
  557. return Status;
  558. }
  559. /**
  560. Set up all BlockIo and virtio-blk aspects of this driver for the specified
  561. device.
  562. @param[in out] Dev The driver instance to configure. The caller is
  563. responsible for Dev->VirtIo's validity (ie. working IO
  564. access to the underlying virtio-blk device).
  565. @retval EFI_SUCCESS Setup complete.
  566. @retval EFI_UNSUPPORTED The driver is unable to work with the virtio ring or
  567. virtio-blk attributes the host provides.
  568. @return Error codes from VirtioRingInit() or
  569. VIRTIO_CFG_READ() / VIRTIO_CFG_WRITE or
  570. VirtioRingMap().
  571. **/
  572. STATIC
  573. EFI_STATUS
  574. EFIAPI
  575. VirtioBlkInit (
  576. IN OUT VBLK_DEV *Dev
  577. )
  578. {
  579. UINT8 NextDevStat;
  580. EFI_STATUS Status;
  581. UINT64 Features;
  582. UINT64 NumSectors;
  583. UINT32 BlockSize;
  584. UINT8 PhysicalBlockExp;
  585. UINT8 AlignmentOffset;
  586. UINT32 OptIoSize;
  587. UINT16 QueueSize;
  588. UINT64 RingBaseShift;
  589. PhysicalBlockExp = 0;
  590. AlignmentOffset = 0;
  591. OptIoSize = 0;
  592. //
  593. // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.
  594. //
  595. NextDevStat = 0; // step 1 -- reset device
  596. Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
  597. if (EFI_ERROR (Status)) {
  598. goto Failed;
  599. }
  600. NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence
  601. Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
  602. if (EFI_ERROR (Status)) {
  603. goto Failed;
  604. }
  605. NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it
  606. Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
  607. if (EFI_ERROR (Status)) {
  608. goto Failed;
  609. }
  610. //
  611. // Set Page Size - MMIO VirtIo Specific
  612. //
  613. Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE);
  614. if (EFI_ERROR (Status)) {
  615. goto Failed;
  616. }
  617. //
  618. // step 4a -- retrieve and validate features
  619. //
  620. Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features);
  621. if (EFI_ERROR (Status)) {
  622. goto Failed;
  623. }
  624. Status = VIRTIO_CFG_READ (Dev, Capacity, &NumSectors);
  625. if (EFI_ERROR (Status)) {
  626. goto Failed;
  627. }
  628. if (NumSectors == 0) {
  629. Status = EFI_UNSUPPORTED;
  630. goto Failed;
  631. }
  632. if (Features & VIRTIO_BLK_F_BLK_SIZE) {
  633. Status = VIRTIO_CFG_READ (Dev, BlkSize, &BlockSize);
  634. if (EFI_ERROR (Status)) {
  635. goto Failed;
  636. }
  637. if ((BlockSize == 0) || (BlockSize % 512 != 0) ||
  638. (ModU64x32 (NumSectors, BlockSize / 512) != 0))
  639. {
  640. //
  641. // We can only handle a logical block consisting of whole sectors,
  642. // and only a disk composed of whole logical blocks.
  643. //
  644. Status = EFI_UNSUPPORTED;
  645. goto Failed;
  646. }
  647. } else {
  648. BlockSize = 512;
  649. }
  650. if (Features & VIRTIO_BLK_F_TOPOLOGY) {
  651. Status = VIRTIO_CFG_READ (
  652. Dev,
  653. Topology.PhysicalBlockExp,
  654. &PhysicalBlockExp
  655. );
  656. if (EFI_ERROR (Status)) {
  657. goto Failed;
  658. }
  659. if (PhysicalBlockExp >= 32) {
  660. Status = EFI_UNSUPPORTED;
  661. goto Failed;
  662. }
  663. Status = VIRTIO_CFG_READ (Dev, Topology.AlignmentOffset, &AlignmentOffset);
  664. if (EFI_ERROR (Status)) {
  665. goto Failed;
  666. }
  667. Status = VIRTIO_CFG_READ (Dev, Topology.OptIoSize, &OptIoSize);
  668. if (EFI_ERROR (Status)) {
  669. goto Failed;
  670. }
  671. }
  672. Features &= VIRTIO_BLK_F_BLK_SIZE | VIRTIO_BLK_F_TOPOLOGY | VIRTIO_BLK_F_RO |
  673. VIRTIO_BLK_F_FLUSH | VIRTIO_F_VERSION_1 |
  674. VIRTIO_F_IOMMU_PLATFORM;
  675. //
  676. // In virtio-1.0, feature negotiation is expected to complete before queue
  677. // discovery, and the device can also reject the selected set of features.
  678. //
  679. if (Dev->VirtIo->Revision >= VIRTIO_SPEC_REVISION (1, 0, 0)) {
  680. Status = Virtio10WriteFeatures (Dev->VirtIo, Features, &NextDevStat);
  681. if (EFI_ERROR (Status)) {
  682. goto Failed;
  683. }
  684. }
  685. //
  686. // step 4b -- allocate virtqueue
  687. //
  688. Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, 0);
  689. if (EFI_ERROR (Status)) {
  690. goto Failed;
  691. }
  692. Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize);
  693. if (EFI_ERROR (Status)) {
  694. goto Failed;
  695. }
  696. if (QueueSize < 3) {
  697. // SynchronousRequest() uses at most three descriptors
  698. Status = EFI_UNSUPPORTED;
  699. goto Failed;
  700. }
  701. Status = VirtioRingInit (Dev->VirtIo, QueueSize, &Dev->Ring);
  702. if (EFI_ERROR (Status)) {
  703. goto Failed;
  704. }
  705. //
  706. // If anything fails from here on, we must release the ring resources
  707. //
  708. Status = VirtioRingMap (
  709. Dev->VirtIo,
  710. &Dev->Ring,
  711. &RingBaseShift,
  712. &Dev->RingMap
  713. );
  714. if (EFI_ERROR (Status)) {
  715. goto ReleaseQueue;
  716. }
  717. //
  718. // Additional steps for MMIO: align the queue appropriately, and set the
  719. // size. If anything fails from here on, we must unmap the ring resources.
  720. //
  721. Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize);
  722. if (EFI_ERROR (Status)) {
  723. goto UnmapQueue;
  724. }
  725. Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE);
  726. if (EFI_ERROR (Status)) {
  727. goto UnmapQueue;
  728. }
  729. //
  730. // step 4c -- Report GPFN (guest-physical frame number) of queue.
  731. //
  732. Status = Dev->VirtIo->SetQueueAddress (
  733. Dev->VirtIo,
  734. &Dev->Ring,
  735. RingBaseShift
  736. );
  737. if (EFI_ERROR (Status)) {
  738. goto UnmapQueue;
  739. }
  740. //
  741. // step 5 -- Report understood features.
  742. //
  743. if (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) {
  744. Features &= ~(UINT64)(VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM);
  745. Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);
  746. if (EFI_ERROR (Status)) {
  747. goto UnmapQueue;
  748. }
  749. }
  750. //
  751. // step 6 -- initialization complete
  752. //
  753. NextDevStat |= VSTAT_DRIVER_OK;
  754. Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
  755. if (EFI_ERROR (Status)) {
  756. goto UnmapQueue;
  757. }
  758. //
  759. // Populate the exported interface's attributes; see UEFI spec v2.4, 12.9 EFI
  760. // Block I/O Protocol.
  761. //
  762. Dev->BlockIo.Revision = 0;
  763. Dev->BlockIo.Media = &Dev->BlockIoMedia;
  764. Dev->BlockIo.Reset = &VirtioBlkReset;
  765. Dev->BlockIo.ReadBlocks = &VirtioBlkReadBlocks;
  766. Dev->BlockIo.WriteBlocks = &VirtioBlkWriteBlocks;
  767. Dev->BlockIo.FlushBlocks = &VirtioBlkFlushBlocks;
  768. Dev->BlockIoMedia.MediaId = 0;
  769. Dev->BlockIoMedia.RemovableMedia = FALSE;
  770. Dev->BlockIoMedia.MediaPresent = TRUE;
  771. Dev->BlockIoMedia.LogicalPartition = FALSE;
  772. Dev->BlockIoMedia.ReadOnly = (BOOLEAN)((Features & VIRTIO_BLK_F_RO) != 0);
  773. Dev->BlockIoMedia.WriteCaching = (BOOLEAN)((Features & VIRTIO_BLK_F_FLUSH) != 0);
  774. Dev->BlockIoMedia.BlockSize = BlockSize;
  775. Dev->BlockIoMedia.IoAlign = 0;
  776. Dev->BlockIoMedia.LastBlock = DivU64x32 (
  777. NumSectors,
  778. BlockSize / 512
  779. ) - 1;
  780. DEBUG ((
  781. DEBUG_INFO,
  782. "%a: LbaSize=0x%x[B] NumBlocks=0x%Lx[Lba]\n",
  783. __FUNCTION__,
  784. Dev->BlockIoMedia.BlockSize,
  785. Dev->BlockIoMedia.LastBlock + 1
  786. ));
  787. if (Features & VIRTIO_BLK_F_TOPOLOGY) {
  788. Dev->BlockIo.Revision = EFI_BLOCK_IO_PROTOCOL_REVISION3;
  789. Dev->BlockIoMedia.LowestAlignedLba = AlignmentOffset;
  790. Dev->BlockIoMedia.LogicalBlocksPerPhysicalBlock = 1u << PhysicalBlockExp;
  791. Dev->BlockIoMedia.OptimalTransferLengthGranularity = OptIoSize;
  792. DEBUG ((
  793. DEBUG_INFO,
  794. "%a: FirstAligned=0x%Lx[Lba] PhysBlkSize=0x%x[Lba]\n",
  795. __FUNCTION__,
  796. Dev->BlockIoMedia.LowestAlignedLba,
  797. Dev->BlockIoMedia.LogicalBlocksPerPhysicalBlock
  798. ));
  799. DEBUG ((
  800. DEBUG_INFO,
  801. "%a: OptimalTransferLengthGranularity=0x%x[Lba]\n",
  802. __FUNCTION__,
  803. Dev->BlockIoMedia.OptimalTransferLengthGranularity
  804. ));
  805. }
  806. return EFI_SUCCESS;
  807. UnmapQueue:
  808. Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap);
  809. ReleaseQueue:
  810. VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
  811. Failed:
  812. //
  813. // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device
  814. // Status. VirtIo access failure here should not mask the original error.
  815. //
  816. NextDevStat |= VSTAT_FAILED;
  817. Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
  818. return Status; // reached only via Failed above
  819. }
  820. /**
  821. Uninitialize the internals of a virtio-blk device that has been successfully
  822. set up with VirtioBlkInit().
  823. @param[in out] Dev The device to clean up.
  824. **/
  825. STATIC
  826. VOID
  827. EFIAPI
  828. VirtioBlkUninit (
  829. IN OUT VBLK_DEV *Dev
  830. )
  831. {
  832. //
  833. // Reset the virtual device -- see virtio-0.9.5, 2.2.2.1 Device Status. When
  834. // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from
  835. // the old comms area.
  836. //
  837. Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
  838. Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Dev->RingMap);
  839. VirtioRingUninit (Dev->VirtIo, &Dev->Ring);
  840. SetMem (&Dev->BlockIo, sizeof Dev->BlockIo, 0x00);
  841. SetMem (&Dev->BlockIoMedia, sizeof Dev->BlockIoMedia, 0x00);
  842. }
  843. /**
  844. Event notification function enqueued by ExitBootServices().
  845. @param[in] Event Event whose notification function is being invoked.
  846. @param[in] Context Pointer to the VBLK_DEV structure.
  847. **/
  848. STATIC
  849. VOID
  850. EFIAPI
  851. VirtioBlkExitBoot (
  852. IN EFI_EVENT Event,
  853. IN VOID *Context
  854. )
  855. {
  856. VBLK_DEV *Dev;
  857. DEBUG ((DEBUG_VERBOSE, "%a: Context=0x%p\n", __FUNCTION__, Context));
  858. //
  859. // Reset the device. This causes the hypervisor to forget about the virtio
  860. // ring.
  861. //
  862. // We allocated said ring in EfiBootServicesData type memory, and code
  863. // executing after ExitBootServices() is permitted to overwrite it.
  864. //
  865. Dev = Context;
  866. Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
  867. }
  868. /**
  869. After we've pronounced support for a specific device in
  870. DriverBindingSupported(), we start managing said device (passed in by the
  871. Driver Execution Environment) with the following service.
  872. See DriverBindingSupported() for specification references.
  873. @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
  874. incorporating this driver (independently of
  875. any device).
  876. @param[in] DeviceHandle The supported device to drive.
  877. @param[in] RemainingDevicePath Relevant only for bus drivers, ignored.
  878. @retval EFI_SUCCESS Driver instance has been created and
  879. initialized for the virtio-blk device, it
  880. is now accessible via EFI_BLOCK_IO_PROTOCOL.
  881. @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
  882. @return Error codes from the OpenProtocol() boot
  883. service, the VirtIo protocol, VirtioBlkInit(),
  884. or the InstallProtocolInterface() boot service.
  885. **/
  886. EFI_STATUS
  887. EFIAPI
  888. VirtioBlkDriverBindingStart (
  889. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  890. IN EFI_HANDLE DeviceHandle,
  891. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
  892. )
  893. {
  894. VBLK_DEV *Dev;
  895. EFI_STATUS Status;
  896. Dev = (VBLK_DEV *)AllocateZeroPool (sizeof *Dev);
  897. if (Dev == NULL) {
  898. return EFI_OUT_OF_RESOURCES;
  899. }
  900. Status = gBS->OpenProtocol (
  901. DeviceHandle,
  902. &gVirtioDeviceProtocolGuid,
  903. (VOID **)&Dev->VirtIo,
  904. This->DriverBindingHandle,
  905. DeviceHandle,
  906. EFI_OPEN_PROTOCOL_BY_DRIVER
  907. );
  908. if (EFI_ERROR (Status)) {
  909. goto FreeVirtioBlk;
  910. }
  911. //
  912. // VirtIo access granted, configure virtio-blk device.
  913. //
  914. Status = VirtioBlkInit (Dev);
  915. if (EFI_ERROR (Status)) {
  916. goto CloseVirtIo;
  917. }
  918. Status = gBS->CreateEvent (
  919. EVT_SIGNAL_EXIT_BOOT_SERVICES,
  920. TPL_CALLBACK,
  921. &VirtioBlkExitBoot,
  922. Dev,
  923. &Dev->ExitBoot
  924. );
  925. if (EFI_ERROR (Status)) {
  926. goto UninitDev;
  927. }
  928. //
  929. // Setup complete, attempt to export the driver instance's BlockIo interface.
  930. //
  931. Dev->Signature = VBLK_SIG;
  932. Status = gBS->InstallProtocolInterface (
  933. &DeviceHandle,
  934. &gEfiBlockIoProtocolGuid,
  935. EFI_NATIVE_INTERFACE,
  936. &Dev->BlockIo
  937. );
  938. if (EFI_ERROR (Status)) {
  939. goto CloseExitBoot;
  940. }
  941. return EFI_SUCCESS;
  942. CloseExitBoot:
  943. gBS->CloseEvent (Dev->ExitBoot);
  944. UninitDev:
  945. VirtioBlkUninit (Dev);
  946. CloseVirtIo:
  947. gBS->CloseProtocol (
  948. DeviceHandle,
  949. &gVirtioDeviceProtocolGuid,
  950. This->DriverBindingHandle,
  951. DeviceHandle
  952. );
  953. FreeVirtioBlk:
  954. FreePool (Dev);
  955. return Status;
  956. }
  957. /**
  958. Stop driving a virtio-blk device and remove its BlockIo interface.
  959. This function replays the success path of DriverBindingStart() in reverse.
  960. The host side virtio-blk device is reset, so that the OS boot loader or the
  961. OS may reinitialize it.
  962. @param[in] This The EFI_DRIVER_BINDING_PROTOCOL object
  963. incorporating this driver (independently of any
  964. device).
  965. @param[in] DeviceHandle Stop driving this device.
  966. @param[in] NumberOfChildren Since this function belongs to a device driver
  967. only (as opposed to a bus driver), the caller
  968. environment sets NumberOfChildren to zero, and
  969. we ignore it.
  970. @param[in] ChildHandleBuffer Ignored (corresponding to NumberOfChildren).
  971. **/
  972. EFI_STATUS
  973. EFIAPI
  974. VirtioBlkDriverBindingStop (
  975. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  976. IN EFI_HANDLE DeviceHandle,
  977. IN UINTN NumberOfChildren,
  978. IN EFI_HANDLE *ChildHandleBuffer
  979. )
  980. {
  981. EFI_STATUS Status;
  982. EFI_BLOCK_IO_PROTOCOL *BlockIo;
  983. VBLK_DEV *Dev;
  984. Status = gBS->OpenProtocol (
  985. DeviceHandle, // candidate device
  986. &gEfiBlockIoProtocolGuid, // retrieve the BlockIo iface
  987. (VOID **)&BlockIo, // target pointer
  988. This->DriverBindingHandle, // requestor driver identity
  989. DeviceHandle, // requesting lookup for dev.
  990. EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no ref. added
  991. );
  992. if (EFI_ERROR (Status)) {
  993. return Status;
  994. }
  995. Dev = VIRTIO_BLK_FROM_BLOCK_IO (BlockIo);
  996. //
  997. // Handle Stop() requests for in-use driver instances gracefully.
  998. //
  999. Status = gBS->UninstallProtocolInterface (
  1000. DeviceHandle,
  1001. &gEfiBlockIoProtocolGuid,
  1002. &Dev->BlockIo
  1003. );
  1004. if (EFI_ERROR (Status)) {
  1005. return Status;
  1006. }
  1007. gBS->CloseEvent (Dev->ExitBoot);
  1008. VirtioBlkUninit (Dev);
  1009. gBS->CloseProtocol (
  1010. DeviceHandle,
  1011. &gVirtioDeviceProtocolGuid,
  1012. This->DriverBindingHandle,
  1013. DeviceHandle
  1014. );
  1015. FreePool (Dev);
  1016. return EFI_SUCCESS;
  1017. }
  1018. //
  1019. // The static object that groups the Supported() (ie. probe), Start() and
  1020. // Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
  1021. // C, 10.1 EFI Driver Binding Protocol.
  1022. //
  1023. STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
  1024. &VirtioBlkDriverBindingSupported,
  1025. &VirtioBlkDriverBindingStart,
  1026. &VirtioBlkDriverBindingStop,
  1027. 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
  1028. NULL, // ImageHandle, to be overwritten by
  1029. // EfiLibInstallDriverBindingComponentName2() in VirtioBlkEntryPoint()
  1030. NULL // DriverBindingHandle, ditto
  1031. };
  1032. //
  1033. // The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
  1034. // EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
  1035. // in English, for display on standard console devices. This is recommended for
  1036. // UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
  1037. // Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
  1038. //
  1039. // Device type names ("Virtio Block Device") are not formatted because the
  1040. // driver supports only that device type. Therefore the driver name suffices
  1041. // for unambiguous identification.
  1042. //
  1043. STATIC
  1044. EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
  1045. { "eng;en", L"Virtio Block Driver" },
  1046. { NULL, NULL }
  1047. };
  1048. STATIC
  1049. EFI_COMPONENT_NAME_PROTOCOL gComponentName;
  1050. EFI_STATUS
  1051. EFIAPI
  1052. VirtioBlkGetDriverName (
  1053. IN EFI_COMPONENT_NAME_PROTOCOL *This,
  1054. IN CHAR8 *Language,
  1055. OUT CHAR16 **DriverName
  1056. )
  1057. {
  1058. return LookupUnicodeString2 (
  1059. Language,
  1060. This->SupportedLanguages,
  1061. mDriverNameTable,
  1062. DriverName,
  1063. (BOOLEAN)(This == &gComponentName) // Iso639Language
  1064. );
  1065. }
  1066. EFI_STATUS
  1067. EFIAPI
  1068. VirtioBlkGetDeviceName (
  1069. IN EFI_COMPONENT_NAME_PROTOCOL *This,
  1070. IN EFI_HANDLE DeviceHandle,
  1071. IN EFI_HANDLE ChildHandle,
  1072. IN CHAR8 *Language,
  1073. OUT CHAR16 **ControllerName
  1074. )
  1075. {
  1076. return EFI_UNSUPPORTED;
  1077. }
  1078. STATIC
  1079. EFI_COMPONENT_NAME_PROTOCOL gComponentName = {
  1080. &VirtioBlkGetDriverName,
  1081. &VirtioBlkGetDeviceName,
  1082. "eng" // SupportedLanguages, ISO 639-2 language codes
  1083. };
  1084. STATIC
  1085. EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {
  1086. (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)&VirtioBlkGetDriverName,
  1087. (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)&VirtioBlkGetDeviceName,
  1088. "en" // SupportedLanguages, RFC 4646 language codes
  1089. };
  1090. //
  1091. // Entry point of this driver.
  1092. //
  1093. EFI_STATUS
  1094. EFIAPI
  1095. VirtioBlkEntryPoint (
  1096. IN EFI_HANDLE ImageHandle,
  1097. IN EFI_SYSTEM_TABLE *SystemTable
  1098. )
  1099. {
  1100. return EfiLibInstallDriverBindingComponentName2 (
  1101. ImageHandle,
  1102. SystemTable,
  1103. &gDriverBinding,
  1104. ImageHandle,
  1105. &gComponentName,
  1106. &gComponentName2
  1107. );
  1108. }