Virtio10.c 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308
  1. /** @file
  2. A non-transitional driver for VirtIo 1.0 PCI devices.
  3. Copyright (C) 2016, Red Hat, Inc.
  4. Copyright (C) 2017, AMD Inc, All rights reserved.<BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include <IndustryStandard/Pci.h>
  8. #include <IndustryStandard/Virtio.h>
  9. #include <Protocol/PciIo.h>
  10. #include <Protocol/PciRootBridgeIo.h>
  11. #include <Protocol/VirtioDevice.h>
  12. #include <Library/BaseMemoryLib.h>
  13. #include <Library/DebugLib.h>
  14. #include <Library/MemoryAllocationLib.h>
  15. #include <Library/PciCapLib.h>
  16. #include <Library/PciCapPciIoLib.h>
  17. #include <Library/UefiBootServicesTableLib.h>
  18. #include <Library/UefiLib.h>
  19. #include "Virtio10.h"
  20. //
  21. // Utility functions
  22. //
  23. /**
  24. Transfer data between the caller and a register in a virtio-1.0 register
  25. block.
  26. @param[in] PciIo The EFI_PCI_IO_PROTOCOL instance that represents
  27. the device.
  28. @param[in] Config The "fat pointer" structure that identifies the
  29. register block to access.
  30. @param[in] Write TRUE if the register should be written, FALSE if
  31. the register should be read.
  32. @param[in] FieldOffset The offset of the register within the register
  33. block.
  34. @param[in] FieldSize The size of the register within the register
  35. block. Can be one of 1, 2, 4 and 8. Accesses to
  36. 8-byte registers are broken up into two 4-byte
  37. accesses.
  38. @param[in,out] Buffer When Write is TRUE, the register is written with
  39. data from Buffer. When Write is FALSE, the caller
  40. receives the register value into Buffer.
  41. @retval EFI_SUCCESS Register access successful.
  42. @retval EFI_INVALID_PARAMETER The register block pointed-to by Config
  43. doesn't exist; or FieldOffset and FieldSize
  44. would overflow the register block; or
  45. FieldSize is invalid.
  46. @return Error codes from
  47. EFI_PCI_IO_PROTOCOL.(Io|Mem).(Read|Write)
  48. member functions.
  49. **/
  50. STATIC
  51. EFI_STATUS
  52. Virtio10Transfer (
  53. IN EFI_PCI_IO_PROTOCOL *PciIo,
  54. IN VIRTIO_1_0_CONFIG *Config,
  55. IN BOOLEAN Write,
  56. IN UINTN FieldOffset,
  57. IN UINTN FieldSize,
  58. IN OUT VOID *Buffer
  59. )
  60. {
  61. UINTN Count;
  62. EFI_PCI_IO_PROTOCOL_WIDTH Width;
  63. EFI_PCI_IO_PROTOCOL_ACCESS *BarType;
  64. EFI_PCI_IO_PROTOCOL_IO_MEM Access;
  65. if (!Config->Exists ||
  66. (FieldSize > Config->Length) ||
  67. (FieldOffset > Config->Length - FieldSize))
  68. {
  69. return EFI_INVALID_PARAMETER;
  70. }
  71. Count = 1;
  72. switch (FieldSize) {
  73. case 1:
  74. Width = EfiPciIoWidthUint8;
  75. break;
  76. case 2:
  77. Width = EfiPciIoWidthUint16;
  78. break;
  79. case 8:
  80. Count = 2;
  81. //
  82. // fall through
  83. //
  84. case 4:
  85. Width = EfiPciIoWidthUint32;
  86. break;
  87. default:
  88. return EFI_INVALID_PARAMETER;
  89. }
  90. BarType = (Config->BarType == Virtio10BarTypeMem) ? &PciIo->Mem : &PciIo->Io;
  91. Access = Write ? BarType->Write : BarType->Read;
  92. return Access (
  93. PciIo,
  94. Width,
  95. Config->Bar,
  96. Config->Offset + FieldOffset,
  97. Count,
  98. Buffer
  99. );
  100. }
  101. /**
  102. Determine if a PCI BAR is IO or MMIO.
  103. @param[in] PciIo The EFI_PCI_IO_PROTOCOL instance that represents the
  104. device.
  105. @param[in] BarIndex The number of the BAR whose type the caller is
  106. interested in.
  107. @param[out] BarType On output, a VIRTIO_1_0_BAR_TYPE value that gives the
  108. type of the BAR.
  109. @retval EFI_SUCCESS The BAR type has been recognized and stored in
  110. BarType.
  111. @retval EFI_UNSUPPORTED The BAR type couldn't be identified.
  112. @return Error codes from
  113. EFI_PCI_IO_PROTOCOL.GetBarAttributes().
  114. **/
  115. STATIC
  116. EFI_STATUS
  117. GetBarType (
  118. IN EFI_PCI_IO_PROTOCOL *PciIo,
  119. IN UINT8 BarIndex,
  120. OUT VIRTIO_1_0_BAR_TYPE *BarType
  121. )
  122. {
  123. EFI_STATUS Status;
  124. VOID *Resources;
  125. Status = PciIo->GetBarAttributes (PciIo, BarIndex, NULL, &Resources);
  126. if (EFI_ERROR (Status)) {
  127. return Status;
  128. }
  129. Status = EFI_UNSUPPORTED;
  130. if (*(UINT8 *)Resources == ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR) {
  131. EFI_ACPI_QWORD_ADDRESS_SPACE_DESCRIPTOR *Descriptor;
  132. Descriptor = Resources;
  133. switch (Descriptor->ResType) {
  134. case ACPI_ADDRESS_SPACE_TYPE_MEM:
  135. *BarType = Virtio10BarTypeMem;
  136. Status = EFI_SUCCESS;
  137. break;
  138. case ACPI_ADDRESS_SPACE_TYPE_IO:
  139. *BarType = Virtio10BarTypeIo;
  140. Status = EFI_SUCCESS;
  141. break;
  142. default:
  143. break;
  144. }
  145. }
  146. FreePool (Resources);
  147. return Status;
  148. }
  149. /*
  150. Traverse the PCI capabilities list of a virtio-1.0 device, and capture the
  151. locations of the interesting virtio-1.0 register blocks.
  152. @param[in,out] Device The VIRTIO_1_0_DEV structure that identifies
  153. the device. On input, the caller is responsible
  154. that the Device->PciIo member be live, and that
  155. the CommonConfig, NotifyConfig,
  156. NotifyOffsetMultiplier and SpecificConfig
  157. members be zeroed. On output, said members
  158. will have been updated from the PCI
  159. capabilities found.
  160. @retval EFI_SUCCESS Traversal successful.
  161. @return Error codes from PciCapPciIoLib, PciCapLib, and the
  162. GetBarType() helper function.
  163. */
  164. STATIC
  165. EFI_STATUS
  166. ParseCapabilities (
  167. IN OUT VIRTIO_1_0_DEV *Device
  168. )
  169. {
  170. EFI_STATUS Status;
  171. PCI_CAP_DEV *PciDevice;
  172. PCI_CAP_LIST *CapList;
  173. UINT16 VendorInstance;
  174. PCI_CAP *VendorCap;
  175. Status = PciCapPciIoDeviceInit (Device->PciIo, &PciDevice);
  176. if (EFI_ERROR (Status)) {
  177. return Status;
  178. }
  179. Status = PciCapListInit (PciDevice, &CapList);
  180. if (EFI_ERROR (Status)) {
  181. goto UninitPciDevice;
  182. }
  183. for (VendorInstance = 0;
  184. !EFI_ERROR (
  185. PciCapListFindCap (
  186. CapList,
  187. PciCapNormal,
  188. EFI_PCI_CAPABILITY_ID_VENDOR,
  189. VendorInstance,
  190. &VendorCap
  191. )
  192. );
  193. VendorInstance++)
  194. {
  195. UINT8 CapLen;
  196. VIRTIO_PCI_CAP VirtIoCap;
  197. VIRTIO_1_0_CONFIG *ParsedConfig;
  198. //
  199. // Big enough to accommodate a VIRTIO_PCI_CAP structure?
  200. //
  201. Status = PciCapRead (
  202. PciDevice,
  203. VendorCap,
  204. OFFSET_OF (EFI_PCI_CAPABILITY_VENDOR_HDR, Length),
  205. &CapLen,
  206. sizeof CapLen
  207. );
  208. if (EFI_ERROR (Status)) {
  209. goto UninitCapList;
  210. }
  211. if (CapLen < sizeof VirtIoCap) {
  212. //
  213. // Too small, move to next.
  214. //
  215. continue;
  216. }
  217. //
  218. // Read interesting part of capability.
  219. //
  220. Status = PciCapRead (PciDevice, VendorCap, 0, &VirtIoCap, sizeof VirtIoCap);
  221. if (EFI_ERROR (Status)) {
  222. goto UninitCapList;
  223. }
  224. switch (VirtIoCap.ConfigType) {
  225. case VIRTIO_PCI_CAP_COMMON_CFG:
  226. ParsedConfig = &Device->CommonConfig;
  227. break;
  228. case VIRTIO_PCI_CAP_NOTIFY_CFG:
  229. ParsedConfig = &Device->NotifyConfig;
  230. break;
  231. case VIRTIO_PCI_CAP_DEVICE_CFG:
  232. ParsedConfig = &Device->SpecificConfig;
  233. break;
  234. default:
  235. //
  236. // Capability is not interesting.
  237. //
  238. continue;
  239. }
  240. //
  241. // Save the location of the register block into ParsedConfig.
  242. //
  243. Status = GetBarType (Device->PciIo, VirtIoCap.Bar, &ParsedConfig->BarType);
  244. if (EFI_ERROR (Status)) {
  245. goto UninitCapList;
  246. }
  247. ParsedConfig->Bar = VirtIoCap.Bar;
  248. ParsedConfig->Offset = VirtIoCap.Offset;
  249. ParsedConfig->Length = VirtIoCap.Length;
  250. if (VirtIoCap.ConfigType == VIRTIO_PCI_CAP_NOTIFY_CFG) {
  251. //
  252. // This capability has an additional field called NotifyOffsetMultiplier;
  253. // parse it too.
  254. //
  255. if (CapLen < sizeof VirtIoCap + sizeof Device->NotifyOffsetMultiplier) {
  256. //
  257. // Too small, move to next.
  258. //
  259. continue;
  260. }
  261. Status = PciCapRead (
  262. PciDevice,
  263. VendorCap,
  264. sizeof VirtIoCap,
  265. &Device->NotifyOffsetMultiplier,
  266. sizeof Device->NotifyOffsetMultiplier
  267. );
  268. if (EFI_ERROR (Status)) {
  269. goto UninitCapList;
  270. }
  271. }
  272. //
  273. // Capability parsed successfully.
  274. //
  275. ParsedConfig->Exists = TRUE;
  276. }
  277. ASSERT_EFI_ERROR (Status);
  278. UninitCapList:
  279. PciCapListUninit (CapList);
  280. UninitPciDevice:
  281. PciCapPciIoDeviceUninit (PciDevice);
  282. return Status;
  283. }
  284. /**
  285. Accumulate the BAR type of a virtio-1.0 register block into a UINT64
  286. attribute map, such that the latter is suitable for enabling IO / MMIO
  287. decoding with EFI_PCI_IO_PROTOCOL.Attributes().
  288. @param[in] Config The "fat pointer" structure that identifies the
  289. register block. It is allowed for the register
  290. block not to exist.
  291. @param[in,out] Attributes On output, if the register block exists,
  292. EFI_PCI_IO_ATTRIBUTE_MEMORY or
  293. EFI_PCI_IO_ATTRIBUTE_IO is OR-ed into Attributes,
  294. according to the register block's BAR type.
  295. **/
  296. STATIC
  297. VOID
  298. UpdateAttributes (
  299. IN VIRTIO_1_0_CONFIG *Config,
  300. IN OUT UINT64 *Attributes
  301. )
  302. {
  303. if (Config->Exists) {
  304. *Attributes |= (Config->BarType == Virtio10BarTypeMem) ?
  305. EFI_PCI_IO_ATTRIBUTE_MEMORY :
  306. EFI_PCI_IO_ATTRIBUTE_IO;
  307. }
  308. }
  309. //
  310. // VIRTIO_DEVICE_PROTOCOL member functions
  311. //
  312. STATIC
  313. EFI_STATUS
  314. EFIAPI
  315. Virtio10GetDeviceFeatures (
  316. IN VIRTIO_DEVICE_PROTOCOL *This,
  317. OUT UINT64 *DeviceFeatures
  318. )
  319. {
  320. VIRTIO_1_0_DEV *Dev;
  321. UINT32 Selector;
  322. UINT32 Features32[2];
  323. Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
  324. for (Selector = 0; Selector < 2; ++Selector) {
  325. EFI_STATUS Status;
  326. //
  327. // Select the low or high half of the features.
  328. //
  329. Status = Virtio10Transfer (
  330. Dev->PciIo,
  331. &Dev->CommonConfig,
  332. TRUE,
  333. OFFSET_OF (VIRTIO_PCI_COMMON_CFG, DeviceFeatureSelect),
  334. sizeof Selector,
  335. &Selector
  336. );
  337. if (EFI_ERROR (Status)) {
  338. return Status;
  339. }
  340. //
  341. // Fetch that half.
  342. //
  343. Status = Virtio10Transfer (
  344. Dev->PciIo,
  345. &Dev->CommonConfig,
  346. FALSE,
  347. OFFSET_OF (VIRTIO_PCI_COMMON_CFG, DeviceFeature),
  348. sizeof Features32[Selector],
  349. &Features32[Selector]
  350. );
  351. if (EFI_ERROR (Status)) {
  352. return Status;
  353. }
  354. }
  355. *DeviceFeatures = LShiftU64 (Features32[1], 32) | Features32[0];
  356. return EFI_SUCCESS;
  357. }
  358. STATIC
  359. EFI_STATUS
  360. EFIAPI
  361. Virtio10SetGuestFeatures (
  362. IN VIRTIO_DEVICE_PROTOCOL *This,
  363. IN UINT64 Features
  364. )
  365. {
  366. VIRTIO_1_0_DEV *Dev;
  367. UINT32 Selector;
  368. UINT32 Features32[2];
  369. Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
  370. Features32[0] = (UINT32)Features;
  371. Features32[1] = (UINT32)RShiftU64 (Features, 32);
  372. for (Selector = 0; Selector < 2; ++Selector) {
  373. EFI_STATUS Status;
  374. //
  375. // Select the low or high half of the features.
  376. //
  377. Status = Virtio10Transfer (
  378. Dev->PciIo,
  379. &Dev->CommonConfig,
  380. TRUE,
  381. OFFSET_OF (VIRTIO_PCI_COMMON_CFG, DriverFeatureSelect),
  382. sizeof Selector,
  383. &Selector
  384. );
  385. if (EFI_ERROR (Status)) {
  386. return Status;
  387. }
  388. //
  389. // Write that half.
  390. //
  391. Status = Virtio10Transfer (
  392. Dev->PciIo,
  393. &Dev->CommonConfig,
  394. TRUE,
  395. OFFSET_OF (VIRTIO_PCI_COMMON_CFG, DriverFeature),
  396. sizeof Features32[Selector],
  397. &Features32[Selector]
  398. );
  399. if (EFI_ERROR (Status)) {
  400. return Status;
  401. }
  402. }
  403. return EFI_SUCCESS;
  404. }
  405. STATIC
  406. EFI_STATUS
  407. EFIAPI
  408. Virtio10SetQueueAddress (
  409. IN VIRTIO_DEVICE_PROTOCOL *This,
  410. IN VRING *Ring,
  411. IN UINT64 RingBaseShift
  412. )
  413. {
  414. VIRTIO_1_0_DEV *Dev;
  415. EFI_STATUS Status;
  416. UINT64 Address;
  417. UINT16 Enable;
  418. Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
  419. Address = (UINTN)Ring->Desc;
  420. Address += RingBaseShift;
  421. Status = Virtio10Transfer (
  422. Dev->PciIo,
  423. &Dev->CommonConfig,
  424. TRUE,
  425. OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueDesc),
  426. sizeof Address,
  427. &Address
  428. );
  429. if (EFI_ERROR (Status)) {
  430. return Status;
  431. }
  432. Address = (UINTN)Ring->Avail.Flags;
  433. Address += RingBaseShift;
  434. Status = Virtio10Transfer (
  435. Dev->PciIo,
  436. &Dev->CommonConfig,
  437. TRUE,
  438. OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueAvail),
  439. sizeof Address,
  440. &Address
  441. );
  442. if (EFI_ERROR (Status)) {
  443. return Status;
  444. }
  445. Address = (UINTN)Ring->Used.Flags;
  446. Address += RingBaseShift;
  447. Status = Virtio10Transfer (
  448. Dev->PciIo,
  449. &Dev->CommonConfig,
  450. TRUE,
  451. OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueUsed),
  452. sizeof Address,
  453. &Address
  454. );
  455. if (EFI_ERROR (Status)) {
  456. return Status;
  457. }
  458. Enable = 1;
  459. Status = Virtio10Transfer (
  460. Dev->PciIo,
  461. &Dev->CommonConfig,
  462. TRUE,
  463. OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueEnable),
  464. sizeof Enable,
  465. &Enable
  466. );
  467. return Status;
  468. }
  469. STATIC
  470. EFI_STATUS
  471. EFIAPI
  472. Virtio10SetQueueSel (
  473. IN VIRTIO_DEVICE_PROTOCOL *This,
  474. IN UINT16 Index
  475. )
  476. {
  477. VIRTIO_1_0_DEV *Dev;
  478. EFI_STATUS Status;
  479. Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
  480. Status = Virtio10Transfer (
  481. Dev->PciIo,
  482. &Dev->CommonConfig,
  483. TRUE,
  484. OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueSelect),
  485. sizeof Index,
  486. &Index
  487. );
  488. return Status;
  489. }
  490. STATIC
  491. EFI_STATUS
  492. EFIAPI
  493. Virtio10SetQueueNotify (
  494. IN VIRTIO_DEVICE_PROTOCOL *This,
  495. IN UINT16 Index
  496. )
  497. {
  498. VIRTIO_1_0_DEV *Dev;
  499. EFI_STATUS Status;
  500. UINT16 SavedQueueSelect;
  501. UINT16 NotifyOffset;
  502. Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
  503. //
  504. // Read NotifyOffset first. NotifyOffset is queue specific, so we have
  505. // to stash & restore the current queue selector around it.
  506. //
  507. // So, start with saving the current queue selector.
  508. //
  509. Status = Virtio10Transfer (
  510. Dev->PciIo,
  511. &Dev->CommonConfig,
  512. FALSE,
  513. OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueSelect),
  514. sizeof SavedQueueSelect,
  515. &SavedQueueSelect
  516. );
  517. if (EFI_ERROR (Status)) {
  518. return Status;
  519. }
  520. //
  521. // Select the requested queue.
  522. //
  523. Status = Virtio10Transfer (
  524. Dev->PciIo,
  525. &Dev->CommonConfig,
  526. TRUE,
  527. OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueSelect),
  528. sizeof Index,
  529. &Index
  530. );
  531. if (EFI_ERROR (Status)) {
  532. return Status;
  533. }
  534. //
  535. // Read the QueueNotifyOff field.
  536. //
  537. Status = Virtio10Transfer (
  538. Dev->PciIo,
  539. &Dev->CommonConfig,
  540. FALSE,
  541. OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueNotifyOff),
  542. sizeof NotifyOffset,
  543. &NotifyOffset
  544. );
  545. if (EFI_ERROR (Status)) {
  546. return Status;
  547. }
  548. //
  549. // Re-select the original queue.
  550. //
  551. Status = Virtio10Transfer (
  552. Dev->PciIo,
  553. &Dev->CommonConfig,
  554. TRUE,
  555. OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueSelect),
  556. sizeof SavedQueueSelect,
  557. &SavedQueueSelect
  558. );
  559. if (EFI_ERROR (Status)) {
  560. return Status;
  561. }
  562. //
  563. // We can now kick the queue.
  564. //
  565. Status = Virtio10Transfer (
  566. Dev->PciIo,
  567. &Dev->NotifyConfig,
  568. TRUE,
  569. NotifyOffset * Dev->NotifyOffsetMultiplier,
  570. sizeof Index,
  571. &Index
  572. );
  573. return Status;
  574. }
  575. STATIC
  576. EFI_STATUS
  577. EFIAPI
  578. Virtio10SetQueueAlign (
  579. IN VIRTIO_DEVICE_PROTOCOL *This,
  580. IN UINT32 Alignment
  581. )
  582. {
  583. return (Alignment == EFI_PAGE_SIZE) ? EFI_SUCCESS : EFI_UNSUPPORTED;
  584. }
  585. STATIC
  586. EFI_STATUS
  587. EFIAPI
  588. Virtio10SetPageSize (
  589. IN VIRTIO_DEVICE_PROTOCOL *This,
  590. IN UINT32 PageSize
  591. )
  592. {
  593. return (PageSize == EFI_PAGE_SIZE) ? EFI_SUCCESS : EFI_UNSUPPORTED;
  594. }
  595. STATIC
  596. EFI_STATUS
  597. EFIAPI
  598. Virtio10GetQueueNumMax (
  599. IN VIRTIO_DEVICE_PROTOCOL *This,
  600. OUT UINT16 *QueueNumMax
  601. )
  602. {
  603. VIRTIO_1_0_DEV *Dev;
  604. EFI_STATUS Status;
  605. Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
  606. Status = Virtio10Transfer (
  607. Dev->PciIo,
  608. &Dev->CommonConfig,
  609. FALSE,
  610. OFFSET_OF (VIRTIO_PCI_COMMON_CFG, QueueSize),
  611. sizeof *QueueNumMax,
  612. QueueNumMax
  613. );
  614. return Status;
  615. }
  616. STATIC
  617. EFI_STATUS
  618. EFIAPI
  619. Virtio10SetQueueNum (
  620. IN VIRTIO_DEVICE_PROTOCOL *This,
  621. IN UINT16 QueueSize
  622. )
  623. {
  624. EFI_STATUS Status;
  625. UINT16 CurrentSize;
  626. //
  627. // This member function is required for VirtIo MMIO, and a no-op in
  628. // VirtIo PCI 0.9.5. In VirtIo 1.0, drivers can theoretically use this
  629. // member to reduce memory consumption, but none of our drivers do. So
  630. // just check that they set the size that is already in effect.
  631. //
  632. Status = Virtio10GetQueueNumMax (This, &CurrentSize);
  633. if (EFI_ERROR (Status)) {
  634. return Status;
  635. }
  636. return (CurrentSize == QueueSize) ? EFI_SUCCESS : EFI_UNSUPPORTED;
  637. }
  638. STATIC
  639. EFI_STATUS
  640. EFIAPI
  641. Virtio10GetDeviceStatus (
  642. IN VIRTIO_DEVICE_PROTOCOL *This,
  643. OUT UINT8 *DeviceStatus
  644. )
  645. {
  646. VIRTIO_1_0_DEV *Dev;
  647. EFI_STATUS Status;
  648. Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
  649. Status = Virtio10Transfer (
  650. Dev->PciIo,
  651. &Dev->CommonConfig,
  652. FALSE,
  653. OFFSET_OF (VIRTIO_PCI_COMMON_CFG, DeviceStatus),
  654. sizeof *DeviceStatus,
  655. DeviceStatus
  656. );
  657. return Status;
  658. }
  659. STATIC
  660. EFI_STATUS
  661. EFIAPI
  662. Virtio10SetDeviceStatus (
  663. IN VIRTIO_DEVICE_PROTOCOL *This,
  664. IN UINT8 DeviceStatus
  665. )
  666. {
  667. VIRTIO_1_0_DEV *Dev;
  668. EFI_STATUS Status;
  669. Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
  670. Status = Virtio10Transfer (
  671. Dev->PciIo,
  672. &Dev->CommonConfig,
  673. TRUE,
  674. OFFSET_OF (VIRTIO_PCI_COMMON_CFG, DeviceStatus),
  675. sizeof DeviceStatus,
  676. &DeviceStatus
  677. );
  678. return Status;
  679. }
  680. STATIC
  681. EFI_STATUS
  682. EFIAPI
  683. Virtio10WriteDevice (
  684. IN VIRTIO_DEVICE_PROTOCOL *This,
  685. IN UINTN FieldOffset,
  686. IN UINTN FieldSize,
  687. IN UINT64 Value
  688. )
  689. {
  690. VIRTIO_1_0_DEV *Dev;
  691. EFI_STATUS Status;
  692. Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
  693. Status = Virtio10Transfer (
  694. Dev->PciIo,
  695. &Dev->SpecificConfig,
  696. TRUE,
  697. FieldOffset,
  698. FieldSize,
  699. &Value
  700. );
  701. return Status;
  702. }
  703. STATIC
  704. EFI_STATUS
  705. EFIAPI
  706. Virtio10ReadDevice (
  707. IN VIRTIO_DEVICE_PROTOCOL *This,
  708. IN UINTN FieldOffset,
  709. IN UINTN FieldSize,
  710. IN UINTN BufferSize,
  711. OUT VOID *Buffer
  712. )
  713. {
  714. VIRTIO_1_0_DEV *Dev;
  715. EFI_STATUS Status;
  716. if (FieldSize != BufferSize) {
  717. return EFI_INVALID_PARAMETER;
  718. }
  719. Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
  720. Status = Virtio10Transfer (
  721. Dev->PciIo,
  722. &Dev->SpecificConfig,
  723. FALSE,
  724. FieldOffset,
  725. FieldSize,
  726. Buffer
  727. );
  728. return Status;
  729. }
  730. STATIC
  731. EFI_STATUS
  732. EFIAPI
  733. Virtio10AllocateSharedPages (
  734. IN VIRTIO_DEVICE_PROTOCOL *This,
  735. IN UINTN Pages,
  736. IN OUT VOID **HostAddress
  737. )
  738. {
  739. VIRTIO_1_0_DEV *Dev;
  740. EFI_STATUS Status;
  741. Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
  742. Status = Dev->PciIo->AllocateBuffer (
  743. Dev->PciIo,
  744. AllocateAnyPages,
  745. EfiBootServicesData,
  746. Pages,
  747. HostAddress,
  748. EFI_PCI_ATTRIBUTE_MEMORY_CACHED
  749. );
  750. return Status;
  751. }
  752. STATIC
  753. VOID
  754. EFIAPI
  755. Virtio10FreeSharedPages (
  756. IN VIRTIO_DEVICE_PROTOCOL *This,
  757. IN UINTN Pages,
  758. IN VOID *HostAddress
  759. )
  760. {
  761. VIRTIO_1_0_DEV *Dev;
  762. Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
  763. Dev->PciIo->FreeBuffer (
  764. Dev->PciIo,
  765. Pages,
  766. HostAddress
  767. );
  768. }
  769. STATIC
  770. EFI_STATUS
  771. EFIAPI
  772. Virtio10MapSharedBuffer (
  773. IN VIRTIO_DEVICE_PROTOCOL *This,
  774. IN VIRTIO_MAP_OPERATION Operation,
  775. IN VOID *HostAddress,
  776. IN OUT UINTN *NumberOfBytes,
  777. OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
  778. OUT VOID **Mapping
  779. )
  780. {
  781. EFI_STATUS Status;
  782. VIRTIO_1_0_DEV *Dev;
  783. EFI_PCI_IO_PROTOCOL_OPERATION PciIoOperation;
  784. Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
  785. //
  786. // Map VIRTIO_MAP_OPERATION to EFI_PCI_IO_PROTOCOL_OPERATION
  787. //
  788. switch (Operation) {
  789. case VirtioOperationBusMasterRead:
  790. PciIoOperation = EfiPciIoOperationBusMasterRead;
  791. break;
  792. case VirtioOperationBusMasterWrite:
  793. PciIoOperation = EfiPciIoOperationBusMasterWrite;
  794. break;
  795. case VirtioOperationBusMasterCommonBuffer:
  796. PciIoOperation = EfiPciIoOperationBusMasterCommonBuffer;
  797. break;
  798. default:
  799. return EFI_INVALID_PARAMETER;
  800. }
  801. Status = Dev->PciIo->Map (
  802. Dev->PciIo,
  803. PciIoOperation,
  804. HostAddress,
  805. NumberOfBytes,
  806. DeviceAddress,
  807. Mapping
  808. );
  809. return Status;
  810. }
  811. STATIC
  812. EFI_STATUS
  813. EFIAPI
  814. Virtio10UnmapSharedBuffer (
  815. IN VIRTIO_DEVICE_PROTOCOL *This,
  816. IN VOID *Mapping
  817. )
  818. {
  819. EFI_STATUS Status;
  820. VIRTIO_1_0_DEV *Dev;
  821. Dev = VIRTIO_1_0_FROM_VIRTIO_DEVICE (This);
  822. Status = Dev->PciIo->Unmap (
  823. Dev->PciIo,
  824. Mapping
  825. );
  826. return Status;
  827. }
  828. STATIC CONST VIRTIO_DEVICE_PROTOCOL mVirtIoTemplate = {
  829. VIRTIO_SPEC_REVISION (1, 0, 0),
  830. 0, // SubSystemDeviceId, filled in dynamically
  831. Virtio10GetDeviceFeatures,
  832. Virtio10SetGuestFeatures,
  833. Virtio10SetQueueAddress,
  834. Virtio10SetQueueSel,
  835. Virtio10SetQueueNotify,
  836. Virtio10SetQueueAlign,
  837. Virtio10SetPageSize,
  838. Virtio10GetQueueNumMax,
  839. Virtio10SetQueueNum,
  840. Virtio10GetDeviceStatus,
  841. Virtio10SetDeviceStatus,
  842. Virtio10WriteDevice,
  843. Virtio10ReadDevice,
  844. Virtio10AllocateSharedPages,
  845. Virtio10FreeSharedPages,
  846. Virtio10MapSharedBuffer,
  847. Virtio10UnmapSharedBuffer
  848. };
  849. //
  850. // EFI_DRIVER_BINDING_PROTOCOL member functions
  851. //
  852. STATIC
  853. EFI_STATUS
  854. EFIAPI
  855. Virtio10BindingSupported (
  856. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  857. IN EFI_HANDLE DeviceHandle,
  858. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
  859. )
  860. {
  861. EFI_STATUS Status;
  862. EFI_PCI_IO_PROTOCOL *PciIo;
  863. PCI_TYPE00 Pci;
  864. Status = gBS->OpenProtocol (
  865. DeviceHandle,
  866. &gEfiPciIoProtocolGuid,
  867. (VOID **)&PciIo,
  868. This->DriverBindingHandle,
  869. DeviceHandle,
  870. EFI_OPEN_PROTOCOL_BY_DRIVER
  871. );
  872. if (EFI_ERROR (Status)) {
  873. return Status;
  874. }
  875. Status = PciIo->Pci.Read (
  876. PciIo,
  877. EfiPciIoWidthUint32,
  878. 0,
  879. sizeof Pci / sizeof (UINT32),
  880. &Pci
  881. );
  882. if (EFI_ERROR (Status)) {
  883. goto CloseProtocol;
  884. }
  885. Status = EFI_UNSUPPORTED;
  886. //
  887. // Recognize non-transitional modern devices. Also, we'll have to parse the
  888. // PCI capability list, so make sure the CapabilityPtr field will be valid.
  889. //
  890. if ((Pci.Hdr.VendorId == VIRTIO_VENDOR_ID) &&
  891. (Pci.Hdr.DeviceId >= 0x1040) &&
  892. (Pci.Hdr.DeviceId <= 0x107F) &&
  893. (Pci.Hdr.RevisionID >= 0x01) &&
  894. (Pci.Device.SubsystemID >= 0x40) &&
  895. ((Pci.Hdr.Status & EFI_PCI_STATUS_CAPABILITY) != 0))
  896. {
  897. //
  898. // The virtio-vga device is special. It can be driven both as a VGA device
  899. // with a linear framebuffer, and through its underlying, modern,
  900. // virtio-gpu-pci device, which has no linear framebuffer itself. For
  901. // compatibility with guest OSes that insist on inheriting a linear
  902. // framebuffer from the firmware, we should leave virtio-vga to
  903. // QemuVideoDxe, and support only virtio-gpu-pci here.
  904. //
  905. // Both virtio-vga and virtio-gpu-pci have DeviceId 0x1050, but only the
  906. // former has device class PCI_CLASS_DISPLAY_VGA.
  907. //
  908. if ((Pci.Hdr.DeviceId != 0x1050) || !IS_PCI_VGA (&Pci)) {
  909. Status = EFI_SUCCESS;
  910. }
  911. }
  912. CloseProtocol:
  913. gBS->CloseProtocol (
  914. DeviceHandle,
  915. &gEfiPciIoProtocolGuid,
  916. This->DriverBindingHandle,
  917. DeviceHandle
  918. );
  919. return Status;
  920. }
  921. STATIC
  922. EFI_STATUS
  923. EFIAPI
  924. Virtio10BindingStart (
  925. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  926. IN EFI_HANDLE DeviceHandle,
  927. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
  928. )
  929. {
  930. VIRTIO_1_0_DEV *Device;
  931. EFI_STATUS Status;
  932. PCI_TYPE00 Pci;
  933. UINT64 SetAttributes;
  934. Device = AllocateZeroPool (sizeof *Device);
  935. if (Device == NULL) {
  936. return EFI_OUT_OF_RESOURCES;
  937. }
  938. Device->Signature = VIRTIO_1_0_SIGNATURE;
  939. CopyMem (&Device->VirtIo, &mVirtIoTemplate, sizeof mVirtIoTemplate);
  940. Status = gBS->OpenProtocol (
  941. DeviceHandle,
  942. &gEfiPciIoProtocolGuid,
  943. (VOID **)&Device->PciIo,
  944. This->DriverBindingHandle,
  945. DeviceHandle,
  946. EFI_OPEN_PROTOCOL_BY_DRIVER
  947. );
  948. if (EFI_ERROR (Status)) {
  949. goto FreeDevice;
  950. }
  951. Status = Device->PciIo->Pci.Read (
  952. Device->PciIo,
  953. EfiPciIoWidthUint32,
  954. 0,
  955. sizeof Pci / sizeof (UINT32),
  956. &Pci
  957. );
  958. if (EFI_ERROR (Status)) {
  959. goto ClosePciIo;
  960. }
  961. Device->VirtIo.SubSystemDeviceId = Pci.Hdr.DeviceId - 0x1040;
  962. Status = ParseCapabilities (Device);
  963. if (EFI_ERROR (Status)) {
  964. goto ClosePciIo;
  965. }
  966. Status = Device->PciIo->Attributes (
  967. Device->PciIo,
  968. EfiPciIoAttributeOperationGet,
  969. 0,
  970. &Device->OriginalPciAttributes
  971. );
  972. if (EFI_ERROR (Status)) {
  973. goto ClosePciIo;
  974. }
  975. SetAttributes = (EFI_PCI_IO_ATTRIBUTE_BUS_MASTER |
  976. EFI_PCI_IO_ATTRIBUTE_DUAL_ADDRESS_CYCLE);
  977. UpdateAttributes (&Device->CommonConfig, &SetAttributes);
  978. UpdateAttributes (&Device->NotifyConfig, &SetAttributes);
  979. UpdateAttributes (&Device->SpecificConfig, &SetAttributes);
  980. Status = Device->PciIo->Attributes (
  981. Device->PciIo,
  982. EfiPciIoAttributeOperationEnable,
  983. SetAttributes,
  984. NULL
  985. );
  986. if (EFI_ERROR (Status)) {
  987. goto ClosePciIo;
  988. }
  989. Status = gBS->InstallProtocolInterface (
  990. &DeviceHandle,
  991. &gVirtioDeviceProtocolGuid,
  992. EFI_NATIVE_INTERFACE,
  993. &Device->VirtIo
  994. );
  995. if (EFI_ERROR (Status)) {
  996. goto RestorePciAttributes;
  997. }
  998. return EFI_SUCCESS;
  999. RestorePciAttributes:
  1000. Device->PciIo->Attributes (
  1001. Device->PciIo,
  1002. EfiPciIoAttributeOperationSet,
  1003. Device->OriginalPciAttributes,
  1004. NULL
  1005. );
  1006. ClosePciIo:
  1007. gBS->CloseProtocol (
  1008. DeviceHandle,
  1009. &gEfiPciIoProtocolGuid,
  1010. This->DriverBindingHandle,
  1011. DeviceHandle
  1012. );
  1013. FreeDevice:
  1014. FreePool (Device);
  1015. return Status;
  1016. }
  1017. STATIC
  1018. EFI_STATUS
  1019. EFIAPI
  1020. Virtio10BindingStop (
  1021. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  1022. IN EFI_HANDLE DeviceHandle,
  1023. IN UINTN NumberOfChildren,
  1024. IN EFI_HANDLE *ChildHandleBuffer
  1025. )
  1026. {
  1027. EFI_STATUS Status;
  1028. VIRTIO_DEVICE_PROTOCOL *VirtIo;
  1029. VIRTIO_1_0_DEV *Device;
  1030. Status = gBS->OpenProtocol (
  1031. DeviceHandle,
  1032. &gVirtioDeviceProtocolGuid,
  1033. (VOID **)&VirtIo,
  1034. This->DriverBindingHandle,
  1035. DeviceHandle,
  1036. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  1037. );
  1038. if (EFI_ERROR (Status)) {
  1039. return Status;
  1040. }
  1041. Device = VIRTIO_1_0_FROM_VIRTIO_DEVICE (VirtIo);
  1042. Status = gBS->UninstallProtocolInterface (
  1043. DeviceHandle,
  1044. &gVirtioDeviceProtocolGuid,
  1045. &Device->VirtIo
  1046. );
  1047. if (EFI_ERROR (Status)) {
  1048. return Status;
  1049. }
  1050. Device->PciIo->Attributes (
  1051. Device->PciIo,
  1052. EfiPciIoAttributeOperationSet,
  1053. Device->OriginalPciAttributes,
  1054. NULL
  1055. );
  1056. gBS->CloseProtocol (
  1057. DeviceHandle,
  1058. &gEfiPciIoProtocolGuid,
  1059. This->DriverBindingHandle,
  1060. DeviceHandle
  1061. );
  1062. FreePool (Device);
  1063. return EFI_SUCCESS;
  1064. }
  1065. STATIC EFI_DRIVER_BINDING_PROTOCOL mDriverBinding = {
  1066. &Virtio10BindingSupported,
  1067. &Virtio10BindingStart,
  1068. &Virtio10BindingStop,
  1069. 0x10, // Version
  1070. NULL, // ImageHandle, to be overwritten
  1071. NULL // DriverBindingHandle, to be overwritten
  1072. };
  1073. //
  1074. // EFI_COMPONENT_NAME_PROTOCOL and EFI_COMPONENT_NAME2_PROTOCOL
  1075. // implementations
  1076. //
  1077. STATIC
  1078. EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
  1079. { "eng;en", L"Virtio 1.0 PCI Driver" },
  1080. { NULL, NULL }
  1081. };
  1082. STATIC
  1083. EFI_COMPONENT_NAME_PROTOCOL mComponentName;
  1084. STATIC
  1085. EFI_STATUS
  1086. EFIAPI
  1087. Virtio10GetDriverName (
  1088. IN EFI_COMPONENT_NAME_PROTOCOL *This,
  1089. IN CHAR8 *Language,
  1090. OUT CHAR16 **DriverName
  1091. )
  1092. {
  1093. return LookupUnicodeString2 (
  1094. Language,
  1095. This->SupportedLanguages,
  1096. mDriverNameTable,
  1097. DriverName,
  1098. (BOOLEAN)(This == &mComponentName) // Iso639Language
  1099. );
  1100. }
  1101. STATIC
  1102. EFI_STATUS
  1103. EFIAPI
  1104. Virtio10GetDeviceName (
  1105. IN EFI_COMPONENT_NAME_PROTOCOL *This,
  1106. IN EFI_HANDLE DeviceHandle,
  1107. IN EFI_HANDLE ChildHandle,
  1108. IN CHAR8 *Language,
  1109. OUT CHAR16 **ControllerName
  1110. )
  1111. {
  1112. return EFI_UNSUPPORTED;
  1113. }
  1114. STATIC
  1115. EFI_COMPONENT_NAME_PROTOCOL mComponentName = {
  1116. &Virtio10GetDriverName,
  1117. &Virtio10GetDeviceName,
  1118. "eng"
  1119. };
  1120. STATIC
  1121. EFI_COMPONENT_NAME2_PROTOCOL mComponentName2 = {
  1122. (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)&Virtio10GetDriverName,
  1123. (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)&Virtio10GetDeviceName,
  1124. "en"
  1125. };
  1126. //
  1127. // Entry point of this driver
  1128. //
  1129. EFI_STATUS
  1130. EFIAPI
  1131. Virtio10EntryPoint (
  1132. IN EFI_HANDLE ImageHandle,
  1133. IN EFI_SYSTEM_TABLE *SystemTable
  1134. )
  1135. {
  1136. return EfiLibInstallDriverBindingComponentName2 (
  1137. ImageHandle,
  1138. SystemTable,
  1139. &mDriverBinding,
  1140. ImageHandle,
  1141. &mComponentName,
  1142. &mComponentName2
  1143. );
  1144. }