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