VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioBlkDxe/VirtioBlk.c@ 94264

Last change on this file since 94264 was 80721, checked in by vboxsync, 5 years ago

Devices/EFI/FirmwareNew: Start upgrade process to edk2-stable201908 (compiles on Windows and works to some extent), bugref:4643

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette