VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/OvmfPkg/VirtioBlkDxe/VirtioBlk.c@ 77662

Last change on this file since 77662 was 77662, checked in by vboxsync, 6 years ago

EFI: First step in UDK2018 merge. Does not build yet.

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