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