VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/Firmware/OvmfPkg/VirtioSerialDxe/VirtioSerial.c

最後變更 在這個檔案是 101291,由 vboxsync 提交於 14 月 前

EFI/FirmwareNew: Make edk2-stable202308 build on all supported platforms (using gcc at least, msvc not tested yet), bugref:4643

  • 屬性 svn:eol-style 設為 native
檔案大小: 20.0 KB
 
1/** @file
2
3 Driver for virtio-serial devices.
4
5 The virtio serial device also known as virtio console device because
6 initially it had only support for a single tty, intended to be used
7 as console. Support for multiple streams and named data ports has
8 been added later on.
9
10 https://docs.oasis-open.org/virtio/virtio/v1.2/cs01/virtio-v1.2-cs01.html#x1-2900003
11
12 SPDX-License-Identifier: BSD-2-Clause-Patent
13
14**/
15
16#include <Library/BaseMemoryLib.h>
17#include <Library/DebugLib.h>
18#include <Library/DevicePathLib.h>
19#include <Library/MemoryAllocationLib.h>
20#include <Library/UefiBootServicesTableLib.h>
21#include <Library/UefiLib.h>
22#include <Library/VirtioLib.h>
23
24#include "VirtioSerial.h"
25
26STATIC LIST_ENTRY mVirtioSerialList;
27
28STATIC CONST CHAR8 *EventNames[] = {
29 [VIRTIO_SERIAL_DEVICE_READY] = "device-ready",
30 [VIRTIO_SERIAL_DEVICE_ADD] = "device-add",
31 [VIRTIO_SERIAL_DEVICE_REMOVE] = "device-remove",
32 [VIRTIO_SERIAL_PORT_READY] = "port-ready",
33 [VIRTIO_SERIAL_CONSOLE_PORT] = "console-port",
34 [VIRTIO_SERIAL_RESIZE] = "resize",
35 [VIRTIO_SERIAL_PORT_OPEN] = "port-open",
36 [VIRTIO_SERIAL_PORT_NAME] = "port-name",
37};
38
39VOID
40EFIAPI
41LogDevicePath (
42 UINT32 Level,
43 const CHAR8 *Func,
44 CHAR16 *Note,
45 EFI_DEVICE_PATH_PROTOCOL *DevicePath
46 )
47{
48 CHAR16 *Str;
49
50 Str = ConvertDevicePathToText (DevicePath, FALSE, FALSE);
51 if (!Str) {
52 DEBUG ((DEBUG_INFO, "ConvertDevicePathToText failed\n"));
53 return;
54 }
55
56 DEBUG ((Level, "%a: %s%s%s\n", Func, Note ? Note : L"", Note ? L": " : L"", Str));
57 FreePool (Str);
58}
59
60EFI_STATUS
61EFIAPI
62VirtioSerialTxControl (
63 IN OUT VIRTIO_SERIAL_DEV *Dev,
64 IN UINT32 Id,
65 IN UINT16 Event,
66 IN UINT16 Value
67 )
68{
69 VIRTIO_SERIAL_CONTROL Control;
70
71 Control.Id = Id;
72 Control.Event = Event;
73 Control.Value = Value;
74
75 DEBUG ((
76 DEBUG_INFO,
77 "%a:%d: >>> event %a, port-id %d, value %d\n",
78 __func__,
79 __LINE__,
80 EventNames[Control.Event],
81 Control.Id,
82 Control.Value
83 ));
84
85 VirtioSerialRingClearTx (Dev, VIRTIO_SERIAL_Q_TX_CTRL);
86 return VirtioSerialRingSendBuffer (Dev, VIRTIO_SERIAL_Q_TX_CTRL, &Control, sizeof (Control), TRUE);
87}
88
89STATIC
90VOID
91EFIAPI
92VirtioSerialRxControl (
93 IN OUT VIRTIO_SERIAL_DEV *Dev
94 )
95{
96 UINT8 Data[CTRL_RX_BUFSIZE+1];
97 UINT32 DataSize;
98 VIRTIO_SERIAL_CONTROL Control;
99 EFI_STATUS Status;
100 BOOLEAN HasData;
101 UINT16 Ready;
102
103 for ( ; ;) {
104 HasData = VirtioSerialRingGetBuffer (Dev, VIRTIO_SERIAL_Q_RX_CTRL, Data, &DataSize);
105 if (!HasData) {
106 return;
107 }
108
109 if (DataSize < sizeof (Control)) {
110 DEBUG ((
111 DEBUG_ERROR,
112 "%a:%d: length mismatch: %d != %d\n",
113 __func__,
114 __LINE__,
115 DataSize,
116 sizeof (Control)
117 ));
118 continue;
119 }
120
121 CopyMem (&Control, Data, sizeof (Control));
122
123 if (Control.Event < ARRAY_SIZE (EventNames)) {
124 DEBUG ((
125 DEBUG_INFO,
126 "%a:%d: <<< event %a, port-id %d, value %d\n",
127 __func__,
128 __LINE__,
129 EventNames[Control.Event],
130 Control.Id,
131 Control.Value
132 ));
133 } else {
134 DEBUG ((
135 DEBUG_ERROR,
136 "%a:%d: unknown event: %d\n",
137 __func__,
138 __LINE__,
139 Control.Event
140 ));
141 }
142
143 switch (Control.Event) {
144 case VIRTIO_SERIAL_DEVICE_ADD:
145 if (Control.Id < MAX_PORTS) {
146 Status = VirtioSerialPortAdd (Dev, Control.Id);
147 Ready = (Status == EFI_SUCCESS) ? 1 : 0;
148 } else {
149 Ready = 0;
150 }
151
152 VirtioSerialTxControl (Dev, Control.Id, VIRTIO_SERIAL_PORT_READY, Ready);
153 if (Ready) {
154 Dev->NumPorts++;
155 }
156
157 break;
158 case VIRTIO_SERIAL_DEVICE_REMOVE:
159 if (Control.Id < MAX_PORTS) {
160 VirtioSerialPortRemove (Dev, Control.Id);
161 }
162
163 break;
164 case VIRTIO_SERIAL_CONSOLE_PORT:
165 if (Control.Id < MAX_PORTS) {
166 VirtioSerialPortSetConsole (Dev, Control.Id);
167 Dev->NumConsoles++;
168 }
169
170 break;
171 case VIRTIO_SERIAL_PORT_NAME:
172 if (Control.Id < MAX_PORTS) {
173 Data[DataSize] = 0;
174 VirtioSerialPortSetName (Dev, Control.Id, Data + sizeof (Control));
175 Dev->NumNamedPorts++;
176 }
177
178 break;
179 case VIRTIO_SERIAL_PORT_OPEN:
180 if (Control.Id < MAX_PORTS) {
181 VirtioSerialPortSetDeviceOpen (Dev, Control.Id, Control.Value);
182 }
183
184 break;
185 default:
186 break;
187 }
188 }
189}
190
191STATIC
192VOID
193EFIAPI
194VirtioSerialTimer (
195 IN EFI_EVENT Event,
196 IN VOID *Context
197 )
198{
199 VIRTIO_SERIAL_DEV *Dev = Context;
200
201 VirtioSerialRxControl (Dev);
202}
203
204STATIC
205VOID
206EFIAPI
207VirtioSerialUninitAllRings (
208 IN OUT VIRTIO_SERIAL_DEV *Dev
209 )
210{
211 UINT16 Index;
212
213 for (Index = 0; Index < MAX_RINGS; Index++) {
214 VirtioSerialUninitRing (Dev, Index);
215 }
216}
217
218STATIC
219EFI_STATUS
220EFIAPI
221VirtioSerialInit (
222 IN OUT VIRTIO_SERIAL_DEV *Dev
223 )
224{
225 UINT8 NextDevStat;
226 EFI_STATUS Status;
227 UINT64 Features;
228 UINTN Retries;
229
230 //
231 // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence.
232 //
233 NextDevStat = 0; // step 1 -- reset device
234 Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
235 if (EFI_ERROR (Status)) {
236 goto Failed;
237 }
238
239 NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence
240 Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
241 if (EFI_ERROR (Status)) {
242 goto Failed;
243 }
244
245 NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it
246 Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
247 if (EFI_ERROR (Status)) {
248 goto Failed;
249 }
250
251 //
252 // Set Page Size - MMIO VirtIo Specific
253 //
254 Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE);
255 if (EFI_ERROR (Status)) {
256 goto Failed;
257 }
258
259 //
260 // step 4a -- retrieve and validate features
261 //
262 Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features);
263 if (EFI_ERROR (Status)) {
264 goto Failed;
265 }
266
267 Features &= (VIRTIO_F_VERSION_1 |
268 VIRTIO_F_IOMMU_PLATFORM |
269 VIRTIO_SERIAL_F_MULTIPORT);
270
271 //
272 // In virtio-1.0, feature negotiation is expected to complete before queue
273 // discovery, and the device can also reject the selected set of features.
274 //
275 if (Dev->VirtIo->Revision >= VIRTIO_SPEC_REVISION (1, 0, 0)) {
276 Status = Virtio10WriteFeatures (Dev->VirtIo, Features, &NextDevStat);
277 if (EFI_ERROR (Status)) {
278 goto Failed;
279 }
280 }
281
282 DEBUG ((
283 DEBUG_INFO,
284 "%a:%d: features ok:%a%a%a\n",
285 __func__,
286 __LINE__,
287 (Features & VIRTIO_F_VERSION_1) ? " v1.0" : "",
288 (Features & VIRTIO_F_IOMMU_PLATFORM) ? " iommu" : "",
289 (Features & VIRTIO_SERIAL_F_MULTIPORT) ? " multiport" : ""
290 ));
291
292 if (Features & VIRTIO_SERIAL_F_MULTIPORT) {
293 Dev->VirtIo->ReadDevice (
294 Dev->VirtIo,
295 OFFSET_OF (VIRTIO_SERIAL_CONFIG, MaxPorts),
296 sizeof (Dev->Config.MaxPorts),
297 sizeof (Dev->Config.MaxPorts),
298 &Dev->Config.MaxPorts
299 );
300 DEBUG ((
301 DEBUG_INFO,
302 "%a:%d: max device ports: %d\n",
303 __func__,
304 __LINE__,
305 Dev->Config.MaxPorts
306 ));
307 }
308
309 Status = VirtioSerialInitRing (Dev, VIRTIO_SERIAL_Q_RX_CTRL, CTRL_RX_BUFSIZE);
310 if (EFI_ERROR (Status)) {
311 goto Failed;
312 }
313
314 Status = VirtioSerialInitRing (Dev, VIRTIO_SERIAL_Q_TX_CTRL, CTRL_TX_BUFSIZE);
315 if (EFI_ERROR (Status)) {
316 goto Failed;
317 }
318
319 //
320 // step 5 -- Report understood features and guest-tuneables.
321 //
322 if (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) {
323 Features &= ~(UINT64)(VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM);
324 Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features);
325 if (EFI_ERROR (Status)) {
326 goto Failed;
327 }
328 }
329
330 //
331 // step 6 -- initialization complete
332 //
333 NextDevStat |= VSTAT_DRIVER_OK;
334 Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
335 if (EFI_ERROR (Status)) {
336 goto Failed;
337 }
338
339 VirtioSerialRingFillRx (Dev, VIRTIO_SERIAL_Q_RX_CTRL);
340 VirtioSerialTxControl (Dev, 0, VIRTIO_SERIAL_DEVICE_READY, 1);
341 for (Retries = 0; Retries < 100; Retries++) {
342 gBS->Stall (1000);
343 VirtioSerialRxControl (Dev);
344 if (Dev->NumPorts && (Dev->NumConsoles + Dev->NumNamedPorts == Dev->NumPorts)) {
345 // port discovery complete
346 break;
347 }
348 }
349
350 Status = gBS->CreateEvent (
351 EVT_TIMER | EVT_NOTIFY_SIGNAL,
352 TPL_NOTIFY,
353 VirtioSerialTimer,
354 Dev,
355 &Dev->Timer
356 );
357 if (EFI_ERROR (Status)) {
358 goto Failed;
359 }
360
361 Status = gBS->SetTimer (
362 Dev->Timer,
363 TimerPeriodic,
364 EFI_TIMER_PERIOD_MILLISECONDS (10)
365 );
366 if (EFI_ERROR (Status)) {
367 goto Failed;
368 }
369
370 DEBUG ((
371 DEBUG_INFO,
372 "%a:%d: OK, %d consoles, %d named ports\n",
373 __func__,
374 __LINE__,
375 Dev->NumConsoles,
376 Dev->NumNamedPorts
377 ));
378 return EFI_SUCCESS;
379
380Failed:
381 VirtioSerialUninitAllRings (Dev);
382
383 //
384 // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device
385 // Status. VirtIo access failure here should not mask the original error.
386 //
387 NextDevStat |= VSTAT_FAILED;
388 Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat);
389
390 DEBUG ((DEBUG_INFO, "%a:%d: ERROR: %r\n", __func__, __LINE__, Status));
391 return Status; // reached only via Failed above
392}
393
394STATIC
395VOID
396EFIAPI
397VirtioSerialUninit (
398 IN OUT VIRTIO_SERIAL_DEV *Dev
399 )
400{
401 UINT32 PortId;
402
403 gBS->CloseEvent (Dev->Timer);
404
405 //
406 // Reset the virtual device -- see virtio-0.9.5, 2.2.2.1 Device Status. When
407 // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from
408 // the old comms area.
409 //
410 Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
411
412 for (PortId = 0; PortId < MAX_PORTS; PortId++) {
413 VirtioSerialPortRemove (Dev, PortId);
414 }
415
416 VirtioSerialUninitAllRings (Dev);
417}
418
419//
420// Event notification function enqueued by ExitBootServices().
421//
422
423STATIC
424VOID
425EFIAPI
426VirtioSerialExitBoot (
427 IN EFI_EVENT Event,
428 IN VOID *Context
429 )
430{
431 VIRTIO_SERIAL_DEV *Dev;
432
433 DEBUG ((DEBUG_INFO, "%a: Context=0x%p\n", __func__, Context));
434 //
435 // Reset the device. This causes the hypervisor to forget about the virtio
436 // ring.
437 //
438 // We allocated said ring in EfiBootServicesData type memory, and code
439 // executing after ExitBootServices() is permitted to overwrite it.
440 //
441 Dev = Context;
442 Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0);
443}
444
445STATIC
446VIRTIO_SERIAL_DEV *
447VirtioSerialFind (
448 EFI_HANDLE DeviceHandle
449 )
450{
451 VIRTIO_SERIAL_DEV *Dev;
452 LIST_ENTRY *Entry;
453
454 BASE_LIST_FOR_EACH (Entry, &mVirtioSerialList) {
455 Dev = CR (Entry, VIRTIO_SERIAL_DEV, Link, VIRTIO_SERIAL_SIG);
456 if (DeviceHandle == Dev->DeviceHandle) {
457 return Dev;
458 }
459 }
460 return NULL;
461}
462
463//
464// Probe, start and stop functions of this driver, called by the DXE core for
465// specific devices.
466//
467// The following specifications document these interfaces:
468// - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol
469// - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol
470//
471// The implementation follows:
472// - Driver Writer's Guide for UEFI 2.3.1 v1.01
473// - 5.1.3.4 OpenProtocol() and CloseProtocol()
474// - UEFI Spec 2.3.1 + Errata C
475// - 6.3 Protocol Handler Services
476//
477
478STATIC
479EFI_STATUS
480EFIAPI
481VirtioSerialDriverBindingSupported (
482 IN EFI_DRIVER_BINDING_PROTOCOL *This,
483 IN EFI_HANDLE DeviceHandle,
484 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
485 )
486{
487 EFI_STATUS Status;
488 VIRTIO_DEVICE_PROTOCOL *VirtIo;
489
490 //
491 // Attempt to open the device with the VirtIo set of interfaces. On success,
492 // the protocol is "instantiated" for the VirtIo device. Covers duplicate
493 // open attempts (EFI_ALREADY_STARTED).
494 //
495 Status = gBS->OpenProtocol (
496 DeviceHandle, // candidate device
497 &gVirtioDeviceProtocolGuid, // for generic VirtIo access
498 (VOID **)&VirtIo, // handle to instantiate
499 This->DriverBindingHandle, // requestor driver identity
500 DeviceHandle, // ControllerHandle, according to
501 // the UEFI Driver Model
502 EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive VirtIo access to
503 // the device; to be released
504 );
505 if (EFI_ERROR (Status)) {
506 return Status;
507 }
508
509 if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_CONSOLE) {
510 Status = EFI_UNSUPPORTED;
511 }
512
513 //
514 // We needed VirtIo access only transitorily, to see whether we support the
515 // device or not.
516 //
517 gBS->CloseProtocol (
518 DeviceHandle,
519 &gVirtioDeviceProtocolGuid,
520 This->DriverBindingHandle,
521 DeviceHandle
522 );
523 return Status;
524}
525
526STATIC
527EFI_STATUS
528EFIAPI
529VirtioSerialDriverBindingStart (
530 IN EFI_DRIVER_BINDING_PROTOCOL *This,
531 IN EFI_HANDLE DeviceHandle,
532 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
533 )
534{
535 VIRTIO_SERIAL_DEV *Dev;
536 EFI_STATUS Status;
537
538 Dev = (VIRTIO_SERIAL_DEV *)AllocateZeroPool (sizeof *Dev);
539 if (Dev == NULL) {
540 return EFI_OUT_OF_RESOURCES;
541 }
542
543 Status = gBS->OpenProtocol (
544 DeviceHandle,
545 &gEfiDevicePathProtocolGuid,
546 (VOID **)&Dev->DevicePath,
547 This->DriverBindingHandle,
548 DeviceHandle,
549 EFI_OPEN_PROTOCOL_GET_PROTOCOL
550 );
551 if (EFI_ERROR (Status)) {
552 goto FreeVirtioSerial;
553 }
554
555 Status = gBS->OpenProtocol (
556 DeviceHandle,
557 &gVirtioDeviceProtocolGuid,
558 (VOID **)&Dev->VirtIo,
559 This->DriverBindingHandle,
560 DeviceHandle,
561 EFI_OPEN_PROTOCOL_BY_DRIVER
562 );
563 if (EFI_ERROR (Status)) {
564 goto FreeVirtioSerial;
565 }
566
567 LogDevicePath (DEBUG_INFO, __func__, L"Dev", Dev->DevicePath);
568
569 //
570 // VirtIo access granted, configure virtio-serial device.
571 //
572 Dev->Signature = VIRTIO_SERIAL_SIG;
573 Dev->DriverBindingHandle = This->DriverBindingHandle;
574 Dev->DeviceHandle = DeviceHandle;
575 Status = VirtioSerialInit (Dev);
576 if (EFI_ERROR (Status)) {
577 goto CloseVirtIo;
578 }
579
580 Status = gBS->CreateEvent (
581 EVT_SIGNAL_EXIT_BOOT_SERVICES,
582 TPL_CALLBACK,
583 &VirtioSerialExitBoot,
584 Dev,
585 &Dev->ExitBoot
586 );
587 if (EFI_ERROR (Status)) {
588 goto UninitDev;
589 }
590
591 InsertTailList (&mVirtioSerialList, &(Dev->Link));
592 return EFI_SUCCESS;
593
594UninitDev:
595 VirtioSerialUninit (Dev);
596
597CloseVirtIo:
598 gBS->CloseProtocol (
599 DeviceHandle,
600 &gVirtioDeviceProtocolGuid,
601 This->DriverBindingHandle,
602 DeviceHandle
603 );
604
605FreeVirtioSerial:
606 FreePool (Dev);
607
608 return Status;
609}
610
611STATIC
612EFI_STATUS
613EFIAPI
614VirtioSerialDriverBindingStop (
615 IN EFI_DRIVER_BINDING_PROTOCOL *This,
616 IN EFI_HANDLE DeviceHandle,
617 IN UINTN NumberOfChildren,
618 IN EFI_HANDLE *ChildHandleBuffer
619 )
620{
621 VIRTIO_SERIAL_DEV *Dev;
622 UINT32 PortId;
623 UINT32 Child;
624
625 Dev = VirtioSerialFind (DeviceHandle);
626 if (!Dev) {
627 return EFI_SUCCESS;
628 }
629
630 if (NumberOfChildren) {
631 for (Child = 0; Child < NumberOfChildren; Child++) {
632 DEBUG ((DEBUG_INFO, "%a:%d: child handle 0x%x\n", __func__, __LINE__, ChildHandleBuffer[Child]));
633 for (PortId = 0; PortId < MAX_PORTS; PortId++) {
634 if (Dev->Ports[PortId].Ready &&
635 Dev->Ports[PortId].SerialIo &&
636 (Dev->Ports[PortId].SerialIo->DeviceHandle == ChildHandleBuffer[Child]))
637 {
638 VirtioSerialPortRemove (Dev, PortId);
639 }
640 }
641 }
642
643 return EFI_SUCCESS;
644 }
645
646 DEBUG ((DEBUG_INFO, "%a:%d: controller handle 0x%x\n", __func__, __LINE__, DeviceHandle));
647
648 gBS->CloseEvent (Dev->ExitBoot);
649
650 VirtioSerialUninit (Dev);
651
652 gBS->CloseProtocol (
653 DeviceHandle,
654 &gVirtioDeviceProtocolGuid,
655 This->DriverBindingHandle,
656 DeviceHandle
657 );
658
659 RemoveEntryList (&(Dev->Link));
660 ZeroMem (Dev, sizeof (*Dev));
661 FreePool (Dev);
662
663 return EFI_SUCCESS;
664}
665
666//
667// The static object that groups the Supported() (ie. probe), Start() and
668// Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Errata
669// C, 10.1 EFI Driver Binding Protocol.
670//
671STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = {
672 &VirtioSerialDriverBindingSupported,
673 &VirtioSerialDriverBindingStart,
674 &VirtioSerialDriverBindingStop,
675 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers
676 NULL, // ImageHandle, to be overwritten by
677 // EfiLibInstallDriverBindingComponentName2() in VirtioSerialEntryPoint()
678 NULL // DriverBindingHandle, ditto
679};
680
681//
682// The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL and
683// EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's name
684// in English, for display on standard console devices. This is recommended for
685// UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Writer's
686// Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names.
687//
688
689STATIC
690EFI_UNICODE_STRING_TABLE mDriverNameTable[] = {
691 { "eng;en", L"Virtio Serial Driver" },
692 { NULL, NULL }
693};
694
695STATIC
696EFI_UNICODE_STRING_TABLE mDeviceNameTable[] = {
697 { "eng;en", L"Virtio Serial Device" },
698 { NULL, NULL }
699};
700
701STATIC
702EFI_UNICODE_STRING_TABLE mPortNameTable[] = {
703 { "eng;en", L"Virtio Serial Port" },
704 { NULL, NULL }
705};
706
707STATIC
708EFI_COMPONENT_NAME_PROTOCOL gComponentName;
709
710STATIC
711EFI_STATUS
712EFIAPI
713VirtioSerialGetDriverName (
714 IN EFI_COMPONENT_NAME_PROTOCOL *This,
715 IN CHAR8 *Language,
716 OUT CHAR16 **DriverName
717 )
718{
719 return LookupUnicodeString2 (
720 Language,
721 This->SupportedLanguages,
722 mDriverNameTable,
723 DriverName,
724 (BOOLEAN)(This == &gComponentName) // Iso639Language
725 );
726}
727
728STATIC
729EFI_STATUS
730EFIAPI
731VirtioSerialGetDeviceName (
732 IN EFI_COMPONENT_NAME_PROTOCOL *This,
733 IN EFI_HANDLE DeviceHandle,
734 IN EFI_HANDLE ChildHandle,
735 IN CHAR8 *Language,
736 OUT CHAR16 **ControllerName
737 )
738{
739 EFI_UNICODE_STRING_TABLE *Table;
740 VIRTIO_SERIAL_DEV *Dev;
741 UINT32 PortId;
742
743 Dev = VirtioSerialFind (DeviceHandle);
744 if (!Dev) {
745 return EFI_UNSUPPORTED;
746 }
747
748 if (ChildHandle) {
749 for (PortId = 0; PortId < MAX_PORTS; PortId++) {
750 if (Dev->Ports[PortId].Ready &&
751 Dev->Ports[PortId].SerialIo &&
752 (Dev->Ports[PortId].SerialIo->DeviceHandle == ChildHandle))
753 {
754 *ControllerName = Dev->Ports[PortId].Name;
755 return EFI_SUCCESS;
756 }
757 }
758
759 Table = mPortNameTable;
760 } else {
761 Table = mDeviceNameTable;
762 }
763
764 return LookupUnicodeString2 (
765 Language,
766 This->SupportedLanguages,
767 Table,
768 ControllerName,
769 (BOOLEAN)(This == &gComponentName)
770 );
771}
772
773STATIC
774EFI_COMPONENT_NAME_PROTOCOL gComponentName = {
775 &VirtioSerialGetDriverName,
776 &VirtioSerialGetDeviceName,
777 "eng" // SupportedLanguages, ISO 639-2 language codes
778};
779
780STATIC
781EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = {
782 (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)&VirtioSerialGetDriverName,
783 (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)&VirtioSerialGetDeviceName,
784 "en" // SupportedLanguages, RFC 4646 language codes
785};
786
787//
788// Entry point of this driver.
789//
790EFI_STATUS
791EFIAPI
792VirtioSerialEntryPoint (
793 IN EFI_HANDLE ImageHandle,
794 IN EFI_SYSTEM_TABLE *SystemTable
795 )
796{
797 InitializeListHead (&mVirtioSerialList);
798 return EfiLibInstallDriverBindingComponentName2 (
799 ImageHandle,
800 SystemTable,
801 &gDriverBinding,
802 ImageHandle,
803 &gComponentName,
804 &gComponentName2
805 );
806}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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