Date   

Re: [PATCH] NetworkPkg/Ip6Dxe: Fix ASSERT logic in Ip6ProcessRouterAdvertise()

Laszlo Ersek
 

Hi Maciej,

On 04/01/20 11:53, Maciej Rabeda wrote:
This patch fixes reversed logic of recently added ASSERTs which should
ensure that Ip6IsNDOptionValid() implementation properly reacts to invalid
packets.

Cc: Jiaxin Wu <jiaxin.wu@...>
Cc: Siyuan Fu <siyuan.fu@...>
Signed-off-by: Maciej Rabeda <maciej.rabeda@...>
Tested-by: Laszlo Ersek <lersek@...>
---
NetworkPkg/Ip6Dxe/Ip6Nd.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
Thanks for the patch. Two meta-suggestions:

(1) we should do one of the following:

(1a) Create a new BZ for this issue, cross-link it -- via the See Also
field -- with TianoCore#2174, and reference the new BZ in this commit
message. If we file this new BZ, it should get the Regression keyword.

(1b) Or else we should reopen TianoCore#2174, and reference *that* BZ in
this commit message.

(2) Independently of (1), the commit message should carry the following tag:

Fixes: 9c20342eed70ec99ec50cd73cb81804299f05403

Regarding this patch, the above updates only affect the commit message,
so I'm not asking for a v2 -- you can implement the commit message
changes right before pushing.

Thanks!
Laszlo



diff --git a/NetworkPkg/Ip6Dxe/Ip6Nd.c b/NetworkPkg/Ip6Dxe/Ip6Nd.c
index fd7f60b2f92c..0780a98cb325 100644
--- a/NetworkPkg/Ip6Dxe/Ip6Nd.c
+++ b/NetworkPkg/Ip6Dxe/Ip6Nd.c
@@ -2111,7 +2111,7 @@ Ip6ProcessRouterAdvertise (
// Option size validity ensured by Ip6IsNDOptionValid().
//
ASSERT (LinkLayerOption.Length != 0);
- ASSERT (Offset + (UINT32) LinkLayerOption.Length * 8 >= (UINT32) Head->PayloadLength);
+ ASSERT (Offset + (UINT32) LinkLayerOption.Length * 8 <= (UINT32) Head->PayloadLength);

ZeroMem (&LinkLayerAddress, sizeof (EFI_MAC_ADDRESS));
CopyMem (&LinkLayerAddress, LinkLayerOption.EtherAddr, 6);
@@ -2164,7 +2164,7 @@ Ip6ProcessRouterAdvertise (
// Option size validity ensured by Ip6IsNDOptionValid().
//
ASSERT (PrefixOption.Length == 4);
- ASSERT (Offset + (UINT32) PrefixOption.Length * 8 >= (UINT32) Head->PayloadLength);
+ ASSERT (Offset + (UINT32) PrefixOption.Length * 8 <= (UINT32) Head->PayloadLength);

PrefixOption.ValidLifetime = NTOHL (PrefixOption.ValidLifetime);
PrefixOption.PreferredLifetime = NTOHL (PrefixOption.PreferredLifetime);
@@ -2334,7 +2334,7 @@ Ip6ProcessRouterAdvertise (
// Option size validity ensured by Ip6IsNDOptionValid().
//
ASSERT (MTUOption.Length == 1);
- ASSERT (Offset + (UINT32) MTUOption.Length * 8 >= (UINT32) Head->PayloadLength);
+ ASSERT (Offset + (UINT32) MTUOption.Length * 8 <= (UINT32) Head->PayloadLength);

//
// Use IPv6 minimum link MTU 1280 bytes as the maximum packet size in order


Re: [PATCH] OvmfPkg/PvScsiDxe: Fix VS2019 build error because of implicit cast

Laszlo Ersek
 

On 04/01/20 10:50, Ard Biesheuvel wrote:
On Wed, 1 Apr 2020 at 10:37, Laszlo Ersek <lersek@...> wrote:

On 04/01/20 00:17, Liran Alon wrote:

I would also mention that there are some bizzare code in EDK2 that
defines it's own ASSERT() macro that just does CpuDeadLoop(). E.g.
ArmVirtPkg/Library/ArmVirtDxeHobLib/HobLib.c
This is a very special case.

Please see the justification in commit ad90df8ac018
("ArmPlatformPkg/ArmVirtualizationPkg: Add private HobLib implementation
for DXE phase", 2014-09-18).

The stock HobLib instance depends on DebugLib, for using the normal
ASSERT() macro.

Furthermore, the stock serial-based DebugLib instance depends on
SerialPortLib, for printing messages.

That produces a HobLib -> DebugLib -> SerialPortLib dependency chain.

But, in case of this particular platform, our SerialPortLib instance
depends on HobLib, for retrieving the particulars of the serial port.
This creates a dependency cycle:

HobLib -> DebugLib -> SerialPortLib -> HobLib

which makes the platform un-buildable.

We had to break the dependency cycle somewhere, and the best (or maybe
only -- I don't recall exactly anymore) link to break was the HobLib ->
DebugLib dependency. We introduced our own HobLib instance, which (IIRC)
was almost identical to the stock one, except that its (only) DebugLib
dependency, namely the ASSERT(), was reimplemented with a plain
CpuDeadLoop(). And so the dependency chain ended up as:

DebugLib -> SerialPortLib -> HobLib

Not circular any more.

and OvmfPkg/Library/XenConsoleSerialPortLib/XenConsoleSerialPortLib.c)
Very similar same case; here we even have a comment:

//
// We can't use DebugLib due to a constructor dependency cycle between DebugLib
// and ourselves.
//

The BaseDebugLibSerialPort instance depends on SerialPortLib, so a
SerialPortLib instance cannot "depend back" on DebugLib, in combination
with BaseDebugLibSerialPort.
There's an additional problem in EDK2 that we never fixed, which is
the fact that constructor dependencies are not transitive across
library implementations that don't have a constructor themselves. For
instance, in the following case

LibA (+)
depends on
LibB (-)
depends on
LibC (+)

where (+) means 'has constructor' and (-) means 'has no constructor',
the EDK2 build tools may emit the LibA and LibC constructor
invocations in any order. However, as soon as you try to fix this, we
end up with circular dependencies all over the place, and none of the
platforms can be built anymore.
Yes, I've been aware of this; I've thought about it for a few minutes
just the other day. I was considering yet another "dynamic PCD setter"
NULL-class library instance, to be linked into various DXE modules.
Given the above problem, I figured if I ever started work on said lib
instance, I'd probably give it an empty CONSTRUCTOR -- not because that
function would have to do anything, but because the lib instance would
likely depend on other libraries, and *those* lib instances might have
important CONSTRUCTORs. And I wouldn't want this new lib instance to
break the dependency chain in the middle.

So in practice, all new lib instances seem to need CONSTRUCTORs now
(even if they are empty), just to avoid the problem you mention. And if
there is a build failure (circular dependency), try to deal with that on
a case by case basis.

(I admit that I didn't remember that we had tried fixing the problem in
BaseTools, and given up because of a multitude of sudden circular
dependencies! Thanks for the reminder!)

Thanks!
Laszlo


Re: [PATCH v2] OvmfPkg/PvScsiDxe: Refactor setup of rings to separate function

Liran Alon
 

On 01/04/2020 13:41, Laszlo Ersek wrote:
On 04/01/20 00:56, Liran Alon wrote:

+ //
+ // Setup rings against device
+ //
+ Status = PvScsiSetupRings (Dev);
+ if (EFI_ERROR (Status)) {
+ goto FreeDMACommBuffer;
I'm going to rename this label to "FreeDmaCommBuffer" upon pushing (due
to de-capitalization of acronyms in edk2 CamelCase).
Thanks. Will note this for next time.

-Liran


Reviewed-by: Laszlo Ersek <lersek@...>

Thank you!
Laszlo


Re: [PATCH] OvmfPkg/PvScsiDxe: Fix VS2019 build error because of implicit cast

Laszlo Ersek
 

On 04/01/20 00:54, Sean via Groups.Io wrote:
I agree that safeintlib is not doing anything too interesting in this case but that's not really the point.  The argument for it is that it becomes the central point of code to check for safe conversions and an indicator that the developer was thoughtful about this conversion and didn't just cast to avoid the compiler complaining.  If everyone starts putting their own checks in place it leads to more code reviews, diversity in solutions, and opportunities for bugs.  All that said those are soft reasons for the change and that is up to you.

@Laszlo - On the ASSERT part, I have a different view point and am more curious about yours.  For release builds, I don't want to see CpuDeadLoops anywhere unless I am ok with the device being returned/refunded.  Our error path would be to exit the function with an error code and potentially log a ReportStatusCode.   I don't think you should continue in an invalid state as that just makes resolving the bug much much harder.    Given that the system can boot to at least a menu without this driver, it seems that failing out of the function would provide a better "RELEASE" experience.
Good points!

(1) There is a big difference between physical firmware and virtual
firmware. Similar difference between physical hardware and virtual
hardware. With virtualization, the "return/refund" case maps to "fix
OVMF, or fix QEMU". In particular the "fix QEMU" part is important,
because the assertion failure would show that QEMU is really broken, and
needs fixing. Thankfully, QEMU is fixable, and in that case, it *should*
be fixed; the "return/refund" path is both the right one, and not as
painful as with physical devices.

To exaggerate your point a bit, I would agree that ASSERT()s have no
place in space-craft software! :)

(2) I have actually considered -- at length -- returning an error code
from this function, instead of the failed assert / CpuDeadLoop(). The
error code from this function would be propagated out through the ext
scsi PassThru method. For that reason, I reviewed the error codes
defined for that protocol member function in the UEFI spec. All error
codes except EFI_TIMEOUT claim that "the SCSI operation was not sent /
not executed", therefore they do not apply in this case -- per spec, we
could only return EFI_TIMEOUT in case we fail to understand the PVSCSI
device model's response (because the device breaks "data sheet
compliance"). While I do think EFI_TIMEOUT is a *good* error code in
this case ultimately -- it shows that we simply can't tell whatever
happened on the device's side --, I figured (given point (1)) it would
be a very unwelcome complication for the code. Because upon returning
EFI_TIMEOUT, we also have to set HostAdapterStatus / TargetStatus to
something sensible (i.e., "fake"), and SenseDataLength to zero. Doable,
but didn't seem worth the churn.

(3) In RHEL OVMF packages, I exclusively ship DEBUG builds. For two
reasons: (a) many places in edk2 core code still use ASSERT() in place
of run-of-the-mill error checking (unfortunately), i.e., not explicit
"if"s; (b) bugs in software are the norm, not the exception, therefore
IMO debugging features should be an unalienable part of every software
package ever shipped to users. (If I could by my consumer electronics /
gadgets with full debug code enabled, I would, too.) When a RHEL user
reports an error, I don't want to start every one of my analyses with
the question, "can you please reproduce this with a debug build first".

I'm aware that debug code has additional cost (larger code size, perhaps
more CPU cycles spent, which is especially important on mobile devices,
yes). In my use case, the slowdown is not egregious -- first, most of
the boot time impact due to DEBUGs can be attributed to QEMU IO port
accesses, and that port is dynamically configurable (disabled by
default), so if it's not enabled, there's virtually no impact; second,
there don't seem to be insanely costly invariant checks built into OVMF
for the DEBUG target either. So I'm consciously committed to shipping
DEBUG only, and I admit that it does bias my thinking about RELEASE --
not that I'm against RELEASE *in general* for edk2, or ignoring RELEASE
willfully, it's just that I likely have blind spots wrt. RELEASE builds.


Finally, given that this is contained in OVMF I am fine with whatever makes the most sense for your platform and usecase.
Thanks a lot for confirming! In this case I'll go ahead with this patch.

Thanks!
Laszlo


Re: [PATCH v2] OvmfPkg/PvScsiDxe: Refactor setup of rings to separate function

Laszlo Ersek
 

On 04/01/20 00:56, Liran Alon wrote:
Previous to this change, PvScsiFreeRings() was not undoing all
operations that was done by PvScsiInitRings().
This is because PvScsiInitRings() was both preparing rings (Allocate
memory and map it for device DMA) and setup the rings against device by
issueing a device command. While PvScsiFreeRings() only unmaps the rings
and free their memory.

Driver do not have a functional error as it makes sure to reset device
before every call site to PvScsiFreeRings(). However, this is not
intuitive.

Therefore, prefer to refactor the setup of the ring against device to a
separate function than PvScsiInitRings().

Signed-off-by: Liran Alon <liran.alon@...>
---
OvmfPkg/PvScsiDxe/PvScsi.c | 163 +++++++++++++++++++------------------
1 file changed, 85 insertions(+), 78 deletions(-)

diff --git a/OvmfPkg/PvScsiDxe/PvScsi.c b/OvmfPkg/PvScsiDxe/PvScsi.c
index 1ca50390c0e5..8c458ecceeb0 100644
--- a/OvmfPkg/PvScsiDxe/PvScsi.c
+++ b/OvmfPkg/PvScsiDxe/PvScsi.c
@@ -991,13 +991,6 @@ PvScsiInitRings (
)
{
EFI_STATUS Status;
- union {
- PVSCSI_CMD_DESC_SETUP_RINGS Cmd;
- UINT32 Uint32;
- } AlignedCmd;
- PVSCSI_CMD_DESC_SETUP_RINGS *Cmd;
-
- Cmd = &AlignedCmd.Cmd;

Status = PvScsiAllocateSharedPages (
Dev,
@@ -1032,6 +1025,69 @@ PvScsiInitRings (
}
ZeroMem (Dev->RingDesc.RingCmps, EFI_PAGE_SIZE);

+ return EFI_SUCCESS;
+
+FreeRingReqs:
+ PvScsiFreeSharedPages (
+ Dev,
+ 1,
+ Dev->RingDesc.RingReqs,
+ &Dev->RingDesc.RingReqsDmaDesc
+ );
+
+FreeRingState:
+ PvScsiFreeSharedPages (
+ Dev,
+ 1,
+ Dev->RingDesc.RingState,
+ &Dev->RingDesc.RingStateDmaDesc
+ );
+
+ return Status;
+}
+
+STATIC
+VOID
+PvScsiFreeRings (
+ IN OUT PVSCSI_DEV *Dev
+ )
+{
+ PvScsiFreeSharedPages (
+ Dev,
+ 1,
+ Dev->RingDesc.RingCmps,
+ &Dev->RingDesc.RingCmpsDmaDesc
+ );
+
+ PvScsiFreeSharedPages (
+ Dev,
+ 1,
+ Dev->RingDesc.RingReqs,
+ &Dev->RingDesc.RingReqsDmaDesc
+ );
+
+ PvScsiFreeSharedPages (
+ Dev,
+ 1,
+ Dev->RingDesc.RingState,
+ &Dev->RingDesc.RingStateDmaDesc
+ );
+}
+
+STATIC
+EFI_STATUS
+PvScsiSetupRings (
+ IN OUT PVSCSI_DEV *Dev
+ )
+{
+ union {
+ PVSCSI_CMD_DESC_SETUP_RINGS Cmd;
+ UINT32 Uint32;
+ } AlignedCmd;
+ PVSCSI_CMD_DESC_SETUP_RINGS *Cmd;
+
+ Cmd = &AlignedCmd.Cmd;
+
ZeroMem (Cmd, sizeof (*Cmd));
Cmd->ReqRingNumPages = 1;
Cmd->CmpRingNumPages = 1;
@@ -1052,71 +1108,12 @@ PvScsiInitRings (
sizeof (*Cmd) % sizeof (UINT32) == 0,
"Cmd must be multiple of 32-bit words"
);
- Status = PvScsiWriteCmdDesc (
- Dev,
- PvScsiCmdSetupRings,
- (UINT32 *)Cmd,
- sizeof (*Cmd) / sizeof (UINT32)
- );
- if (EFI_ERROR (Status)) {
- goto FreeRingCmps;
- }
-
- return EFI_SUCCESS;
-
-FreeRingCmps:
- PvScsiFreeSharedPages (
- Dev,
- 1,
- Dev->RingDesc.RingCmps,
- &Dev->RingDesc.RingCmpsDmaDesc
- );
-
-FreeRingReqs:
- PvScsiFreeSharedPages (
- Dev,
- 1,
- Dev->RingDesc.RingReqs,
- &Dev->RingDesc.RingReqsDmaDesc
- );
-
-FreeRingState:
- PvScsiFreeSharedPages (
- Dev,
- 1,
- Dev->RingDesc.RingState,
- &Dev->RingDesc.RingStateDmaDesc
- );
-
- return Status;
-}
-
-STATIC
-VOID
-PvScsiFreeRings (
- IN OUT PVSCSI_DEV *Dev
- )
-{
- PvScsiFreeSharedPages (
- Dev,
- 1,
- Dev->RingDesc.RingCmps,
- &Dev->RingDesc.RingCmpsDmaDesc
- );
-
- PvScsiFreeSharedPages (
- Dev,
- 1,
- Dev->RingDesc.RingReqs,
- &Dev->RingDesc.RingReqsDmaDesc
- );
-
- PvScsiFreeSharedPages (
- Dev,
- 1,
- Dev->RingDesc.RingState,
- &Dev->RingDesc.RingStateDmaDesc
- );
+ return PvScsiWriteCmdDesc (
+ Dev,
+ PvScsiCmdSetupRings,
+ (UINT32 *)Cmd,
+ sizeof (*Cmd) / sizeof (UINT32)
+ );
}

STATIC
@@ -1171,6 +1168,14 @@ PvScsiInit (
goto FreeRings;
}

+ //
+ // Setup rings against device
+ //
+ Status = PvScsiSetupRings (Dev);
+ if (EFI_ERROR (Status)) {
+ goto FreeDMACommBuffer;
I'm going to rename this label to "FreeDmaCommBuffer" upon pushing (due
to de-capitalization of acronyms in edk2 CamelCase).

Reviewed-by: Laszlo Ersek <lersek@...>

Thank you!
Laszlo

+ }
+
//
// Populate the exported interface's attributes
//
@@ -1202,13 +1207,15 @@ PvScsiInit (

return EFI_SUCCESS;

+FreeDMACommBuffer:
+ PvScsiFreeSharedPages (
+ Dev,
+ EFI_SIZE_TO_PAGES (sizeof (*Dev->DmaBuf)),
+ Dev->DmaBuf,
+ &Dev->DmaBufDmaDesc
+ );
+
FreeRings:
- //
- // Reset device to stop device usage of the rings.
- // This is required to safely free the rings.
- //
- PvScsiResetAdapter (Dev);
-
PvScsiFreeRings (Dev);

RestorePciAttributes:


Re: [PATCH v2 14/28] Platform/NXP: rename the ArmPlatformLib as per ArmPlatformPkg

Leif Lindholm
 

On Fri, Mar 20, 2020 at 20:05:29 +0530, Pankaj Bansal wrote:
From: Pankaj Bansal <pankaj.bansal@...>

Keep the names and location of files as mentioned in ArmPlatformPkg.
This helps in porting the common changes (if any in future) easily.

Signed-off-by: Pankaj Bansal <pankaj.bansal@...>
Reviewed-by: Leif Lindholm <leif@...>

---
Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc | 2 +-
.../AArch64/ArmPlatformHelper.S} | 2 +-
.../Library/{PlatformLib => ArmPlatformLib}/ArmPlatformLib.c | 2 +-
.../{PlatformLib => ArmPlatformLib}/ArmPlatformLib.inf | 4 ++--
.../NxpQoriqLsMem.c => ArmPlatformLib/ArmPlatformLibMem.c} | 0
5 files changed, 5 insertions(+), 5 deletions(-)
rename Platform/NXP/LS1043aRdbPkg/Library/{PlatformLib/NxpQoriqLsHelper.S => ArmPlatformLib/AArch64/ArmPlatformHelper.S} (88%)
rename Platform/NXP/LS1043aRdbPkg/Library/{PlatformLib => ArmPlatformLib}/ArmPlatformLib.c (93%)
rename Platform/NXP/LS1043aRdbPkg/Library/{PlatformLib => ArmPlatformLib}/ArmPlatformLib.inf (89%)
rename Platform/NXP/LS1043aRdbPkg/Library/{PlatformLib/NxpQoriqLsMem.c => ArmPlatformLib/ArmPlatformLibMem.c} (100%)

diff --git a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
index 1975f2c4c52c..e5383aaf0cc5 100644
--- a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
+++ b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
@@ -26,7 +26,7 @@ [Defines]
!include Silicon/NXP/LS1043A/LS1043A.dsc.inc

[LibraryClasses.common]
- ArmPlatformLib|Platform/NXP/LS1043aRdbPkg/Library/PlatformLib/ArmPlatformLib.inf
+ ArmPlatformLib|Platform/NXP/LS1043aRdbPkg/Library/ArmPlatformLib/ArmPlatformLib.inf
RealTimeClockLib|Silicon/Maxim/Library/Ds1307RtcLib/Ds1307RtcLib.inf

[PcdsFixedAtBuild.common]
diff --git a/Platform/NXP/LS1043aRdbPkg/Library/PlatformLib/NxpQoriqLsHelper.S b/Platform/NXP/LS1043aRdbPkg/Library/ArmPlatformLib/AArch64/ArmPlatformHelper.S
similarity index 88%
rename from Platform/NXP/LS1043aRdbPkg/Library/PlatformLib/NxpQoriqLsHelper.S
rename to Platform/NXP/LS1043aRdbPkg/Library/ArmPlatformLib/AArch64/ArmPlatformHelper.S
index 84ee8c9f9700..dfbf73675a2d 100644
--- a/Platform/NXP/LS1043aRdbPkg/Library/PlatformLib/NxpQoriqLsHelper.S
+++ b/Platform/NXP/LS1043aRdbPkg/Library/ArmPlatformLib/AArch64/ArmPlatformHelper.S
@@ -1,7 +1,7 @@
# @file
#
# Copyright (c) 2012-2013, ARM Limited. All rights reserved.
-# Copyright 2017 NXP
+# Copyright 2017, 2020 NXP
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
diff --git a/Platform/NXP/LS1043aRdbPkg/Library/PlatformLib/ArmPlatformLib.c b/Platform/NXP/LS1043aRdbPkg/Library/ArmPlatformLib/ArmPlatformLib.c
similarity index 93%
rename from Platform/NXP/LS1043aRdbPkg/Library/PlatformLib/ArmPlatformLib.c
rename to Platform/NXP/LS1043aRdbPkg/Library/ArmPlatformLib/ArmPlatformLib.c
index eac7d4aa4e47..718c71bf02eb 100644
--- a/Platform/NXP/LS1043aRdbPkg/Library/PlatformLib/ArmPlatformLib.c
+++ b/Platform/NXP/LS1043aRdbPkg/Library/ArmPlatformLib/ArmPlatformLib.c
@@ -6,7 +6,7 @@
*
* Copyright (c) 2011-2012, ARM Limited. All rights reserved.
* Copyright (c) 2016, Freescale Semiconductor, Inc. All rights reserved.
-* Copyright 2017 NXP
+* Copyright 2017, 2020 NXP
* SPDX-License-Identifier: BSD-2-Clause-Patent
*
**/
diff --git a/Platform/NXP/LS1043aRdbPkg/Library/PlatformLib/ArmPlatformLib.inf b/Platform/NXP/LS1043aRdbPkg/Library/ArmPlatformLib/ArmPlatformLib.inf
similarity index 89%
rename from Platform/NXP/LS1043aRdbPkg/Library/PlatformLib/ArmPlatformLib.inf
rename to Platform/NXP/LS1043aRdbPkg/Library/ArmPlatformLib/ArmPlatformLib.inf
index 7563a1c43630..7a43ad86d183 100644
--- a/Platform/NXP/LS1043aRdbPkg/Library/PlatformLib/ArmPlatformLib.inf
+++ b/Platform/NXP/LS1043aRdbPkg/Library/ArmPlatformLib/ArmPlatformLib.inf
@@ -27,8 +27,8 @@ [LibraryClasses]
SocLib

[Sources.common]
- NxpQoriqLsHelper.S | GCC
- NxpQoriqLsMem.c
+ AArch64/ArmPlatformHelper.S | GCC
+ ArmPlatformLibMem.c
ArmPlatformLib.c

[Ppis]
diff --git a/Platform/NXP/LS1043aRdbPkg/Library/PlatformLib/NxpQoriqLsMem.c b/Platform/NXP/LS1043aRdbPkg/Library/ArmPlatformLib/ArmPlatformLibMem.c
similarity index 100%
rename from Platform/NXP/LS1043aRdbPkg/Library/PlatformLib/NxpQoriqLsMem.c
rename to Platform/NXP/LS1043aRdbPkg/Library/ArmPlatformLib/ArmPlatformLibMem.c
--
2.17.1


Re: [PATCH v2 13/28] Silicon/NXP: Move dsc file

Leif Lindholm
 

On Fri, Mar 20, 2020 at 20:05:28 +0530, Pankaj Bansal wrote:
From: Pankaj Bansal <pankaj.bansal@...>

As per convention being followed in edk2-platforms, keep the dec
file and dsc file together.

Signed-off-by: Pankaj Bansal <pankaj.bansal@...>
Reviewed-by: Leif Lindholm <leif@...>

---
Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc | 2 +-
{Platform => Silicon}/NXP/NxpQoriqLs.dsc.inc | 0
2 files changed, 1 insertion(+), 1 deletion(-)
rename {Platform => Silicon}/NXP/NxpQoriqLs.dsc.inc (100%)

diff --git a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
index 385b6e067e26..1975f2c4c52c 100644
--- a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
+++ b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
@@ -22,7 +22,7 @@ [Defines]
OUTPUT_DIRECTORY = Build/LS1043aRdbPkg
FLASH_DEFINITION = Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.fdf

-!include Platform/NXP/NxpQoriqLs.dsc.inc
+!include Silicon/NXP/NxpQoriqLs.dsc.inc
!include Silicon/NXP/LS1043A/LS1043A.dsc.inc

[LibraryClasses.common]
diff --git a/Platform/NXP/NxpQoriqLs.dsc.inc b/Silicon/NXP/NxpQoriqLs.dsc.inc
similarity index 100%
rename from Platform/NXP/NxpQoriqLs.dsc.inc
rename to Silicon/NXP/NxpQoriqLs.dsc.inc
--
2.17.1


Re: [PATCH v2 12/28] Silicon/NXP: Remove unnecessary PCDs

Leif Lindholm
 

On Fri, Mar 20, 2020 at 20:05:27 +0530, Pankaj Bansal wrote:
From: Pankaj Bansal <pankaj.bansal@...>

The memory map of an SOC is fixed in hardware. it doesn't change with
platform that uses SOC. So, there is no need to keep PCDs for these values
and we can use macros for these in SOC header file.

Any Platform using the SOC, can make use of the SOC header file.

Signed-off-by: Pankaj Bansal <pankaj.bansal@...>
Reviewed-by: Leif Lindholm <leif@...>

---
.../Drivers/PlatformDxe/PlatformDxe.c | 15 ++--
.../Drivers/PlatformDxe/PlatformDxe.inf | 10 +--
.../Library/PlatformLib/ArmPlatformLib.inf | 21 +----
.../Library/PlatformLib/NxpQoriqLsMem.c | 79 +++++++++----------
Silicon/NXP/Include/Chassis2/NxpSoc.h | 2 +
Silicon/NXP/LS1043A/Include/Soc.h | 44 +++++++++++
Silicon/NXP/LS1043A/LS1043A.dsc.inc | 26 ------
Silicon/NXP/Library/SocLib/Chassis2/Soc.c | 2 +-
Silicon/NXP/Library/SocLib/LS1043aSocLib.inf | 1 -
Silicon/NXP/NxpQoriqLs.dec | 47 -----------
10 files changed, 97 insertions(+), 150 deletions(-)
create mode 100644 Silicon/NXP/LS1043A/Include/Soc.h

diff --git a/Platform/NXP/LS1043aRdbPkg/Drivers/PlatformDxe/PlatformDxe.c b/Platform/NXP/LS1043aRdbPkg/Drivers/PlatformDxe/PlatformDxe.c
index f89dcdeff3c1..62c400eb1a58 100644
--- a/Platform/NXP/LS1043aRdbPkg/Drivers/PlatformDxe/PlatformDxe.c
+++ b/Platform/NXP/LS1043aRdbPkg/Drivers/PlatformDxe/PlatformDxe.c
@@ -1,7 +1,7 @@
/** @file
LS1043 DXE platform driver.

- Copyright 2018-2019 NXP
+ Copyright 2018-2020 NXP

SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -14,6 +14,7 @@
#include <Library/PcdLib.h>
#include <Library/UefiBootServicesTableLib.h>
#include <Library/UefiLib.h>
+#include <Soc.h>

#include <Protocol/NonDiscoverableDevice.h>

@@ -22,7 +23,7 @@ typedef struct {
UINT8 EndDesc;
} ADDRESS_SPACE_DESCRIPTOR;

-STATIC ADDRESS_SPACE_DESCRIPTOR mI2cDesc[FixedPcdGet64 (PcdNumI2cController)];
+STATIC ADDRESS_SPACE_DESCRIPTOR mI2cDesc[LS1043A_I2C_NUM_CONTROLLERS];

STATIC
EFI_STATUS
@@ -65,19 +66,19 @@ PopulateI2cInformation (
{
UINT32 Index;

- for (Index = 0; Index < FixedPcdGet32 (PcdNumI2cController); Index++) {
+ for (Index = 0; Index < ARRAY_SIZE (mI2cDesc); Index++) {
mI2cDesc[Index].StartDesc.Desc = ACPI_ADDRESS_SPACE_DESCRIPTOR;
mI2cDesc[Index].StartDesc.Len = sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR) - 3;
mI2cDesc[Index].StartDesc.ResType = ACPI_ADDRESS_SPACE_TYPE_MEM;
mI2cDesc[Index].StartDesc.GenFlag = 0;
mI2cDesc[Index].StartDesc.SpecificFlag = 0;
mI2cDesc[Index].StartDesc.AddrSpaceGranularity = 32;
- mI2cDesc[Index].StartDesc.AddrRangeMin = FixedPcdGet64 (PcdI2c0BaseAddr) +
- (Index * FixedPcdGet32 (PcdI2cSize));
+ mI2cDesc[Index].StartDesc.AddrRangeMin = LS1043A_I2C0_PHYS_ADDRESS +
+ (Index * LS1043A_I2C_SIZE);
mI2cDesc[Index].StartDesc.AddrRangeMax = mI2cDesc[Index].StartDesc.AddrRangeMin +
- FixedPcdGet32 (PcdI2cSize) - 1;
+ LS1043A_I2C_SIZE - 1;
mI2cDesc[Index].StartDesc.AddrTranslationOffset = 0;
- mI2cDesc[Index].StartDesc.AddrLen = FixedPcdGet32 (PcdI2cSize);
+ mI2cDesc[Index].StartDesc.AddrLen = LS1043A_I2C_SIZE;

mI2cDesc[Index].EndDesc = ACPI_END_TAG_DESCRIPTOR;
}
diff --git a/Platform/NXP/LS1043aRdbPkg/Drivers/PlatformDxe/PlatformDxe.inf b/Platform/NXP/LS1043aRdbPkg/Drivers/PlatformDxe/PlatformDxe.inf
index d689cf4db58e..038d48949a39 100644
--- a/Platform/NXP/LS1043aRdbPkg/Drivers/PlatformDxe/PlatformDxe.inf
+++ b/Platform/NXP/LS1043aRdbPkg/Drivers/PlatformDxe/PlatformDxe.inf
@@ -2,7 +2,7 @@
#
# Component description file for LS1043 DXE platform driver.
#
-# Copyright 2018-2019 NXP
+# Copyright 2018-2020 NXP
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -21,9 +21,10 @@ [Sources]

[Packages]
ArmPkg/ArmPkg.dec
- MdePkg/MdePkg.dec
MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
Silicon/Maxim/Library/Ds1307RtcLib/Ds1307RtcLib.dec
+ Silicon/NXP/LS1043A/LS1043A.dec
Silicon/NXP/NxpQoriqLs.dec

[LibraryClasses]
@@ -43,10 +44,5 @@ [Protocols]
gEdkiiNonDiscoverableDeviceProtocolGuid ## PRODUCES
gDs1307RealTimeClockLibI2cMasterProtocolGuid ## PRODUCES

-[FixedPcd]
- gNxpQoriqLsTokenSpaceGuid.PcdI2c0BaseAddr
- gNxpQoriqLsTokenSpaceGuid.PcdI2cSize
- gNxpQoriqLsTokenSpaceGuid.PcdNumI2cController
-
[Depex]
TRUE
diff --git a/Platform/NXP/LS1043aRdbPkg/Library/PlatformLib/ArmPlatformLib.inf b/Platform/NXP/LS1043aRdbPkg/Library/PlatformLib/ArmPlatformLib.inf
index f7ae74afc6ca..7563a1c43630 100644
--- a/Platform/NXP/LS1043aRdbPkg/Library/PlatformLib/ArmPlatformLib.inf
+++ b/Platform/NXP/LS1043aRdbPkg/Library/PlatformLib/ArmPlatformLib.inf
@@ -1,7 +1,7 @@
# @file
#
# Copyright (c) 2016, Freescale Semiconductor, Inc. All rights reserved.
-# Copyright 2017, 2019 NXP
+# Copyright 2017, 2019-2020 NXP
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -19,6 +19,7 @@ [Packages]
ArmPlatformPkg/ArmPlatformPkg.dec
EmbeddedPkg/EmbeddedPkg.dec
MdePkg/MdePkg.dec
+ Silicon/NXP/LS1043A/LS1043A.dec
Silicon/NXP/NxpQoriqLs.dec

[LibraryClasses]
@@ -35,21 +36,3 @@ [Ppis]

[FixedPcd]
gArmTokenSpaceGuid.PcdArmPrimaryCore
- gNxpQoriqLsTokenSpaceGuid.PcdCcsrBaseAddr
- gNxpQoriqLsTokenSpaceGuid.PcdCcsrSize
- gNxpQoriqLsTokenSpaceGuid.PcdIfcRegion1BaseAddr
- gNxpQoriqLsTokenSpaceGuid.PcdIfcRegion1Size
- gNxpQoriqLsTokenSpaceGuid.PcdIfcRegion2BaseAddr
- gNxpQoriqLsTokenSpaceGuid.PcdIfcRegion2Size
- gNxpQoriqLsTokenSpaceGuid.PcdQmanSwpBaseAddr
- gNxpQoriqLsTokenSpaceGuid.PcdQmanSwpSize
- gNxpQoriqLsTokenSpaceGuid.PcdBmanSwpBaseAddr
- gNxpQoriqLsTokenSpaceGuid.PcdBmanSwpSize
- gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseAddr
- gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseSize
- gNxpQoriqLsTokenSpaceGuid.PcdPciExp2BaseAddr
- gNxpQoriqLsTokenSpaceGuid.PcdPciExp2BaseSize
- gNxpQoriqLsTokenSpaceGuid.PcdPciExp3BaseAddr
- gNxpQoriqLsTokenSpaceGuid.PcdPciExp3BaseSize
- gNxpQoriqLsTokenSpaceGuid.PcdQspiRegionBaseAddr
- gNxpQoriqLsTokenSpaceGuid.PcdQspiRegionSize
diff --git a/Platform/NXP/LS1043aRdbPkg/Library/PlatformLib/NxpQoriqLsMem.c b/Platform/NXP/LS1043aRdbPkg/Library/PlatformLib/NxpQoriqLsMem.c
index c6c256da0727..f5fa308551aa 100644
--- a/Platform/NXP/LS1043aRdbPkg/Library/PlatformLib/NxpQoriqLsMem.c
+++ b/Platform/NXP/LS1043aRdbPkg/Library/PlatformLib/NxpQoriqLsMem.c
@@ -6,7 +6,7 @@
*
* Copyright (c) 2011, ARM Limited. All rights reserved.
* Copyright (c) 2016, Freescale Semiconductor, Inc. All rights reserved.
-* Copyright 2017, 2019 NXP
+* Copyright 2017, 2019-2020 NXP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*
@@ -16,7 +16,7 @@
#include <Library/DebugLib.h>
#include <Library/PcdLib.h>
#include <Library/MemoryAllocationLib.h>
-#include <DramInfo.h>
+#include <Soc.h>

#define MAX_VIRTUAL_MEMORY_MAP_DESCRIPTORS 25

@@ -38,7 +38,6 @@ ArmPlatformGetVirtualMemoryMap (
{
UINTN Index;
ARM_MEMORY_REGION_DESCRIPTOR *VirtualMemoryTable;
- DRAM_INFO DramInfo;

Index = 0;

@@ -51,24 +50,20 @@ ArmPlatformGetVirtualMemoryMap (
return;
}

- if (GetDramBankInfo (&DramInfo)) {
- DEBUG ((DEBUG_ERROR, "Failed to get DRAM information, exiting...\n"));
- return;
- }
+ VirtualMemoryTable[Index].PhysicalBase = LS1043A_DRAM0_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].VirtualBase = LS1043A_DRAM0_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].Length = LS1043A_DRAM0_SIZE;
+ VirtualMemoryTable[Index++].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK;

-
- for (Index = 0; Index < DramInfo.NumOfDrams; Index++) {
- // DRAM1 (Must be 1st entry)
- VirtualMemoryTable[Index].PhysicalBase = DramInfo.DramRegion[Index].BaseAddress;
- VirtualMemoryTable[Index].VirtualBase = DramInfo.DramRegion[Index].BaseAddress;
- VirtualMemoryTable[Index].Length = DramInfo.DramRegion[Index].Size;
- VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK;
- }
+ VirtualMemoryTable[Index].PhysicalBase = LS1043A_DRAM1_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].VirtualBase = LS1043A_DRAM1_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].Length = LS1043A_DRAM1_SIZE;
+ VirtualMemoryTable[Index++].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_WRITE_BACK;

// CCSR Space
- VirtualMemoryTable[Index].PhysicalBase = FixedPcdGet64 (PcdCcsrBaseAddr);
- VirtualMemoryTable[Index].VirtualBase = FixedPcdGet64 (PcdCcsrBaseAddr);
- VirtualMemoryTable[Index].Length = FixedPcdGet64 (PcdCcsrSize);
+ VirtualMemoryTable[Index].PhysicalBase = LS1043A_CCSR_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].VirtualBase = LS1043A_CCSR_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].Length = LS1043A_CCSR_SIZE;
VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;

// IFC region 1
@@ -85,51 +80,51 @@ ArmPlatformGetVirtualMemoryMap (
// For write transactions from non-core masters (like system DMA), the address
// should be 16 byte aligned and the data size should be multiple of 16 bytes.
//
- VirtualMemoryTable[++Index].PhysicalBase = FixedPcdGet64 (PcdIfcRegion1BaseAddr);
- VirtualMemoryTable[Index].VirtualBase = FixedPcdGet64 (PcdIfcRegion1BaseAddr);
- VirtualMemoryTable[Index].Length = FixedPcdGet64 (PcdIfcRegion1Size);
+ VirtualMemoryTable[++Index].PhysicalBase = LS1043A_IFC0_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].VirtualBase = LS1043A_IFC0_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].Length = LS1043A_IFC0_SIZE;
VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;

// QMAN SWP
- VirtualMemoryTable[++Index].PhysicalBase = FixedPcdGet64 (PcdQmanSwpBaseAddr);
- VirtualMemoryTable[Index].VirtualBase = FixedPcdGet64 (PcdQmanSwpBaseAddr);
- VirtualMemoryTable[Index].Length = FixedPcdGet64 (PcdQmanSwpSize);
+ VirtualMemoryTable[++Index].PhysicalBase = LS1043A_QMAN_SW_PORTAL_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].VirtualBase = LS1043A_QMAN_SW_PORTAL_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].Length = LS1043A_QMAN_SW_PORTAL_SIZE;
VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED;

// BMAN SWP
- VirtualMemoryTable[++Index].PhysicalBase = FixedPcdGet64 (PcdBmanSwpBaseAddr);
- VirtualMemoryTable[Index].VirtualBase = FixedPcdGet64 (PcdBmanSwpBaseAddr);
- VirtualMemoryTable[Index].Length = FixedPcdGet64 (PcdBmanSwpSize);
+ VirtualMemoryTable[++Index].PhysicalBase = LS1043A_BMAN_SW_PORTAL_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].VirtualBase = LS1043A_BMAN_SW_PORTAL_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].Length = LS1043A_QMAN_SW_PORTAL_SIZE;
VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED;

// IFC region 2
- VirtualMemoryTable[++Index].PhysicalBase = FixedPcdGet64 (PcdIfcRegion2BaseAddr);
- VirtualMemoryTable[Index].VirtualBase = FixedPcdGet64 (PcdIfcRegion2BaseAddr);
- VirtualMemoryTable[Index].Length = FixedPcdGet64 (PcdIfcRegion2Size);
+ VirtualMemoryTable[++Index].PhysicalBase = LS1043A_IFC1_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].VirtualBase = LS1043A_IFC1_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].Length = LS1043A_IFC1_SIZE;
VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;

// PCIe1
- VirtualMemoryTable[++Index].PhysicalBase = FixedPcdGet64 (PcdPciExp1BaseAddr);
- VirtualMemoryTable[Index].VirtualBase = FixedPcdGet64 (PcdPciExp1BaseAddr);
- VirtualMemoryTable[Index].Length = FixedPcdGet64 (PcdPciExp1BaseSize);
+ VirtualMemoryTable[++Index].PhysicalBase = LS1043A_PCI0_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].VirtualBase = LS1043A_PCI0_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].Length = LS1043A_PCI_SIZE;
VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;

// PCIe2
- VirtualMemoryTable[++Index].PhysicalBase = FixedPcdGet64 (PcdPciExp2BaseAddr);
- VirtualMemoryTable[Index].VirtualBase = FixedPcdGet64 (PcdPciExp2BaseAddr);
- VirtualMemoryTable[Index].Length = FixedPcdGet64 (PcdPciExp2BaseSize);
+ VirtualMemoryTable[++Index].PhysicalBase = LS1043A_PCI1_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].VirtualBase = LS1043A_PCI1_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].Length = LS1043A_PCI_SIZE;
VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;

// PCIe3
- VirtualMemoryTable[++Index].PhysicalBase = FixedPcdGet64 (PcdPciExp3BaseAddr);
- VirtualMemoryTable[Index].VirtualBase = FixedPcdGet64 (PcdPciExp3BaseAddr);
- VirtualMemoryTable[Index].Length = FixedPcdGet64 (PcdPciExp3BaseSize);
+ VirtualMemoryTable[++Index].PhysicalBase = LS1043A_PCI2_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].VirtualBase = LS1043A_PCI2_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].Length = LS1043A_PCI_SIZE;
VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_DEVICE;

// QSPI region
- VirtualMemoryTable[++Index].PhysicalBase = FixedPcdGet64 (PcdQspiRegionBaseAddr);
- VirtualMemoryTable[Index].VirtualBase = FixedPcdGet64 (PcdQspiRegionBaseAddr);
- VirtualMemoryTable[Index].Length = FixedPcdGet64 (PcdQspiRegionSize);
+ VirtualMemoryTable[++Index].PhysicalBase = LS1043A_QSPI_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].VirtualBase = LS1043A_QSPI_PHYS_ADDRESS;
+ VirtualMemoryTable[Index].Length = LS1043A_QSPI_SIZE;
VirtualMemoryTable[Index].Attributes = ARM_MEMORY_REGION_ATTRIBUTE_UNCACHED_UNBUFFERED;

// End of Table
diff --git a/Silicon/NXP/Include/Chassis2/NxpSoc.h b/Silicon/NXP/Include/Chassis2/NxpSoc.h
index 74330b6205e7..6812beafe447 100644
--- a/Silicon/NXP/Include/Chassis2/NxpSoc.h
+++ b/Silicon/NXP/Include/Chassis2/NxpSoc.h
@@ -12,6 +12,8 @@

#define CLK_FREQ 100000000

+#define CHASSIS2_DCFG_ADDRESS 0x1EE0000
+
/* SMMU Defintions */
#define SMMU_BASE_ADDR 0x09000000
#define SMMU_REG_SCR0 (SMMU_BASE_ADDR + 0x0)
diff --git a/Silicon/NXP/LS1043A/Include/Soc.h b/Silicon/NXP/LS1043A/Include/Soc.h
new file mode 100644
index 000000000000..441871757d67
--- /dev/null
+++ b/Silicon/NXP/LS1043A/Include/Soc.h
@@ -0,0 +1,44 @@
+/** @file
+
+ Copyright 2020 NXP
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+#ifndef SOC_H__
+#define SOC_H__
+
+/**
+ Soc Memory Map
+**/
+#define LS1043A_DRAM0_PHYS_ADDRESS 0x80000000
+#define LS1043A_DRAM0_SIZE SIZE_2GB
+#define LS1043A_DRAM1_PHYS_ADDRESS 0x880000000
+#define LS1043A_DRAM1_SIZE 0x780000000 // 30 GB
+
+#define LS1043A_CCSR_PHYS_ADDRESS 0x1000000
+#define LS1043A_CCSR_SIZE 0xF000000
+
+#define LS1043A_IFC0_PHYS_ADDRESS 0x60000000
+#define LS1043A_IFC0_SIZE SIZE_512MB
+#define LS1043A_IFC1_PHYS_ADDRESS 0x620000000
+#define LS1043A_IFC1_SIZE 0xE0000000 // 3.5 GB
+
+#define LS1043A_QSPI_PHYS_ADDRESS 0x40000000
+#define LS1043A_QSPI_SIZE SIZE_512MB
+
+#define LS1043A_QMAN_SW_PORTAL_PHYS_ADDRESS 0x500000000
+#define LS1043A_QMAN_SW_PORTAL_SIZE SIZE_128MB
+#define LS1043A_BMAN_SW_PORTAL_PHYS_ADDRESS 0x508000000
+#define LS1043A_BMAN_SW_PORTAL_SIZE SIZE_128MB
+
+#define LS1043A_PCI0_PHYS_ADDRESS 0x4000000000
+#define LS1043A_PCI1_PHYS_ADDRESS 0x4800000000
+#define LS1043A_PCI2_PHYS_ADDRESS 0x5000000000
+#define LS1043A_PCI_SIZE SIZE_32GB
+
+#define LS1043A_I2C0_PHYS_ADDRESS 0x2180000
+#define LS1043A_I2C_SIZE 0x10000
+#define LS1043A_I2C_NUM_CONTROLLERS 4
+
+#endif // SOC_H__
diff --git a/Silicon/NXP/LS1043A/LS1043A.dsc.inc b/Silicon/NXP/LS1043A/LS1043A.dsc.inc
index f57a0d95b8e1..6239cfe761e6 100644
--- a/Silicon/NXP/LS1043A/LS1043A.dsc.inc
+++ b/Silicon/NXP/LS1043A/LS1043A.dsc.inc
@@ -29,32 +29,6 @@ [PcdsFixedAtBuild.common]
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase|0x021c0500
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseMmio|TRUE

- #
- # CCSR Address Space and other attached Memories
- #
- gNxpQoriqLsTokenSpaceGuid.PcdCcsrBaseAddr|0x01000000
- gNxpQoriqLsTokenSpaceGuid.PcdCcsrSize|0x0F000000
- gNxpQoriqLsTokenSpaceGuid.PcdIfcRegion1BaseAddr|0x60000000
- gNxpQoriqLsTokenSpaceGuid.PcdIfcRegion1Size|0x20000000
- gNxpQoriqLsTokenSpaceGuid.PcdIfcRegion2BaseAddr|0x0620000000
- gNxpQoriqLsTokenSpaceGuid.PcdIfcRegion2Size|0x00E0000000
- gNxpQoriqLsTokenSpaceGuid.PcdQmanSwpBaseAddr|0x0500000000
- gNxpQoriqLsTokenSpaceGuid.PcdQmanSwpSize|0x0080000000
- gNxpQoriqLsTokenSpaceGuid.PcdBmanSwpBaseAddr|0x0508000000
- gNxpQoriqLsTokenSpaceGuid.PcdBmanSwpSize|0x0080000000
- gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseAddr|0x4000000000
- gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseSize|0x800000000
- gNxpQoriqLsTokenSpaceGuid.PcdPciExp2BaseAddr|0x4800000000
- gNxpQoriqLsTokenSpaceGuid.PcdPciExp2BaseSize|0x800000000
- gNxpQoriqLsTokenSpaceGuid.PcdPciExp3BaseAddr|0x5000000000
- gNxpQoriqLsTokenSpaceGuid.PcdPciExp3BaseSize|0x800000000
- gNxpQoriqLsTokenSpaceGuid.PcdGutsBaseAddr|0x01EE0000
- gNxpQoriqLsTokenSpaceGuid.PcdI2c0BaseAddr|0x02180000
- gNxpQoriqLsTokenSpaceGuid.PcdI2cSize|0x10000
- gNxpQoriqLsTokenSpaceGuid.PcdNumI2cController|4
- gNxpQoriqLsTokenSpaceGuid.PcdQspiRegionBaseAddr|0x40000000
- gNxpQoriqLsTokenSpaceGuid.PcdQspiRegionSize|0x20000000
-
#
# Big Endian IPs
#
diff --git a/Silicon/NXP/Library/SocLib/Chassis2/Soc.c b/Silicon/NXP/Library/SocLib/Chassis2/Soc.c
index d992e53546f4..98ca2e162f7b 100644
--- a/Silicon/NXP/Library/SocLib/Chassis2/Soc.c
+++ b/Silicon/NXP/Library/SocLib/Chassis2/Soc.c
@@ -34,7 +34,7 @@ GetSysInfo (
CCSR_GUR *GurBase;
UINTN SysClk;

- GurBase = (VOID *)PcdGet64 (PcdGutsBaseAddr);
+ GurBase = (CCSR_GUR *)CHASSIS2_DCFG_ADDRESS;
SysClk = CLK_FREQ;

SetMem (PtrSysInfo, sizeof (SYS_INFO), 0);
diff --git a/Silicon/NXP/Library/SocLib/LS1043aSocLib.inf b/Silicon/NXP/Library/SocLib/LS1043aSocLib.inf
index f75a8d19f5a5..b7c7fc78cc8f 100644
--- a/Silicon/NXP/Library/SocLib/LS1043aSocLib.inf
+++ b/Silicon/NXP/Library/SocLib/LS1043aSocLib.inf
@@ -36,5 +36,4 @@ [BuildOptions]
[FixedPcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString
gNxpQoriqLsTokenSpaceGuid.PcdGurBigEndian
- gNxpQoriqLsTokenSpaceGuid.PcdGutsBaseAddr
gNxpQoriqLsTokenSpaceGuid.PcdPlatformFreqDiv
diff --git a/Silicon/NXP/NxpQoriqLs.dec b/Silicon/NXP/NxpQoriqLs.dec
index 943dbac81013..b478560450b3 100644
--- a/Silicon/NXP/NxpQoriqLs.dec
+++ b/Silicon/NXP/NxpQoriqLs.dec
@@ -22,53 +22,6 @@ [Guids.common]
gNxpNonDiscoverableI2cMasterGuid = { 0x5f2c099c, 0x54a3, 0x4dd4, {0x9e, 0xc5, 0xe9, 0x12, 0x8c, 0x36, 0x81, 0x6a}}

[PcdsFixedAtBuild.common]
- #
- # Pcds for I2C Controller
- #
- gNxpQoriqLsTokenSpaceGuid.PcdI2cSpeed|0|UINT32|0x00000001
- gNxpQoriqLsTokenSpaceGuid.PcdNumI2cController|0|UINT32|0x00000002
-
- #
- # Pcds for base address and size
- #
- gNxpQoriqLsTokenSpaceGuid.PcdGutsBaseAddr|0x0|UINT64|0x00000100
- gNxpQoriqLsTokenSpaceGuid.PcdClkBaseAddr|0x0|UINT64|0x00000103
- gNxpQoriqLsTokenSpaceGuid.PcdDdrBaseAddr|0x0|UINT64|0x00000105
- gNxpQoriqLsTokenSpaceGuid.PcdSdxcBaseAddr|0x0|UINT64|0x00000106
- gNxpQoriqLsTokenSpaceGuid.PcdScfgBaseAddr|0x0|UINT64|0x00000107
- gNxpQoriqLsTokenSpaceGuid.PcdI2c0BaseAddr|0x0|UINT64|0x00000108
- gNxpQoriqLsTokenSpaceGuid.PcdI2cSize|0x0|UINT32|0x00000109
- gNxpQoriqLsTokenSpaceGuid.PcdDcsrBaseAddr|0x0|UINT64|0x0000010A
- gNxpQoriqLsTokenSpaceGuid.PcdDcsrSize|0x0|UINT64|0x0000010B
- gNxpQoriqLsTokenSpaceGuid.PcdSataBaseAddr|0x0|UINT32|0x0000010C
- gNxpQoriqLsTokenSpaceGuid.PcdSataSize|0x0|UINT32|0x0000010D
- gNxpQoriqLsTokenSpaceGuid.PcdQmanSwpBaseAddr|0x0|UINT64|0x0000010E
- gNxpQoriqLsTokenSpaceGuid.PcdQmanSwpSize|0x0|UINT64|0x0000010F
- gNxpQoriqLsTokenSpaceGuid.PcdBmanSwpBaseAddr|0x0|UINT64|0x00000110
- gNxpQoriqLsTokenSpaceGuid.PcdBmanSwpSize|0x0|UINT64|0x00000111
- gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseAddr|0x0|UINT64|0x00000112
- gNxpQoriqLsTokenSpaceGuid.PcdPciExp1BaseSize|0x0|UINT64|0x00000113
- gNxpQoriqLsTokenSpaceGuid.PcdPciExp2BaseAddr|0x0|UINT64|0x00000114
- gNxpQoriqLsTokenSpaceGuid.PcdPciExp2BaseSize|0x0|UINT64|0x00000115
- gNxpQoriqLsTokenSpaceGuid.PcdPciExp3BaseAddr|0x0|UINT64|0x00000116
- gNxpQoriqLsTokenSpaceGuid.PcdPciExp3BaseSize|0x0|UINT64|0x00000117
- gNxpQoriqLsTokenSpaceGuid.PcdPciExp4BaseAddr|0x0|UINT64|0x0000118
- gNxpQoriqLsTokenSpaceGuid.PcdPciExp4BaseSize|0x0|UINT64|0x0000119
- gNxpQoriqLsTokenSpaceGuid.PcdQspiRegionBaseAddr|0x0|UINT64|0x0000011A
- gNxpQoriqLsTokenSpaceGuid.PcdQspiRegionSize|0x0|UINT64|0x0000011B
- gNxpQoriqLsTokenSpaceGuid.PcdQspiRegion2BaseAddr|0x0|UINT64|0x0000011C
- gNxpQoriqLsTokenSpaceGuid.PcdQspiRegion2Size|0x0|UINT64|0x0000011D
- gNxpQoriqLsTokenSpaceGuid.PcdCcsrBaseAddr|0x0|UINT64|0x00000122
- gNxpQoriqLsTokenSpaceGuid.PcdCcsrSize|0x0|UINT64|0x00000123
-
- #
- # IFC PCDs
- #
- gNxpQoriqLsTokenSpaceGuid.PcdIfcRegion1BaseAddr|0x0|UINT64|0x00000190
- gNxpQoriqLsTokenSpaceGuid.PcdIfcRegion1Size|0x0|UINT64|0x00000191
- gNxpQoriqLsTokenSpaceGuid.PcdIfcRegion2BaseAddr|0x0|UINT64|0x00000192
- gNxpQoriqLsTokenSpaceGuid.PcdIfcRegion2Size|0x0|UINT64|0x00000193
-
#
# Platform PCDs
#
--
2.17.1


Re: [PATCH v2 11/28] Silicon/NXP: remove not needed components

Leif Lindholm
 

On Fri, Mar 20, 2020 at 20:05:26 +0530, Pankaj Bansal wrote:
From: Pankaj Bansal <pankaj.bansal@...>

The structures elements and functions that are not necessary for booting
for now are being deleted.
Once the directory structure has been changed (i.e. we have clear
distinction between chassis code and header files and SOC code and header
files), we will put back the code and
structure components back at their appropriate respective place.

Also right now all the elements are being defined in structures, which are
not being used right now. So to simplify the code restructuring, I have
removed those for now. When we need to use those elements, we can define
those one by one.

Signed-off-by: Pankaj Bansal <pankaj.bansal@...>
Reviewed-by: Leif Lindholm <leif@...>

---
Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc | 4 -
Silicon/NXP/Include/Chassis2/LsSerDes.h | 62 ----
Silicon/NXP/Include/Chassis2/NxpSoc.h | 314 +------------------
Silicon/NXP/LS1043A/Include/SocSerDes.h | 51 ---
Silicon/NXP/LS1043A/LS1043A.dsc.inc | 6 -
Silicon/NXP/Library/SocLib/Chassis.c | 220 -------------
Silicon/NXP/Library/SocLib/Chassis2/Soc.c | 79 -----
Silicon/NXP/Library/SocLib/LS1043aSocLib.inf | 7 +-
Silicon/NXP/Library/SocLib/NxpChassis.h | 90 ------
Silicon/NXP/Library/SocLib/SerDes.c | 268 ----------------
Silicon/NXP/NxpQoriqLs.dec | 27 --
11 files changed, 3 insertions(+), 1125 deletions(-)
delete mode 100644 Silicon/NXP/Include/Chassis2/LsSerDes.h
delete mode 100644 Silicon/NXP/LS1043A/Include/SocSerDes.h
delete mode 100644 Silicon/NXP/Library/SocLib/SerDes.c

diff --git a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
index 802cccdce63b..385b6e067e26 100644
--- a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
+++ b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
@@ -39,10 +39,6 @@ [PcdsFixedAtBuild.common]
gArmTokenSpaceGuid.PcdSystemMemorySize|0x7BE00000
gArmPlatformTokenSpaceGuid.PcdSystemMemoryUefiRegionSize|0x02000000

- #
- # Board Specific Pcds
- #
- gNxpQoriqLsTokenSpaceGuid.PcdSerdes2Enabled|FALSE
gNxpQoriqLsTokenSpaceGuid.PcdPlatformFreqDiv|0x1

#
diff --git a/Silicon/NXP/Include/Chassis2/LsSerDes.h b/Silicon/NXP/Include/Chassis2/LsSerDes.h
deleted file mode 100644
index 9afbc522398a..000000000000
--- a/Silicon/NXP/Include/Chassis2/LsSerDes.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/** LsSerDes.h
- The Header file of SerDes Module for Chassis 2
-
- Copyright 2017-2019 NXP
-
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef LS_SERDES_H_
-#define LS_SERDES_H_
-
-#include <Uefi/UefiBaseType.h>
-
-#define SRDS_MAX_LANES 4
-
-typedef enum {
- None = 0,
- Pcie1,
- Pcie2,
- Pcie3,
- Sata,
- SgmiiFm1Dtsec1,
- SgmiiFm1Dtsec2,
- SgmiiFm1Dtsec5,
- SgmiiFm1Dtsec6,
- SgmiiFm1Dtsec9,
- SgmiiFm1Dtsec10,
- QsgmiiFm1A,
- XfiFm1Mac9,
- XfiFm1Mac10,
- Sgmii2500Fm1Dtsec2,
- Sgmii2500Fm1Dtsec5,
- Sgmii2500Fm1Dtsec9,
- Sgmii2500Fm1Dtsec10,
- SerdesPrtclCount
-} SERDES_PROTOCOL;
-
-typedef enum {
- Srds1 = 0,
- Srds2,
- SrdsMaxNum
-} SERDES_NUMBER;
-
-typedef struct {
- UINT16 Protocol;
- UINT8 SrdsLane[SRDS_MAX_LANES];
-} SERDES_CONFIG;
-
-typedef VOID
-(*SERDES_PROBE_LANES_CALLBACK) (
- IN SERDES_PROTOCOL LaneProtocol,
- IN VOID *Arg
- );
-
-VOID
-SerDesProbeLanes(
- IN SERDES_PROBE_LANES_CALLBACK SerDesLaneProbeCallback,
- IN VOID *Arg
- );
-
-#endif /* LS_SERDES_H_ */
diff --git a/Silicon/NXP/Include/Chassis2/NxpSoc.h b/Silicon/NXP/Include/Chassis2/NxpSoc.h
index f05a813750e8..74330b6205e7 100644
--- a/Silicon/NXP/Include/Chassis2/NxpSoc.h
+++ b/Silicon/NXP/Include/Chassis2/NxpSoc.h
@@ -1,7 +1,7 @@
/** Soc.h
* Header defining the Base addresses, sizes, flags etc for chassis 1
*
-* Copyright 2017-2019 NXP
+* Copyright 2017-2020 NXP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*
@@ -10,22 +10,7 @@
#ifndef NXP_SOC_H_
#define NXP_SOC_H_

-#define HWA_CGA_M1_CLK_SEL 0xe0000000
-#define HWA_CGA_M1_CLK_SHIFT 29
-
-#define TP_CLUSTER_EOC_MASK 0xc0000000 /* end of clusters mask */
-#define NUM_CC_PLLS 2
#define CLK_FREQ 100000000
-#define MAX_CPUS 4
-#define NUM_FMAN 1
-#define CHECK_CLUSTER(Cluster) ((Cluster & TP_CLUSTER_EOC_MASK) == 0x0)
-
-/* RCW SERDES MACRO */
-#define RCWSR_INDEX 4
-#define RCWSR_SRDS1_PRTCL_MASK 0xffff0000
-#define RCWSR_SRDS1_PRTCL_SHIFT 16
-#define RCWSR_SRDS2_PRTCL_MASK 0x0000ffff
-#define RCWSR_SRDS2_PRTCL_SHIFT 0

/* SMMU Defintions */
#define SMMU_BASE_ADDR 0x09000000
@@ -41,312 +26,17 @@
#define IDR1_PAGESIZE_MASK 0x80000000

typedef struct {
- UINTN FreqProcessor[MAX_CPUS];
UINTN FreqSystemBus;
- UINTN FreqDdrBus;
- UINTN FreqLocalBus;
- UINTN FreqSdhc;
- UINTN FreqFman[NUM_FMAN];
- UINTN FreqQman;
} SYS_INFO;

/* Device Configuration and Pin Control */
typedef struct {
- UINT32 PorSr1; /* POR status 1 */
-#define CHASSIS2_CCSR_PORSR1_RCW_MASK 0xFF800000
- UINT32 PorSr2; /* POR status 2 */
- UINT8 Res008[0x20-0x8];
- UINT32 GppOrCr1; /* General-purpose POR configuration */
- UINT32 GppOrCr2;
- UINT32 DcfgFuseSr; /* Fuse status register */
- UINT8 Res02c[0x70-0x2c];
- UINT32 DevDisr; /* Device disable control */
- UINT32 DevDisr2; /* Device disable control 2 */
- UINT32 DevDisr3; /* Device disable control 3 */
- UINT32 DevDisr4; /* Device disable control 4 */
- UINT32 DevDisr5; /* Device disable control 5 */
- UINT32 DevDisr6; /* Device disable control 6 */
- UINT32 DevDisr7; /* Device disable control 7 */
- UINT8 Res08c[0x94-0x8c];
- UINT32 CoreDisrU; /* uppper portion for support of 64 cores */
- UINT32 CoreDisrL; /* lower portion for support of 64 cores */
- UINT8 Res09c[0xa0-0x9c];
- UINT32 Pvr; /* Processor version */
- UINT32 Svr; /* System version */
- UINT32 Mvr; /* Manufacturing version */
- UINT8 Res0ac[0xb0-0xac];
- UINT32 RstCr; /* Reset control */
- UINT32 RstRqPblSr; /* Reset request preboot loader status */
- UINT8 Res0b8[0xc0-0xb8];
- UINT32 RstRqMr1; /* Reset request mask */
- UINT8 Res0c4[0xc8-0xc4];
- UINT32 RstRqSr1; /* Reset request status */
- UINT8 Res0cc[0xd4-0xcc];
- UINT32 RstRqWdTmrL; /* Reset request WDT mask */
- UINT8 Res0d8[0xdc-0xd8];
- UINT32 RstRqWdtSrL; /* Reset request WDT status */
- UINT8 Res0e0[0xe4-0xe0];
- UINT32 BrrL; /* Boot release */
- UINT8 Res0e8[0x100-0xe8];
+ UINT8 Res0[0x100-0x00];
UINT32 RcwSr[16]; /* Reset control word status */
#define CHASSIS2_RCWSR0_SYS_PLL_RAT_SHIFT 25
#define CHASSIS2_RCWSR0_SYS_PLL_RAT_MASK 0x1f
-#define CHASSIS2_RCWSR0_MEM_PLL_RAT_SHIFT 16
-#define CHASSIS2_RCWSR0_MEM_PLL_RAT_MASK 0x3f
- UINT8 Res140[0x200-0x140];
- UINT32 ScratchRw[4]; /* Scratch Read/Write */
- UINT8 Res210[0x300-0x210];
- UINT32 ScratcHw1R[4]; /* Scratch Read (Write once) */
- UINT8 Res310[0x400-0x310];
- UINT32 CrstSr[12];
- UINT8 Res430[0x500-0x430];
- /* PCI Express n Logical I/O Device Number register */
- UINT32 DcfgCcsrPex1LiodNr;
- UINT32 DcfgCcsrPex2LiodNr;
- UINT32 DcfgCcsrPex3LiodNr;
- UINT32 DcfgCcsrPex4LiodNr;
- /* RIO n Logical I/O Device Number register */
- UINT32 DcfgCcsrRio1LiodNr;
- UINT32 DcfgCcsrRio2LiodNr;
- UINT32 DcfgCcsrRio3LiodNr;
- UINT32 DcfgCcsrRio4LiodNr;
- /* USB Logical I/O Device Number register */
- UINT32 DcfgCcsrUsb1LiodNr;
- UINT32 DcfgCcsrUsb2LiodNr;
- UINT32 DcfgCcsrUsb3LiodNr;
- UINT32 DcfgCcsrUsb4LiodNr;
- /* SD/MMC Logical I/O Device Number register */
- UINT32 DcfgCcsrSdMmc1LiodNr;
- UINT32 DcfgCcsrSdMmc2LiodNr;
- UINT32 DcfgCcsrSdMmc3LiodNr;
- UINT32 DcfgCcsrSdMmc4LiodNr;
- /* RIO Message Unit Logical I/O Device Number register */
- UINT32 DcfgCcsrRiomaintLiodNr;
- UINT8 Res544[0x550-0x544];
- UINT32 SataLiodNr[4];
- UINT8 Res560[0x570-0x560];
- UINT32 DcfgCcsrMisc1LiodNr;
- UINT32 DcfgCcsrMisc2LiodNr;
- UINT32 DcfgCcsrMisc3LiodNr;
- UINT32 DcfgCcsrMisc4LiodNr;
- UINT32 DcfgCcsrDma1LiodNr;
- UINT32 DcfgCcsrDma2LiodNr;
- UINT32 DcfgCcsrDma3LiodNr;
- UINT32 DcfgCcsrDma4LiodNr;
- UINT32 DcfgCcsrSpare1LiodNr;
- UINT32 DcfgCcsrSpare2LiodNr;
- UINT32 DcfgCcsrSpare3LiodNr;
- UINT32 DcfgCcsrSpare4LiodNr;
- UINT8 Res5a0[0x600-0x5a0];
- UINT32 DcfgCcsrPblSr;
- UINT32 PamuBypENr;
- UINT32 DmaCr1;
- UINT8 Res60c[0x610-0x60c];
- UINT32 DcfgCcsrGenSr1;
- UINT32 DcfgCcsrGenSr2;
- UINT32 DcfgCcsrGenSr3;
- UINT32 DcfgCcsrGenSr4;
- UINT32 DcfgCcsrGenCr1;
- UINT32 DcfgCcsrGenCr2;
- UINT32 DcfgCcsrGenCr3;
- UINT32 DcfgCcsrGenCr4;
- UINT32 DcfgCcsrGenCr5;
- UINT32 DcfgCcsrGenCr6;
- UINT32 DcfgCcsrGenCr7;
- UINT8 Res63c[0x658-0x63c];
- UINT32 DcfgCcsrcGenSr1;
- UINT32 DcfgCcsrcGenSr0;
- UINT8 Res660[0x678-0x660];
- UINT32 DcfgCcsrcGenCr1;
- UINT32 DcfgCcsrcGenCr0;
- UINT8 Res680[0x700-0x680];
- UINT32 DcfgCcsrSrIoPstecr;
- UINT32 DcfgCcsrDcsrCr;
- UINT8 Res708[0x740-0x708]; /* add more registers when needed */
- UINT32 TpItyp[64]; /* Topology Initiator Type Register */
- struct {
- UINT32 Upper;
- UINT32 Lower;
- } TpCluster[16];
- UINT8 Res8c0[0xa00-0x8c0]; /* add more registers when needed */
- UINT32 DcfgCcsrQmBmWarmRst;
- UINT8 Resa04[0xa20-0xa04]; /* add more registers when needed */
- UINT32 DcfgCcsrReserved0;
- UINT32 DcfgCcsrReserved1;
} CCSR_GUR;

-/* Supplemental Configuration Unit */
-typedef struct {
- UINT8 Res000[0x070-0x000];
- UINT32 Usb1Prm1Cr;
- UINT32 Usb1Prm2Cr;
- UINT32 Usb1Prm3Cr;
- UINT32 Usb2Prm1Cr;
- UINT32 Usb2Prm2Cr;
- UINT32 Usb2Prm3Cr;
- UINT32 Usb3Prm1Cr;
- UINT32 Usb3Prm2Cr;
- UINT32 Usb3Prm3Cr;
- UINT8 Res094[0x100-0x094];
- UINT32 Usb2Icid;
- UINT32 Usb3Icid;
- UINT8 Res108[0x114-0x108];
- UINT32 DmaIcid;
- UINT32 SataIcid;
- UINT32 Usb1Icid;
- UINT32 QeIcid;
- UINT32 SdhcIcid;
- UINT32 EdmaIcid;
- UINT32 EtrIcid;
- UINT32 Core0SftRst;
- UINT32 Core1SftRst;
- UINT32 Core2SftRst;
- UINT32 Core3SftRst;
- UINT8 Res140[0x158-0x140];
- UINT32 AltCBar;
- UINT32 QspiCfg;
- UINT8 Res160[0x180-0x160];
- UINT32 DmaMcr;
- UINT8 Res184[0x188-0x184];
- UINT32 GicAlign;
- UINT32 DebugIcid;
- UINT8 Res190[0x1a4-0x190];
- UINT32 SnpCnfGcr;
-#define CCSR_SCFG_SNPCNFGCR_SECRDSNP BIT31
-#define CCSR_SCFG_SNPCNFGCR_SECWRSNP BIT30
-#define CCSR_SCFG_SNPCNFGCR_SATARDSNP BIT23
-#define CCSR_SCFG_SNPCNFGCR_SATAWRSNP BIT22
-#define CCSR_SCFG_SNPCNFGCR_USB1RDSNP BIT21
-#define CCSR_SCFG_SNPCNFGCR_USB1WRSNP BIT20
-#define CCSR_SCFG_SNPCNFGCR_USB2RDSNP BIT15
-#define CCSR_SCFG_SNPCNFGCR_USB2WRSNP BIT16
-#define CCSR_SCFG_SNPCNFGCR_USB3RDSNP BIT13
-#define CCSR_SCFG_SNPCNFGCR_USB3WRSNP BIT14
- UINT8 Res1a8[0x1ac-0x1a8];
- UINT32 IntpCr;
- UINT8 Res1b0[0x204-0x1b0];
- UINT32 CoreSrEnCr;
- UINT8 Res208[0x220-0x208];
- UINT32 RvBar00;
- UINT32 RvBar01;
- UINT32 RvBar10;
- UINT32 RvBar11;
- UINT32 RvBar20;
- UINT32 RvBar21;
- UINT32 RvBar30;
- UINT32 RvBar31;
- UINT32 LpmCsr;
- UINT8 Res244[0x400-0x244];
- UINT32 QspIdQScr;
- UINT32 EcgTxcMcr;
- UINT32 SdhcIoVSelCr;
- UINT32 RcwPMuxCr0;
- /**Setting RCW PinMux Register bits 17-19 to select USB2_DRVVBUS
- *Setting RCW PinMux Register bits 21-23 to select USB2_PWRFAULT
- *Setting RCW PinMux Register bits 25-27 to select USB3_DRVVBUS
- Setting RCW PinMux Register bits 29-31 to select USB3_DRVVBUS*/
-#define CCSR_SCFG_RCWPMUXCRO_SELCR_USB 0x3333
- /**Setting RCW PinMux Register bits 17-19 to select USB2_DRVVBUS
- *Setting RCW PinMux Register bits 21-23 to select USB2_PWRFAULT
- *Setting RCW PinMux Register bits 25-27 to select IIC4_SCL
- Setting RCW PinMux Register bits 29-31 to select IIC4_SDA*/
-#define CCSR_SCFG_RCWPMUXCRO_NOT_SELCR_USB 0x3300
- UINT32 UsbDrvVBusSelCr;
-#define CCSR_SCFG_USBDRVVBUS_SELCR_USB1 0x00000000
-#define CCSR_SCFG_USBDRVVBUS_SELCR_USB2 0x00000001
-#define CCSR_SCFG_USBDRVVBUS_SELCR_USB3 0x00000003
- UINT32 UsbPwrFaultSelCr;
-#define CCSR_SCFG_USBPWRFAULT_INACTIVE 0x00000000
-#define CCSR_SCFG_USBPWRFAULT_SHARED 0x00000001
-#define CCSR_SCFG_USBPWRFAULT_DEDICATED 0x00000002
-#define CCSR_SCFG_USBPWRFAULT_USB3_SHIFT 4
-#define CCSR_SCFG_USBPWRFAULT_USB2_SHIFT 2
-#define CCSR_SCFG_USBPWRFAULT_USB1_SHIFT 0
- UINT32 UsbRefclkSelcr1;
- UINT32 UsbRefclkSelcr2;
- UINT32 UsbRefclkSelcr3;
- UINT8 Res424[0x600-0x424];
- UINT32 ScratchRw[4];
- UINT8 Res610[0x680-0x610];
- UINT32 CoreBCr;
- UINT8 Res684[0x1000-0x684];
- UINT32 Pex1MsiIr;
- UINT32 Pex1MsiR;
- UINT8 Res1008[0x2000-0x1008];
- UINT32 Pex2;
- UINT32 Pex2MsiR;
- UINT8 Res2008[0x3000-0x2008];
- UINT32 Pex3MsiIr;
- UINT32 Pex3MsiR;
-} CCSR_SCFG;
-
-#define USB_TXVREFTUNE 0x9
-#define USB_SQRXTUNE 0xFC7FFFFF
-#define USB_PCSTXSWINGFULL 0x47
-#define USB_PHY_RX_EQ_VAL_1 0x0000
-#define USB_PHY_RX_EQ_VAL_2 0x8000
-#define USB_PHY_RX_EQ_VAL_3 0x8003
-#define USB_PHY_RX_EQ_VAL_4 0x800b
-
-/*USB_PHY_SS memory map*/
-typedef struct {
- UINT16 IpIdcodeLo;
- UINT16 SupIdcodeHi;
- UINT8 Res4[0x0006-0x0004];
- UINT16 RtuneDebug;
- UINT16 RtuneStat;
- UINT16 SupSsPhase;
- UINT16 SsFreq;
- UINT8 ResE[0x0020-0x000e];
- UINT16 Ateovrd;
- UINT16 MpllOvrdInLo;
- UINT8 Res24[0x0026-0x0024];
- UINT16 SscOvrdIn;
- UINT8 Res28[0x002A-0x0028];
- UINT16 LevelOvrdIn;
- UINT8 Res2C[0x0044-0x002C];
- UINT16 ScopeCount;
- UINT8 Res46[0x0060-0x0046];
- UINT16 MpllLoopCtl;
- UINT8 Res62[0x006C-0x0062];
- UINT16 SscClkCntrl;
- UINT8 Res6E[0x2002-0x006E];
- UINT16 Lane0TxOvrdInHi;
- UINT16 Lane0TxOvrdDrvLo;
- UINT8 Res2006[0x200C-0x2006];
- UINT16 Lane0RxOvrdInHi;
- UINT8 Res200E[0x2022-0x200E];
- UINT16 Lane0TxCmWaitTimeOvrd;
- UINT8 Res2024[0x202A-0x2024];
- UINT16 Lane0TxLbertCtl;
- UINT16 Lane0RxLbertCtl;
- UINT16 Lane0RxLbertErr;
- UINT8 Res2030[0x205A-0x2030];
- UINT16 Lane0TxAltBlock;
-} CCSR_USB_PHY;
-
-/* Clocking */
-typedef struct {
- struct {
- UINT32 ClkCnCSr; /* core cluster n clock control status */
- UINT8 Res004[0x0c];
- UINT32 ClkcGHwAcSr; /* Clock generator n hardware accelerator */
- UINT8 Res014[0x0c];
- } ClkcSr[4];
- UINT8 Res040[0x780]; /* 0x100 */
- struct {
- UINT32 PllCnGSr;
- UINT8 Res804[0x1c];
- } PllCgSr[NUM_CC_PLLS];
- UINT8 Res840[0x1c0];
- UINT32 ClkPCSr; /* 0xa00 Platform clock domain control/status */
- UINT8 Resa04[0x1fc];
- UINT32 PllPGSr; /* 0xc00 Platform PLL General Status */
- UINT8 Resc04[0x1c];
- UINT32 PllDGSr; /* 0xc20 DDR PLL General Status */
- UINT8 Resc24[0x3dc];
-} CCSR_CLOCK;
-
VOID
GetSysInfo (
OUT SYS_INFO *
diff --git a/Silicon/NXP/LS1043A/Include/SocSerDes.h b/Silicon/NXP/LS1043A/Include/SocSerDes.h
deleted file mode 100644
index 2d1c6f10f932..000000000000
--- a/Silicon/NXP/LS1043A/Include/SocSerDes.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/** @file
- The Header file of SerDes Module for LS1043A
-
- Copyright 2017-2019 NXP
-
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifndef SOC_SERDES_H_
-#define SOC_SERDES_H_
-
-#ifdef CHASSIS2
-#include <Chassis2/LsSerDes.h>
-#endif
-
-SERDES_CONFIG SerDes1ConfigTbl[] = {
- /* SerDes 1 */
- {0x1555, {XfiFm1Mac9, Pcie1, Pcie2, Pcie3 } },
- {0x2555, {Sgmii2500Fm1Dtsec9, Pcie1, Pcie2, Pcie3 } },
- {0x4555, {QsgmiiFm1A, Pcie1, Pcie2, Pcie3 } },
- {0x4558, {QsgmiiFm1A, Pcie1, Pcie2, Sata } },
- {0x1355, {XfiFm1Mac9, SgmiiFm1Dtsec2, Pcie2, Pcie3 } },
- {0x2355, {Sgmii2500Fm1Dtsec9, SgmiiFm1Dtsec2, Pcie2, Pcie3 } },
- {0x3335, {SgmiiFm1Dtsec9, SgmiiFm1Dtsec2, SgmiiFm1Dtsec5, Pcie3 } },
- {0x3355, {SgmiiFm1Dtsec9, SgmiiFm1Dtsec2, Pcie2, Pcie3 } },
- {0x3358, {SgmiiFm1Dtsec9, SgmiiFm1Dtsec2, Pcie2, Sata } },
- {0x3555, {SgmiiFm1Dtsec9, Pcie1, Pcie2, Pcie3 } },
- {0x3558, {SgmiiFm1Dtsec9, Pcie1, Pcie2, Sata } },
- {0x7000, {Pcie1, Pcie1, Pcie1, Pcie1 } },
- {0x9998, {Pcie1, Pcie2, Pcie3, Sata } },
- {0x6058, {Pcie1, Pcie1, Pcie2, Sata } },
- {0x1455, {XfiFm1Mac9, QsgmiiFm1A, Pcie2, Pcie3 } },
- {0x2455, {Sgmii2500Fm1Dtsec9, QsgmiiFm1A, Pcie2, Pcie3 } },
- {0x2255, {Sgmii2500Fm1Dtsec9, Sgmii2500Fm1Dtsec2, Pcie2, Pcie3 } },
- {0x3333, {SgmiiFm1Dtsec9, SgmiiFm1Dtsec2, SgmiiFm1Dtsec5, SgmiiFm1Dtsec6 } },
- {0x1460, {XfiFm1Mac9, QsgmiiFm1A, Pcie3, Pcie3 } },
- {0x2460, {Sgmii2500Fm1Dtsec9, QsgmiiFm1A, Pcie3, Pcie3 } },
- {0x3460, {SgmiiFm1Dtsec9, QsgmiiFm1A, Pcie3, Pcie3 } },
- {0x3455, {SgmiiFm1Dtsec9, QsgmiiFm1A, Pcie2, Pcie3 } },
- {0x9960, {Pcie1, Pcie2, Pcie3, Pcie3 } },
- {0x2233, {Sgmii2500Fm1Dtsec9, SgmiiFm1Dtsec2, SgmiiFm1Dtsec5, SgmiiFm1Dtsec6 }},
- {0x2533, {Sgmii2500Fm1Dtsec9, Pcie1, SgmiiFm1Dtsec5, SgmiiFm1Dtsec6 } },
- {}
-};
-
-SERDES_CONFIG *SerDesConfigTbl[] = {
- SerDes1ConfigTbl
-};
-
-#endif /* SOC_SERDES_H_ */
diff --git a/Silicon/NXP/LS1043A/LS1043A.dsc.inc b/Silicon/NXP/LS1043A/LS1043A.dsc.inc
index f6f15a482a85..f57a0d95b8e1 100644
--- a/Silicon/NXP/LS1043A/LS1043A.dsc.inc
+++ b/Silicon/NXP/LS1043A/LS1043A.dsc.inc
@@ -34,12 +34,10 @@ [PcdsFixedAtBuild.common]
#
gNxpQoriqLsTokenSpaceGuid.PcdCcsrBaseAddr|0x01000000
gNxpQoriqLsTokenSpaceGuid.PcdCcsrSize|0x0F000000
- gNxpQoriqLsTokenSpaceGuid.PcdClkBaseAddr|0x01EE1000
gNxpQoriqLsTokenSpaceGuid.PcdIfcRegion1BaseAddr|0x60000000
gNxpQoriqLsTokenSpaceGuid.PcdIfcRegion1Size|0x20000000
gNxpQoriqLsTokenSpaceGuid.PcdIfcRegion2BaseAddr|0x0620000000
gNxpQoriqLsTokenSpaceGuid.PcdIfcRegion2Size|0x00E0000000
- gNxpQoriqLsTokenSpaceGuid.PcdIfcNandReservedSize|0x2EA
gNxpQoriqLsTokenSpaceGuid.PcdQmanSwpBaseAddr|0x0500000000
gNxpQoriqLsTokenSpaceGuid.PcdQmanSwpSize|0x0080000000
gNxpQoriqLsTokenSpaceGuid.PcdBmanSwpBaseAddr|0x0508000000
@@ -50,10 +48,7 @@ [PcdsFixedAtBuild.common]
gNxpQoriqLsTokenSpaceGuid.PcdPciExp2BaseSize|0x800000000
gNxpQoriqLsTokenSpaceGuid.PcdPciExp3BaseAddr|0x5000000000
gNxpQoriqLsTokenSpaceGuid.PcdPciExp3BaseSize|0x800000000
- gNxpQoriqLsTokenSpaceGuid.PcdScfgBaseAddr|0x1570000
gNxpQoriqLsTokenSpaceGuid.PcdGutsBaseAddr|0x01EE0000
- gNxpQoriqLsTokenSpaceGuid.PcdWatchdog1BaseAddr|0x02AD0000
- gNxpQoriqLsTokenSpaceGuid.PcdSdxcBaseAddr|0x01560000
gNxpQoriqLsTokenSpaceGuid.PcdI2c0BaseAddr|0x02180000
gNxpQoriqLsTokenSpaceGuid.PcdI2cSize|0x10000
gNxpQoriqLsTokenSpaceGuid.PcdNumI2cController|4
@@ -64,6 +59,5 @@ [PcdsFixedAtBuild.common]
# Big Endian IPs
#
gNxpQoriqLsTokenSpaceGuid.PcdGurBigEndian|TRUE
- gNxpQoriqLsTokenSpaceGuid.PcdWatchdogBigEndian|TRUE

##
diff --git a/Silicon/NXP/Library/SocLib/Chassis.c b/Silicon/NXP/Library/SocLib/Chassis.c
index 2f192e890bcf..847331a63152 100644
--- a/Silicon/NXP/Library/SocLib/Chassis.c
+++ b/Silicon/NXP/Library/SocLib/Chassis.c
@@ -25,16 +25,6 @@
#include <DramInfo.h>
#include "NxpChassis.h"

-/*
- * Structure to list available SOCs.
- * Name, Soc Version, Number of Cores
- */
-STATIC CPU_TYPE mCpuTypeList[] = {
- CPU_TYPE_ENTRY (LS1043A, LS1043A, 4),
- CPU_TYPE_ENTRY (LS1046A, LS1046A, 4),
- CPU_TYPE_ENTRY (LS2088A, LS2088A, 8),
-};
-
UINT32
EFIAPI
GurRead (
@@ -48,174 +38,6 @@ GurRead (
}
}

-/*
- * Return the type of initiator (core or hardware accelerator)
- */
-UINT32
-InitiatorType (
- IN UINT32 Cluster,
- IN UINTN InitId
- )
-{
- CCSR_GUR *GurBase;
- UINT32 Idx;
- UINT32 Type;
-
- GurBase = (VOID *)PcdGet64 (PcdGutsBaseAddr);
- Idx = (Cluster >> (InitId * 8)) & TP_CLUSTER_INIT_MASK;
- Type = GurRead ((UINTN)&GurBase->TpItyp[Idx]);
-
- if (Type & TP_ITYP_AV_MASK) {
- return Type;
- }
-
- return 0;
-}
-
-/*
- * Return the mask for number of cores on this SOC.
- */
-UINT32
-CpuMask (
- VOID
- )
-{
- CCSR_GUR *GurBase;
- UINTN ClusterIndex;
- UINTN Count;
- UINT32 Cluster;
- UINT32 Type;
- UINT32 Mask;
- UINTN InitiatorIndex;
-
- GurBase = (VOID *)PcdGet64 (PcdGutsBaseAddr);
- ClusterIndex = 0;
- Count = 0;
- Mask = 0;
-
- do {
- Cluster = GurRead ((UINTN)&GurBase->TpCluster[ClusterIndex].Lower);
- for (InitiatorIndex = 0; InitiatorIndex < TP_INIT_PER_CLUSTER; InitiatorIndex++) {
- Type = InitiatorType (Cluster, InitiatorIndex);
- if (Type) {
- if (TP_ITYP_TYPE_MASK (Type) == TP_ITYP_TYPE_ARM) {
- Mask |= 1 << Count;
- }
- Count++;
- }
- }
- ClusterIndex++;
- } while (CHECK_CLUSTER (Cluster));
-
- return Mask;
-}
-
-/*
- * Return the number of cores on this SOC.
- */
-UINTN
-CpuNumCores (
- VOID
- )
-{
- UINTN Count;
- UINTN Num;
-
- Count = 0;
- Num = CpuMask ();
-
- while (Num) {
- Count += Num & 1;
- Num >>= 1;
- }
-
- return Count;
-}
-
-/*
- * Return core's cluster
- */
-INT32
-QoriqCoreToCluster (
- IN UINTN Core
- )
-{
- CCSR_GUR *GurBase;
- UINTN ClusterIndex;
- UINTN Count;
- UINT32 Cluster;
- UINT32 Type;
- UINTN InitiatorIndex;
-
- GurBase = (VOID *)PcdGet64 (PcdGutsBaseAddr);
- ClusterIndex = 0;
- Count = 0;
- do {
- Cluster = GurRead ((UINTN)&GurBase->TpCluster[ClusterIndex].Lower);
- for (InitiatorIndex = 0; InitiatorIndex < TP_INIT_PER_CLUSTER; InitiatorIndex++) {
- Type = InitiatorType (Cluster, InitiatorIndex);
- if (Type) {
- if (Count == Core) {
- return ClusterIndex;
- }
- Count++;
- }
- }
- ClusterIndex++;
- } while (CHECK_CLUSTER (Cluster));
-
- return -1; // cannot identify the cluster
-}
-
-/*
- * Return the type of core i.e. A53, A57 etc of inputted
- * core number.
- */
-UINTN
-QoriqCoreToType (
- IN UINTN Core
- )
-{
- CCSR_GUR *GurBase;
- UINTN ClusterIndex;
- UINTN Count;
- UINT32 Cluster;
- UINT32 Type;
- UINTN InitiatorIndex;
-
- GurBase = (VOID *)PcdGet64 (PcdGutsBaseAddr);
- ClusterIndex = 0;
- Count = 0;
-
- do {
- Cluster = GurRead ((UINTN)&GurBase->TpCluster[ClusterIndex].Lower);
- for (InitiatorIndex = 0; InitiatorIndex < TP_INIT_PER_CLUSTER; InitiatorIndex++) {
- Type = InitiatorType (Cluster, InitiatorIndex);
- if (Type) {
- if (Count == Core) {
- return Type;
- }
- Count++;
- }
- }
- ClusterIndex++;
- } while (CHECK_CLUSTER (Cluster));
-
- return EFI_NOT_FOUND; /* cannot identify the cluster */
-}
-
-STATIC
-UINTN
-CpuMaskNext (
- IN UINTN Cpu,
- IN UINTN Mask
- )
-{
- for (Cpu++; !((1 << Cpu) & Mask); Cpu++);
-
- return Cpu;
-}
-
/*
* Return system bus frequency
*/
@@ -231,21 +53,6 @@ GetBusFrequency (
return SocSysInfo.FreqSystemBus;
}

-/*
- * Return SDXC bus frequency
- */
-UINT64
-GetSdxcFrequency (
- VOID
- )
-{
- SYS_INFO SocSysInfo;
-
- GetSysInfo (&SocSysInfo);
-
- return SocSysInfo.FreqSdhc;
-}
-
/*
* Setup SMMU in bypass mode
* and also set its pagesize
@@ -268,33 +75,6 @@ SmmuInit (
MmioWrite32 ((UINTN)SMMU_REG_NSCR0, Value);
}

-/*
- * Return current Soc Name form mCpuTypeList
- */
-CHAR8 *
-GetSocName (
- VOID
- )
-{
- UINT8 Count;
- UINTN Svr;
- UINTN Ver;
- CCSR_GUR *GurBase;
-
- GurBase = (VOID *)PcdGet64 (PcdGutsBaseAddr);
-
- Svr = GurRead ((UINTN)&GurBase->Svr);
- Ver = SVR_SOC_VER (Svr);
-
- for (Count = 0; Count < ARRAY_SIZE (mCpuTypeList); Count++) {
- if ((mCpuTypeList[Count].SocVer & SVR_WO_E) == Ver) {
- return (CHAR8 *)mCpuTypeList[Count].Name;
- }
- }
-
- return NULL;
-}
-
UINTN
GetDramSize (
IN VOID
diff --git a/Silicon/NXP/Library/SocLib/Chassis2/Soc.c b/Silicon/NXP/Library/SocLib/Chassis2/Soc.c
index 687a1d940066..d992e53546f4 100644
--- a/Silicon/NXP/Library/SocLib/Chassis2/Soc.c
+++ b/Silicon/NXP/Library/SocLib/Chassis2/Soc.c
@@ -32,38 +32,14 @@ GetSysInfo (
)
{
CCSR_GUR *GurBase;
- CCSR_CLOCK *ClkBase;
- UINTN CpuIndex;
- UINT32 TempRcw;
- UINT32 CPllSel;
- UINT32 CplxPll;
- CONST UINT8 CoreCplxPll[8] = {
- [0] = 0, /* CC1 PPL / 1 */
- [1] = 0, /* CC1 PPL / 2 */
- [4] = 1, /* CC2 PPL / 1 */
- [5] = 1, /* CC2 PPL / 2 */
- };
-
- CONST UINT8 CoreCplxPllDivisor[8] = {
- [0] = 1, /* CC1 PPL / 1 */
- [1] = 2, /* CC1 PPL / 2 */
- [4] = 1, /* CC2 PPL / 1 */
- [5] = 2, /* CC2 PPL / 2 */
- };
-
- UINTN PllCount;
- UINTN FreqCPll[NUM_CC_PLLS];
- UINTN PllRatio[NUM_CC_PLLS];
UINTN SysClk;

GurBase = (VOID *)PcdGet64 (PcdGutsBaseAddr);
- ClkBase = (VOID *)PcdGet64 (PcdClkBaseAddr);
SysClk = CLK_FREQ;

SetMem (PtrSysInfo, sizeof (SYS_INFO), 0);

PtrSysInfo->FreqSystemBus = SysClk;
- PtrSysInfo->FreqDdrBus = SysClk;

//
// selects the platform clock:SYSCLK ratio and calculate
@@ -72,61 +48,6 @@ GetSysInfo (
PtrSysInfo->FreqSystemBus *= (GurRead ((UINTN)&GurBase->RcwSr[0]) >>
CHASSIS2_RCWSR0_SYS_PLL_RAT_SHIFT) &
CHASSIS2_RCWSR0_SYS_PLL_RAT_MASK;
- //
- // selects the DDR PLL:SYSCLK Ratio and calculate DDR frequency
- //
- PtrSysInfo->FreqDdrBus *= (GurRead ((UINTN)&GurBase->RcwSr[0]) >>
- CHASSIS2_RCWSR0_MEM_PLL_RAT_SHIFT) &
- CHASSIS2_RCWSR0_MEM_PLL_RAT_MASK;
-
- for (PllCount = 0; PllCount < NUM_CC_PLLS; PllCount++) {
- PllRatio[PllCount] = (GurRead ((UINTN)&ClkBase->PllCgSr[PllCount].PllCnGSr) >> 1) & 0xff;
- if (PllRatio[PllCount] > 4) {
- FreqCPll[PllCount] = SysClk * PllRatio[PllCount];
- } else {
- FreqCPll[PllCount] = PtrSysInfo->FreqSystemBus * PllRatio[PllCount];
- }
- }
-
- //
- // Calculate Core frequency
- //
- for (CpuIndex = 0; CpuIndex < MAX_CPUS; CpuIndex++) {
- CPllSel = (GurRead ((UINTN)&ClkBase->ClkcSr[CpuIndex].ClkCnCSr) >> 27) & 0xf;
- CplxPll = CoreCplxPll[CPllSel];
-
- PtrSysInfo->FreqProcessor[CpuIndex] = FreqCPll[CplxPll] / CoreCplxPllDivisor[CPllSel];
- }
-
- //
- // Calculate FMAN frequency
- //
- TempRcw = GurRead ((UINTN)&GurBase->RcwSr[7]);
- switch ((TempRcw & HWA_CGA_M1_CLK_SEL) >> HWA_CGA_M1_CLK_SHIFT) {
- case 2:
- PtrSysInfo->FreqFman[0] = FreqCPll[0] / 2;
- break;
- case 3:
- PtrSysInfo->FreqFman[0] = FreqCPll[0] / 3;
- break;
- case 4:
- PtrSysInfo->FreqFman[0] = FreqCPll[0] / 4;
- break;
- case 5:
- PtrSysInfo->FreqFman[0] = PtrSysInfo->FreqSystemBus;
- break;
- case 6:
- PtrSysInfo->FreqFman[0] = FreqCPll[1] / 2;
- break;
- case 7:
- PtrSysInfo->FreqFman[0] = FreqCPll[1] / 3;
- break;
- default:
- DEBUG ((DEBUG_WARN, "Error: Unknown FMan1 clock select!\n"));
- break;
- }
- PtrSysInfo->FreqSdhc = PtrSysInfo->FreqSystemBus/PcdGet32 (PcdPlatformFreqDiv);
- PtrSysInfo->FreqQman = PtrSysInfo->FreqSystemBus/PcdGet32 (PcdPlatformFreqDiv);
}

/**
diff --git a/Silicon/NXP/Library/SocLib/LS1043aSocLib.inf b/Silicon/NXP/Library/SocLib/LS1043aSocLib.inf
index cb670a12797e..f75a8d19f5a5 100644
--- a/Silicon/NXP/Library/SocLib/LS1043aSocLib.inf
+++ b/Silicon/NXP/Library/SocLib/LS1043aSocLib.inf
@@ -1,6 +1,6 @@
# @file
#
-# Copyright 2017-2019 NXP
+# Copyright 2017-2020 NXP
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -18,7 +18,6 @@ [Packages]
MdeModulePkg/MdeModulePkg.dec
MdePkg/MdePkg.dec
Silicon/NXP/NxpQoriqLs.dec
- Silicon/NXP/LS1043A/LS1043A.dec

[LibraryClasses]
ArmSmcLib
@@ -30,16 +29,12 @@ [LibraryClasses]
[Sources.common]
Chassis.c
Chassis2/Soc.c
- SerDes.c

[BuildOptions]
GCC:*_*_*_CC_FLAGS = -DCHASSIS2

[FixedPcd]
gEfiMdeModulePkgTokenSpaceGuid.PcdFirmwareVersionString
- gNxpQoriqLsTokenSpaceGuid.PcdClkBaseAddr
gNxpQoriqLsTokenSpaceGuid.PcdGurBigEndian
gNxpQoriqLsTokenSpaceGuid.PcdGutsBaseAddr
gNxpQoriqLsTokenSpaceGuid.PcdPlatformFreqDiv
- gNxpQoriqLsTokenSpaceGuid.PcdScfgBaseAddr
- gNxpQoriqLsTokenSpaceGuid.PcdSerdes2Enabled
diff --git a/Silicon/NXP/Library/SocLib/NxpChassis.h b/Silicon/NXP/Library/SocLib/NxpChassis.h
index a11acf71563e..836df103f80f 100644
--- a/Silicon/NXP/Library/SocLib/NxpChassis.h
+++ b/Silicon/NXP/Library/SocLib/NxpChassis.h
@@ -10,58 +10,6 @@
#ifndef NXP_CHASSIS_H_
#define NXP_CHASSIS_H_

-#define TP_ITYP_AV_MASK 0x00000001 /* Initiator available */
-#define TP_ITYP_TYPE_MASK(x) (((x) & 0x6) >> 1) /* Initiator Type */
-#define TP_ITYP_TYPE_ARM 0x0
-#define TP_ITYP_TYPE_PPC 0x1
-#define TP_ITYP_TYPE_OTHER 0x2 /* StarCore DSP */
-#define TP_ITYP_TYPE_HA 0x3 /* HW Accelerator */
-#define TP_ITYP_THDS(x) (((x) & 0x18) >> 3) /* # threads */
-#define TP_ITYP_VERSION(x) (((x) & 0xe0) >> 5) /* Initiator Version */
-#define TP_CLUSTER_INIT_MASK 0x0000003f /* initiator mask */
-#define TP_INIT_PER_CLUSTER 4
-
-#define TY_ITYP_VERSION_A7 0x1
-#define TY_ITYP_VERSION_A53 0x2
-#define TY_ITYP_VERSION_A57 0x3
-#define TY_ITYP_VERSION_A72 0x4
-
-#define CPU_TYPE_ENTRY(N, V, NC) { .Name = #N, .SocVer = SVR_##V, .NumCores = (NC)}
-
-#define SVR_WO_E 0xFFFFFE
-#define SVR_LS1043A 0x879200
-#define SVR_LS1046A 0x870700
-#define SVR_LS2088A 0x870901
-
-#define SVR_MAJOR(svr) (((svr) >> 4) & 0xf)
-#define SVR_MINOR(svr) (((svr) >> 0) & 0xf)
-#define SVR_SOC_VER(svr) (((svr) >> 8) & SVR_WO_E)
-#define IS_E_PROCESSOR(svr) (!((svr >> 8) & 0x1))
-
-#define MHZ 1000000
-
-typedef struct {
- CHAR8 *Name;
- UINT32 SocVer;
- UINT32 NumCores;
-} CPU_TYPE;
-
-typedef struct {
- UINTN CpuClk; /* CPU clock in Hz! */
- UINTN BusClk;
- UINTN MemClk;
- UINTN PciClk;
- UINTN SdhcClk;
-} SOC_CLOCK_INFO;
-
-/*
- * Initialize Clock structure
- */
-VOID
-ClockInit (
- VOID
- );
-
/*
* Setup SMMU in bypass mode
* and also set its pagesize
@@ -71,42 +19,4 @@ SmmuInit (
VOID
);

-UINT32
-InitiatorType (
- IN UINT32 Cluster,
- IN UINTN InitId
- );
-
-/*
- * Return the mask for number of cores on this SOC.
- */
-UINT32
-CpuMask (
- VOID
- );
-
-/*
- * Return the number of cores on this SOC.
- */
-UINTN
-CpuNumCores (
- VOID
- );
-
-/*
- * Return the type of initiator for core/hardware accelerator for given core index.
- */
-UINTN
-QoriqCoreToType (
- IN UINTN Core
- );
-
-/*
- * Return the cluster of initiator for core/hardware accelerator for given core index.
- */
-INT32
-QoriqCoreToCluster (
- IN UINTN Core
- );
-
#endif /* NXP_CHASSIS_H_ */
diff --git a/Silicon/NXP/Library/SocLib/SerDes.c b/Silicon/NXP/Library/SocLib/SerDes.c
deleted file mode 100644
index b9909d922138..000000000000
--- a/Silicon/NXP/Library/SocLib/SerDes.c
+++ /dev/null
@@ -1,268 +0,0 @@
-/** SerDes.c
- Provides the basic interfaces for SerDes Module
-
- Copyright 2017-2019 NXP
-
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#ifdef CHASSIS2
-#include <Chassis2/LsSerDes.h>
-#include <Chassis2/NxpSoc.h>
-#elif CHASSIS3
-#include <Chassis3/LsSerDes.h>
-#include <Chassis3/NxpSoc.h>
-#endif
-#include <Library/DebugLib.h>
-#include <SocSerDes.h>
-#include <Uefi.h>
-
-/**
- Function to get serdes Lane protocol corresponding to
- serdes protocol.
-
- @param SerDes Serdes number.
- @param Cfg Serdes Protocol.
- @param Lane Serdes Lane number.
-
- @return Serdes Lane protocol.
-
-**/
-STATIC
-SERDES_PROTOCOL
-GetSerDesPrtcl (
- IN INTN SerDes,
- IN INTN Cfg,
- IN INTN Lane
- )
-{
- SERDES_CONFIG *Config;
-
- if (SerDes >= ARRAY_SIZE (SerDesConfigTbl)) {
- return 0;
- }
-
- Config = SerDesConfigTbl[SerDes];
- while (Config->Protocol) {
- if (Config->Protocol == Cfg) {
- return Config->SrdsLane[Lane];
- }
- Config++;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Function to check if inputted protocol is a valid serdes protocol.
-
- @param SerDes Serdes number.
- @param Prtcl Serdes Protocol to be verified.
-
- @return EFI_INVALID_PARAMETER Input parameter in invalid.
- @return EFI_NOT_FOUND Serdes Protocol not a valid protocol.
- @return EFI_SUCCESS Serdes Protocol is a valid protocol.
-
-**/
-STATIC
-EFI_STATUS
-CheckSerDesPrtclValid (
- IN INTN SerDes,
- IN UINT32 Prtcl
- )
-{
- SERDES_CONFIG *Config;
- INTN Cnt;
-
- if (SerDes >= ARRAY_SIZE (SerDesConfigTbl)) {
- return EFI_INVALID_PARAMETER;
- }
-
- Config = SerDesConfigTbl[SerDes];
- while (Config->Protocol) {
- if (Config->Protocol == Prtcl) {
- DEBUG ((DEBUG_INFO, "Protocol: %x Matched with the one in Table\n", Prtcl));
- break;
- }
- Config++;
- }
-
- if (!Config->Protocol) {
- return EFI_NOT_FOUND;
- }
-
- for (Cnt = 0; Cnt < SRDS_MAX_LANES; Cnt++) {
- if (Config->SrdsLane[Cnt] != None) {
- return EFI_SUCCESS;
- }
- }
-
- return EFI_NOT_FOUND;
-}
-
-/**
- Function to fill serdes map information.
-
- @param Srds Serdes number.
- @param SerdesProtocolMask Serdes Protocol Mask.
- @param SerdesProtocolShift Serdes Protocol shift value.
- @param SerDesPrtclMap Pointer to Serdes Protocol map.
-
-**/
-STATIC
-VOID
-LSSerDesMap (
- IN UINT32 Srds,
- IN UINT32 SerdesProtocolMask,
- IN UINT32 SerdesProtocolShift,
- OUT UINT64 *SerDesPrtclMap
- )
-{
- CCSR_GUR *Gur;
- UINT32 SrdsProt;
- INTN Lane;
- UINT32 Flag;
-
- Gur = (VOID *)PcdGet64 (PcdGutsBaseAddr);
- *SerDesPrtclMap = 0x0;
- Flag = 0;
-
- SrdsProt = GurRead ((UINTN)&Gur->RcwSr[RCWSR_INDEX]) & SerdesProtocolMask;
- SrdsProt >>= SerdesProtocolShift;
-
- DEBUG ((DEBUG_INFO, "Using SERDES%d Protocol: %d (0x%x)\n",
- Srds + 1, SrdsProt, SrdsProt));
-
- if (EFI_SUCCESS != CheckSerDesPrtclValid (Srds, SrdsProt)) {
- DEBUG ((DEBUG_ERROR, "SERDES%d[PRTCL] = 0x%x is not valid\n",
- Srds + 1, SrdsProt));
- Flag++;
- }
-
- for (Lane = 0; Lane < SRDS_MAX_LANES; Lane++) {
- SERDES_PROTOCOL LanePrtcl = GetSerDesPrtcl (Srds, SrdsProt, Lane);
- if (LanePrtcl >= SerdesPrtclCount) {
- DEBUG ((DEBUG_ERROR, "Unknown SerDes lane protocol %d\n", LanePrtcl));
- Flag++;
- } else {
- *SerDesPrtclMap |= (1u << LanePrtcl);
- }
- }
-
- if (Flag) {
- DEBUG ((DEBUG_ERROR, "Could not configure SerDes module!!\n"));
- } else {
- DEBUG ((DEBUG_INFO, "Successfully configured SerDes module!!\n"));
- }
-}
-
-/**
- Get lane protocol on provided serdes lane and execute callback function.
-
- @param Srds Serdes number.
- @param SerdesProtocolMask Mask to get Serdes Protocol for Srds
- @param SerdesProtocolShift Shift value to get Serdes Protocol for Srds.
- @param SerDesLaneProbeCallback Pointer Callback function to be called for Lane protocol
- @param Arg Pointer to Arguments to be passed to callback function.
-
-**/
-STATIC
-VOID
-SerDesInstanceProbeLanes (
- IN UINT32 Srds,
- IN UINT32 SerdesProtocolMask,
- IN UINT32 SerdesProtocolShift,
- IN SERDES_PROBE_LANES_CALLBACK SerDesLaneProbeCallback,
- IN VOID *Arg
- )
-{
-
- CCSR_GUR *Gur;
- UINT32 SrdsProt;
- INTN Lane;
-
- Gur = (VOID *)PcdGet64 (PcdGutsBaseAddr);;
-
- SrdsProt = GurRead ((UINTN)&Gur->RcwSr[RCWSR_INDEX]) & SerdesProtocolMask;
- SrdsProt >>= SerdesProtocolShift;
-
- /*
- * Invoke callback for all lanes in the SerDes instance:
- */
- for (Lane = 0; Lane < SRDS_MAX_LANES; Lane++) {
- SERDES_PROTOCOL LanePrtcl = GetSerDesPrtcl (Srds, SrdsProt, Lane);
- if ((LanePrtcl >= SerdesPrtclCount) || (LanePrtcl < None)) {
- DEBUG ((DEBUG_ERROR, "Unknown SerDes lane protocol %d\n", LanePrtcl));
- } else if (LanePrtcl != None) {
- SerDesLaneProbeCallback (LanePrtcl, Arg);
- }
- }
-}
-
-/**
- Probe all serdes lanes for lane protocol and execute provided callback function.
-
- @param SerDesLaneProbeCallback Pointer Callback function to be called for Lane protocol
- @param Arg Pointer to Arguments to be passed to callback function.
-
-**/
-VOID
-SerDesProbeLanes (
- IN SERDES_PROBE_LANES_CALLBACK SerDesLaneProbeCallback,
- IN VOID *Arg
- )
-{
- SerDesInstanceProbeLanes (Srds1,
- RCWSR_SRDS1_PRTCL_MASK,
- RCWSR_SRDS1_PRTCL_SHIFT,
- SerDesLaneProbeCallback,
- Arg);
-
- if (PcdGetBool (PcdSerdes2Enabled)) {
- SerDesInstanceProbeLanes (Srds2,
- RCWSR_SRDS2_PRTCL_MASK,
- RCWSR_SRDS2_PRTCL_SHIFT,
- SerDesLaneProbeCallback,
- Arg);
- }
-}
-
-/**
- Function to return Serdes protocol map for all serdes available on board.
-
- @param SerDesPrtclMap Pointer to Serdes protocl map.
-
-**/
-VOID
-GetSerdesProtocolMaps (
- OUT UINT64 *SerDesPrtclMap
- )
-{
- LSSerDesMap (Srds1,
- RCWSR_SRDS1_PRTCL_MASK,
- RCWSR_SRDS1_PRTCL_SHIFT,
- SerDesPrtclMap);
-
- if (PcdGetBool (PcdSerdes2Enabled)) {
- LSSerDesMap (Srds2,
- RCWSR_SRDS2_PRTCL_MASK,
- RCWSR_SRDS2_PRTCL_SHIFT,
- SerDesPrtclMap);
- }
-
-}
-
-BOOLEAN
-IsSerDesLaneProtocolConfigured (
- IN UINT64 SerDesPrtclMap,
- IN SERDES_PROTOCOL Device
- )
-{
- if ((Device >= SerdesPrtclCount) || (Device < None)) {
- ASSERT ((Device > None) && (Device < SerdesPrtclCount));
- DEBUG ((DEBUG_ERROR, "Unknown SerDes lane protocol Device %d\n", Device));
- }
-
- return (SerDesPrtclMap & (1u << Device)) != 0 ;
-}
diff --git a/Silicon/NXP/NxpQoriqLs.dec b/Silicon/NXP/NxpQoriqLs.dec
index 4a1cfb3e278e..943dbac81013 100644
--- a/Silicon/NXP/NxpQoriqLs.dec
+++ b/Silicon/NXP/NxpQoriqLs.dec
@@ -32,10 +32,7 @@ [PcdsFixedAtBuild.common]
# Pcds for base address and size
#
gNxpQoriqLsTokenSpaceGuid.PcdGutsBaseAddr|0x0|UINT64|0x00000100
- gNxpQoriqLsTokenSpaceGuid.PcdPiFdSize|0x0|UINT32|0x00000101
- gNxpQoriqLsTokenSpaceGuid.PcdPiFdBaseAddress|0x0|UINT64|0x00000102
gNxpQoriqLsTokenSpaceGuid.PcdClkBaseAddr|0x0|UINT64|0x00000103
- gNxpQoriqLsTokenSpaceGuid.PcdWatchdog1BaseAddr|0x0|UINT64|0x00000104
gNxpQoriqLsTokenSpaceGuid.PcdDdrBaseAddr|0x0|UINT64|0x00000105
gNxpQoriqLsTokenSpaceGuid.PcdSdxcBaseAddr|0x0|UINT64|0x00000106
gNxpQoriqLsTokenSpaceGuid.PcdScfgBaseAddr|0x0|UINT64|0x00000107
@@ -61,10 +58,6 @@ [PcdsFixedAtBuild.common]
gNxpQoriqLsTokenSpaceGuid.PcdQspiRegionSize|0x0|UINT64|0x0000011B
gNxpQoriqLsTokenSpaceGuid.PcdQspiRegion2BaseAddr|0x0|UINT64|0x0000011C
gNxpQoriqLsTokenSpaceGuid.PcdQspiRegion2Size|0x0|UINT64|0x0000011D
- gNxpQoriqLsTokenSpaceGuid.PcdSystemMemoryExBase|0x0|UINT64|0x0000011E
- gNxpQoriqLsTokenSpaceGuid.PcdSystemMemoryExSize|0x0|UINT64|0x0000011F
- gNxpQoriqLsTokenSpaceGuid.PcdUsbBaseAddr|0x0|UINT32|0x00000120
- gNxpQoriqLsTokenSpaceGuid.PcdUsbSize|0x0|UINT32|0x00000121
gNxpQoriqLsTokenSpaceGuid.PcdCcsrBaseAddr|0x0|UINT64|0x00000122
gNxpQoriqLsTokenSpaceGuid.PcdCcsrSize|0x0|UINT64|0x00000123

@@ -75,36 +68,16 @@ [PcdsFixedAtBuild.common]
gNxpQoriqLsTokenSpaceGuid.PcdIfcRegion1Size|0x0|UINT64|0x00000191
gNxpQoriqLsTokenSpaceGuid.PcdIfcRegion2BaseAddr|0x0|UINT64|0x00000192
gNxpQoriqLsTokenSpaceGuid.PcdIfcRegion2Size|0x0|UINT64|0x00000193
- gNxpQoriqLsTokenSpaceGuid.PcdIfcNandReservedSize|0x0|UINT32|0x00000194
- gNxpQoriqLsTokenSpaceGuid.PcdFlashDeviceBase64|0x0|UINT64|0x00000195
- gNxpQoriqLsTokenSpaceGuid.PcdFlashReservedRegionBase64|0x0|UINT64|0x00000196
-
- #
- # NV Pcd
- #
- gNxpQoriqLsTokenSpaceGuid.PcdNvFdBase|0x0|UINT64|0x00000210
- gNxpQoriqLsTokenSpaceGuid.PcdNvFdSize|0x0|UINT64|0x00000211

#
# Platform PCDs
#
gNxpQoriqLsTokenSpaceGuid.PcdPlatformFreqDiv|0x0|UINT32|0x00000250
- gNxpQoriqLsTokenSpaceGuid.PcdSerdes2Enabled|FALSE|BOOLEAN|0x00000251
-
- #
- # Clock PCDs
- #
- gNxpQoriqLsTokenSpaceGuid.PcdSysClk|0x0|UINT64|0x000002A0
- gNxpQoriqLsTokenSpaceGuid.PcdDdrClk|0x0|UINT64|0x000002A1

#
# Pcds to support Big Endian IPs
#
- gNxpQoriqLsTokenSpaceGuid.PcdMmcBigEndian|FALSE|BOOLEAN|0x0000310
gNxpQoriqLsTokenSpaceGuid.PcdGurBigEndian|FALSE|BOOLEAN|0x0000311
- gNxpQoriqLsTokenSpaceGuid.PcdPciLutBigEndian|FALSE|BOOLEAN|0x00000312
- gNxpQoriqLsTokenSpaceGuid.PcdWatchdogBigEndian|FALSE|BOOLEAN|0x00000313
- gNxpQoriqLsTokenSpaceGuid.PcdIfcBigEndian|FALSE|BOOLEAN|0x00000314

[PcdsFeatureFlag]
gNxpQoriqLsTokenSpaceGuid.PcdI2cErratumA009203|FALSE|BOOLEAN|0x00000315
--
2.17.1


[PATCH v2] ShellPkg: Fix 'ping' command Ip4 receive flow.

Maciej Rabeda
 

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3D2032

'ping' command's receive flow utilizes a single Rx token which it
attempts to reuse before recycling the previously received packet.
This causes a situation where under ICMP traffic,
Ping6OnEchoReplyReceived() function will receive an already
recycled packet with EFI_SUCCESS token status and finally
dereference invalid pointers from RxData structure.

Cc: Ray Ni <ray.ni@...>
Cc: Zhichao Gao <zhichao.gao@...>
Signed-off-by: Maciej Rabeda <maciej.rabeda@...>
Reviewed-by: Siyuan Fu <siyuan.fu@...>
Acked-by: Zhichao Gao <zhichao.gao@...>
---
ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c b/ShellPk=
g/Library/UefiShellNetwork1CommandsLib/Ping.c
index 23567fa2c1bb..a3fa32515192 100644
--- a/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c
+++ b/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c
@@ -614,6 +614,11 @@ Ping6OnEchoReplyReceived (
=0D
ON_EXIT:=0D
=0D
+ //=0D
+ // Recycle the packet before reusing RxToken=0D
+ //=0D
+ gBS->SignalEvent (Private->IpChoice =3D=3D PING_IP_CHOICE_IP6?((EFI_IP6_=
RECEIVE_DATA*)Private->RxToken.Packet.RxData)->RecycleSignal:((EFI_IP4_RECE=
IVE_DATA*)Private->RxToken.Packet.RxData)->RecycleSignal);=0D
+=0D
if (Private->RxCount < Private->SendNum) {=0D
//=0D
// Continue to receive icmp echo reply packets.=0D
@@ -632,10 +637,6 @@ ON_EXIT:
//=0D
Private->Status =3D EFI_SUCCESS;=0D
}=0D
- //=0D
- // Singal to recycle the each rxdata here, not at the end of process.=0D
- //=0D
- gBS->SignalEvent (Private->IpChoice =3D=3D PING_IP_CHOICE_IP6?((EFI_IP6_=
RECEIVE_DATA*)Private->RxToken.Packet.RxData)->RecycleSignal:((EFI_IP4_RECE=
IVE_DATA*)Private->RxToken.Packet.RxData)->RecycleSignal);=0D
}=0D
=0D
/**=0D
--=20
2.24.0.windows.2


Re: [PATCH v2 10/28] Silicon/NXP: remove print information from Soc lib

Leif Lindholm
 

On Fri, Mar 20, 2020 at 20:05:25 +0530, Pankaj Bansal wrote:
From: Pankaj Bansal <pankaj.bansal@...>

The Soc info being printed can be removed from SOC lib.
We are in the process of implementing PEI Phase.
After PEI phase impelmentation this info would be printed in
implementation
common PEIM based on the information retrieved from PPIs.
e.g. gArmMpCoreInfoPpiGuid can be used to print cluser and
cluster
core info.

Signed-off-by: Pankaj Bansal <pankaj.bansal@...>
With the commit message typos fixed:
Reviewed-by: Leif Lindholm <leif@...>

---
Silicon/NXP/Library/SocLib/Chassis.c | 132 ----------------------
Silicon/NXP/Library/SocLib/Chassis2/Soc.c | 16 +--
Silicon/NXP/Library/SocLib/NxpChassis.h | 26 +----
3 files changed, 2 insertions(+), 172 deletions(-)

diff --git a/Silicon/NXP/Library/SocLib/Chassis.c b/Silicon/NXP/Library/SocLib/Chassis.c
index b8a8118c5e24..2f192e890bcf 100644
--- a/Silicon/NXP/Library/SocLib/Chassis.c
+++ b/Silicon/NXP/Library/SocLib/Chassis.c
@@ -216,67 +216,6 @@ CpuMaskNext (
return Cpu;
}

-/*
- * Print CPU information
- */
-VOID
-PrintCpuInfo (
- VOID
- )
-{
- SYS_INFO SysInfo;
- UINTN CoreIndex;
- UINTN Core;
- UINT32 Type;
- UINT32 NumCpus;
- UINT32 Mask;
- CHAR8 *CoreName;
-
- GetSysInfo (&SysInfo);
- DEBUG ((DEBUG_INIT, "Clock Configuration:"));
-
- NumCpus = CpuNumCores ();
- Mask = CpuMask ();
-
- for (CoreIndex = 0, Core = CpuMaskNext(-1, Mask);
- CoreIndex < NumCpus;
- CoreIndex++, Core = CpuMaskNext(Core, Mask))
- {
- if (!(CoreIndex % 3)) {
- DEBUG ((DEBUG_INIT, "\n "));
- }
-
- Type = TP_ITYP_VERSION (QoriqCoreToType (Core));
- switch (Type) {
- case TY_ITYP_VERSION_A7:
- CoreName = "A7";
- break;
- case TY_ITYP_VERSION_A53:
- CoreName = "A53";
- break;
- case TY_ITYP_VERSION_A57:
- CoreName = "A57";
- break;
- case TY_ITYP_VERSION_A72:
- CoreName = "A72";
- break;
- default:
- CoreName = " Unknown Core ";
- }
- DEBUG ((DEBUG_INIT, "CPU%d(%a):%-4d MHz ",
- Core, CoreName, SysInfo.FreqProcessor[Core] / MHZ));
- }
-
- DEBUG ((DEBUG_INIT, "\n Bus: %-4d MHz ", SysInfo.FreqSystemBus / MHZ));
- DEBUG ((DEBUG_INIT, "DDR: %-4d MT/s", SysInfo.FreqDdrBus / MHZ));
-
- if (SysInfo.FreqFman[0] != 0) {
- DEBUG ((DEBUG_INIT, "\n FMAN: %-4d MHz ", SysInfo.FreqFman[0] / MHZ));
- }
-
- DEBUG ((DEBUG_INIT, "\n"));
-}
-
/*
* Return system bus frequency
*/
@@ -307,77 +246,6 @@ GetSdxcFrequency (
return SocSysInfo.FreqSdhc;
}

-/*
- * Print Soc information
- */
-VOID
-PrintSoc (
- VOID
- )
-{
- CHAR8 Buf[20];
- CCSR_GUR *GurBase;
- UINTN Count;
- //
- // Svr : System Version Register
- //
- UINTN Svr;
- UINTN Ver;
-
- GurBase = (VOID *)PcdGet64 (PcdGutsBaseAddr);
-
- Svr = GurRead ((UINTN)&GurBase->Svr);
- Ver = SVR_SOC_VER (Svr);
-
- for (Count = 0; Count < ARRAY_SIZE (mCpuTypeList); Count++) {
- if ((mCpuTypeList[Count].SocVer & SVR_WO_E) == Ver) {
- AsciiStrCpyS (Buf, sizeof (Buf), mCpuTypeList[Count].Name);
-
- if (IS_E_PROCESSOR (Svr)) {
- AsciiStrCatS (Buf, sizeof (Buf), "E");
- }
- break;
- }
- }
-
- DEBUG ((DEBUG_INFO, "SoC: %a (0x%x); Rev %d.%d\n",
- Buf, Svr, SVR_MAJOR (Svr), SVR_MINOR (Svr)));
-
- return;
-}
-
-/*
- * Dump RCW (Reset Control Word) on console
- */
-VOID
-PrintRCW (
- VOID
- )
-{
- CCSR_GUR *Base;
- UINTN Count;
-
- Base = (VOID *)PcdGet64 (PcdGutsBaseAddr);
-
- /*
- * Display the RCW, so that no one gets confused as to what RCW
- * we're actually using for this boot.
- */
-
- DEBUG ((DEBUG_INIT, "Reset Configuration Word (RCW):"));
- for (Count = 0; Count < ARRAY_SIZE (Base->RcwSr); Count++) {
- UINT32 Rcw = SwapMmioRead32 ((UINTN)&Base->RcwSr[Count]);
-
- if ((Count % 4) == 0) {
- DEBUG ((DEBUG_INIT, "\n %08x:", Count * 4));
- }
-
- DEBUG ((DEBUG_INIT, " %08x", Rcw));
- }
-
- DEBUG ((DEBUG_INIT, "\n"));
-}
-
/*
* Setup SMMU in bypass mode
* and also set its pagesize
diff --git a/Silicon/NXP/Library/SocLib/Chassis2/Soc.c b/Silicon/NXP/Library/SocLib/Chassis2/Soc.c
index bfb8b8cb339a..687a1d940066 100644
--- a/Silicon/NXP/Library/SocLib/Chassis2/Soc.c
+++ b/Silicon/NXP/Library/SocLib/Chassis2/Soc.c
@@ -1,7 +1,7 @@
/** @Soc.c
SoC specific Library containg functions to initialize various SoC components

- Copyright 2017-2019 NXP
+ Copyright 2017-2020 NXP

SPDX-License-Identifier: BSD-2-Clause-Patent

@@ -131,10 +131,6 @@ GetSysInfo (

/**
Function to initialize SoC specific constructs
- CPU Info
- SoC Personality
- Board Personality
- RCW prints
**/
VOID
SocInit (
@@ -147,16 +143,6 @@ SocInit (
// Early init serial Port to get board information.
//
SerialPortInitialize ();
- DEBUG ((DEBUG_INIT, "\nUEFI firmware (version %s built at %a on %a)\n",
- (CHAR16*)PcdGetPtr (PcdFirmwareVersionString), __TIME__, __DATE__));
-
- PrintCpuInfo ();
-
- //
- // Print Reset control Word
- //
- PrintRCW ();
- PrintSoc ();

return;
}
diff --git a/Silicon/NXP/Library/SocLib/NxpChassis.h b/Silicon/NXP/Library/SocLib/NxpChassis.h
index 99f6439d8f35..a11acf71563e 100644
--- a/Silicon/NXP/Library/SocLib/NxpChassis.h
+++ b/Silicon/NXP/Library/SocLib/NxpChassis.h
@@ -1,7 +1,7 @@
/** @file
* Header defining the Base addresses, sizes, flags etc for chassis 1
*
-* Copyright 2017-2019 NXP
+* Copyright 2017-2020 NXP
*
* SPDX-License-Identifier: BSD-2-Clause-Patent
*
@@ -54,14 +54,6 @@ typedef struct {
UINTN SdhcClk;
} SOC_CLOCK_INFO;

-/*
- * Print Soc information
- */
-VOID
-PrintSoc (
- VOID
- );
-
/*
* Initialize Clock structure
*/
@@ -79,22 +71,6 @@ SmmuInit (
VOID
);

-/*
- * Print CPU information
- */
-VOID
-PrintCpuInfo (
- VOID
- );
-
-/*
- * Dump RCW (Reset Control Word) on console
- */
-VOID
-PrintRCW (
- VOID
- );
-
UINT32
InitiatorType (
IN UINT32 Cluster,
--
2.17.1


Re: [PATCH v2 09/28] Silicon/NXP: Drop DUartPortLib

Leif Lindholm
 

On Fri, Mar 20, 2020 at 20:05:24 +0530, Pankaj Bansal wrote:
From: Pankaj Bansal <pankaj.bansal@...>

DUartPortLib is for ns16550 compatible UART in LS1043A. Therefore, we can
remove it and use BaseSerialPortLib16550.

Signed-off-by: Pankaj Bansal <pankaj.bansal@...>
Reviewed-by: Leif Lindholm <leif@...>

---
Silicon/NXP/Library/DUartPortLib/DUart.h | 122 ------
.../NXP/Library/DUartPortLib/DUartPortLib.c | 364 ------------------
.../NXP/Library/DUartPortLib/DUartPortLib.inf | 34 --
3 files changed, 520 deletions(-)
delete mode 100644 Silicon/NXP/Library/DUartPortLib/DUart.h
delete mode 100644 Silicon/NXP/Library/DUartPortLib/DUartPortLib.c
delete mode 100644 Silicon/NXP/Library/DUartPortLib/DUartPortLib.inf

diff --git a/Silicon/NXP/Library/DUartPortLib/DUart.h b/Silicon/NXP/Library/DUartPortLib/DUart.h
deleted file mode 100644
index c71e2ce55d1d..000000000000
--- a/Silicon/NXP/Library/DUartPortLib/DUart.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/** DUart.h
-* Header defining the DUART constants (Base addresses, sizes, flags)
-*
-* Based on Serial I/O Port library headers available in PL011Uart.h
-*
-* Copyright (c) 2011-2012, ARM Limited. All rights reserved.
-* Copyright (c) 2016, Freescale Semiconductor, Inc. All rights reserved.
-* Copyright 2017 NXP
-*
-* SPDX-License-Identifier: BSD-2-Clause-Patent
-*
-**/
-
-#ifndef DUART_H_
-#define DUART_H_
-
-// FIFO Control Register
-#define DUART_FCR_FIFO_EN 0x01 /* Fifo enable */
-#define DUART_FCR_CLEAR_RCVR 0x02 /* Clear the RCVR FIFO */
-#define DUART_FCR_CLEAR_XMIT 0x04 /* Clear the XMIT FIFO */
-#define DUART_FCR_DMA_SELECT 0x08 /* For DMA applications */
-#define DUART_FCR_TRIGGER_MASK 0xC0 /* Mask for the FIFO trigger range */
-#define DUART_FCR_TRIGGER_1 0x00 /* Mask for trigger set at 1 */
-#define DUART_FCR_TRIGGER_4 0x40 /* Mask for trigger set at 4 */
-#define DUART_FCR_TRIGGER_8 0x80 /* Mask for trigger set at 8 */
-#define DUART_FCR_TRIGGER_14 0xC0 /* Mask for trigger set at 14 */
-#define DUART_FCR_RXSR 0x02 /* Receiver soft reset */
-#define DUART_FCR_TXSR 0x04 /* Transmitter soft reset */
-
-// Modem Control Register
-#define DUART_MCR_DTR 0x01 /* Reserved */
-#define DUART_MCR_RTS 0x02 /* RTS */
-#define DUART_MCR_OUT1 0x04 /* Reserved */
-#define DUART_MCR_OUT2 0x08 /* Reserved */
-#define DUART_MCR_LOOP 0x10 /* Enable loopback test mode */
-#define DUART_MCR_AFE 0x20 /* AFE (Auto Flow Control) */
-#define DUART_MCR_DMA_EN 0x04
-#define DUART_MCR_TX_DFR 0x08
-
-// Line Control Register
-/*
-* Note: if the word length is 5 bits (DUART_LCR_WLEN5), then setting
-* DUART_LCR_STOP will select 1.5 stop bits, not 2 stop bits.
-*/
-#define DUART_LCR_WLS_MSK 0x03 /* character length select mask */
-#define DUART_LCR_WLS_5 0x00 /* 5 bit character length */
-#define DUART_LCR_WLS_6 0x01 /* 6 bit character length */
-#define DUART_LCR_WLS_7 0x02 /* 7 bit character length */
-#define DUART_LCR_WLS_8 0x03 /* 8 bit character length */
-#define DUART_LCR_STB 0x04 /* # stop Bits, off=1, on=1.5 or 2) */
-#define DUART_LCR_PEN 0x08 /* Parity eneble */
-#define DUART_LCR_EPS 0x10 /* Even Parity Select */
-#define DUART_LCR_STKP 0x20 /* Stick Parity */
-#define DUART_LCR_SBRK 0x40 /* Set Break */
-#define DUART_LCR_BKSE 0x80 /* Bank select enable */
-#define DUART_LCR_DLAB 0x80 /* Divisor latch access bit */
-
-// Line Status Register
-#define DUART_LSR_DR 0x01 /* Data ready */
-#define DUART_LSR_OE 0x02 /* Overrun */
-#define DUART_LSR_PE 0x04 /* Parity error */
-#define DUART_LSR_FE 0x08 /* Framing error */
-#define DUART_LSR_BI 0x10 /* Break */
-#define DUART_LSR_THRE 0x20 /* Xmit holding register empty */
-#define DUART_LSR_TEMT 0x40 /* Xmitter empty */
-#define DUART_LSR_ERR 0x80 /* Error */
-
-// Modem Status Register
-#define DUART_MSR_DCTS 0x01 /* Delta CTS */
-#define DUART_MSR_DDSR 0x02 /* Reserved */
-#define DUART_MSR_TERI 0x04 /* Reserved */
-#define DUART_MSR_DDCD 0x08 /* Reserved */
-#define DUART_MSR_CTS 0x10 /* Clear to Send */
-#define DUART_MSR_DSR 0x20 /* Reserved */
-#define DUART_MSR_RI 0x40 /* Reserved */
-#define DUART_MSR_DCD 0x80 /* Reserved */
-
-// Interrupt Identification Register
-#define DUART_IIR_NO_INT 0x01 /* No interrupts pending */
-#define DUART_IIR_ID 0x06 /* Mask for the interrupt ID */
-#define DUART_IIR_MSI 0x00 /* Modem status interrupt */
-#define DUART_IIR_THRI 0x02 /* Transmitter holding register empty */
-#define DUART_IIR_RDI 0x04 /* Receiver data interrupt */
-#define DUART_IIR_RLSI 0x06 /* Receiver line status interrupt */
-
-// Interrupt Enable Register
-#define DUART_IER_MSI 0x08 /* Enable Modem status interrupt */
-#define DUART_IER_RLSI 0x04 /* Enable receiver line status interrupt */
-#define DUART_IER_THRI 0x02 /* Enable Transmitter holding register int. */
-#define DUART_IER_RDI 0x01 /* Enable receiver data interrupt */
-
-// LCR defaults
-#define DUART_LCR_8N1 0x03
-#define DUART_LCRVAL DUART_LCR_8N1 /* 8 data, 1 stop, no parity */
-#define DUART_MCRVAL (DUART_MCR_DTR | \
- DUART_MCR_RTS) /* RTS/DTR */
-#define DUART_FCRVAL (DUART_FCR_FIFO_EN | \
- DUART_FCR_RXSR | \
- DUART_FCR_TXSR) /* Clear & enable FIFOs */
-
-#define URBR 0x0
-#define UTHR 0x0
-#define UDLB 0x0
-#define UDMB 0x1
-#define UIER 0x1
-#define UIIR 0x2
-#define UFCR 0x2
-#define UAFR 0x2
-#define ULCR 0x3
-#define UMCR 0x4
-#define ULSR 0x5
-#define UMSR 0x6
-#define USCR 0x7
-#define UDSR 0x10
-
-extern
-UINT64
-GetBusFrequency (
- VOID
- );
-
-#endif /* DUART_H_ */
diff --git a/Silicon/NXP/Library/DUartPortLib/DUartPortLib.c b/Silicon/NXP/Library/DUartPortLib/DUartPortLib.c
deleted file mode 100644
index c3c738d3cca8..000000000000
--- a/Silicon/NXP/Library/DUartPortLib/DUartPortLib.c
+++ /dev/null
@@ -1,364 +0,0 @@
-/** DuartPortLib.c
- DUART (NS16550) library functions
-
- Based on Serial I/O Port library functions available in PL011SerialPortLib.c
-
- Copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
- Copyright (c) 2012 - 2013, ARM Ltd. All rights reserved.<BR>
- Copyright (c) 2016, Freescale Semiconductor, Inc. All rights reserved.
- Copyright 2017 NXP
-
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <Base.h>
-#include <Library/IoLib.h>
-#include <Library/PcdLib.h>
-#include <Library/SerialPortLib.h>
-
-#include "DUart.h"
-
-STATIC CONST UINT32 mInvalidControlBits = (EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE | \
- EFI_SERIAL_DATA_TERMINAL_READY);
-
-/**
- Assert or deassert the control signals on a serial port.
- The following control signals are set according their bit settings :
- . Request to Send
- . Data Terminal Ready
-
- @param[in] Control The following bits are taken into account :
- . EFI_SERIAL_REQUEST_TO_SEND : assert/deassert the
- "Request To Send" control signal if this bit is
- equal to one/zero.
- . EFI_SERIAL_DATA_TERMINAL_READY : assert/deassert
- the "Data Terminal Ready" control signal if this
- bit is equal to one/zero.
- . EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE : enable/disable
- the hardware loopback if this bit is equal to
- one/zero.
- . EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE : not supported.
- . EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE : enable/
- disable the hardware flow control based on CTS (Clear
- To Send) and RTS (Ready To Send) control signals.
-
- @retval EFI_SUCCESS The new control bits were set on the device.
- @retval EFI_UNSUPPORTED The device does not support this operation.
-
-**/
-EFI_STATUS
-EFIAPI
-SerialPortSetControl (
- IN UINT32 Control
- )
-{
- UINT32 McrBits;
- UINTN UartBase;
-
- UartBase = (UINTN)PcdGet64 (PcdSerialRegisterBase);
-
- if (Control & (mInvalidControlBits)) {
- return EFI_UNSUPPORTED;
- }
-
- McrBits = MmioRead8 (UartBase + UMCR);
-
- if (Control & EFI_SERIAL_REQUEST_TO_SEND) {
- McrBits |= DUART_MCR_RTS;
- } else {
- McrBits &= ~DUART_MCR_RTS;
- }
-
- if (Control & EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE) {
- McrBits |= DUART_MCR_LOOP;
- } else {
- McrBits &= ~DUART_MCR_LOOP;
- }
-
- if (Control & EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE) {
- McrBits |= DUART_MCR_AFE;
- } else {
- McrBits &= ~DUART_MCR_AFE;
- }
-
- MmioWrite32 (UartBase + UMCR, McrBits);
-
- return EFI_SUCCESS;
-}
-
-/**
- Retrieve the status of the control bits on a serial device.
-
- @param[out] Control Status of the control bits on a serial device :
-
- . EFI_SERIAL_DATA_CLEAR_TO_SEND,
- EFI_SERIAL_DATA_SET_READY,
- EFI_SERIAL_RING_INDICATE,
- EFI_SERIAL_CARRIER_DETECT,
- EFI_SERIAL_REQUEST_TO_SEND,
- EFI_SERIAL_DATA_TERMINAL_READY
- are all related to the DTE (Data Terminal Equipment)
- and DCE (Data Communication Equipment) modes of
- operation of the serial device.
- . EFI_SERIAL_INPUT_BUFFER_EMPTY : equal to one if the
- receive buffer is empty, 0 otherwise.
- . EFI_SERIAL_OUTPUT_BUFFER_EMPTY : equal to one if the
- transmit buffer is empty, 0 otherwise.
- . EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE : equal to one if
- the hardware loopback is enabled (the ouput feeds the
- receive buffer), 0 otherwise.
- . EFI_SERIAL_SOFTWARE_LOOPBACK_ENABLE : equal to one if
- a loopback is accomplished by software, 0 otherwise.
- . EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE : equal to
- one if the hardware flow control based on CTS (Clear
- To Send) and RTS (Ready To Send) control signals is
- enabled, 0 otherwise.
-
- @retval EFI_SUCCESS The control bits were read from the serial device.
-
-**/
-EFI_STATUS
-EFIAPI
-SerialPortGetControl (
- OUT UINT32 *Control
- )
-{
- UINT32 MsrRegister;
- UINT32 McrRegister;
- UINT32 LsrRegister;
- UINTN UartBase;
-
- UartBase = (UINTN)PcdGet64 (PcdSerialRegisterBase);
-
- MsrRegister = MmioRead8 (UartBase + UMSR);
- McrRegister = MmioRead8 (UartBase + UMCR);
- LsrRegister = MmioRead8 (UartBase + ULSR);
-
- *Control = 0;
-
- if ((MsrRegister & DUART_MSR_CTS) == DUART_MSR_CTS) {
- *Control |= EFI_SERIAL_CLEAR_TO_SEND;
- }
-
- if ((McrRegister & DUART_MCR_RTS) == DUART_MCR_RTS) {
- *Control |= EFI_SERIAL_REQUEST_TO_SEND;
- }
-
- if ((LsrRegister & DUART_LSR_TEMT) == DUART_LSR_TEMT) {
- *Control |= EFI_SERIAL_OUTPUT_BUFFER_EMPTY;
- }
-
- if ((McrRegister & DUART_MCR_AFE) == DUART_MCR_AFE) {
- *Control |= EFI_SERIAL_HARDWARE_FLOW_CONTROL_ENABLE;
- }
-
- if ((McrRegister & DUART_MCR_LOOP) == DUART_MCR_LOOP) {
- *Control |= EFI_SERIAL_HARDWARE_LOOPBACK_ENABLE;
- }
-
- return EFI_SUCCESS;
-}
-
-/*
- * Return Baud divisor on basis of Baudrate
- */
-UINT32
-CalculateBaudDivisor (
- IN UINT64 BaudRate
- )
-{
- UINTN DUartClk;
- UINTN FreqSystemBus;
-
- FreqSystemBus = GetBusFrequency ();
- DUartClk = FreqSystemBus/PcdGet32(PcdPlatformFreqDiv);
-
- return ((DUartClk)/(BaudRate * 16));
-}
-
-/*
- Initialise the serial port to the specified settings.
- All unspecified settings will be set to the default values.
-
- @return Always return EFI_SUCCESS or EFI_INVALID_PARAMETER.
-
- **/
-VOID
-EFIAPI
-DuartInitializePort (
- IN UINT64 BaudRate
- )
-{
- UINTN UartBase;
- UINT32 BaudDivisor;
-
- UartBase = (UINTN)PcdGet64 (PcdSerialRegisterBase);
- BaudDivisor = CalculateBaudDivisor (BaudRate);
-
-
- while (!(MmioRead8 (UartBase + ULSR) & DUART_LSR_TEMT));
-
- //
- // Enable and assert interrupt when new data is available on
- // external device,
- // setup data format, setup baud divisor
- //
- MmioWrite8 (UartBase + UIER, 0x1);
- MmioWrite8 (UartBase + ULCR, DUART_LCR_BKSE | DUART_LCRVAL);
- MmioWrite8 (UartBase + UDLB, 0);
- MmioWrite8 (UartBase + UDMB, 0);
- MmioWrite8 (UartBase + ULCR, DUART_LCRVAL);
- MmioWrite8 (UartBase + UMCR, DUART_MCRVAL);
- MmioWrite8 (UartBase + UFCR, DUART_FCRVAL);
- MmioWrite8 (UartBase + ULCR, DUART_LCR_BKSE | DUART_LCRVAL);
- MmioWrite8 (UartBase + UDLB, BaudDivisor & 0xff);
- MmioWrite8 (UartBase + UDMB, (BaudDivisor >> 8) & 0xff);
- MmioWrite8 (UartBase + ULCR, DUART_LCRVAL);
-
- return;
-}
-
-/**
- Programmed hardware of Serial port.
-
- @return Always return EFI_SUCCESS.
-
-**/
-EFI_STATUS
-EFIAPI
-SerialPortInitialize (
- VOID
- )
-{
- UINT64 BaudRate;
- BaudRate = (UINTN)PcdGet64 (PcdUartDefaultBaudRate);
-
-
- DuartInitializePort (BaudRate);
-
- return EFI_SUCCESS;
-}
-
-/**
- Write data to serial device.
-
- @param Buffer Point of data buffer which need to be written.
- @param NumberOfBytes Number of output bytes which are cached in Buffer.
-
- @retval 0 Write data failed.
- @retval !0 Actual number of bytes written to serial device.
-
-**/
-UINTN
-EFIAPI
-SerialPortWrite (
- IN UINT8 *Buffer,
- IN UINTN NumberOfBytes
- )
-{
- UINT8 *Final;
- UINTN UartBase;
-
- Final = &Buffer[NumberOfBytes];
- UartBase = (UINTN)PcdGet64 (PcdSerialRegisterBase);
-
- while (Buffer < Final) {
- while ((MmioRead8 (UartBase + ULSR) & DUART_LSR_THRE) == 0);
- MmioWrite8 (UartBase + UTHR, *Buffer++);
- }
-
- return NumberOfBytes;
-}
-
-/**
- Read data from serial device and save the data in buffer.
-
- @param Buffer Point of data buffer which need to be written.
- @param NumberOfBytes Number of output bytes which are cached in Buffer.
-
- @retval 0 Read data failed.
- @retval !0 Actual number of bytes read from serial device.
-
-**/
-UINTN
-EFIAPI
-SerialPortRead (
- OUT UINT8 *Buffer,
- IN UINTN NumberOfBytes
- )
-{
- UINTN Count;
- UINTN UartBase;
-
- UartBase = (UINTN)PcdGet64 (PcdSerialRegisterBase);
-
- for (Count = 0; Count < NumberOfBytes; Count++, Buffer++) {
- // Loop while waiting for a new char(s) to arrive in the
- // RxFIFO
- while ((MmioRead8 (UartBase + ULSR) & DUART_LSR_DR) == 0);
-
- *Buffer = MmioRead8 (UartBase + URBR);
- }
-
- return NumberOfBytes;
-}
-
-/**
- Check to see if any data is available to be read from the debug device.
-
- @retval EFI_SUCCESS At least one byte of data is available to be read
- @retval EFI_NOT_READY No data is available to be read
- @retval EFI_DEVICE_ERROR The serial device is not functioning properly
-
-**/
-BOOLEAN
-EFIAPI
-SerialPortPoll (
- VOID
- )
-{
- UINTN UartBase;
-
- UartBase = (UINTN)PcdGet64 (PcdSerialRegisterBase);
-
- return ((MmioRead8 (UartBase + ULSR) & DUART_LSR_DR) != 0);
-}
-
-/**
- Set new attributes to LS1043a.
-
- @param BaudRate The baud rate of the serial device. If the baud rate is not supported,
- the speed will be reduced down to the nearest supported one and the
- variable's value will be updated accordingly.
- @param ReceiveFifoDepth The number of characters the device will buffer on input. If the specified
- value is not supported, the variable's value will be reduced down to the
- nearest supported one.
- @param Timeout If applicable, the number of microseconds the device will wait
- before timing out a Read or a Write operation.
- @param Parity If applicable, this is the EFI_PARITY_TYPE that is computed or checked
- as each character is transmitted or received. If the device does not
- support parity, the value is the default parity value.
- @param DataBits The number of data bits in each character
- @param StopBits If applicable, the EFI_STOP_BITS_TYPE number of stop bits per character.
- If the device does not support stop bits, the value is the default stop
- bit value.
-
- @retval EFI_SUCCESS All attributes were set correctly on the serial device.
-
-**/
-EFI_STATUS
-EFIAPI
-SerialPortSetAttributes (
- IN OUT UINT64 *BaudRate,
- IN OUT UINT32 *ReceiveFifoDepth,
- IN OUT UINT32 *Timeout,
- IN OUT EFI_PARITY_TYPE *Parity,
- IN OUT UINT8 *DataBits,
- IN OUT EFI_STOP_BITS_TYPE *StopBits
- )
-{
- DuartInitializePort (*BaudRate);
-
- return EFI_SUCCESS;
-}
diff --git a/Silicon/NXP/Library/DUartPortLib/DUartPortLib.inf b/Silicon/NXP/Library/DUartPortLib/DUartPortLib.inf
deleted file mode 100644
index 7a2fa619b027..000000000000
--- a/Silicon/NXP/Library/DUartPortLib/DUartPortLib.inf
+++ /dev/null
@@ -1,34 +0,0 @@
-# DUartPortLib.inf
-#
-# Component description file for DUartPortLib module
-#
-# Copyright (c) 2013, Freescale Ltd. All rights reserved.
-# Copyright 2017 NXP
-#
-# SPDX-License-Identifier: BSD-2-Clause-Patent
-#
-
-[Defines]
- INF_VERSION = 0x0001001A
- BASE_NAME = DUartPortLib
- FILE_GUID = c42dfe79-8de5-429e-a055-2d0a58591498
- MODULE_TYPE = BASE
- VERSION_STRING = 1.0
- LIBRARY_CLASS = SerialPortLib
-
-[Sources.common]
- DUartPortLib.c
-
-[LibraryClasses]
- PcdLib
- SocLib
-
-[Packages]
- MdeModulePkg/MdeModulePkg.dec
- MdePkg/MdePkg.dec
- Silicon/NXP/NxpQoriqLs.dec
-
-[Pcd]
- gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase
- gEfiMdePkgTokenSpaceGuid.PcdUartDefaultBaudRate
- gNxpQoriqLsTokenSpaceGuid.PcdPlatformFreqDiv
--
2.17.1


Re: [PATCH v2 08/28] Silicon/NXP/LS1043A: Use BaseSerialPortLib16550 as SerialPortLib

Leif Lindholm
 

On Fri, Mar 20, 2020 at 20:05:23 +0530, Pankaj Bansal wrote:
From: Pankaj Bansal <pankaj.bansal@...>

UART Programming model in LS1043A is compatible with PC16550D.
Therefore, BaseSerialPortLib16550 can be used instead of our own
implementation of SerialPortLib.

Signed-off-by: Pankaj Bansal <pankaj.bansal@...>
Reviewed-by: Leif Lindholm <leif@...>
(If the need for SerialUartClockLib goes away, that line can be
dropped without re-review being required.)

---
Platform/NXP/NxpQoriqLs.dsc.inc | 3 +++
Silicon/NXP/LS1043A/LS1043A.dsc.inc | 5 ++++-
2 files changed, 7 insertions(+), 1 deletion(-)

diff --git a/Platform/NXP/NxpQoriqLs.dsc.inc b/Platform/NXP/NxpQoriqLs.dsc.inc
index 94d3e53a046b..234a5e2707cd 100644
--- a/Platform/NXP/NxpQoriqLs.dsc.inc
+++ b/Platform/NXP/NxpQoriqLs.dsc.inc
@@ -98,6 +98,9 @@ [LibraryClasses.common]
ResetSystemLib|ArmPkg/Library/ArmSmcPsciResetSystemLib/ArmSmcPsciResetSystemLib.inf
IoAccessLib|Silicon/NXP/Library/IoAccessLib/IoAccessLib.inf

+ PciExpressLib|MdePkg/Library/BasePciExpressLib/BasePciExpressLib.inf
+ PciLib|MdePkg/Library/BasePciLibPciExpress/BasePciLibPciExpress.inf
+
[LibraryClasses.common.SEC]
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
UefiDecompressLib|MdePkg/Library/BaseUefiDecompressLib/BaseUefiDecompressLib.inf
diff --git a/Silicon/NXP/LS1043A/LS1043A.dsc.inc b/Silicon/NXP/LS1043A/LS1043A.dsc.inc
index d2d4133428c3..f6f15a482a85 100644
--- a/Silicon/NXP/LS1043A/LS1043A.dsc.inc
+++ b/Silicon/NXP/LS1043A/LS1043A.dsc.inc
@@ -8,8 +8,10 @@
#

[LibraryClasses.common]
+ PlatformHookLib|MdeModulePkg/Library/BasePlatformHookLibNull/BasePlatformHookLibNull.inf
SocLib|Silicon/NXP/Library/SocLib/LS1043aSocLib.inf
- SerialPortLib|Silicon/NXP/Library/DUartPortLib/DUartPortLib.inf
+ SerialUartClockLib|Silicon/NXP/Library/SerialUartClockLib/SerialUartClockLib.inf
+ SerialPortLib|MdeModulePkg/Library/BaseSerialPortLib16550/BaseSerialPortLib16550.inf

################################################################################
#
@@ -25,6 +27,7 @@ [PcdsDynamicDefault.common]

[PcdsFixedAtBuild.common]
gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase|0x021c0500
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialUseMmio|TRUE

#
# CCSR Address Space and other attached Memories
--
2.17.1


Re: [PATCH v2 07/28] Silicon/NXP: Implement SerialUartClockLib

Leif Lindholm
 

On Fri, Mar 20, 2020 at 20:05:22 +0530, Pankaj Bansal wrote:
From: Pankaj Bansal <pankaj.bansal@...>

Implement SerialUartClockLib for all NXP Layerscape Platforms.

Signed-off-by: Pankaj Bansal <pankaj.bansal@...>
---
.../SerialUartClockLib/SerialUartClockLib.c | 27 +++++++++++++++++++
.../SerialUartClockLib/SerialUartClockLib.inf | 26 ++++++++++++++++++
I requested after the initial submission that you "either follow the
manual git setup steps from
https://github.com/tianocore/tianocore.github.io/wiki/Laszlo%27s-unkempt-git-guide-for-edk2-contributors-and-maintainers
or execute edk2/BaseTools/Scripts/SetupGit.py in each of the tianocore
repositories"

Now, neither appears to have happened, as .c still comes before .inf
and paths are still truncated.

But in addition to that, we realised that git happily ignores settings
for --stat. So, please, execute aforementioned script, but then
generate v3 with --stat=1000 --stat-graph-width=20.

For this particular patch, the side discussion on the edk2 portion may
make it redundant, so I'm deferring review.

/
Leif

2 files changed, 53 insertions(+)
create mode 100644 Silicon/NXP/Library/SerialUartClockLib/SerialUartClockLib.c
create mode 100644 Silicon/NXP/Library/SerialUartClockLib/SerialUartClockLib.inf

diff --git a/Silicon/NXP/Library/SerialUartClockLib/SerialUartClockLib.c b/Silicon/NXP/Library/SerialUartClockLib/SerialUartClockLib.c
new file mode 100644
index 000000000000..9d49d7b4748b
--- /dev/null
+++ b/Silicon/NXP/Library/SerialUartClockLib/SerialUartClockLib.c
@@ -0,0 +1,27 @@
+/** @file
+*
+* Copyright 2020 NXP
+*
+* SPDX-License-Identifier: BSD-2-Clause-Patent
+*
+**/
+
+#include <Base.h>
+
+extern
+UINT64
+GetBusFrequency (
+ VOID
+ );
+
+/**
+ Return clock in for Uart IP
+**/
+UINT32
+EFIAPI
+BaseSerialPortGetClock (
+ VOID
+ )
+{
+ return GetBusFrequency ();
+}
diff --git a/Silicon/NXP/Library/SerialUartClockLib/SerialUartClockLib.inf b/Silicon/NXP/Library/SerialUartClockLib/SerialUartClockLib.inf
new file mode 100644
index 000000000000..9a3e80cf521d
--- /dev/null
+++ b/Silicon/NXP/Library/SerialUartClockLib/SerialUartClockLib.inf
@@ -0,0 +1,26 @@
+# @file
+# Copyright 2020 NXP
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+
+[Defines]
+ INF_VERSION = 1.27
+ BASE_NAME = SerialUartClockLib
+ FILE_GUID = fa65495e-d3c8-4ea3-9737-994e9ccbaf11
+ MODULE_TYPE = BASE
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = SerialUartClockLib
+
+[Packages]
+ MdeModulePkg/MdeModulePkg.dec
+ MdePkg/MdePkg.dec
+ Silicon/NXP/NxpQoriqLs.dec
+
+[Sources.common]
+ SerialUartClockLib.c
+
+[LibraryClasses]
+ SocLib
+
--
2.17.1


[PATCH] NetworkPkg/Ip6Dxe: Fix ASSERT logic in Ip6ProcessRouterAdvertise()

Maciej Rabeda
 

This patch fixes reversed logic of recently added ASSERTs which should
ensure that Ip6IsNDOptionValid() implementation properly reacts to invalid
packets.

Cc: Jiaxin Wu <jiaxin.wu@...>
Cc: Siyuan Fu <siyuan.fu@...>
Signed-off-by: Maciej Rabeda <maciej.rabeda@...>
Tested-by: Laszlo Ersek <lersek@...>
---
NetworkPkg/Ip6Dxe/Ip6Nd.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/NetworkPkg/Ip6Dxe/Ip6Nd.c b/NetworkPkg/Ip6Dxe/Ip6Nd.c
index fd7f60b2f92c..0780a98cb325 100644
--- a/NetworkPkg/Ip6Dxe/Ip6Nd.c
+++ b/NetworkPkg/Ip6Dxe/Ip6Nd.c
@@ -2111,7 +2111,7 @@ Ip6ProcessRouterAdvertise (
// Option size validity ensured by Ip6IsNDOptionValid().=0D
//=0D
ASSERT (LinkLayerOption.Length !=3D 0);=0D
- ASSERT (Offset + (UINT32) LinkLayerOption.Length * 8 >=3D (UINT32) H=
ead->PayloadLength);=0D
+ ASSERT (Offset + (UINT32) LinkLayerOption.Length * 8 <=3D (UINT32) H=
ead->PayloadLength);=0D
=0D
ZeroMem (&LinkLayerAddress, sizeof (EFI_MAC_ADDRESS));=0D
CopyMem (&LinkLayerAddress, LinkLayerOption.EtherAddr, 6);=0D
@@ -2164,7 +2164,7 @@ Ip6ProcessRouterAdvertise (
// Option size validity ensured by Ip6IsNDOptionValid().=0D
//=0D
ASSERT (PrefixOption.Length =3D=3D 4);=0D
- ASSERT (Offset + (UINT32) PrefixOption.Length * 8 >=3D (UINT32) Head=
->PayloadLength);=0D
+ ASSERT (Offset + (UINT32) PrefixOption.Length * 8 <=3D (UINT32) Head=
->PayloadLength);=0D
=0D
PrefixOption.ValidLifetime =3D NTOHL (PrefixOption.ValidLifetime=
);=0D
PrefixOption.PreferredLifetime =3D NTOHL (PrefixOption.PreferredLife=
time);=0D
@@ -2334,7 +2334,7 @@ Ip6ProcessRouterAdvertise (
// Option size validity ensured by Ip6IsNDOptionValid().=0D
//=0D
ASSERT (MTUOption.Length =3D=3D 1);=0D
- ASSERT (Offset + (UINT32) MTUOption.Length * 8 >=3D (UINT32) Head->P=
ayloadLength);=0D
+ ASSERT (Offset + (UINT32) MTUOption.Length * 8 <=3D (UINT32) Head->P=
ayloadLength);=0D
=0D
//=0D
// Use IPv6 minimum link MTU 1280 bytes as the maximum packet size i=
n order=0D
--=20
2.24.0.windows.2


Re: [PATCH v2 06/28] NXP/LS1043aRdb: Move Soc specific components to soc files

Leif Lindholm
 

On Fri, Mar 20, 2020 at 20:05:21 +0530, Pankaj Bansal wrote:
From: Pankaj Bansal <pankaj.bansal@...>

Soc specific components ought to be part of Soc files and not
platform files. move the same to SOC files

Signed-off-by: Pankaj Bansal <pankaj.bansal@...>
Reviewed-by: Leif Lindholm <leif@...>

---
Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc | 7 +------
Platform/NXP/NxpQoriqLs.dsc.inc | 2 ++
Silicon/NXP/LS1043A/LS1043A.dsc.inc | 7 ++++++-
3 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
index c8105593533f..802cccdce63b 100644
--- a/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
+++ b/Platform/NXP/LS1043aRdbPkg/LS1043aRdbPkg.dsc
@@ -2,7 +2,7 @@
#
# LS1043ARDB Board package.
#
-# Copyright 2017-2019 NXP
+# Copyright 2017-2020 NXP
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
@@ -26,11 +26,7 @@ [Defines]
!include Silicon/NXP/LS1043A/LS1043A.dsc.inc

[LibraryClasses.common]
- SocLib|Silicon/NXP/Library/SocLib/LS1043aSocLib.inf
ArmPlatformLib|Platform/NXP/LS1043aRdbPkg/Library/PlatformLib/ArmPlatformLib.inf
- ResetSystemLib|ArmPkg/Library/ArmSmcPsciResetSystemLib/ArmSmcPsciResetSystemLib.inf
- SerialPortLib|Silicon/NXP/Library/DUartPortLib/DUartPortLib.inf
- IoAccessLib|Silicon/NXP/Library/IoAccessLib/IoAccessLib.inf
RealTimeClockLib|Silicon/Maxim/Library/Ds1307RtcLib/Ds1307RtcLib.inf

[PcdsFixedAtBuild.common]
@@ -46,7 +42,6 @@ [PcdsFixedAtBuild.common]
#
# Board Specific Pcds
#
- gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase|0x021c0500
gNxpQoriqLsTokenSpaceGuid.PcdSerdes2Enabled|FALSE
gNxpQoriqLsTokenSpaceGuid.PcdPlatformFreqDiv|0x1

diff --git a/Platform/NXP/NxpQoriqLs.dsc.inc b/Platform/NXP/NxpQoriqLs.dsc.inc
index b28e0615f7ca..94d3e53a046b 100644
--- a/Platform/NXP/NxpQoriqLs.dsc.inc
+++ b/Platform/NXP/NxpQoriqLs.dsc.inc
@@ -95,6 +95,8 @@ [LibraryClasses.common]
ReportStatusCodeLib|MdeModulePkg/Library/DxeReportStatusCodeLib/DxeReportStatusCodeLib.inf

I2cLib|Silicon/NXP/Library/I2cLib/I2cLib.inf
+ ResetSystemLib|ArmPkg/Library/ArmSmcPsciResetSystemLib/ArmSmcPsciResetSystemLib.inf
+ IoAccessLib|Silicon/NXP/Library/IoAccessLib/IoAccessLib.inf

[LibraryClasses.common.SEC]
PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
diff --git a/Silicon/NXP/LS1043A/LS1043A.dsc.inc b/Silicon/NXP/LS1043A/LS1043A.dsc.inc
index dbd680b0ad28..d2d4133428c3 100644
--- a/Silicon/NXP/LS1043A/LS1043A.dsc.inc
+++ b/Silicon/NXP/LS1043A/LS1043A.dsc.inc
@@ -1,12 +1,16 @@
# LS1043A.dsc
# LS1043A Soc package.
#
-# Copyright 2017-2019 NXP
+# Copyright 2017-2020 NXP
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
#

+[LibraryClasses.common]
+ SocLib|Silicon/NXP/Library/SocLib/LS1043aSocLib.inf
+ SerialPortLib|Silicon/NXP/Library/DUartPortLib/DUartPortLib.inf
+
################################################################################
#
# Pcd Section - list of all EDK II PCD Entries defined by this Platform
@@ -20,6 +24,7 @@ [PcdsDynamicDefault.common]
gArmTokenSpaceGuid.PcdGicInterruptInterfaceBase|0x01402000

[PcdsFixedAtBuild.common]
+ gEfiMdeModulePkgTokenSpaceGuid.PcdSerialRegisterBase|0x021c0500

#
# CCSR Address Space and other attached Memories
--
2.17.1


Re: [PATCH v3 0/3] Return GetVariable() attr if EFI_BUFFER_TOO_SMALL

Laszlo Ersek
 

On 04/01/20 03:15, Michael Kubacki wrote:
I have those options set correctly in git config.

After a quick look, as far as I can tell, this is because the
Message-Id in my email is modified such the the In-Reply-To and
References headers do not refer to the actual Message-Id in the cover
letter:

Cover letter:

Subject: [edk2-devel] [PATCH v3 0/3] Return GetVariable() attr if
EFI_BUFFER_TOO_SMALL
Date: Fri, 27 Mar 2020 14:55:33 -0700
Message-Id: <160047F24E1D38F5.15390@groups.io>

The original Message-Id in the cover letter was moved to
X-Microsoft-Original-Message-Id:

X-Microsoft-Original-Message-ID:
<20200327215536.9556-1-michael.kubacki@...>

The first patch in the series:

Subject: [edk2-devel] [PATCH v3 1/3] MdeModulePkg Variable: Return
GetVariable() attr if EFI_BUFFER_TOO_SMALL
Date: Fri, 27 Mar 2020 14:55:34 -0700
Message-Id: <160047F33E58AD06.17905@groups.io>
In-Reply-To: <20200327215536.9556-1-michael.kubacki@...>
References: <20200327215536.9556-1-michael.kubacki@...>

Please let me know if you have suggestions. I'll look into it more.
(1) *Normally*, here's what I would tell you:

Please log in to your groups.io account, and navigate to the following
setting:

Your name (upper right corner)
Account
Preferences (top of left sidebar)
I always want copies of my own emails (checkbox at the bottom)

Please *untick* this checkbox.

The name of the checkbox is very misleading. The actual behavior is the
following:

"I am a gmail user, and gmail de-duplicates messages that are sent to
me both directly, and reflected through the mailing list. As a
special case, the same de-duplication applies to messages I send to
the list, and are reflected to me by the list -- gmail just hides
those from me as "seen". I don't like this; I want my reflected
copies of messages that I sent. Because the de-duplication is
Message-ID based, groups.io should please falsify the Message-ID on
those messages that I send *AND* are delivered back to me *only*"

Meaning, if you have this box checked, then groups.io places
<....@groups.io>-style message IDs in the emails that it sends back *to
you* (only to you) *and* that originate from you.


(2) *However*, that is not the problem here. (Or, more precisely, not
the only problem.) Because, as I say above, this message-ID
re-generation by groups.io only applies to *you*; so the threading of
your patch series would only be broken in *your* list folder, not in
mine (or in any other list subscriber's).

But, the threading *is* broken on my end too.

And the reason for that is that the SMTP server that you use, ignores
the Message-ID put in place by git-send-email, and generates its own.

Your original message ID (as stated above), from git-send-email, is:

20200327215536.9556-1-michael.kubacki@...

But the message ID in my list folder is:

MWHPR07MB3440A69B5AFAD0E373974FBFE9CC0@...

Therefore, the original message-id (from git-send-email) is not moved to
the X-Microsoft-Original-Message-ID header by groups.io -- instead, it
is moved there by your SMTP server, at <outlook.com>.

Can you disable that somehow? It is incorrect behavior. An SMTP server
itself should only put a Message-ID on an outgoing email if that email
doesn't already come with one.

To summarize, there are two issues:

(a) your groups.io account settings have the gmail-oriented Message-ID
falsification enabled, which breaks threading for you (and only for you)

(b) your SMTP server overwrites the git-send-email-generated Message-ID
with its own, which breaks threading for every list subscriber
(including you).

You can easily remedy (a) in your groups.io account settings. Not sure
how you can fix problem (b) -- can you use a different SMTP server
maybe?

(I've been very happy that we've finally seen patches posted to the list
from a @microsoft.com email address -- it would be fantastic if that
continued, with the threading fixed even!)

Thanks!
Laszlo


Re: [PATCH] Features/Intel/UserInterface: Add VirtualKeyboardFeaturePkg

Ni, Ray
 

Ming,
1. Can you update all the "TODO" in Readme.md to fill with detailed information?
2. gEfiTouchPanelGuid contains the 'Efi' prefix but isn't defined in UEFI or PI spec. Can you please rename it to "gEdkiiTouchPanelGuid"?
Because there is no header file associated with this GUID, the rename without changing the GUID value may have no impact to other code.
3. Can you please evaluate all the debug messages controlled by DEBUG_VK_* macro? Can some debug messages be removed? Can the proper
debug error level (ERROR, WARN, INFO, VERBOSE) be assigned to the remaining debug messages?
I would like to remove all the DEBUG_VK_* macros.

4. Can you please check whether the code can pass ECC check?

Thanks,
Ray

-----Original Message-----
From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of Tan, Ming
Sent: Thursday, March 26, 2020 8:44 AM
To: devel@edk2.groups.io
Subject: [edk2-devel] [PATCH] Features/Intel/UserInterface: Add VirtualKeyboardFeaturePkg

REF: https://bugzilla.tianocore.org/show_bug.cgi?id=2603

It add a VirtualKeyboardDxe driver.
It is used with a touch panel, simulate a keyboard in the screen.

Signed-off-by: Ming Tan <ming.tan@...>
---
.../Include/PostMemory.fdf | 10 +
.../Include/PreMemory.fdf | 8 +
.../Include/VirtualKeyboardFeature.dsc | 96 ++
.../VirtualKeyboardFeaturePkg/Readme.md | 95 ++
.../CapitalLetterKeyboard.bmp | Bin 0 -> 330454 bytes
.../VirtualKeyboardDxe/ComponentName.c | 159 ++
.../VirtualKeyboardDxe/ComponentName.h | 95 ++
.../VirtualKeyboardDxe/DigitKeyboard.bmp | Bin 0 -> 330454 bytes
.../VirtualKeyboardDxe/FullIcon.bmp | Bin 0 -> 5454 bytes
.../VirtualKeyboardDxe/Keyboard.c | 1400 +++++++++++++++++
.../VirtualKeyboardDxe/KeyboardLayout.c | 1364 ++++++++++++++++
.../VirtualKeyboardDxe/KeyboardLayout.idf | 12 +
.../VirtualKeyboardDxe/SimpleIcon.bmp | Bin 0 -> 2814 bytes
.../VirtualKeyboardDxe/SimpleKeyboard.bmp | Bin 0 -> 30054 bytes
.../VirtualKeyboardDxe/VirtualKeyboard.h | 777 +++++++++
.../VirtualKeyboardDriver.c | 541 +++++++
.../VirtualKeyboardDxe/VirtualKeyboardDxe.inf | 77 +
.../VirtualKeyboardFeaturePkg.dec | 26 +
.../VirtualKeyboardFeaturePkg.dsc | 30 +
19 files changed, 4690 insertions(+)
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/PostMemory.fdf
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/PreMemory.fdf
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/VirtualKeyboardFeature.dsc
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Readme.md
create mode 100644
Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/CapitalLetterKeyboard.bmp
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/ComponentName.c
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/ComponentName.h
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/DigitKeyboard.bmp
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/FullIcon.bmp
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/Keyboard.c
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/KeyboardLayout.c
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/KeyboardLayout.idf
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/SimpleIcon.bmp
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/SimpleKeyboard.bmp
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboard.h
create mode 100644
Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboardDriver.c
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboardDxe.inf
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardFeaturePkg.dec
create mode 100644 Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardFeaturePkg.dsc

diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/PostMemory.fdf
b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/PostMemory.fdf
new file mode 100644
index 0000000000..bf4a4d5078
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/PostMemory.fdf
@@ -0,0 +1,10 @@
+## @file

+# FDF file for post-memory modules that enable Virtual Keyboard.

+#

+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>

+#

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

+

+ INF UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboardDxe.inf

diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/PreMemory.fdf
b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/PreMemory.fdf
new file mode 100644
index 0000000000..c39a057f94
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/PreMemory.fdf
@@ -0,0 +1,8 @@
+## @file

+# FDF file for pre-memory modules that enable Virtual Keyboard.

+#

+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>

+#

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/VirtualKeyboardFeature.dsc
b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/VirtualKeyboardFeature.dsc
new file mode 100644
index 0000000000..c10fb2d567
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Include/VirtualKeyboardFeature.dsc
@@ -0,0 +1,96 @@
+## @file

+# This is a build description file for the Virtual Keyboard feature.

+# This file should be included into another package DSC file to build this feature.

+#

+# The DEC files are used by the utilities that parse DSC and

+# INF files to generate AutoGen.c and AutoGen.h files

+# for the build infrastructure.

+#

+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>

+#

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

+

+################################################################################

+#

+# Defines Section - statements that will be processed to create a Makefile.

+#

+################################################################################

+[Defines]

+!ifndef $(PEI_ARCH)

+ !error "PEI_ARCH must be specified to build this feature!"

+!endif

+!ifndef $(DXE_ARCH)

+ !error "DXE_ARCH must be specified to build this feature!"

+!endif

+

+################################################################################

+#

+# Library Class section - list of all Library Classes needed by this feature.

+#

+################################################################################

+[LibraryClasses]

+ #######################################

+ # Edk2 Packages

+ #######################################

+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf

+ BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf

+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf

+ UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf

+ UefiDriverEntryPoint|MdePkg/Library/UefiDriverEntryPoint/UefiDriverEntryPoint.inf

+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf

+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf

+ HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf

+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLib.inf

+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf

+ UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf

+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf

+

+[LibraryClasses.common.UEFI_DRIVER]

+ #######################################

+ # Edk2 Packages

+ #######################################

+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf

+

+###################################################################################################

+#

+# Components Section - list of the modules and components that will be processed by compilation

+# tools and the EDK II tools to generate PE32/PE32+/Coff image files.

+#

+# Note: The EDK II DSC file is not used to specify how compiled binary images get placed

+# into firmware volume images. This section is just a list of modules to compile from

+# source into UEFI-compliant binaries.

+# It is the FDF file that contains information on combining binary files into firmware

+# volume images, whose concept is beyond UEFI and is described in PI specification.

+# Binary modules do not need to be listed in this section, as they should be

+# specified in the FDF file. For example: Shell binary (Shell_Full.efi), FAT binary (Fat.efi),

+# Logo (Logo.bmp), and etc.

+# There may also be modules listed in this section that are not required in the FDF file,

+# When a module listed here is excluded from FDF file, then UEFI-compliant binary will be

+# generated for it, but the binary will not be put into any firmware volume.

+#

+###################################################################################################

+#

+# Feature DXE Components

+#

+[Components.X64]

+ #####################################

+ # Virtual Keyboard Feature Package

+ #####################################

+ UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboardDxe.inf

+

+###################################################################################################

+#

+# BuildOptions Section - Define the module specific tool chain flags that should be used as

+# the default flags for a module. These flags are appended to any

+# standard flags that are defined by the build process. They can be

+# applied for any modules or only those modules with the specific

+# module style (EDK or EDKII) specified in [Components] section.

+#

+# For advanced features, it is recommended to enable [BuildOptions] in

+# the applicable INF file so it does not affect the whole board package

+# build when this DSC file is active.

+#

+###################################################################################################

+[BuildOptions]

diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Readme.md
b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Readme.md
new file mode 100644
index 0000000000..17a3a00215
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/Readme.md
@@ -0,0 +1,95 @@
+# Overview

+* **Feature Name:** Virtual Keyboard

+* **PI Phase(s) Supported:** DXE

+* **SMM Required?** No

+

+## Purpose

+This feature provides a DXE virtual keyboard driver, used with a touch panel.

+

+# High-Level Theory of Operation

+This driver will use the following protocol:

+ gEfiAbsolutePointerProtocolGuid

+ gEfiTouchPanelGuid

+ gEfiGraphicsOutputProtocolGuid

+

+It will show a picture like a keyboard in the graphic output, then detect

+position when user touch the touch panel, then calculate the key which the

+user want to type.

+

+## Firmware Volumes

+*_TODO_*

+A bulleted list of the firmware volumes that feature module(s) are placed in.

+

+## Modules

+VirtualKeyboardDxe: The main driver of virtual keyboard

+

+## <Module Name>

+*_TODO_*

+Each module in the feature should have a section that describes the module in a level of detail that is useful

+to better understand the module source code.

+

+## <Library Name>

+*_TODO_*

+Each library in the feature should have a section that describes the library in a level of detail that is useful

+to better understand the library source code.

+

+## Key Functions

+*_TODO_*

+A bulleted list of key functions for interacting with the feature.

+

+Not all features need to be listed. Only functions exposed through external interfaces that are important for feature

+users to be aware of.

+

+## Configuration

+*_TODO_*

+Information that is useful for configuring the feature.

+

+Not all configuration options need to be listed. This section is used to provide more background on configuration

+options than possible elsewhere.

+

+## Data Flows

+*_TODO_*

+Architecturally defined data structures and flows for the feature.

+

+## Control Flows

+*_TODO_*

+Key control flows for the feature.

+

+## Build Flows

+*_TODO_*

+Any special build flows should be described in this section.

+

+This is particularly useful for features that use custom build tools or require non-standard tool configuration. If the

+standard flow in the feature package template is used, this section may be empty.

+

+## Test Point Results

+*_TODO_*

+The test(s) that can verify porting is complete for the feature.

+

+Each feature must describe at least one test point to verify the feature is successful. If the test point is not

+implemented, this should be stated.

+

+## Functional Exit Criteria

+*_TODO_*

+The testable functionality for the feature.

+

+This section should provide an ordered list of criteria that a board integrator can reference to ensure the feature is

+functional on their board.

+

+## Feature Enabling Checklist

+*_TODO_*

+An ordered list of required activities to achieve desired functionality for the feature.

+

+## Performance Impact

+A general expectation for the impact on overall boot performance due to using this feature.

+

+This section is expected to provide guidance on:

+* How to estimate performance impact due to the feature

+* How to measure performance impact of the feature

+* How to manage performance impact of the feature

+

+## Common Optimizations

+*_TODO_*

+Common size or performance tuning options for this feature.

+

+This section is recommended but not required. If not used, the contents should be left empty.

diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/CapitalLetterKeyboard.bmp
b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/CapitalLetterKeyboard.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..759c3d46a9f0cf6a69fa98563cd04f7a082d3b4d
GIT binary patch
literal 330454
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
Ka0)zo_WuC{9xg=y

literal 0
HcmV?d00001

diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/ComponentName.c
b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/ComponentName.c
new file mode 100644
index 0000000000..6ac28ab90b
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/ComponentName.c
@@ -0,0 +1,159 @@
+/** @file

+ Virtual Keyboard driver name.

+

+ Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#include "VirtualKeyboard.h"

+

+//

+// EFI Component Name Protocol

+//

+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gVirtualKeyboardComponentName = {

+ VirtualKeyboardComponentNameGetDriverName,

+ VirtualKeyboardComponentNameGetControllerName,

+ "eng"

+};

+

+//

+// EFI Component Name 2 Protocol

+//

+GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gVirtualKeyboardComponentName2 = {

+ (EFI_COMPONENT_NAME2_GET_DRIVER_NAME) VirtualKeyboardComponentNameGetDriverName,

+ (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) VirtualKeyboardComponentNameGetControllerName,

+ "en"

+};

+

+//

+// Table of driver names

+//

+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mVirtualKeyboardDriverNameTable[] = {

+ {

+ "eng;en",

+ L"UEFI Virtual Keyboard Driver"

+ },

+ {

+ NULL,

+ NULL

+ }

+};

+

+//

+// Controller name string table

+//

+GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mVirtualKeyboardControllerNameStringTable[] = {

+ {

+ "eng",

+ L"UEFI Virtual Keyboard Driver"

+ },

+ {

+ NULL,

+ NULL

+ }

+};

+

+/**

+ Retrieves a Unicode string that is the user-readable name of the EFI Driver.

+

+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.

+ @param[in] Language A pointer to a three-character ISO 639-2 language identifier.

+ This is the language of the driver name that that the caller

+ is requesting, and it must match one of the languages specified

+ in SupportedLanguages. The number of languages supported by a

+ driver is up to the driver writer.

+ @param[out] DriverName A pointer to the Unicode string to return. This Unicode string

+ is the name of the driver specified by This in the language

+ specified by Language.

+

+ @retval EFI_SUCCESS The Unicode string for the Driver specified by This

+ and the language specified by Language was returned

+ in DriverName.

+ @retval EFI_INVALID_PARAMETER Language is NULL.

+ @retval EFI_INVALID_PARAMETER DriverName is NULL.

+ @retval EFI_UNSUPPORTED The driver specified by This does not support the

+ language specified by Language.

+

+**/

+EFI_STATUS

+EFIAPI

+VirtualKeyboardComponentNameGetDriverName (

+ IN EFI_COMPONENT_NAME_PROTOCOL *This,

+ IN CHAR8 *Language,

+ OUT CHAR16 **DriverName

+ )

+{

+ return LookupUnicodeString2 (

+ Language,

+ This->SupportedLanguages,

+ mVirtualKeyboardDriverNameTable,

+ DriverName,

+ (BOOLEAN)(This == &gVirtualKeyboardComponentName)

+ );

+}

+

+/**

+ Retrieves a Unicode string that is the user readable name of the controller

+ that is being managed by an EFI Driver.

+

+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.

+ @param[in] ControllerHandle The handle of a controller that the driver specified by

+ This is managing. This handle specifies the controller

+ whose name is to be returned.

+ @param[in] ChildHandle The handle of the child controller to retrieve the name

+ of. This is an optional parameter that may be NULL. It

+ will be NULL for device drivers. It will also be NULL

+ for a bus drivers that wish to retrieve the name of the

+ bus controller. It will not be NULL for a bus driver

+ that wishes to retrieve the name of a child controller.

+ @param[in] Language A pointer to a three character ISO 639-2 language

+ identifier. This is the language of the controller name

+ that the caller is requesting, and it must match one

+ of the languages specified in SupportedLanguages. The

+ number of languages supported by a driver is up to the

+ driver writer.

+ @param[out] ControllerName A pointer to the Unicode string to return. This Unicode

+ string is the name of the controller specified by

+ ControllerHandle and ChildHandle in the language specified

+ by Language, from the point of view of the driver specified

+ by This.

+

+ @retval EFI_SUCCESS The Unicode string for the user-readable name in the

+ language specified by Language for the driver

+ specified by This was returned in DriverName.

+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.

+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.

+ @retval EFI_INVALID_PARAMETER Language is NULL.

+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.

+ @retval EFI_UNSUPPORTED The driver specified by This is not currently managing

+ the controller specified by ControllerHandle and

+ ChildHandle.

+ @retval EFI_UNSUPPORTED The driver specified by This does not support the

+ language specified by Language.

+

+**/

+EFI_STATUS

+EFIAPI

+VirtualKeyboardComponentNameGetControllerName (

+ IN EFI_COMPONENT_NAME_PROTOCOL *This,

+ IN EFI_HANDLE ControllerHandle,

+ IN EFI_HANDLE ChildHandle, OPTIONAL

+ IN CHAR8 *Language,

+ OUT CHAR16 **ControllerName

+ )

+{

+ //

+ // ChildHandle must be NULL for a Device Driver

+ //

+ if (ChildHandle != NULL) {

+ return EFI_UNSUPPORTED;

+ }

+ return LookupUnicodeString2 (

+ Language,

+ This->SupportedLanguages,

+ mVirtualKeyboardControllerNameStringTable,

+ ControllerName,

+ (BOOLEAN)(This == &gVirtualKeyboardComponentName)

+ );

+}

diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/ComponentName.h
b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/ComponentName.h
new file mode 100644
index 0000000000..327ce9f9cb
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/ComponentName.h
@@ -0,0 +1,95 @@
+/** @file

+ Header file for Virtual Keyboard driver name.

+

+ Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#ifndef _VIRTUAL_KEYBOARD_COMPONENT_NAME_H_

+#define _VIRTUAL_KEYBOARD_COMPONENT_NAME_H_

+

+#include <Uefi.h>

+#include <Protocol/ComponentName.h>

+#include <Protocol/ComponentName2.h>

+

+/**

+ Retrieves a Unicode string that is the user-readable name of the EFI Driver.

+

+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.

+ @param[in] Language A pointer to a three-character ISO 639-2 language identifier.

+ This is the language of the driver name that that the caller

+ is requesting, and it must match one of the languages specified

+ in SupportedLanguages. The number of languages supported by a

+ driver is up to the driver writer.

+ @param[out] DriverName A pointer to the Unicode string to return. This Unicode string

+ is the name of the driver specified by This in the language

+ specified by Language.

+

+ @retval EFI_SUCCESS The Unicode string for the Driver specified by This

+ and the language specified by Language was returned

+ in DriverName.

+ @retval EFI_INVALID_PARAMETER Language is NULL.

+ @retval EFI_INVALID_PARAMETER DriverName is NULL.

+ @retval EFI_UNSUPPORTED The driver specified by This does not support the

+ language specified by Language.

+

+**/

+EFI_STATUS

+EFIAPI

+VirtualKeyboardComponentNameGetDriverName (

+ IN EFI_COMPONENT_NAME_PROTOCOL *This,

+ IN CHAR8 *Language,

+ OUT CHAR16 **DriverName

+ );

+

+/**

+ Retrieves a Unicode string that is the user readable name of the controller

+ that is being managed by an EFI Driver.

+

+ @param[in] This A pointer to the EFI_COMPONENT_NAME_PROTOCOL instance.

+ @param[in] ControllerHandle The handle of a controller that the driver specified by

+ This is managing. This handle specifies the controller

+ whose name is to be returned.

+ @param[in] ChildHandle The handle of the child controller to retrieve the name

+ of. This is an optional parameter that may be NULL. It

+ will be NULL for device drivers. It will also be NULL

+ for a bus drivers that wish to retrieve the name of the

+ bus controller. It will not be NULL for a bus driver

+ that wishes to retrieve the name of a child controller.

+ @param[in] Language A pointer to a three character ISO 639-2 language

+ identifier. This is the language of the controller name

+ that the caller is requesting, and it must match one

+ of the languages specified in SupportedLanguages. The

+ number of languages supported by a driver is up to the

+ driver writer.

+ @param[out] ControllerName A pointer to the Unicode string to return. This Unicode

+ string is the name of the controller specified by

+ ControllerHandle and ChildHandle in the language specified

+ by Language, from the point of view of the driver specified

+ by This.

+

+ @retval EFI_SUCCESS The Unicode string for the user-readable name in the

+ language specified by Language for the driver

+ specified by This was returned in DriverName.

+ @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.

+ @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.

+ @retval EFI_INVALID_PARAMETER Language is NULL.

+ @retval EFI_INVALID_PARAMETER ControllerName is NULL.

+ @retval EFI_UNSUPPORTED The driver specified by This is not currently managing

+ the controller specified by ControllerHandle and

+ ChildHandle.

+ @retval EFI_UNSUPPORTED The driver specified by This does not support the

+ language specified by Language.

+

+**/

+EFI_STATUS

+EFIAPI

+VirtualKeyboardComponentNameGetControllerName (

+ IN EFI_COMPONENT_NAME_PROTOCOL *This,

+ IN EFI_HANDLE ControllerHandle,

+ IN EFI_HANDLE ChildHandle, OPTIONAL

+ IN CHAR8 *Language,

+ OUT CHAR16 **ControllerName

+ );

+#endif

diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/DigitKeyboard.bmp
b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/DigitKeyboard.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..b64d62034817e7407120ee2181c935e07bef5a8c
GIT binary patch
literal 330454
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

literal 0
HcmV?d00001

diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/FullIcon.bmp
b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/FullIcon.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..b940505c8bc74ad6550bc322629d7975c1e1c1fc
GIT binary patch
literal 5454
zcmdUyTS!(}6o56!L@l#1k<1H~<*msK=EYIGfJHUFgo!=$AR-O~g3Ln$_Tv5C7@{FW
zuaziT6L~3b87f|a5!5uTbW}2D5<@ff*ZKTcvp6&*5#z(Z`TxV--&uR@b@o|%t#u-Q
zirH&rZa;AK<^LmpPyW_cZd|Rb+&<nn4?bRUiz^!H>wdS8R##V7QBl$K<d1cWYA;{D
ztZVAFD3jL*2L~Hl`%J6LZf@c|8xF%GjEsyJ{RdKAU2P;=(N9lLXQANWU{&7M)&|ib
zoyp0`=g*%vw)L&AuN^pWKyM*7F)?9hXD7tQ#s+ft?p+nwqR!Q;S6L`LJY4m6b#+0u
zZ{MzDW@ct|bX06Ubm)+BvDx0<UI<el_wL<Ofi3EY%@Gk1s$XojwY3#uZEbDoHhXz_
z>C>^R<KyGTHv*}xtyO_7>J%0hvQTJfsOs<N=zy@jN?yNyjc+ux_O7p)LPA3J?c3++
z>FMO;BsL#Bc+kVc!`<E8$Hxa!UtjO&=*XjOQDfb*vN9GrckZ04t1GKGI5_n5^gz75
zz4!0mk1<@|ym`YJtZUwgb&HFO@87>)T3UMd?j1wg!omWC#w~`ctE&(Mwy2?ed3l+I
z(9eooA!}=E5V1`y85$b0#P}@x{Fk}?ZEkdDXJ>gplgWhtz!<)L`xf%y!v{{T5P2hW
zb93B<z*kmQkfDzTuFPdf69FJ^mLXzvM9KX8JOoujm?BD8PG%vdO{TNY4Xu4^rqvTC
zPVC;jd#|}UJ39vk2J&_W1_pNR+U4Tnf+xqv$D_QmvU10c9Y_%gFI~C>NlHq>@sNRc
zcW<~^OiawqojboXH;fq@8{?$x*|P_=etv!kG&D5G6vWP+JqzLViCT`^qeqV*iHV8G
zh&^&eA4+&A%_;b~o=rNWMV^-|sqoaPQ>eOg=Z+Grg~Y|hDe3L)g%}S$PWa-*i*4Js
zi40~VK%Jvg$RLo+%uFR>vr(<yqVuKr%q>nRhmN<P@@LMRK{@-ZBsn=5a^b=SC4GIQ
z)OBN0;AK(Lu!kbUjv+t@(kW3<QIPEHY$Z)iO`oXMTbtw*WGupFBC|dY9X15tz@HUH
zM@RGcw{PE8g3Cc-V`G(wZxHI0;2Zd}4kh?Mc<?|;SXdZJGBPrhJbd^Na{l~zCB_c^
ztU2ZM>C+sL@6FBM-=9}Th`={|eSMD}J$m@?VL5SB9aK{g>XWpzG?ZVye3?E3{`Bcn
zNJ2uwkt0Vq#Wcdgt5>f$-~j;vsKsp%XlZF7Pca3tix)3K%FD}{&f+AF_V#v2YHBJn
zVvk(Wh7v*tHK#?!XA7+P>zg-nI@L&PYb!N2hngXN$Qy*v=s<WW#8m`{MMOvlbrik_
zflIXS?CeAsLNr5wCQ2ZUjg1V+&N%bq$BzjP{r&wA5{IZo6%hu)p=fSy7PXRb5XKA$
zoHY0B*)!^AlWB#7qOQ(FtkNMJh%w5gq@+M{b8}UOyAX1R5<(?JhoWR^YD&q;lP3|V
zsi{#S-zoUH5={L>3EwH-R`XxEas^eTrKPI;{{8!qpr9ZnQr?h2l^{Sy(4iz&W2}~%
zKQb~>Wu)fU@V-fWMmgVBn|!By$>w9nj_Gn@Gx=A^SK4e$N&n+_%GcZc4g36Gn?JkH
z)JPOL#tkth0ytY#RaK<|1W!moL4gwPLX1VrXZ?A4dRnJQF<|^OCWE8o`0?W^Be7bC
zbT|?CbA8K3+_-V$2JTc+Qj(LC!;lK|w}0EUYu6y0N^a55&(G)JL->fu%gckXmPC@9
zH*Xdf7emNv;v1p^wPFv|JGT&^kmF+wC2USsRu+U4EuL`e)~%wVA_yD{kzt4)l+dAo
p86F<C#GKOBxe+HVs7?Mk@$)bFIfd8L^U5+T;g?l#J@wbDe*hRVpnL!T

literal 0
HcmV?d00001

diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/Keyboard.c
b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/Keyboard.c
new file mode 100644
index 0000000000..a2c9a3bfc4
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/Keyboard.c
@@ -0,0 +1,1400 @@
+/** @file

+ Virtural Keyboard Control Engine

+

+ Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#include "VirtualKeyboard.h"

+

+/**

+ Notify all keyboards pressed specific key need to hidden Virtual

+ Keyboard.

+

+ @param[in] KeyData Keyboard pressed specific key data

+

+ @retval EFI_SUCCESS Success for the function.

+ @retval EFI_NOT_FOUND Not found Virtual Keyboard protocol.

+

+**/

+EFI_STATUS

+EFIAPI

+VkNotifyKeyCallback (

+ IN EFI_KEY_DATA *KeyData

+ )

+{

+ EFI_STATUS Status;

+ VK_CONTEXT *VkContext;

+ UINTN MaxColumn;

+ UINTN MaxRow;

+ UINT32 HorizontalPixel;

+ UINT32 VerticalPixel;

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkNotifyKeyCallback Start\n"));

+

+ Status = gBS->LocateProtocol (&gEfiCallerIdGuid, NULL, (VOID **) &VkContext);

+ if (EFI_ERROR (Status)) {

+ return Status;

+ }

+

+ gST->ConOut->QueryMode (

+ gST->ConOut,

+ gST->ConOut->Mode->Mode,

+ &MaxColumn,

+ &MaxRow

+ );

+ HorizontalPixel = VkContext->GraphicsOutput->Mode->Info->HorizontalResolution;

+ VerticalPixel = VkContext->GraphicsOutput->Mode->Info->VerticalResolution;

+

+ //

+ // CursorRow and CursorColumn are started from 0, so need to add 2 not 1.

+ //

+ if (((UINTN)(gST->ConOut->Mode->CursorColumn * EFI_GLYPH_WIDTH) < VkContext->SimIconBackWidth) &&

+ ((UINTN)((gST->ConOut->Mode->CursorRow + 2) * EFI_GLYPH_HEIGHT) > (VerticalPixel - VkContext-
SimIconBackHeight))) {
+ SaveVkIconBackgroundBltBuffer (VkContext, VkDisplayAttributeSimpleBottom);

+ } else if (((UINTN)((gST->ConOut->Mode->CursorColumn + 2) * EFI_GLYPH_WIDTH) > (HorizontalPixel - VkContext-
FullIconBackWidth)) &&
+ ((UINTN)((gST->ConOut->Mode->CursorRow + 2) * EFI_GLYPH_HEIGHT) > (VerticalPixel - VkContext-
FullIconBackHeight))){
+ SaveVkIconBackgroundBltBuffer (VkContext, VkDisplayAttributeFullBottom);

+ }

+

+ //

+ // Hide icon/keyboard to prevent screen scroll up.

+ //

+ if ((KeyData->Key.UnicodeChar == CHAR_CARRIAGE_RETURN) ||

+ (KeyData->Key.ScanCode == SCAN_ESC) ||

+ ((gST->ConOut->Mode->CursorColumn >= (INT32) (MaxColumn - 2)) &&

+ (gST->ConOut->Mode->CursorRow == (INT32) (MaxRow - 1)))) {

+ HideVkBody (VkContext);

+ HideVkIcon (VkContext);

+ VkContext->IconReDrawCheck = 0;

+ }

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkNotifyKeyCallback End\n"));

+ return EFI_SUCCESS;

+}

+

+/**

+ Judge whether is a registed key.

+

+ @param[in] RegsiteredData A pointer to a buffer that is filled in with the keystroke

+ state data for the key that was registered.

+ @param[in] InputData A pointer to a buffer that is filled in with the keystroke

+ state data for the key that was pressed.

+

+ @retval TRUE Key be pressed matches a registered key.

+ @retval FLASE Match failed.

+

+**/

+BOOLEAN

+IsKeyRegistered (

+ IN EFI_KEY_DATA *RegsiteredData,

+ IN EFI_KEY_DATA *InputData

+ )

+{

+ ASSERT (RegsiteredData != NULL && InputData != NULL);

+

+ if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) ||

+ (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) {

+ return FALSE;

+ }

+

+ //

+ // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means these state could be ignored.

+ //

+ if (RegsiteredData->KeyState.KeyShiftState != 0 &&

+ RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState) {

+ return FALSE;

+ }

+ if (RegsiteredData->KeyState.KeyToggleState != 0 &&

+ RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState) {

+ return FALSE;

+ }

+

+ return TRUE;

+}

+

+/**

+ Pop the key from the keybuffer.

+

+ @param[in, out] VkContext Address of an VK_CONTEXT structure.

+ @param[out] KeyData The EFI stand key infomation when code get the key will put

+ correct mapping key.

+

+ @retval EFI_SUCCESS The keystroke information was returned.

+ @retval EFI_NOT_READY The keystroke data is empty.

+

+**/

+EFI_STATUS

+VkPopTheKey (

+ IN OUT VK_CONTEXT *VkContext,

+ OUT EFI_KEY_DATA *KeyData OPTIONAL

+ )

+{

+ EFI_STATUS Status;

+ UINT8 IndexSt;

+ UINT8 IndexEd;

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkPopTheKey Start\n"));

+ //

+ // KeyBuffer

+ // [ 0 ]

+ // [ 1 ]<-*IndexSt/IndexEd

+ // [ 2 ]

+ // [ ... ]

+ // [MAX_KEY_BUF_SIZE - 1]

+ //

+ Status = EFI_SUCCESS;

+ IndexSt = VkContext->KeyStartIndex;

+ IndexEd = VkContext->KeyEndIndex;

+

+ if (IndexEd == IndexSt) {

+ DEBUG ((DEBUG_VK_KEYS, "ERROR - Keyboard buffer is empty.\n"));

+ Status = EFI_NOT_READY;

+ goto Error;

+ }

+

+ DEBUG ((DEBUG_VK_KEYS | DEBUG_INFO, "VkPopTheKey Unicode: %08x\n", VkContext-
Keybuffer[IndexSt].Key.UnicodeChar));
+ DEBUG ((DEBUG_VK_KEYS | DEBUG_INFO, "VkPopTheKey ScanCode: %08x\n", VkContext-
Keybuffer[IndexSt].Key.ScanCode));
+ DEBUG ((DEBUG_VK_KEYS | DEBUG_INFO, "VkPopTheKey ShiftState: %08x\n", VkContext-
Keybuffer[IndexSt].KeyState.KeyShiftState));
+ DEBUG ((DEBUG_VK_KEYS | DEBUG_INFO, "VkPopTheKey ToggleState:%08x\n", VkContext-
Keybuffer[IndexSt].KeyState.KeyToggleState));
+

+ if (KeyData != NULL) {

+ *KeyData = VkContext->Keybuffer[IndexSt];

+ }

+ VkContext->KeyStartIndex = ++IndexSt % MAX_KEY_BUF_SIZE;

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkPopTheKey Success, Status: %r\n", Status));

+ goto End;

+

+Error:

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkPopTheKey Failed, Status: %r\n", Status));

+

+End:

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkPopTheKey End\n"));

+ return Status;

+}

+

+/**

+ Push the event mapping key index to the input key buffer.

+

+ @param[in, out] VkContext Address of an VK_CONTEXT structure.

+ @param[in] Unicode The font's unicode number.

+

+ @retval EFI_SUCCESS The maping key index did put the key buffer.

+

+**/

+EFI_STATUS

+VkPushTheKey (

+ IN OUT VK_CONTEXT *VkContext,

+ IN UINT16 Unicode

+ )

+{

+ UINT8 IndexSt;

+ UINT8 IndexEd;

+ EFI_KEY_DATA KeyData;

+ EFI_STATUS Status;

+ LIST_ENTRY *Link;

+ VK_NOTIFY *CurrentNotify;

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkPushTheKey Start\n"));

+ //

+ // KeyBuffer

+ // [ 0 ]

+ // [ 1 ]<-IndexSt/*IndexEd

+ // [ 2 ]

+ // [ ... ]

+ // [MAX_KEY_BUF_SIZE - 1]

+ //

+ IndexSt = VkContext->KeyStartIndex;

+ IndexEd = VkContext->KeyEndIndex;

+

+ Status = EFI_SUCCESS;

+

+ //

+ // Check Keyboard Buffer if is full that will pop the first key

+ //

+ if (VkContext->IsSupportPartialKey &&

+ ((VkContext->KeyEndIndex + 2) % MAX_KEY_BUF_SIZE) == IndexSt) {

+ VkPopTheKey (VkContext, NULL);

+ }

+

+ if (((VkContext->KeyEndIndex + 1) % MAX_KEY_BUF_SIZE) == IndexSt) {

+ VkPopTheKey (VkContext, NULL);

+ }

+

+ KeyData.Key.ScanCode = SCAN_NULL;

+ KeyData.Key.UnicodeChar = CHAR_NULL;

+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID;

+ KeyData.KeyState.KeyToggleState = VkContext->KeyToggleState;

+ KeyData.KeyState.KeyToggleState &= ~EFI_CAPS_LOCK_ACTIVE;

+ KeyData.KeyState.KeyToggleState |= VkContext->IsCapsLockFlag ? EFI_CAPS_LOCK_ACTIVE : 0;

+

+ switch (Unicode) {

+ case VkKeyShift:

+ VkContext->IsShiftKeyFlag = !VkContext->IsShiftKeyFlag;

+ if (VkContext->PageNumber >= VkPage2 && VkContext->PageNumber <= VkPage3) {

+ VkContext->IsShiftKeyFlag ? VkContext->PageNumber++ : VkContext->PageNumber--;

+ }

+ VkContext->IsRedrawUpdateUI = TRUE;

+ break;

+

+ case VkKeyTwoPage:

+ switch (VkContext->PageNumber) {

+ case VkPage0:

+ case VkPage1:

+ VkContext->IsShiftKeyFlag = FALSE;

+ VkContext->PageNumber = VkContext->IsShiftKeyFlag ? VkPage3 : VkPage2;

+ break;

+

+ case VkPage2:

+ case VkPage3:

+ VkContext->IsShiftKeyFlag = FALSE;

+ VkContext->PageNumber = VkContext->IsCapsLockFlag ? VkPage1 : VkPage0;

+ break;

+

+ default:

+ break;

+ }

+ VkContext->IsRedrawUpdateUI = TRUE;

+ break;

+

+ case VkKeyCapslock:

+ VkContext->IsCapsLockFlag = !VkContext->IsCapsLockFlag;

+ if (VkContext->PageNumber >= VkPage0 && VkContext->PageNumber <= VkPage1) {

+ VkContext->IsCapsLockFlag ? VkContext->PageNumber++ : VkContext->PageNumber--;

+ }

+ KeyData.KeyState.KeyToggleState &= ~EFI_CAPS_LOCK_ACTIVE;

+ KeyData.KeyState.KeyToggleState |= VkContext->IsCapsLockFlag ? EFI_CAPS_LOCK_ACTIVE : 0;

+ VkContext->IsRedrawUpdateUI = TRUE;

+ break;

+

+ default:

+ if ((Unicode & VkKeyScanMask) != 0) {

+ KeyData.Key.ScanCode = Unicode & ~VkKeyScanMask;

+ } else {

+ KeyData.Key.UnicodeChar = Unicode;

+ }

+ break;

+ }

+

+ if (KeyData.Key.ScanCode == SCAN_NULL && KeyData.Key.UnicodeChar == CHAR_NULL) {

+ if (!VkContext->IsSupportPartialKey) {

+ goto End;

+ }

+ }

+

+ for (Link = GetFirstNode (&VkContext->NotifyList); !IsNull (&VkContext->NotifyList, Link); Link = GetNextNode
(&VkContext->NotifyList, Link)) {

+ CurrentNotify = CR (Link, VK_NOTIFY, NotifyEntry, VK_NOTIFY_SIGNATURE);

+ //

+ // The key notification function needs to run at TPL_CALLBACK

+ // while current TPL is TPL_NOTIFY. It will be invoked in

+ // VkKeyNotifyProcessHandler() which runs at TPL_CALLBACK.

+ //

+ if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {

+ VkContext->Keybuffer[IndexEd] = KeyData;

+ VkContext->KeyEndIndex = ++IndexEd % MAX_KEY_BUF_SIZE;

+ gBS->SignalEvent (VkContext->KeyNotifyProcessEvent);

+ }

+ }

+ VkContext->Keybuffer[IndexEd] = KeyData;

+ VkContext->KeyEndIndex = ++IndexEd % MAX_KEY_BUF_SIZE;

+

+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT, "VkPushTheKey Success, Status: %r\n", Status));

+ goto End;

+

+End:

+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT, "VkPushTheKey End\n"));

+ return Status;

+}

+

+/**

+ Process key notify.

+

+ @param[in] Event Indicates the event that invoke this function.

+ @param[in] Context Indicates the calling context.

+

+**/

+VOID

+EFIAPI

+VkKeyNotifyProcessHandler (

+ IN EFI_EVENT Event,

+ IN VOID *Context

+ )

+{

+ EFI_STATUS Status;

+ VK_CONTEXT *VkContext;

+ EFI_KEY_DATA KeyData;

+ LIST_ENTRY *Link;

+ LIST_ENTRY *NotifyList;

+ VK_NOTIFY *CurrentNotify;

+ EFI_TPL OldTpl;

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyNotifyProcessHandler Start\n"));

+ VkContext = (VK_CONTEXT *) Context;

+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);

+

+ //

+ // Invoke notification functions.

+ //

+ NotifyList = &VkContext->NotifyList;

+ Status = VkPopTheKey (VkContext, &KeyData);

+ if (EFI_ERROR (Status)) {

+ goto Error;

+ }

+

+ for (Link = GetFirstNode (NotifyList); !IsNull (NotifyList, Link); Link = GetNextNode (NotifyList, Link)) {

+ CurrentNotify = CR (Link, VK_NOTIFY, NotifyEntry, VK_NOTIFY_SIGNATURE);

+ if (IsKeyRegistered (&CurrentNotify->KeyData, &KeyData)) {

+ CurrentNotify->KeyNotificationFn (&KeyData);

+ }

+ }

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyNotifyProcessHandler Success, Status: %r\n", Status));

+ goto End;

+

+Error:

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyNotifyProcessHandler Failed, Status: %r\n", Status));

+

+End:

+ gBS->RestoreTPL (OldTpl);

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyNotifyProcessHandler End\n"));

+}

+

+/**

+ Push the event mapping key index to the input key buffer.

+

+ @param[in] VkContext Address of an VK_CONTEXT structure.

+ @param[out] KeyItem Key Item.

+ @param[out] Index Index of Key Item.

+ @param[in] TouchX X position of finger touch.

+ @param[in] TouchY Y position of finger touch.

+

+ @retval TRUE Touch on Virtual Keyboard.

+ @retval FALSE Not touch on Virtual Keyboard.

+

+**/

+BOOLEAN

+IsTouchVk (

+ IN VK_CONTEXT *VkContext,

+ OUT VK_STRUCT *KeyItem,

+ OUT UINT32 *Index,

+ IN UINT32 TouchX,

+ IN UINT32 TouchY

+ )

+{

+ for (*Index = 0; *Index < VkContext->NumOfKeysInfo; (*Index)++) {

+ if (VkContext->KeyboardBodyPtr[*Index].DisStartX < TouchX &&

+ VkContext->KeyboardBodyPtr[*Index].DisEndX > TouchX &&

+ VkContext->KeyboardBodyPtr[*Index].DisStartY < TouchY &&

+ VkContext->KeyboardBodyPtr[*Index].DisEndY > TouchY) {

+ break;

+ }

+ }

+ if (*Index != VkContext->NumOfKeysInfo) {

+ *KeyItem = VkContext->KeyboardBodyPtr[*Index];

+ }

+

+ return *Index != VkContext->NumOfKeysInfo;

+}

+

+VOID

+EFIAPI

+VkReadyToBootCallBack (

+ IN EFI_EVENT Event,

+ IN VOID *Context

+ )

+{

+ VK_CONTEXT *VkContext;

+ VkContext = (VK_CONTEXT *)Context;

+

+ HideVkBody (VkContext);

+ VkContext->TargetKeyboardDisplay = VkDisplayAttributeNone;

+}

+

+/**

+ Timer event

+

+ This routine is called at TPL_VK_SYNC.

+

+ This routine polls for touch panel input.

+

+ @param[in] Event Event whose notification function is being invoked.

+ @param[in] Context Pointer to the notification function's context,

+ which is implementation-dependent. Context corresponds

+ to NotifyContext in CreateEventEx().

+

+**/

+VOID

+EFIAPI

+VkTimer (

+ IN EFI_EVENT Event,

+ IN VOID *Context

+ )

+{

+ EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer;

+ EFI_ABSOLUTE_POINTER_STATE Point;

+ EFI_STATUS Status;

+ UINT32 TouchX;

+ UINT32 TouchY;

+ VK_CONTEXT *VkContext;

+ UINT32 Index;

+ VK_STRUCT KeyItem;

+ UINT32 Font;

+

+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT, "VkTimer Start\n"));

+ VkContext = (VK_CONTEXT *)Context;

+

+ //

+ // Update keyboard UI layout

+ //

+ CheckIconCleared (VkContext);

+ CheckScreenCleared (VkContext);

+ CheckBackgroundChanged (VkContext);

+ if (VkContext->IsRedrawUpdateUI) {

+ HideVkBody (VkContext);

+ DrawKeyboardLayout (VkContext);

+ VkContext->IsRedrawUpdateUI = FALSE;

+ }

+

+ //

+ // Error handle for invalid information

+ //

+ AbsolutePointer = VkContext->AbsolutePointer;

+ Status = gBS->CheckEvent (AbsolutePointer->WaitForInput);

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_VK_POINTS, "ERROR - VkContext->AbsolutePointer->WaitForInput-
CheckEvent failed! Status: %r\n", Status));
+ goto Error;

+ }

+

+ Status = AbsolutePointer->GetState (AbsolutePointer, &Point);

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_VK_POINTS, "ERROR - GetState failed, Status: %r\n", Status));

+ goto Error;

+ }

+

+ if (VkContext->AbsolutePointer->Mode->AbsoluteMaxX <= Point.CurrentX) {

+ DEBUG ((

+ DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_VK_POINTS,

+ "ERROR - X value exceeds maximum: X: 0x%016Lx, MaxX: 0x%016Lx\n",

+ Point.CurrentX,

+ VkContext->AbsolutePointer->Mode->AbsoluteMaxX

+ ));

+ Status = EFI_PROTOCOL_ERROR;

+ goto Error;

+ }

+ if (VkContext->AbsolutePointer->Mode->AbsoluteMaxY <= Point.CurrentY) {

+ DEBUG ((

+ DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_VK_POINTS,

+ "ERROR - Y value exceeds maximum: Y: 0x%016Lx, MaxY: 0x%016Lx\n",

+ Point.CurrentY,

+ VkContext->AbsolutePointer->Mode->AbsoluteMaxY

+ ));

+ Status = EFI_PROTOCOL_ERROR;

+ goto Error;

+ }

+

+ //

+ // Update the touch active status

+ //

+ VkContext->TouchActive = ((Point.ActiveButtons & EFI_ABSP_TouchActive) != 0) ? TRUE : FALSE;

+ if (!VkContext->TouchActive) {

+ VkContext->KeyPressed = FALSE;

+ }

+ ConvertCoordinate (VkContext, Point, &TouchX, &TouchY);

+

+ if (!VkContext->KeyPressed &&

+ VkContext->TouchActive &&

+ IsTouchVk (VkContext, &KeyItem, &Index, TouchX, TouchY)) {

+ VkGetMappingFont (VkContext, KeyItem, &Font);

+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO, "VK Touch event is trigger!\n" ));

+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO | DEBUG_VK_POINTS, "TouchActive: 0x%04x \n",
VkContext->TouchActive));

+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO | DEBUG_VK_POINTS, "CurrentKeyboardDisplay: 0x%04x \n",
VkContext->CurrentKeyboardDisplay));

+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO | DEBUG_VK_POINTS, "X: 0x%016Lx\n",
Point.CurrentX));

+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO | DEBUG_VK_POINTS, "Y: 0x%016Lx\n",
Point.CurrentY));

+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO | DEBUG_VK_POINTS, "Z: 0x%016Lx\n",
Point.CurrentZ));

+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO | DEBUG_VK_POINTS, "Buttons: 0x%08x \n",
Point.ActiveButtons));

+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO | DEBUG_VK_POINTS, "MapKey Index: 0x%04x \n",
Index));

+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT | DEBUG_INFO | DEBUG_VK_POINTS, "Key Unicode: 0x%08x \n", Font));

+

+ switch (Font) {

+ //

+ // Touch the small keyboard icon, show/hide the keyboard.

+ //

+ case VkKeyTypeMaximum:

+ KeyboardLayoutHandler (VkContext, Index);

+ break;

+

+ //

+ // Touch the key raw.

+ //

+ default:

+ if (VkContext->CurrentKeyboardDisplay == VkDisplayAttributeNone) {

+ break;

+ }

+ VkPushTheKey (VkContext, (UINT16) Font);

+ }

+ VkContext->KeyPressed = TRUE;

+ }

+

+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT, "VkTimer Success, Status: %r\n", Status));

+ goto End;

+

+Error:

+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT, "VkTimer Failed, Status: %r\n", Status));

+

+End:

+ DEBUG ((DEBUG_VK_TIMER_ENTRY_EXIT, "VkTimer End\n"));

+ return;

+}

+

+/**

+ VkTouchWaitForKey - SignalEvent when the keybuffer has keys.

+

+ @param[in] Event Event whose notification function is being invoked.

+ @param[in] Context Pointer to the notification function's context,

+ which is implementation-dependent. Context corresponds

+ to NotifyContext in CreateEventEx().

+

+**/

+VOID

+EFIAPI

+VkTouchWaitForKey (

+ IN EFI_EVENT Event,

+ IN VOID *Context

+ )

+{

+ VK_CONTEXT *VkContext;

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkTouchWaitForKey Start\n"));

+ VkContext = (VK_CONTEXT*) Context;

+

+ if (VkContext->KeyStartIndex != VkContext->KeyEndIndex) {

+ DEBUG ((DEBUG_VK_KEYS, "Signal VkTouchWaitForKey\n"));

+ gBS->SignalEvent (Event);

+ }

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkTouchWaitForKey End\n"));

+}

+

+/**

+ Get image file data from BIOS image through specific ImageId.

+

+ @param[in] VkContext Address of an VK_CONTEXT structure.

+ @param[in] ImageId Guid to get specific image file used.

+

+ @retval EFI_IMAGE_INPUT Image data on BIOS image.

+

+**/

+EFI_IMAGE_INPUT*

+VkGetImage (

+ IN VK_CONTEXT *VkContext,

+ IN EFI_IMAGE_ID ImageId

+ )

+{

+ EFI_STATUS Status;

+ EFI_IMAGE_INPUT Image;

+ EFI_IMAGE_INPUT *VkImage;

+

+

+ Status = VkContext->HiiImageEx->GetImageEx (

+ VkContext->HiiImageEx,

+ VkContext->HiiHandle,

+ ImageId,

+ &Image

+ );

+ if (EFI_ERROR (Status)) {

+ ASSERT_EFI_ERROR (Status);

+ }

+

+ VkImage = AllocateCopyPool (sizeof (EFI_IMAGE_INPUT), &Image);

+ if (VkImage == NULL) {

+ ASSERT_EFI_ERROR (EFI_OUT_OF_RESOURCES);

+ return NULL;

+ }

+

+ return VkImage;

+}

+

+/**

+ Dump partial debug message on VkContext.

+

+ @param[in] VkContext Address of an VK_CONTEXT structure.

+

+**/

+VOID

+VkDumpContext (

+ IN VK_CONTEXT *VkContext

+ )

+{

+ DEBUG ((

+ DEBUG_VK_ROUTINE_ENTRY_EXIT,

+ "VkContext->Signature: 0x%016x\n",

+ VkContext->Signature

+ ));

+ DEBUG ((

+ DEBUG_VK_ROUTINE_ENTRY_EXIT,

+ "VkContext->Controller: 0x%016x\n",

+ VkContext->Controller

+ ));

+ DEBUG ((

+ DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_VK_GRAPHICS_INFO,

+ "VkContext->GraphicsOutput->Mode->MaxMode: 0x%08x\n",

+ VkContext->GraphicsOutput->Mode->MaxMode

+ ));

+ DEBUG ((

+ DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_VK_GRAPHICS_INFO,

+ "VkContext->GraphicsOutput->Mode->Mode: 0x%08x\n",

+ VkContext->GraphicsOutput->Mode->Mode

+ ));

+ DEBUG ((

+ DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_VK_GRAPHICS_INFO,

+ "VkContext->GraphicsOutput->Mode->Info->HorizontalResolution: 0x%08x\n",

+ VkContext->GraphicsOutput->Mode->Info->HorizontalResolution

+ ));

+ DEBUG ((

+ DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_VK_GRAPHICS_INFO,

+ "VkContext->GraphicsOutput->Mode->Info->VerticalResolution: 0x%08x\n",

+ VkContext->GraphicsOutput->Mode->Info->VerticalResolution

+ ));

+ DEBUG ((

+ DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_VK_POINTS,

+ "VkContext->AbsolutePointer->Mode X: 0x%016Lx - 0x%016Lx\n",

+ VkContext->AbsolutePointer->Mode->AbsoluteMinX,

+ VkContext->AbsolutePointer->Mode->AbsoluteMaxX

+ ));

+ DEBUG ((

+ DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_VK_POINTS,

+ "VkContext->AbsolutePointer->Mode Y: 0x%016Lx - 0x%016Lx\n",

+ VkContext->AbsolutePointer->Mode->AbsoluteMinY,

+ VkContext->AbsolutePointer->Mode->AbsoluteMaxY

+ ));

+ DEBUG ((

+ DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_VK_POINTS,

+ "VkContext->AbsolutePointer->Mode Z: 0x%016Lx - 0x%016Lx\n",

+ VkContext->AbsolutePointer->Mode->AbsoluteMinZ,

+ VkContext->AbsolutePointer->Mode->AbsoluteMaxZ

+ ));

+ DEBUG ((

+ DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_VK_POINTS,

+ "VkContext->AbsolutePointer->Mode->Attributes: 0x%08x\n",

+ VkContext->AbsolutePointer->Mode->Attributes

+ ));

+}

+

+/**

+ Start the virtual keyboard driver

+

+ This routine allocates the necessary resources for the driver.

+

+ This routine is called by VirtualKeyboardDriverStart to complete the driver

+ initialization.

+

+ @param[in, out] VkContext Address of an VK_CONTEXT structure

+ @param[in] Controller Handle of device to work with.

+

+ @retval EFI_SUCCESS Driver API properly initialized

+

+**/

+EFI_STATUS

+VkApiStart (

+ IN OUT VK_CONTEXT *VkContext,

+ IN EFI_HANDLE Controller

+ )

+{

+ EFI_STATUS Status;

+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;

+ EFI_KEY_DATA KeyData;

+ EFI_HANDLE NotifyHandle;

+ EFI_EVENT ReadyToBootEvent;

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkApiStart Start\n"));

+

+ Status = gBS->CreateEvent (

+ EVT_NOTIFY_SIGNAL,

+ TPL_CALLBACK,

+ VkKeyNotifyProcessHandler,

+ VkContext,

+ &VkContext->KeyNotifyProcessEvent

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to create VkContext-
KeyNotifyProcessEvent, Status: %r\n", Status));
+ goto Error;

+ }

+

+ Status = gBS->CreateEvent (

+ EVT_NOTIFY_WAIT,

+ TPL_NOTIFY,

+ VkTouchWaitForKey,

+ VkContext,

+ &(VkContext->SimpleTextIn.WaitForKey)

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to create VkContext-
SimpleTextIn.WaitForKey, Status: %r\n", Status));
+ goto Error;

+ }

+

+ Status = gBS->CreateEvent (

+ EVT_NOTIFY_WAIT,

+ TPL_NOTIFY,

+ VkTouchWaitForKey,

+ VkContext,

+ &(VkContext->SimpleTextInEx.WaitForKeyEx)

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to create VkContext-
SimpleTextInEx.WaitForKeyEx, Status %r\n", Status));
+ goto Error;

+ }

+

+ Status = gBS->CreateEvent (

+ EVT_TIMER | EVT_NOTIFY_SIGNAL,

+ TPL_VK_SYNC,

+ VkTimer,

+ (VOID *)VkContext,

+ &(VkContext->TimerEvent)

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to create the timer event, Status: %r\n",
Status));

+ goto Error;

+ }

+

+ Status = gBS->SetTimer (

+ VkContext->TimerEvent,

+ TimerPeriodic,

+ (UINT64) VK_POLL_INTERVAL

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to set the timer event, Status: %r\n",
Status));

+ goto Error;

+ }

+

+ //

+ // Create event to clear keyboard before boot into OS.

+ //

+ Status = EfiCreateEventReadyToBootEx (

+ TPL_CALLBACK,

+ VkReadyToBootCallBack,

+ (VOID *)VkContext,

+ &ReadyToBootEvent

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to create ReadyToBootEvent,
Status: %r\n", Status));

+ goto Error;

+ }

+

+ Status = gBS->LocateProtocol (

+ &gEfiHiiImageExProtocolGuid,

+ NULL,

+ (VOID **) &VkContext->HiiImageEx

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to open HiiImageEx protocol,
Status: %r\n", Status));

+ goto Error;

+ }

+

+ //

+ // Initialize VkContext

+ //

+ VkContext->Signature = VK_SIGNATURE;

+ VkContext->Controller = Controller;

+ VkContext->SimpleTextIn.Reset = VkKeyboardReset;

+ VkContext->SimpleTextIn.ReadKeyStroke = VkKeyboardReadKeyStroke;

+ VkContext->SimpleTextInEx.Reset = VkKeyboardResetEx;

+ VkContext->SimpleTextInEx.ReadKeyStrokeEx = VkKeyboardReadKeyStrokeEx;

+ VkContext->SimpleTextInEx.SetState = VkKeyboardSetState;

+ VkContext->SimpleTextInEx.RegisterKeyNotify = VkKeyboardRegisterKeyNotify;

+ VkContext->SimpleTextInEx.UnregisterKeyNotify = VkKeyboardUnregisterKeyNotify;

+ VkContext->IsIconShowed = FALSE;

+ VkContext->IsBackgroundChanged = FALSE;

+ VkContext->PageNumber = 0;

+ VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone;

+ VkContext->TargetKeyboardDisplay = VkDisplayAttributeNone;

+ VkContext->VkBodyBackgroundBltBuffer = NULL;

+ VkContext->VkBodyCompoundBltBuffer = NULL;

+ VkContext->VkBodyBltSize = 0;

+ VkContext->VkBodyBltStartX = 0;

+ VkContext->VkBodyBltStartY = 0;

+ VkContext->VkBodyBltHeight = 0;

+ VkContext->VkBodyBltWidth = 0;

+ VkContext->IconBltBuffer = NULL;

+ VkContext->IconBltSize = 0;

+ VkContext->IconReDrawCheck = 0;

+ VkContext->FullIconUpdatedFlag = FALSE;

+ VkContext->SimIconUpdatedFlag = FALSE;

+ VkContext->KeyStartIndex = 0;

+ VkContext->KeyEndIndex = 0;

+ VkContext->KeyToggleState = EFI_TOGGLE_STATE_VALID;

+ VkContext->SmallIcon = VkGetImage (VkContext, IMAGE_TOKEN (IMG_VK_SIMPLEICON));

+ VkContext->FullIcon = VkGetImage (VkContext, IMAGE_TOKEN (IMG_VK_FULLICON));

+ VkContext->SimKeyBody = VkGetImage (VkContext, IMAGE_TOKEN (IMG_VK_SIMPLEKEYBOARD));

+ VkContext->DigKeyBody = VkGetImage (VkContext, IMAGE_TOKEN (IMG_VK_DIGITKEYBOARD));

+ VkContext->CapLeKeyBody = VkGetImage (VkContext, IMAGE_TOKEN (IMG_VK_CAPITALLETTERKEYBOARD));

+

+ InitializeListHead (&VkContext->NotifyList);

+

+ Status = SetCharacterPosition (VkContext, 800, 600);

+ ASSERT_EFI_ERROR (Status);

+

+ Status = DrawKeyboardLayout (VkContext);

+ ASSERT_EFI_ERROR (Status);

+

+ Status = HideVkBody (VkContext);

+ ASSERT_EFI_ERROR (Status);

+

+ Status = HideVkIcon (VkContext);

+ ASSERT_EFI_ERROR (Status);

+

+ DEBUG_CODE (

+ VkDumpContext (VkContext);

+ );

+

+ Status = gBS->HandleProtocol (

+ gST->ConsoleInHandle,

+ &gEfiSimpleTextInputExProtocolGuid,

+ (VOID **)&SimpleEx

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to found ConIn Protocol, Status: %r\n",
Status));

+ goto Error;

+ }

+

+ KeyData.KeyState.KeyToggleState = 0;

+ KeyData.KeyState.KeyShiftState = 0;

+ KeyData.Key.ScanCode = SCAN_ESC;

+ KeyData.Key.UnicodeChar = CHAR_NULL;

+ NotifyHandle = NULL;

+ Status = SimpleEx->RegisterKeyNotify (

+ SimpleEx,

+ &KeyData,

+ VkNotifyKeyCallback,

+ &NotifyHandle

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to register 'Esc', Status: %r\n", Status));

+ goto Error;

+ }

+

+ KeyData.KeyState.KeyToggleState = 0;

+ KeyData.KeyState.KeyShiftState = 0;

+ KeyData.Key.ScanCode = SCAN_NULL;

+ KeyData.Key.UnicodeChar = CHAR_CARRIAGE_RETURN;

+ Status = SimpleEx->RegisterKeyNotify (

+ SimpleEx,

+ &KeyData,

+ VkNotifyKeyCallback,

+ &NotifyHandle

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to register 'Enter', Status: %r\n", Status));

+ goto Error;

+ }

+

+ for (KeyData.Key.UnicodeChar = L' '; KeyData.Key.UnicodeChar <= L'~'; KeyData.Key.UnicodeChar++) {

+ Status = SimpleEx->RegisterKeyNotify (

+ SimpleEx,

+ &KeyData,

+ VkNotifyKeyCallback,

+ &NotifyHandle

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((

+ DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR,

+ "ERROR - Failed to register '%c', Status: %r\n",

+ KeyData.Key.UnicodeChar,

+ Status

+ ));

+ break;

+ }

+ }

+ if (EFI_ERROR(Status)) {

+ goto Error;

+ }

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkApiStart Success, Status: %r\n", Status));

+ goto End;

+

+Error:

+ VkApiStop (VkContext);

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkApiStart Failed, Status: %r\n", Status));

+

+End:

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkApiStart End\n"));

+ return Status;

+}

+

+/**

+ Stop the virtual keyboard driver

+

+ This routine releases the resources allocated by VKApiStart.

+

+ This routine is called by VirtualKeyboardDriverStop to initiate the driver

+ shutdown.

+

+ @param[in] VkContext Address of an VK_CONTEXT structure

+

+**/

+VOID

+VkApiStop (

+ IN VK_CONTEXT *VkContext

+ )

+{

+ EFI_STATUS Status;

+ VK_NOTIFY *NotifyNode;

+ LIST_ENTRY *NotifyList;

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkApiStop Start\n"));

+

+ Status = gBS->SetTimer (VkContext->TimerEvent, TimerCancel, 0);

+ ASSERT_EFI_ERROR (Status);

+

+ if (VkContext->KeyNotifyProcessEvent != NULL) {

+ Status = gBS->CloseEvent (VkContext->KeyNotifyProcessEvent);

+ ASSERT_EFI_ERROR (Status);

+ VkContext->KeyNotifyProcessEvent = NULL;

+ }

+

+ if (VkContext->TimerEvent != NULL) {

+ Status = gBS->CloseEvent (VkContext->TimerEvent);

+ ASSERT_EFI_ERROR (Status);

+ VkContext->TimerEvent = NULL;

+ }

+

+ if (VkContext->SimpleTextIn.WaitForKey != NULL) {

+ Status = gBS->CloseEvent (VkContext->SimpleTextIn.WaitForKey);

+ ASSERT_EFI_ERROR (Status);

+ VkContext->SimpleTextIn.WaitForKey = NULL;

+ }

+

+ if (VkContext->SimpleTextInEx.WaitForKeyEx != NULL) {

+ Status = gBS->CloseEvent (VkContext->SimpleTextInEx.WaitForKeyEx);

+ ASSERT_EFI_ERROR (Status);

+ VkContext->SimpleTextInEx.WaitForKeyEx = NULL;

+ }

+

+ NotifyList = &VkContext->NotifyList;

+ if (NotifyList != NULL) {

+ while (!IsListEmpty (NotifyList)) {

+ NotifyNode = CR (NotifyList->ForwardLink, VK_NOTIFY, NotifyEntry, VK_NOTIFY_SIGNATURE);

+ RemoveEntryList (NotifyList->ForwardLink);

+ gBS->FreePool (NotifyNode);

+ }

+ }

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkApiStop End\n"));

+}

+

+/**

+ Reset the input device and optionally run diagnostics

+

+ @param[in] This Protocol instance pointer.

+ @param[in] ExtendedVerification Driver may perform diagnostics on reset.

+

+ @retval EFI_SUCCESS The device was reset.

+ @retval EFI_DEVICE_ERROR The device is not functioning properly and could not be reset.

+

+**/

+EFI_STATUS

+EFIAPI

+VkKeyboardReset (

+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,

+ IN BOOLEAN ExtendedVerification

+ )

+{

+ EFI_STATUS Status;

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReset Start\n"));

+ Status = EFI_SUCCESS;

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReset End\n"));

+ return Status;

+}

+

+/**

+ Resets the input device hardware.

+

+ The Reset() function resets the input device hardware. As part

+ of initialization process, the firmware/device will make a quick

+ but reasonable attempt to verify that the device is functioning.

+ If the ExtendedVerification flag is TRUE the firmware may take

+ an extended amount of time to verify the device is operating on

+ reset. Otherwise the reset operation is to occur as quickly as

+ possible. The hardware verification process is not defined by

+ this specification and is left up to the platform firmware or

+ driver to implement.

+

+ @param[in] This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.

+

+ @param[in] ExtendedVerification Indicates that the driver may perform a more exhaustive

+ verification operation of the device during reset.

+

+ @retval EFI_SUCCESS The device was reset.

+ @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset.

+

+**/

+EFI_STATUS

+EFIAPI

+VkKeyboardResetEx (

+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,

+ IN BOOLEAN ExtendedVerification

+ )

+{

+ EFI_STATUS Status;

+ VK_CONTEXT *VkContext;

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardResetEx Start\n"));

+

+ Status = EFI_SUCCESS;

+ if (This == NULL) {

+ Status = EFI_INVALID_PARAMETER;

+ goto Error;

+ }

+

+ VkContext = VK_CONTEXT_FROM_SIMPLETEXTINEX_PROTOCOL (This);

+

+ Status = VkContext->SimpleTextIn.Reset (&VkContext->SimpleTextIn, ExtendedVerification);

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_KEYS, "ERROR - Failed to VK reset, Status: %r\n", Status));

+ goto Error;

+ }

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardResetEx Success, Status: %r\n", Status));

+ goto End;

+

+Error:

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardResetEx Failed, Status: %r\n", Status));

+

+End:

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardResetEx End\n"));

+ return Status;

+}

+

+/**

+ Reads the next keystroke from the input device. The WaitForKey Event can

+ be used to test for existence of a keystroke via WaitForEvent () call.

+

+ @param[in] This Protocol instance pointer.

+ @param[out] Key Driver may perform diagnostics on reset.

+

+ @retval EFI_SUCCESS The keystroke information was returned.

+ @retval EFI_NOT_READY There was no keystroke data available.

+ @retval EFI_DEVICE_ERROR The keystroke information was not returned due to

+ hardware errors.

+

+**/

+EFI_STATUS

+EFIAPI

+VkKeyboardReadKeyStroke (

+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,

+ OUT EFI_INPUT_KEY *Key

+ )

+{

+ EFI_STATUS Status;

+ VK_CONTEXT *VkContext;

+ EFI_KEY_DATA TmpKeyData;

+ EFI_TPL OldTpl;

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReadKeyStroke Start\n"));

+

+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);

+ if (This == NULL || Key == NULL) {

+ Status = EFI_INVALID_PARAMETER;

+ goto Error;

+ }

+

+ VkContext = VK_CONTEXT_FROM_PROTOCOL (This);

+

+ Status = VkKeyboardReadKeyStrokeEx (&VkContext->SimpleTextInEx, &TmpKeyData);

+ if (EFI_ERROR (Status)) {

+ goto Error;

+ }

+ *Key = TmpKeyData.Key;

+

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReadKeyStroke Success, Status: %r\n", Status));

+ goto End;

+

+Error:

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReadKeyStroke Failed, Status: %r\n", Status));

+

+End:

+ gBS->RestoreTPL (OldTpl);

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReadKeyStroke End\n"));

+ return Status;

+}

+

+/**

+ Reads the next keystroke from the input device.

+

+ @param[in] This Protocol instance pointer.

+ @param[out] KeyData A pointer to a buffer that is filled in with the keystroke

+ state data for the key that was pressed.

+

+ @retval EFI_SUCCESS The keystroke information was returned.

+ @retval EFI_NOT_READY There was no keystroke data available.

+ @retval EFI_INVALID_PARAMETER This or KeyData is NULL.

+

+**/

+EFI_STATUS

+EFIAPI

+VkKeyboardReadKeyStrokeEx (

+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,

+ OUT EFI_KEY_DATA *KeyData

+ )

+{

+ VK_CONTEXT *VkContext;

+ EFI_STATUS Status;

+ EFI_TPL OldTpl;

+ EFI_KEY_DATA TmpKeyData;

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReadKeyStrokeEx Start\n"));

+

+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);

+ if (This == NULL || KeyData == NULL) {

+ Status = EFI_INVALID_PARAMETER;

+ goto Error;

+ }

+

+ VkContext = VK_CONTEXT_FROM_SIMPLETEXTINEX_PROTOCOL (This);

+

+ while (TRUE) {

+ Status = VkPopTheKey (VkContext, &TmpKeyData);

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_KEYS, "ERROR - Failed to VkPopTheKey check whether keybuffer is empty, Status: %r\n", Status));

+ goto Error;

+ }

+ if (TmpKeyData.Key.ScanCode != SCAN_NULL || TmpKeyData.Key.UnicodeChar != CHAR_NULL) {

+ break;

+ }

+ }

+ *KeyData = TmpKeyData;

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReadKeyStrokeEx Success, Status: %r\n", Status));

+ goto End;

+

+Error:

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReadKeyStrokeEx Failed, Status: %r\n", Status));

+

+End:

+ gBS->RestoreTPL (OldTpl);

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardReadKeyStrokeEx End\n"));

+ return Status;

+}

+

+/**

+ Set certain state for the input device.

+

+ @param[in] This Protocol instance pointer.

+ @param[in] KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the

+ state for the input device.

+

+ @retval EFI_SUCCESS The device state was set appropriately.

+ @retval EFI_INVALID_PARAMETER This or KeyToggleState is NULL.

+

+**/

+EFI_STATUS

+EFIAPI

+VkKeyboardSetState (

+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,

+ IN EFI_KEY_TOGGLE_STATE *KeyToggleState

+ )

+{

+ EFI_STATUS Status;

+ VK_CONTEXT *VkContext;

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardSetState Start\n"));

+

+ Status = EFI_SUCCESS;

+ if (This == NULL || KeyToggleState == NULL) {

+ Status = EFI_INVALID_PARAMETER;

+ goto Error;

+ }

+

+ VkContext = VK_CONTEXT_FROM_SIMPLETEXTINEX_PROTOCOL (This);

+

+ VkContext->KeyToggleState = *KeyToggleState;

+ VkContext->IsCapsLockFlag = (*KeyToggleState & EFI_CAPS_LOCK_ACTIVE) == EFI_CAPS_LOCK_ACTIVE;

+ VkContext->IsSupportPartialKey = (*KeyToggleState & EFI_KEY_STATE_EXPOSED) == EFI_KEY_STATE_EXPOSED;

+

+ if (VkContext->PageNumber >= VkPage0 && VkContext->PageNumber <= VkPage1) {

+ VkContext->PageNumber = VkContext->IsCapsLockFlag ? VkPage1 : VkPage0;

+ }

+

+ HideVkBody (VkContext);

+ DrawKeyboardLayout (VkContext);

+

+ DEBUG ((DEBUG_VK_KEYS | DEBUG_INFO, "VkContext->KeyToggleState: %02x\n", VkContext->KeyToggleState));

+ DEBUG ((DEBUG_VK_KEYS | DEBUG_INFO, "VkContext->IsCapsLockFlag: %02x\n", VkContext->IsCapsLockFlag));

+ DEBUG ((DEBUG_VK_KEYS | DEBUG_INFO, "VkContext->IsSupportPartialKey: %02x\n", VkContext->IsSupportPartialKey));

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardSetState Success, Status: %r\n", Status));

+ goto End;

+

+Error:

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardSetState Failed, Status: %r\n", Status));

+

+End:

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardSetState End\n"));

+ return Status;

+}

+

+/**

+ Register a notification function for a particular keystroke for the input device.

+

+ @param[in] This Protocol instance pointer.

+ @param[in] KeyData A pointer to a buffer that is filled in with the keystroke

+ information data for the key that was pressed.

+ @param[in] KeyNotificationFunction Points to the function to be called when the key

+ sequence is typed specified by KeyData.

+ @param[out] NotifyHandle Points to the unique handle assigned to the registered notification.

+

+ @retval EFI_SUCCESS The notification function was registered successfully.

+ @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data structures.

+ @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL.

+

+**/

+EFI_STATUS

+EFIAPI

+VkKeyboardRegisterKeyNotify (

+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,

+ IN EFI_KEY_DATA *KeyData,

+ IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,

+ OUT EFI_HANDLE *NotifyHandle

+ )

+{

+ EFI_STATUS Status;

+ EFI_TPL OldTpl;

+ VK_CONTEXT *VkContext;

+ LIST_ENTRY *Link;

+ VK_NOTIFY *CurrentNotify;

+ VK_NOTIFY *NewNotify;

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardRegisterKeyNotify Start\n"));

+

+ //

+ // Enter critical section

+ //

+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);

+ Status = EFI_SUCCESS;

+ if (This == NULL || KeyData == NULL || NotifyHandle == NULL || KeyNotificationFunction == NULL) {

+ Status = EFI_INVALID_PARAMETER;

+ goto Error;

+ }

+ VkContext = VK_CONTEXT_FROM_SIMPLETEXTINEX_PROTOCOL (This);

+

+

+ //

+ // Return EFI_SUCCESS if the (KeyData, NotificationFunction) is already registered.

+ //

+ for (Link = VkContext->NotifyList.ForwardLink; Link != &VkContext->NotifyList; Link = Link->ForwardLink) {

+ CurrentNotify = CR (Link, VK_NOTIFY, NotifyEntry, VK_NOTIFY_SIGNATURE);

+ if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) {

+ if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) {

+ *NotifyHandle = CurrentNotify;

+ Status = EFI_SUCCESS;

+ goto End;

+ }

+ }

+ }

+

+ //

+ // Allocate resource to save the notification function

+ //

+ NewNotify = (VK_NOTIFY *) AllocateZeroPool (sizeof (VK_NOTIFY));

+ if (NewNotify == NULL) {

+ Status = EFI_OUT_OF_RESOURCES;

+ goto Error;

+ }

+

+ NewNotify->Signature = VK_NOTIFY_SIGNATURE;

+ NewNotify->KeyNotificationFn = KeyNotificationFunction;

+ CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA));

+ InsertTailList (&VkContext->NotifyList, &NewNotify->NotifyEntry);

+

+ *NotifyHandle = NewNotify;

+ Status = EFI_SUCCESS;

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardRegisterKeyNotify Success, Status: %r\n", Status));

+ goto End;

+

+Error:

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardRegisterKeyNotify Failed, Status: %r\n", Status));

+

+End:

+ //

+ // Leave critical section and return

+ //

+ gBS->RestoreTPL (OldTpl);

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardRegisterKeyNotify End\n"));

+ return Status;

+}

+

+/**

+ Remove a registered notification function from a particular keystroke.

+

+ @param[in] This Protocol instance pointer.

+ @param[in] NotificationHandle The handle of the notification function being unregistered.

+

+ @retval EFI_SUCCESS The notification function was unregistered successfully.

+ @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid

+

+**/

+EFI_STATUS

+EFIAPI

+VkKeyboardUnregisterKeyNotify (

+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,

+ IN EFI_HANDLE NotificationHandle

+ )

+{

+ EFI_STATUS Status;

+ VK_CONTEXT *VkContext;

+ EFI_TPL OldTpl;

+ LIST_ENTRY *Link;

+ VK_NOTIFY *CurrentNotify;

+ BOOLEAN IsFindNotifyHandle;

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardUnregisterKeyNotify Start\n"));

+

+ //

+ // Enter critical section

+ //

+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);

+ Status = EFI_SUCCESS;

+ if (This == NULL || NotificationHandle == NULL) {

+ Status = EFI_INVALID_PARAMETER;

+ goto Error;

+ }

+ VkContext = VK_CONTEXT_FROM_SIMPLETEXTINEX_PROTOCOL (This);

+

+ IsFindNotifyHandle = FALSE;

+ for (Link = VkContext->NotifyList.ForwardLink; Link != &VkContext->NotifyList; Link = Link->ForwardLink) {

+ CurrentNotify = CR (Link, VK_NOTIFY, NotifyEntry, VK_NOTIFY_SIGNATURE);

+ if (CurrentNotify == NotificationHandle) {

+ //

+ // Remove the notification function from NotifyList and free resources

+ //

+ RemoveEntryList (&CurrentNotify->NotifyEntry);

+

+ gBS->FreePool (CurrentNotify);

+ IsFindNotifyHandle = TRUE;

+ break;

+ }

+ }

+

+ if (!IsFindNotifyHandle) {

+ Status = EFI_INVALID_PARAMETER;

+ goto Error;

+ }

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardUnregisterKeyNotify Success, Status: %r\n", Status));

+ goto End;

+

+Error:

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardUnregisterKeyNotify Failed, Status: %r\n", Status));

+

+End:

+ //

+ // Leave critical section and return

+ //

+ gBS->RestoreTPL (OldTpl);

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VkKeyboardUnregisterKeyNotify End\n"));

+ return Status;

+}

diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/KeyboardLayout.c
b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/KeyboardLayout.c
new file mode 100644
index 0000000000..dcf78985ee
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/KeyboardLayout.c
@@ -0,0 +1,1364 @@
+/** @file

+ Virtural Keyboard Layout Engine

+

+ Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#include "VirtualKeyboard.h"

+

+//

+// 1.FullKeyboardBody

+// Follow below design

+// (1).\KeyboardLayout\CapitalLetterKeyboard.bmp

+// (2).\KeyboardLayout\DigitKeyboard.bmp

+// Based on keyboard's (startX, startY)

+//

+// Page0Font

+// +---+---+---+---+---+---+---+---+---+---+---+

+// | q | w | e | r | t | y | u | i | o | p |<X|| Line 0

+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

+// | | a | s | d | f | g | h | j | k | l | F2| | Line 1

+// +-+---+---+---+---+---+---+---+---+---+---+-+

+// |Caps | z | x | c | v | b | n | m |aU |Enter| Line 2

+// +-----+---+---+---+---+---+---+---+---+---+-+

+// | Esc |12#| Space |aL |aD |aR | | Line 3

+// +-----+---+-------------------+---+---+---+-+

+//

+// Page1Font

+// +---+---+---+---+---+---+---+---+---+---+---+

+// | Q | W | E | R | T | Y | U | I | O | P |<X|| Line 0

+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

+// | | A | S | D | F | G | H | J | K | L | F2| | Line 1

+// +-+---+---+---+---+---+---+---+---+---+---+-+

+// |Caps | Z | X | C | V | B | N | M |aU |Enter| Line 2

+// +-----+---+---+---+---+---+---+---+---+---+-+

+// | Esc |12#| Space |aL |aD |aR | | Line 3

+// +-----+---+-------------------+---+---+---+-+

+//

+// Page2Font

+// +---+---+---+---+---+---+---+---+---+---+---+

+// | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 |<X|| Line 0

+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

+// | |F1 |F2 |F3 |F4 |F5 |F6 |F7 |F8 |F9 |F10| | Line 1

+// +-+---+---+---+---+---+---+---+---+---+---+-+

+// |Shift| . | ; | ' | , | . | / |F11|F12|Enter| Line 2

+// +-----+---+---+---+---+---+---+---+---+---+-+

+// | Esc |12#| Space | \ | - | = | | Line 3

+// +-----+---+-------------------+---+---+---+-+

+//

+// Page3Font

+// +---+---+---+---+---+---+---+---+---+---+---+

+// | ! | @ | # | $ | % | ^ | & | * | ( | ) |<X|| Line 0

+// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

+// | |F1 |F2 |F3 |F4 |F5 |F6 |F7 |F8 |F9 |F10| | Line 1

+// +-+---+---+---+---+---+---+---+---+---+---+-+

+// |Shift| ~ | : | " | < | > | ? |F11|F12|Enter| Line 2

+// +-----+---+---+---+---+---+---+---+---+---+-+

+// | Esc |12#| Space | | | _ | + | | Line 3

+// +-----+---+-------------------+---+---+---+-+

+//

+// 2.Screen Corner

+// Follow below design

+// (1).\KeyboardLayout\SimpleIcon.bmp # Screen Corner A/B

+// (2).\KeyboardLayout\FullIcon.bmp # Screen Corner C/D

+// +-+------------------------------------+-+

+// |A| |C|

+// +-+ +-+

+// | |

+// | |

+// | |

+// | |

+// | |

+// | |

+// +-+ +-+

+// |B| |D|

+// +-+------------------------------------+-+

+//

+VK_STRUCT mFullKeyboardBody[] = {

+ // StartX StartY EndX EndY Page0Font Page1Font Page2Font Page3Font

+ // Line 0

+ { 0x0000, 0x0000, 0x0032, 0x0032, {L'q', L'Q', L'1', L'!' }},

+ { 0x0032, 0x0000, 0x0064, 0x0032, {L'w', L'W', L'2', L'@' }},

+ { 0x0064, 0x0000, 0x0096, 0x0032, {L'e', L'E', L'3', L'#' }},

+ { 0x0096, 0x0000, 0x00C8, 0x0032, {L'r', L'R', L'4', L'$' }},

+ { 0x00C8, 0x0000, 0x00FA, 0x0032, {L't', L'T', L'5', L'%' }},

+ { 0x00FA, 0x0000, 0x012C, 0x0032, {L'y', L'Y', L'6', L'^' }},

+ { 0x012C, 0x0000, 0x015E, 0x0032, {L'u', L'U', L'7', L'&' }},

+ { 0x015E, 0x0000, 0x0190, 0x0032, {L'i', L'I', L'8', L'*' }},

+ { 0x0190, 0x0000, 0x01C2, 0x0032, {L'o', L'O', L'9', L'(' }},

+ { 0x01C2, 0x0000, 0x01F4, 0x0032, {L'p', L'P', L'0', L')' }},

+ { 0x01F4, 0x0000, 0x0226, 0x0032, {VkKeyBackspace, VkKeyBackspace, VkKeyBackspace, VkKeyBackspace }},

+ // Line 1

+ { 0x0000, 0x0032, 0x0019, 0x0064, {VkKeyNull, VkKeyNull, VkKeyNull, VkKeyNull }},

+ { 0x0019, 0x0032, 0x004B, 0x0064, {L'a', L'A', VkKeyF1, VkKeyF1 }},

+ { 0x004B, 0x0032, 0x007D, 0x0064, {L's', L'S', VkKeyF2, VkKeyF2 }},

+ { 0x007D, 0x0032, 0x00AF, 0x0064, {L'd', L'D', VkKeyF3, VkKeyF3 }},

+ { 0x00AF, 0x0032, 0x00E1, 0x0064, {L'f', L'F', VkKeyF4, VkKeyF4 }},

+ { 0x00E1, 0x0032, 0x0113, 0x0064, {L'g', L'G', VkKeyF5, VkKeyF5 }},

+ { 0x0113, 0x0032, 0x0145, 0x0064, {L'h', L'H', VkKeyF6, VkKeyF6 }},

+ { 0x0145, 0x0032, 0x0177, 0x0064, {L'j', L'J', VkKeyF7, VkKeyF7 }},

+ { 0x0177, 0x0032, 0x01A9, 0x0064, {L'k', L'K', VkKeyF8, VkKeyF8 }},

+ { 0x01A9, 0x0032, 0x01DB, 0x0064, {L'l', L'L', VkKeyF9, VkKeyF9 }},

+ { 0x01DB, 0x0032, 0x020D, 0x0064, {VkKeyF2, VkKeyF2, VkKeyF10, VkKeyF10 }},

+ // Line 2

+ { 0x0000, 0x0064, 0x004B, 0x0096, {VkKeyCapslock, VkKeyCapslock, VkKeyShift, VkKeyShift }},

+ { 0x004B, 0x0064, 0x007D, 0x0096, {L'z', L'Z', L'`', L'~' }},

+ { 0x007D, 0x0064, 0x00AF, 0x0096, {L'x', L'X', L';', L':' }},

+ { 0x00AF, 0x0064, 0x00E1, 0x0096, {L'c', L'C', L'\'', L'"' }},

+ { 0x00E1, 0x0064, 0x0113, 0x0096, {L'v', L'V', L',', L'<' }},

+ { 0x0113, 0x0064, 0x0145, 0x0096, {L'b', L'B', L'.', L'>' }},

+ { 0x0145, 0x0064, 0x0177, 0x0096, {L'n', L'N', L'/', L'?' }},

+ { 0x0177, 0x0064, 0x01A9, 0x0096, {L'm', L'M', VkKeyF11, VkKeyF11 }},

+ { 0x01A9, 0x0064, 0x01DB, 0x0096, {VkKeyUp, VkKeyUp, VkKeyF12, VkKeyF12 }},

+ { 0x01DB, 0x0064, 0x0226, 0x0096, {VkKeyEnter, VkKeyEnter, VkKeyEnter, VkKeyEnter }},

+ // Line 3

+ { 0x0000, 0x0096, 0x004B, 0x00C8, {VkKeyEsc, VkKeyEsc, VkKeyEsc, VkKeyEsc }},

+ { 0x004B, 0x0096, 0x007D, 0x00C8, {VkKeyTwoPage, VkKeyTwoPage, VkKeyTwoPage, VkKeyTwoPage }},

+ { 0x007D, 0x0096, 0x0177, 0x00C8, {L' ', L' ', L' ', L' ' }},

+ { 0x0177, 0x0096, 0x01A9, 0x00C8, {VkKeyLeft, VkKeyLeft, L'\\', L'|' }},

+ { 0x01A9, 0x0096, 0x01DB, 0x00C8, {VkKeyDown, VkKeyDown, L'-', L'_' }},

+ { 0x01DB, 0x0096, 0x020D, 0x00C8, {VkKeyRight, VkKeyRight, L'=', L'+' }},

+ // Screen Corner A

+ { 0x0000, 0x0000, 0x001E, 0x001E, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum,
VkKeyTypeMaximum}},

+ // Screen Corner B

+ { 0x0000, 0x023A, 0x001E, 0x0258, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum,
VkKeyTypeMaximum}},

+ // Screen Corner C

+ { 0x02E4, 0x0000, 0x0320, 0x001E, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum,
VkKeyTypeMaximum}},

+ // Screen Corner D

+ { 0x02E4, 0x023A, 0x0320, 0x0258, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum,
VkKeyTypeMaximum}}

+};

+

+//

+// 1.SimpleKeyboardBody

+// Follow below design

+// (1).\KeyboardLayout\SimpleKeyboard.bmp

+// Based on keyboard's (startX, startY)

+// +-----+-----+

+// | Esc |Enter| Line 0

+// +-----+-----+

+// | Up | Down| Line 1

+// +-----+-----+

+//

+// 2.Screen Corner

+// Follow below design

+// (1).\KeyboardLayout\SimpleIcon.bmp # Screen Corner A/B

+// (2).\KeyboardLayout\FullIcon.bmp # Screen Corner C/D

+// +-+------------------------------------+-+

+// |A| |C|

+// +-+ +-+

+// | |

+// | |

+// | |

+// | |

+// | |

+// | |

+// +-+ +-+

+// |B| |D|

+// +-+------------------------------------+-+

+//

+VK_STRUCT mSimpleKeyboardBody[] = {

+ // StartX StartY EndX EndY Page0Font Page1Font Page2Font Page3Font

+ // Line 0

+ { 0x0000, 0x0000, 0x0032, 0x0032, {VkKeyEsc, VkKeyEsc, VkKeyEsc, VkKeyEsc }},

+ { 0x0032, 0x0000, 0x0064, 0x0032, {VkKeyEnter, VkKeyEnter, VkKeyEnter, VkKeyEnter }},

+ // Line 1

+ { 0x0000, 0x0032, 0x0032, 0x0064, {VkKeyUp, VkKeyUp, VkKeyUp, VkKeyUp }},

+ { 0x0032, 0x0032, 0x0064, 0x0064, {VkKeyDown, VkKeyDown, VkKeyDown, VkKeyDown }},

+ // Screen Corner A

+ { 0x0000, 0x0000, 0x001E, 0x001E, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum,
VkKeyTypeMaximum}},

+ // Screen Corner B

+ { 0x0000, 0x023A, 0x001E, 0x0258, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum,
VkKeyTypeMaximum}},

+ // Screen Corner C

+ { 0x02E4, 0x0000, 0x0320, 0x001E, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum,
VkKeyTypeMaximum}},

+ // Screen Corner D

+ { 0x02E4, 0x023A, 0x0320, 0x0258, {VkKeyTypeMaximum, VkKeyTypeMaximum, VkKeyTypeMaximum,
VkKeyTypeMaximum}}

+};

+

+EFI_STATUS

+ModifyShiftKeyColor (

+ IN VK_CONTEXT *VkContext,

+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **BltBuffer

+ )

+{

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *TempBltBuffer;

+ UINTN BltSize;

+ BOOLEAN IsPressed;

+

+ TempBltBuffer = *BltBuffer;

+ BltSize = VkContext->VkBodyBltHeight * VkContext->VkBodyBltWidth;

+ IsPressed = VkContext->PageNumber <= VkPage1 ?

+ VkContext->IsCapsLockFlag :

+ VkContext->IsShiftKeyFlag;

+

+ while (BltSize-- != 0) {

+ //

+ // Color gradient issue

+ //

+ if (((TempBltBuffer->Red - TempBltBuffer->Green) > 0x20) &&

+ ((TempBltBuffer->Red - TempBltBuffer->Blue) > 0x20)) {

+ if (IsPressed) {

+ TempBltBuffer->Red = 0;

+ TempBltBuffer->Green = 255;

+ TempBltBuffer->Blue = 255;

+ } else {

+ TempBltBuffer->Red = 255;

+ TempBltBuffer->Green = 255;

+ TempBltBuffer->Blue = 255;

+ }

+ }

+ TempBltBuffer++;

+ }

+

+ return EFI_SUCCESS;

+}

+

+EFI_STATUS

+MakeKeyboardTransparent (

+ IN VK_CONTEXT *VkContext,

+ IN BOOLEAN IsTransparent,

+ IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltIn,

+ IN OUT EFI_GRAPHICS_OUTPUT_BLT_PIXEL **BltOut

+ )

+{

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Compound;

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Keyboard;

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background;

+ UINTN BltSize;

+

+ if (*BltOut == NULL) {

+ *BltOut = AllocateZeroPool (VkContext->VkBodyBltSize);

+ if (*BltOut == NULL) {

+ return EFI_OUT_OF_RESOURCES;

+ }

+ }

+ Compound = *BltOut;

+ Keyboard = BltIn;

+ Background = VkContext->VkBodyBackgroundBltBuffer;

+ BltSize = VkContext->VkBodyBltHeight * VkContext->VkBodyBltWidth;

+ while (BltSize-- != 0) {

+ if (IsTransparent) {

+ Compound->Red = (Keyboard->Red * TRANSPARENCY_WEIGHT) / 100 + (Background->Red * (100 -
TRANSPARENCY_WEIGHT)) / 100;

+ Compound->Green = (Keyboard->Green * TRANSPARENCY_WEIGHT) / 100 + (Background->Green * (100 -
TRANSPARENCY_WEIGHT)) / 100;

+ Compound->Blue = (Keyboard->Blue * TRANSPARENCY_WEIGHT) / 100 + (Background->Blue * (100 -
TRANSPARENCY_WEIGHT)) / 100;

+ } else {

+ *Compound = *Keyboard;

+ }

+ Compound++;

+ Keyboard++;

+ Background++;

+ }

+

+ return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EFIAPI

+SaveVkBodyBackgroundBltBuffer (

+ IN VK_CONTEXT *VkContext,

+ IN UINTN BltSize

+ )

+{

+ EFI_STATUS Status;

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *CurrentBltBuffer;

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *CurrentBltBufferSave;

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *OldBltBuffer;

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *OldBltBufferSave;

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Compound;

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Background;

+ UINTN Size;

+

+ CurrentBltBufferSave = NULL;

+ OldBltBufferSave = NULL;

+

+ //

+ // Save original blt buffer first.

+ //

+ OldBltBuffer = AllocateZeroPool (VkContext->VkBodyBltSize);

+ if (OldBltBuffer == NULL) {

+ return EFI_OUT_OF_RESOURCES;

+ }

+ if (VkContext->VkBodyBackgroundBltBuffer != NULL) {

+ CopyMem (OldBltBuffer, VkContext->VkBodyBackgroundBltBuffer, VkContext->VkBodyBltSize);

+ }

+

+ if (VkContext->VkBodyBackgroundBltBuffer == NULL) {

+ VkContext->VkBodyBltSize = BltSize;

+ VkContext->VkBodyBackgroundBltBuffer = AllocateZeroPool (VkContext->VkBodyBltSize);

+ ASSERT (VkContext->VkBodyBackgroundBltBuffer != NULL);

+ if (VkContext->VkBodyBackgroundBltBuffer == NULL) {

+ return EFI_OUT_OF_RESOURCES;

+ }

+ } else if (BltSize > VkContext->VkBodyBltSize) {

+ VkContext->VkBodyBltSize = BltSize;

+ FreePool (VkContext->VkBodyBackgroundBltBuffer);

+ VkContext->VkBodyBackgroundBltBuffer = NULL;

+ VkContext->VkBodyBackgroundBltBuffer = AllocateZeroPool (VkContext->VkBodyBltSize);

+ ASSERT (VkContext->VkBodyBackgroundBltBuffer != NULL);

+ if (VkContext->VkBodyBackgroundBltBuffer == NULL) {

+ return EFI_OUT_OF_RESOURCES;

+ }

+ } else {

+ ZeroMem (VkContext->VkBodyBackgroundBltBuffer, VkContext->VkBodyBltSize);

+ }

+

+ CurrentBltBuffer = NULL;

+ if (VkContext->IsBackgroundChanged == TRUE) {

+ //

+ // Background changed, merge current visioning blt buffer with old background blt buffer.

+ //

+ Compound = VkContext->VkBodyCompoundBltBuffer;

+ Background = VkContext->VkBodyBackgroundBltBuffer;

+ CurrentBltBuffer = AllocateZeroPool (VkContext->VkBodyBltSize);

+ ASSERT (CurrentBltBuffer != NULL);

+ if (CurrentBltBuffer == NULL) {

+ return EFI_OUT_OF_RESOURCES;

+ }

+ Status = VkContext->GraphicsOutput->Blt (

+ VkContext->GraphicsOutput,

+ CurrentBltBuffer,

+ EfiBltVideoToBltBuffer,

+ VkContext->VkBodyBltStartX,

+ VkContext->VkBodyBltStartY,

+ 0,

+ 0,

+ VkContext->VkBodyBltWidth,

+ VkContext->VkBodyBltHeight,

+ VkContext->VkBodyBltWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)

+ );

+ CurrentBltBufferSave = CurrentBltBuffer;

+ OldBltBufferSave = OldBltBuffer;

+ Size = VkContext->VkBodyBltHeight * VkContext->VkBodyBltWidth;

+ while (Size-- != 0) {

+ if ((Compound->Red != CurrentBltBuffer->Red) ||

+ (Compound->Green != CurrentBltBuffer->Green) ||

+ (Compound->Blue != CurrentBltBuffer->Blue)) {

+ *Background = *CurrentBltBuffer;

+ } else {

+ *Background = *OldBltBuffer;

+ }

+ Compound++;

+ Background++;

+ CurrentBltBuffer++;

+ OldBltBuffer++;

+ }

+ } else {

+ //

+ // Background NOT changed, save it to VkBodyBackgroundBltBuffer directly.

+ //

+ Status = VkContext->GraphicsOutput->Blt (

+ VkContext->GraphicsOutput,

+ VkContext->VkBodyBackgroundBltBuffer,

+ EfiBltVideoToBltBuffer,

+ VkContext->VkBodyBltStartX,

+ VkContext->VkBodyBltStartY,

+ 0,

+ 0,

+ VkContext->VkBodyBltWidth,

+ VkContext->VkBodyBltHeight,

+ VkContext->VkBodyBltWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)

+ );

+ }

+

+ if (CurrentBltBufferSave != NULL) {

+ FreePool (CurrentBltBufferSave);

+ }

+ if (OldBltBufferSave != NULL) {

+ FreePool (OldBltBufferSave);

+ }

+

+ return Status;

+}

+

+EFI_STATUS

+EFIAPI

+RestoreVkBodyBackgroundBltBuffer (

+ IN VK_CONTEXT *VkContext

+ )

+{

+ EFI_STATUS Status;

+

+ if (VkContext->VkBodyBackgroundBltBuffer == NULL) {

+ return EFI_UNSUPPORTED;

+ }

+

+ Status = VkContext->GraphicsOutput->Blt (

+ VkContext->GraphicsOutput,

+ VkContext->VkBodyBackgroundBltBuffer,

+ EfiBltBufferToVideo,

+ 0,

+ 0,

+ VkContext->VkBodyBltStartX,

+ VkContext->VkBodyBltStartY,

+ VkContext->VkBodyBltWidth,

+ VkContext->VkBodyBltHeight,

+ VkContext->VkBodyBltWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)

+ );

+

+ FreePool (VkContext->VkBodyBackgroundBltBuffer);

+ VkContext->VkBodyBackgroundBltBuffer = NULL;

+

+ return Status;

+}

+

+EFI_STATUS

+SetCharacterPosition (

+ IN VK_CONTEXT *VkContext,

+ IN UINT32 DestX,

+ IN UINT32 DestY

+ )

+{

+ UINTN Index;

+ VK_STRUCT *KeyArryPtr;

+ UINT32 KeyArrySize;

+

+ switch (VkContext->TargetKeyboardDisplay) {

+ case VkDisplayAttributeSimpleTop:

+ case VkDisplayAttributeSimpleBottom:

+ KeyArryPtr = mSimpleKeyboardBody;

+ KeyArrySize = DIM (mSimpleKeyboardBody);

+ break;

+

+ case VkDisplayAttributeFullBottom:

+ case VkDisplayAttributeFullTop:

+ KeyArryPtr = mFullKeyboardBody;

+ KeyArrySize = DIM (mFullKeyboardBody);

+ break;

+

+ case VkDisplayAttributeNone:

+ KeyArryPtr = mFullKeyboardBody;

+ KeyArrySize = DIM (mFullKeyboardBody);

+ break;

+

+ default:

+ return EFI_UNSUPPORTED;

+ }

+

+ for (Index = 0; Index < KeyArrySize; Index++) {

+ VkContext->KeyboardBodyPtr[Index] = KeyArryPtr[Index];

+ }

+ VkContext->NumOfKeysInfo = KeyArrySize;

+

+ for (Index = 0; Index < (VkContext->NumOfKeysInfo - 4); Index++) {

+ VkContext->KeyboardBodyPtr[Index].DisStartX += (UINT16)DestX;

+ VkContext->KeyboardBodyPtr[Index].DisStartY += (UINT16)DestY;

+ VkContext->KeyboardBodyPtr[Index].DisEndX += (UINT16)DestX;

+ VkContext->KeyboardBodyPtr[Index].DisEndY += (UINT16)DestY;

+ }

+

+ return EFI_SUCCESS;

+}

+

+EFI_STATUS

+EFIAPI

+SaveVkIconBackgroundBltBuffer (

+ IN VK_CONTEXT *VkContext,

+ IN VK_DISPLAY_ATTRIBUTE IconType

+ )

+{

+ EFI_STATUS Status;

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *GraphicBlt;

+ UINTN BltSize;

+ UINTN Height;

+ UINTN Width;

+ INTN StartX;

+ INTN StartY;

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *TempIconBackBuffer;

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *IconBackBuffer;

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Compound;

+ UINTN Size;

+ BOOLEAN SaveCursor;

+

+ Status = EFI_SUCCESS;

+ StartX = 0;

+ StartY = 0;

+ TempIconBackBuffer = NULL;

+ IconBackBuffer = NULL;

+ Compound = NULL;

+

+ if ((IconType == VkDisplayAttributeFullTop) ||

+ (IconType == VkDisplayAttributeSimpleTop)) {

+ return EFI_SUCCESS;

+ }

+

+ SaveCursor = gST->ConOut->Mode->CursorVisible;

+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);

+

+ if (IconType == VkDisplayAttributeFullBottom) {

+ GraphicBlt = VkContext->FullIcon->Bitmap;

+ BltSize = VkContext->FullIcon->Height * VkContext->FullIcon->Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);

+ Height = VkContext->FullIcon->Height;

+ Width = VkContext->FullIcon->Width;

+ StartX = VkContext->FullIconBackStartX;

+ StartY = VkContext->FullIconBackStartY;

+ } else if (IconType == VkDisplayAttributeSimpleBottom) {

+ GraphicBlt = VkContext->SmallIcon->Bitmap;

+ BltSize = VkContext->SmallIcon->Height * VkContext->SmallIcon->Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);

+ Height = VkContext->SmallIcon->Height;

+ Width = VkContext->SmallIcon->Width;

+ StartX = VkContext->SimIconBackStartX;

+ StartY = VkContext->SimIconBackStartY;

+ } else {

+ gST->ConOut->EnableCursor (gST->ConOut, SaveCursor);

+ return EFI_UNSUPPORTED;

+ }

+

+ IconBackBuffer = AllocateZeroPool (BltSize);

+ if (IconBackBuffer == NULL) {

+ gST->ConOut->EnableCursor (gST->ConOut, SaveCursor);

+ return EFI_OUT_OF_RESOURCES;

+ }

+ TempIconBackBuffer = IconBackBuffer;

+ Status = VkContext->GraphicsOutput->Blt (

+ VkContext->GraphicsOutput,

+ IconBackBuffer,

+ EfiBltVideoToBltBuffer,

+ StartX,

+ StartY,

+ 0,

+ 0,

+ Width,

+ Height,

+ Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)

+ );

+

+ if (IconType == VkDisplayAttributeFullBottom) {

+ //

+ // Store full icon background framebuffer

+ //

+ VkContext->FullIconBackHeight = Height;

+ VkContext->FullIconBackWidth = Width;

+ if (VkContext->FullIconUpdatedFlag == FALSE) {

+ //

+ // No icon draw, save the buffer directly.

+ //

+ if (VkContext->FullIconBackBuffer == NULL) {

+ VkContext->FullIconBackBuffer = AllocateZeroPool (BltSize);

+ VkContext->FullIconBackSize = BltSize;

+ }

+ CopyMem (VkContext->FullIconBackBuffer, IconBackBuffer, BltSize);

+ VkContext->FullIconUpdatedFlag = TRUE;

+ } else {

+ if (CompareMem (VkContext->FullIconBackBuffer, IconBackBuffer, BltSize) != 0) {

+ Compound = VkContext->FullIconBackBuffer;

+ Size = Height * Width;

+ while (Size-- != 0) {

+ if ((GraphicBlt->Red != IconBackBuffer->Red) ||

+ (GraphicBlt->Green != IconBackBuffer->Green) ||

+ (GraphicBlt->Blue != IconBackBuffer->Blue)) {

+ *Compound = *IconBackBuffer;

+ }

+ Compound++;

+ GraphicBlt++;

+ IconBackBuffer++;

+ }

+ }

+ }

+ } else if (IconType == VkDisplayAttributeSimpleBottom) {

+ //

+ // Store simple icon background framebuffer

+ //

+ VkContext->SimIconBackHeight = Height;

+ VkContext->SimIconBackWidth = Width;

+ if (VkContext->SimIconUpdatedFlag == FALSE) {

+ //

+ // No icon draw, save the buffer directly.

+ //

+ if (VkContext->SimIconBackBuffer == NULL) {

+ VkContext->SimIconBackBuffer = AllocateZeroPool (BltSize);

+ VkContext->SimIconBackSize = BltSize;

+ }

+ CopyMem (VkContext->SimIconBackBuffer, IconBackBuffer, BltSize);

+ VkContext->SimIconUpdatedFlag = TRUE;

+ } else {

+ if (CompareMem (VkContext->SimIconBackBuffer, IconBackBuffer, BltSize) != 0) {

+ Compound = VkContext->SimIconBackBuffer;

+ Size = Height * Width;

+ while (Size-- != 0) {

+ if ((GraphicBlt->Red != IconBackBuffer->Red) ||

+ (GraphicBlt->Green != IconBackBuffer->Green) ||

+ (GraphicBlt->Blue != IconBackBuffer->Blue)) {

+ *Compound = *IconBackBuffer;

+ }

+ Compound++;

+ GraphicBlt++;

+ IconBackBuffer++;

+ }

+ }

+ }

+ }

+

+ if (TempIconBackBuffer != NULL) FreePool (TempIconBackBuffer);

+

+ gST->ConOut->EnableCursor (gST->ConOut, SaveCursor);

+ return Status;

+}

+

+/**

+ Use to draw the keyboard icon.

+

+ @param[in] VkContext Pointer to virtual keyboard's context

+ @param[in] VkImage Image of keyboard to display on the screen.

+ @param[in] Attribute Attribute of keyboard to display on the screen.

+

+ @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and keyboard icon displayed.

+ @retval EFI_UNSUPPORTED KeyboardFile not found

+ @retval EFI_INVALID_PARAMETER Attribute is unknown.

+

+**/

+EFI_STATUS

+EFIAPI

+DrawVkIcon (

+ IN VK_CONTEXT *VkContext,

+ IN EFI_IMAGE_INPUT *VkImage,

+ IN VK_DISPLAY_ATTRIBUTE Attribute

+ )

+{

+ EFI_STATUS Status;

+ UINT32 SizeOfX;

+ UINT32 SizeOfY;

+ INTN DestX;

+ INTN DestY;

+ UINTN CoordinateX;

+ UINTN CoordinateY;

+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *Blt;

+ UINTN BltSize;

+ UINTN Height;

+ UINTN Width;

+

+ Status = EFI_SUCCESS;

+ GraphicsOutput = VkContext->GraphicsOutput;

+ SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;

+ SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;

+ CoordinateX = 0;

+ CoordinateY = 0;

+ Height = VkImage->Height;

+ Width = VkImage->Width;

+ Blt = VkImage->Bitmap;

+ BltSize = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * (UINT32)(Width * Height);

+

+ //

+ // Calculate the display position according to Attribute.

+ //

+ switch (Attribute) {

+ case VkDisplayAttributeSimpleTop:

+ DestX = CoordinateX;

+ DestY = CoordinateY;

+ break;

+

+ case VkDisplayAttributeFullTop:

+ DestX = (SizeOfX - Width - CoordinateX);

+ DestY = CoordinateY;;

+ break;

+

+ case VkDisplayAttributeFullBottom:

+ DestX = (SizeOfX - Width - CoordinateX);

+ DestY = (SizeOfY - Height - CoordinateY);

+ VkContext->FullIconBackStartX = DestX;

+ VkContext->FullIconBackStartY = DestY;

+ break;

+

+ case VkDisplayAttributeSimpleBottom:

+ DestX = CoordinateX;

+ DestY = (SizeOfY - Height - CoordinateY);

+

+ //

+ // Save to check icon/screen cleared

+ //

+ if (VkContext->IconBltBuffer == NULL) {

+ VkContext->IconBltSize = BltSize;

+ VkContext->IconBltWidth = Width;

+ VkContext->IconBltHeight = Height;

+ VkContext->IconBltBuffer = AllocateZeroPool (BltSize);

+ }

+ CopyMem (VkContext->IconBltBuffer, Blt, VkContext->IconBltSize);

+

+ VkContext->SimIconBackStartX = DestX;

+ VkContext->SimIconBackStartY = DestY;

+ break;

+

+ case VkDisplayAttributeNone:

+ return EFI_SUCCESS;

+

+ default:

+ return EFI_INVALID_PARAMETER;

+ }

+

+ if ((DestX >= 0) && (DestY >= 0)) {

+ //

+ // Store icon background framebuffer

+ //

+ SaveVkIconBackgroundBltBuffer (VkContext, Attribute);

+ Status = GraphicsOutput->Blt (

+ GraphicsOutput,

+ Blt,

+ EfiBltBufferToVideo,

+ 0,

+ 0,

+ (UINTN) DestX,

+ (UINTN) DestY,

+ Width,

+ Height,

+ Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)

+ );

+ }

+

+ return Status;

+}

+

+/**

+ Use to draw the keyboard.

+

+ @param[in] VkContext Pointer to virtual keyboard's context

+ @param[in] VkImage Image of keyboard to display on the screen.

+ @param[in] Attribute Attribute of keyboard to display on the screen.

+

+ @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and keyboard displayed.

+ @retval EFI_UNSUPPORTED KeyboardFile not found

+ @retval EFI_INVALID_PARAMETER Attribute is unknown.

+

+**/

+EFI_STATUS

+EFIAPI

+DrawVkBody (

+ IN VK_CONTEXT *VkContext,

+ IN EFI_IMAGE_INPUT *VkImage,

+ IN VK_DISPLAY_ATTRIBUTE Attribute

+ )

+{

+ EFI_STATUS Status;

+ UINT32 SizeOfX;

+ UINT32 SizeOfY;

+ INTN DestX;

+ INTN DestY;

+ UINTN BltSize;

+ UINTN Height;

+ UINTN Width;

+ UINTN CoordinateY;

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltIn;

+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;

+

+ Status = EFI_SUCCESS;

+ GraphicsOutput = VkContext->GraphicsOutput;

+ SizeOfX = GraphicsOutput->Mode->Info->HorizontalResolution;

+ SizeOfY = GraphicsOutput->Mode->Info->VerticalResolution;

+ CoordinateY = 0;

+ Height = VkImage->Height;

+ Width = VkImage->Width;

+ BltSize = sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL) * (UINT32)(Width * Height);

+ BltIn = AllocateCopyPool (BltSize, VkImage->Bitmap);

+

+ if (BltIn == NULL) {

+ return EFI_OUT_OF_RESOURCES;

+ }

+

+ //

+ // Calculate the display position according to Attribute.

+ //

+ switch (Attribute) {

+ case VkDisplayAttributeSimpleTop:

+ DestX = ((SizeOfX / 2) - Width) / 4;

+ DestY = CoordinateY;

+ VkContext->CurrentKeyboardDisplay = VkDisplayAttributeSimpleTop;

+ break;

+

+ case VkDisplayAttributeSimpleBottom:

+ DestX = ((SizeOfX / 2) - Width) / 4;

+ DestY = (SizeOfY - Height - CoordinateY);

+ VkContext->CurrentKeyboardDisplay = VkDisplayAttributeSimpleBottom;

+ break;

+

+ case VkDisplayAttributeFullTop:

+ DestX = (SizeOfX - Width) / 2;

+ DestY = CoordinateY;

+ VkContext->CurrentKeyboardDisplay = VkDisplayAttributeFullTop;

+ break;

+

+ case VkDisplayAttributeFullBottom:

+ DestX = (SizeOfX - Width) / 2;

+ DestY = (SizeOfY - Height - CoordinateY);

+ VkContext->CurrentKeyboardDisplay = VkDisplayAttributeFullBottom;

+ break;

+

+ case VkDisplayAttributeNone:

+ VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone;

+ goto DVKBODY_Exit;

+

+ default:

+ VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone;

+ Status = EFI_INVALID_PARAMETER;

+ goto DVKBODY_Exit;

+ }

+ if ((DestX >= 0) && (DestY >= 0)) {

+ SetCharacterPosition (VkContext, (UINT32)DestX, (UINT32)DestY);

+

+ //

+ // Store current framebuffer

+ //

+ VkContext->VkBodyBltStartX = DestX;

+ VkContext->VkBodyBltStartY = DestY;

+ VkContext->VkBodyBltHeight = Height;

+ VkContext->VkBodyBltWidth = Width;

+ SaveVkBodyBackgroundBltBuffer (VkContext, BltSize);

+

+ //

+ // Free compound buffer first.

+ //

+ if (VkContext->VkBodyCompoundBltBuffer != NULL) {

+ FreePool (VkContext->VkBodyCompoundBltBuffer);

+ }

+ VkContext->VkBodyCompoundBltBuffer = NULL;

+ ModifyShiftKeyColor (VkContext, &BltIn);

+ MakeKeyboardTransparent (VkContext, TRUE, BltIn, &(VkContext->VkBodyCompoundBltBuffer));

+

+ //

+ // Draw keyboard body

+ //

+ Status = GraphicsOutput->Blt (

+ GraphicsOutput,

+ VkContext->VkBodyCompoundBltBuffer,

+ EfiBltBufferToVideo,

+ 0,

+ 0,

+ (UINTN) DestX,

+ (UINTN) DestY,

+ Width,

+ Height,

+ Width * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)

+ );

+ }

+

+

+DVKBODY_Exit:

+ if (BltIn != NULL) {

+ FreePool (BltIn);

+ }

+

+ return Status;

+}

+

+/**

+ Clear the keyboard body

+

+ @param VkContext Code context.

+

+ @retval EFI_SUCCESS Clear rectangle is done.

+

+**/

+EFI_STATUS

+HideVkBody (

+ IN VK_CONTEXT *VkContext

+ )

+{

+ RestoreVkBodyBackgroundBltBuffer (VkContext);

+ VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone;

+

+ return EFI_SUCCESS;

+}

+

+

+/**

+ Clear the keyboard icon

+

+ @param VkContext Code context.

+

+ @retval EFI_SUCCESS Clear rectangle is done.

+

+**/

+EFI_STATUS

+HideVkIcon (

+ IN VK_CONTEXT *VkContext

+ )

+{

+ EFI_STATUS Status;

+

+ if ((VkContext->FullIconBackBuffer == NULL) || (VkContext->SimIconBackBuffer == NULL)) {

+ return EFI_UNSUPPORTED;

+ }

+

+ if ((VkContext->FullIconUpdatedFlag == FALSE) || (VkContext->SimIconUpdatedFlag == FALSE)) {

+ return EFI_UNSUPPORTED;

+ }

+ Status = VkContext->GraphicsOutput->Blt (

+ VkContext->GraphicsOutput,

+ VkContext->FullIconBackBuffer,

+ EfiBltBufferToVideo,

+ 0,

+ 0,

+ VkContext->FullIconBackStartX,

+ VkContext->FullIconBackStartY,

+ VkContext->FullIconBackWidth,

+ VkContext->FullIconBackHeight,

+ VkContext->FullIconBackWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)

+ );

+

+ ZeroMem (VkContext->FullIconBackBuffer, VkContext->FullIconBackSize);

+ VkContext->FullIconUpdatedFlag = FALSE;

+

+

+ Status = VkContext->GraphicsOutput->Blt (

+ VkContext->GraphicsOutput,

+ VkContext->SimIconBackBuffer,

+ EfiBltBufferToVideo,

+ 0,

+ 0,

+ VkContext->SimIconBackStartX,

+ VkContext->SimIconBackStartY,

+ VkContext->SimIconBackWidth,

+ VkContext->SimIconBackHeight,

+ VkContext->SimIconBackWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)

+ );

+ if (!EFI_ERROR (Status)) {

+ if (VkContext->ScreenCheckBuffer == NULL) {

+ VkContext->ScreenCheckBufferSize = VkContext->SimIconBackHeight *

+ VkContext->SimIconBackWidth *

+ sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL);

+ VkContext->ScreenCheckBuffer = AllocateZeroPool (VkContext->ScreenCheckBufferSize);

+ }

+

+ CopyMem (

+ VkContext->ScreenCheckBuffer,

+ VkContext->SimIconBackBuffer,

+ (VkContext->SimIconBackHeight * VkContext->SimIconBackWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL))

+ );

+ }

+ ZeroMem (VkContext->SimIconBackBuffer, VkContext->SimIconBackSize);

+ VkContext->SimIconUpdatedFlag = FALSE;

+

+ return EFI_SUCCESS;

+}

+

+/**

+ Draw key board on the display

+

+ @param[in] VkContext Graphic Protocol for draw the alphabet.

+

+ @retval EFI_SUCCESS Draw keyboard was done.

+ @retval EFI_UNSUPPORTED Did not get key mapping table.

+

+**/

+EFI_STATUS

+DrawKeyboardLayout (

+ IN VK_CONTEXT *VkContext

+ )

+{

+ EFI_STATUS Status;

+ if (!VkContext->IsIconShowed) {

+ Status = DrawVkIcon (VkContext, VkContext->SmallIcon, VkDisplayAttributeSimpleTop);

+ ASSERT_EFI_ERROR (Status);

+

+ Status = DrawVkIcon (VkContext, VkContext->SmallIcon, VkDisplayAttributeSimpleBottom);

+ ASSERT_EFI_ERROR (Status);

+

+ Status = DrawVkIcon (VkContext, VkContext->FullIcon, VkDisplayAttributeFullTop);

+ ASSERT_EFI_ERROR (Status);

+

+ Status = DrawVkIcon (VkContext, VkContext->FullIcon, VkDisplayAttributeFullBottom);

+ ASSERT_EFI_ERROR (Status);

+ VkContext->IsIconShowed = TRUE;

+ }

+

+ if (VkContext->TargetKeyboardDisplay != VkContext->CurrentKeyboardDisplay) {

+ switch (VkContext->TargetKeyboardDisplay) {

+ case VkDisplayAttributeSimpleTop:

+ case VkDisplayAttributeSimpleBottom:

+ DrawVkBody (VkContext, VkContext->SimKeyBody, VkContext->TargetKeyboardDisplay);

+ break;

+

+ case VkDisplayAttributeFullTop:

+ case VkDisplayAttributeFullBottom:

+ if (VkContext->PageNumber <= VkPage1) {

+ DrawVkBody (VkContext, VkContext->CapLeKeyBody, VkContext->TargetKeyboardDisplay);

+ } else {

+ DrawVkBody (VkContext, VkContext->DigKeyBody, VkContext->TargetKeyboardDisplay);

+ }

+

+ case VkDisplayAttributeNone:

+ break;

+

+ default:

+ break;

+ }

+ }

+

+ return EFI_SUCCESS;

+}

+

+EFI_STATUS

+KeyboardLayoutHandler (

+ IN VK_CONTEXT *VkContext,

+ IN UINT32 Index

+ )

+{

+ EFI_STATUS Status;

+

+ Status = EFI_SUCCESS;

+

+ if (Index == (VkContext->NumOfKeysInfo - 4)) {

+ //

+ // Touch the LeftTop icon

+ //

+ if (VkContext->CurrentKeyboardDisplay == VkDisplayAttributeSimpleTop) {

+ VkContext->TargetKeyboardDisplay = VkDisplayAttributeNone;

+ } else {

+ VkContext->TargetKeyboardDisplay = VkDisplayAttributeSimpleTop;

+ }

+ } else if (Index == (VkContext->NumOfKeysInfo - 3)) {

+ //

+ // Touch the LeftBottom icon

+ //

+ if (VkContext->CurrentKeyboardDisplay == VkDisplayAttributeSimpleBottom) {

+ VkContext->TargetKeyboardDisplay = VkDisplayAttributeNone;

+ } else {

+ VkContext->TargetKeyboardDisplay = VkDisplayAttributeSimpleBottom;

+ }

+ } else if (Index == (VkContext->NumOfKeysInfo - 2)) {

+ //

+ // Touch the RightTop icon

+ //

+ if (VkContext->CurrentKeyboardDisplay == VkDisplayAttributeFullTop) {

+ VkContext->TargetKeyboardDisplay = VkDisplayAttributeNone;

+ } else {

+ VkContext->TargetKeyboardDisplay = VkDisplayAttributeFullTop;

+ }

+ } else {

+ //

+ // Touch the RightBottom icon

+ //

+ if (VkContext->CurrentKeyboardDisplay == VkDisplayAttributeFullBottom) {

+ VkContext->TargetKeyboardDisplay = VkDisplayAttributeNone;

+ } else {

+ VkContext->TargetKeyboardDisplay = VkDisplayAttributeFullBottom;

+ }

+ }

+

+ if (VkContext->TargetKeyboardDisplay == VkDisplayAttributeNone) {

+ //

+ // Just hide the current keyboard

+ //

+ HideVkBody (VkContext);

+ VkContext->KeyTouchedTimeOut = VK_REPEAT_TIMEOUT;

+

+ } else {

+ //

+ // If current keyboard status is NOT none,

+ // hide current keyboard first and then draw the target keyboard

+ //

+ if (VkContext->CurrentKeyboardDisplay != VkDisplayAttributeNone) {

+ HideVkBody (VkContext);

+ }

+ Status = DrawKeyboardLayout (VkContext);

+ }

+

+ return Status;

+}

+

+/**

+ This routine is used to check if icon has been cleared.

+

+ @param[in] VkContext Pointer to virtual keyboard's context

+

+ @retval EFI_SUCCESS Function completed.

+

+**/

+EFI_STATUS

+CheckIconCleared (

+ IN VK_CONTEXT *VkContext

+ )

+{

+ EFI_STATUS Status;

+ UINT32 VerticalResolution;

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;

+

+ Status = EFI_SUCCESS;

+ BltBuffer = NULL;

+ VkContext->IconReDrawCheck++;

+ if (VkContext->IconReDrawCheck <= 10) {

+ //

+ // Check it every 10 * 100ms.

+ //

+ return Status;

+ }

+

+ //

+ // Check if right-bottomed region is black, if yes, clean screen happened, need to re-draw keyboard.

+ //

+ VerticalResolution = VkContext->GraphicsOutput->Mode->Info->VerticalResolution;

+ BltBuffer = AllocateZeroPool (VkContext->IconBltSize);

+ if (BltBuffer == NULL) {

+ return EFI_OUT_OF_RESOURCES;

+ }

+ Status = VkContext->GraphicsOutput->Blt (

+ VkContext->GraphicsOutput,

+ BltBuffer,

+ EfiBltVideoToBltBuffer,

+ 0,

+ (VerticalResolution - VkContext->IconBltHeight),

+ 0,

+ 0,

+ VkContext->IconBltWidth,

+ VkContext->IconBltHeight,

+ VkContext->IconBltWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)

+ );

+ if (EFI_ERROR (Status)) {

+ FreePool (BltBuffer);

+ return Status;

+ }

+ VkContext->IsIconShowed = TRUE;

+ if (VkContext->IconBltBuffer == NULL) {

+ //

+ // No icon has been drawn.

+ //

+ VkContext->IsIconShowed = FALSE;

+ } else {

+ if (CompareMem (BltBuffer, VkContext->IconBltBuffer, VkContext->IconBltSize) != 0) {

+ //

+ // Icon has been overridden, need to re-draw.

+ //

+ VkContext->IsIconShowed = FALSE;

+ }

+ }

+

+ if (VkContext->IsIconShowed == FALSE) {

+ if (VkContext->ScreenCheckBuffer != NULL) {

+ if (CompareMem (BltBuffer, VkContext->ScreenCheckBuffer, VkContext->IconBltSize) == 0) {

+ //

+ // Icon has been overridden, force to re-draw the keyboard.

+ //

+ Status = DrawKeyboardLayout (VkContext);

+ } else {

+ //

+ // Save blt buffer of icon position and use it to check if icon is overridden.

+ //

+ CopyMem (VkContext->ScreenCheckBuffer, BltBuffer, VkContext->IconBltSize);

+ }

+ } else {

+ //

+ // Draw the keyboard.

+ //

+ Status = DrawKeyboardLayout (VkContext);

+ }

+ }

+

+ if (BltBuffer != NULL) {

+ FreePool (BltBuffer);

+ }

+

+ VkContext->IconReDrawCheck = 0;

+

+ return Status;

+}

+

+/**

+ ConvertCoordinate - Convert the touch panel's coordinate to display's coordinate.

+

+ @param[in] VkContext Virtual Keyboard context.

+ @param[in] Point The coordinate reported from touch panel.

+ @param[out] TouchX The coordinate X converted to display panel.

+ @param[out] TouchY The coordinate Y converted to display panel..

+

+ @retval EFI_SUCCESS Convert success.

+

+**/

+EFI_STATUS

+ConvertCoordinate (

+ IN VK_CONTEXT *VkContext,

+ IN EFI_ABSOLUTE_POINTER_STATE Point,

+ OUT UINT32 *TouchX,

+ OUT UINT32 *TouchY

+ )

+{

+ UINT64 AbsoluteMaxX;

+ UINT64 AbsoluteMaxY;

+ UINT32 HorizontalResolution;

+ UINT32 VerticalResolution;

+

+ AbsoluteMaxX = VkContext->AbsolutePointer->Mode->AbsoluteMaxX;

+ AbsoluteMaxY = VkContext->AbsolutePointer->Mode->AbsoluteMaxY;

+ HorizontalResolution = VkContext->GraphicsOutput->Mode->Info->HorizontalResolution;

+ VerticalResolution = VkContext->GraphicsOutput->Mode->Info->VerticalResolution;

+ *TouchX = (UINT32) MultU64x32 (Point.CurrentX, HorizontalResolution) / (UINT32) AbsoluteMaxX;

+ *TouchY = (UINT32) MultU64x32 (Point.CurrentY, VerticalResolution) / (UINT32) AbsoluteMaxY;

+

+ return EFI_SUCCESS;

+}

+

+/**

+ This routine is used to check if screen has been cleared.

+

+ @param[in] VkContext Pointer to virtual keyboard's context

+

+ @retval EFI_SUCCESS Function completed.

+

+**/

+EFI_STATUS

+CheckScreenCleared (

+ IN VK_CONTEXT *VkContext

+ )

+{

+ EFI_STATUS Status;

+ UINT32 HorizontalResolution;

+ UINT32 VerticalResolution;

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBufferIndex;

+ UINTN BltSize;

+ BOOLEAN IsScreenCleared;

+

+ //

+ // Check left-bottom side.

+ // If IconBltBuffer is null, checking is meaningless.

+ //

+ if (VkContext->IconBltBuffer == NULL) {

+ return EFI_SUCCESS;

+ }

+

+ IsScreenCleared = FALSE;

+ Status = EFI_SUCCESS;

+ if ((gST->ConOut->Mode->CursorColumn == 0) && (gST->ConOut->Mode->CursorRow == 0)) {

+ //

+ // System may call gST->ConOut->ClearScreen

+ //

+ HorizontalResolution = VkContext->GraphicsOutput->Mode->Info->HorizontalResolution;

+ VerticalResolution = VkContext->GraphicsOutput->Mode->Info->VerticalResolution;

+ BltBuffer = AllocateZeroPool (VkContext->IconBltSize);

+ if (BltBuffer == NULL) {

+ return EFI_OUT_OF_RESOURCES;

+ }

+

+ BltBufferIndex = BltBuffer;

+ Status = VkContext->GraphicsOutput->Blt (

+ VkContext->GraphicsOutput,

+ BltBuffer,

+ EfiBltVideoToBltBuffer,

+ (HorizontalResolution - VkContext->IconBltWidth),

+ (VerticalResolution - VkContext->IconBltHeight),

+ 0,

+ 0,

+ VkContext->IconBltWidth,

+ VkContext->IconBltHeight,

+ VkContext->IconBltWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)

+ );

+ if (EFI_ERROR (Status)) {

+ FreePool (BltBuffer);

+ return Status;

+ }

+ BltSize = VkContext->IconBltHeight * VkContext->IconBltWidth;

+ IsScreenCleared = TRUE;

+ while (BltSize-- != 0) {

+ if ((BltBufferIndex->Red != 0) || (BltBufferIndex->Green != 0) || (BltBufferIndex->Blue != 0)) {

+ IsScreenCleared = FALSE;

+ break;

+ }

+ BltBufferIndex++;

+ }

+ FreePool (BltBuffer);

+ }

+

+ if (IsScreenCleared == TRUE) {

+ VkContext->IsIconShowed = FALSE;

+ VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone;

+

+ if (VkContext->VkBodyBackgroundBltBuffer != NULL) {

+ FreePool (VkContext->VkBodyBackgroundBltBuffer);

+ VkContext->VkBodyBackgroundBltBuffer = NULL;

+ }

+

+ if (VkContext->VkBodyCompoundBltBuffer != NULL) {

+ FreePool (VkContext->VkBodyCompoundBltBuffer);

+ VkContext->VkBodyCompoundBltBuffer = NULL;

+ }

+

+ if (VkContext->IconBltBuffer != NULL) {

+ FreePool (VkContext->IconBltBuffer);

+ VkContext->IconBltBuffer = NULL;

+ }

+

+ }

+

+ return Status;

+}

+

+/**

+ This routine is used to check if background beneath virtual keyboard has been cleared.

+

+ @param[in] VkContext Pointer to virtual keyboard's context

+

+ @retval EFI_SUCCESS Function completed.

+

+**/

+EFI_STATUS

+CheckBackgroundChanged (

+ IN VK_CONTEXT *VkContext

+ )

+{

+ EFI_STATUS Status;

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *BltBuffer;

+

+ Status = EFI_SUCCESS;

+ VkContext->IsBackgroundChanged = FALSE;

+

+ if ((VkContext->CurrentKeyboardDisplay == VkDisplayAttributeNone) || (VkContext->VkBodyCompoundBltBuffer ==
NULL)) {

+ return EFI_SUCCESS;

+ }

+

+ BltBuffer = AllocateZeroPool (VkContext->VkBodyBltSize);

+ if (BltBuffer == NULL) {

+ return EFI_OUT_OF_RESOURCES;

+ }

+ Status = VkContext->GraphicsOutput->Blt (

+ VkContext->GraphicsOutput,

+ BltBuffer,

+ EfiBltVideoToBltBuffer,

+ VkContext->VkBodyBltStartX,

+ VkContext->VkBodyBltStartY,

+ 0,

+ 0,

+ VkContext->VkBodyBltWidth,

+ VkContext->VkBodyBltHeight,

+ VkContext->VkBodyBltWidth * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL)

+ );

+ if (EFI_ERROR (Status)) {

+ FreePool (BltBuffer);

+ return Status;

+ }

+ if (CompareMem (BltBuffer, VkContext->VkBodyCompoundBltBuffer, VkContext->VkBodyBltSize) != 0) {

+ VkContext->IsBackgroundChanged = TRUE;

+ VkContext->CurrentKeyboardDisplay = VkDisplayAttributeNone;

+ DrawKeyboardLayout (VkContext);

+ }

+

+ if (BltBuffer != NULL) {

+ FreePool (BltBuffer);

+ }

+

+ return Status;

+}

+

+/**

+ Get unicode by VkContext->PageNumber and VkContext->KeyboardBodyPtr.

+

+ @param[in] VkContext Address of an VK_CONTEXT structure.

+ @param[in] KeyItem Key Item.

+ @param[out] FontPtr Follow VkContext->PageNumber to translate

+ font unicode.

+

+ @retval EFI_SUCCESS Finish translating FontPtr.

+ @retval EFI_INVALID_PARAMETER VkContext or FontPtr is NULL.

+

+**/

+EFI_STATUS

+VkGetMappingFont (

+ IN VK_CONTEXT *VkContext,

+ IN VK_STRUCT KeyItem,

+ OUT UINT32 *FontPtr

+ )

+{

+ if ((VkContext == NULL) || (FontPtr == NULL) || (VkContext->PageNumber>=VkPageMaximum)) {

+ return EFI_INVALID_PARAMETER;

+ }

+ *FontPtr = (UINT32) KeyItem.PageFont[VkContext->PageNumber];

+

+ return EFI_SUCCESS;

+}

diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/KeyboardLayout.idf
b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/KeyboardLayout.idf
new file mode 100644
index 0000000000..995bd0d859
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/KeyboardLayout.idf
@@ -0,0 +1,12 @@
+// /** @file

+// Virtual Keyboard Layout

+//

+// Copyright (c) 2019 - 2020, Intel Corporation. All rights reserved.<BR>

+//

+// SPDX-License-Identifier: BSD-2-Clause-Patent

+//

+#image IMG_VK_CAPITALLETTERKEYBOARD TRANSPARENT CapitalLetterKeyboard.bmp

+#image IMG_VK_DIGITKEYBOARD TRANSPARENT DigitKeyboard.bmp

+#image IMG_VK_FULLICON TRANSPARENT FullIcon.bmp

+#image IMG_VK_SIMPLEICON TRANSPARENT SimpleIcon.bmp

+#image IMG_VK_SIMPLEKEYBOARD TRANSPARENT SimpleKeyboard.bmp

diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/SimpleIcon.bmp
b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/SimpleIcon.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..16816f031eb98bf8169c7119b95ea3ed1371f41d
GIT binary patch
literal 2814
zcmeHDu?>JQ41<*mn3%bM1K9bStAMDgEvtknP%#v#jj<EA^|~EHm%hdJ+18X--;Igi
zvz~tHZ083bZvKJwS=AedIaS~0$e`HvNI;OvAp=5}kZlld1O%z<Y2HkwWx^;3ew~S4
zE{O5qpp83T)f<O7RWIkrpxE|EK#<BI145UOZ4hn*1gY$4-b|%s!YByBnW#Y!<5EEz
Lcf5u-&Un3EdmJn}

literal 0
HcmV?d00001

diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/SimpleKeyboard.bmp
b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/SimpleKeyboard.bmp
new file mode 100644
index 0000000000000000000000000000000000000000..3004a534f026fe4906e64480f2239b7b7923640b
GIT binary patch
literal 30054
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
D{aYn_

literal 0
HcmV?d00001

diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboard.h
b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboard.h
new file mode 100644
index 0000000000..debd4346c7
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboard.h
@@ -0,0 +1,777 @@
+/** @file

+ Header file for Virtual Keyboard driver.

+

+ Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#ifndef _VIRTUAL_KEYBOARD_H_

+#define _VIRTUAL_KEYBOARD_H_

+

+#include <Uefi.h>

+#include <Library/BaseMemoryLib.h>

+#include <Library/DebugLib.h>

+#include <Library/MemoryAllocationLib.h>

+#include <Library/UefiBootServicesTableLib.h>

+#include <Library/UefiDriverEntryPoint.h>

+#include <Library/UefiLib.h>

+#include <Library/BaseLib.h>

+#include <Library/PcdLib.h>

+#include <Library/HiiLib.h>

+#include <Protocol/AbsolutePointer.h>

+#include <Protocol/GraphicsOutput.h>

+#include <Protocol/SimpleTextIn.h>

+#include <Protocol/SimpleTextInEx.h>

+#include <Protocol/SimpleTextOut.h>

+#include <Protocol/HiiDatabase.h>

+#include <Protocol/HiiImageEx.h>

+#include <Protocol/HiiPackageList.h>

+#include <Guid/ConsoleInDevice.h>

+#include "ComponentName.h"

+

+//

+// Global Variables

+//

+extern EFI_DRIVER_BINDING_PROTOCOL gVirtualKeyboardDriverBinding;

+extern EFI_COMPONENT_NAME_PROTOCOL gVirtualKeyboardComponentName;

+extern EFI_COMPONENT_NAME2_PROTOCOL gVirtualKeyboardComponentName2;

+

+///

+/// Debug raw data points

+///

+#define DEBUG_VK_POINTS 0x40000000

+

+///

+/// Debug data point scaling

+///

+#define DEBUG_VK_POINT_SCALING 0x20000000

+

+///

+/// Debug key press

+///

+#define DEBUG_VK_KEYS 0x10000000

+

+///

+/// Debug routine entry and exit

+///

+#define DEBUG_VK_ROUTINE_ENTRY_EXIT 0x08000000

+

+///

+/// Display the graphics info

+///

+#define DEBUG_VK_GRAPHICS_INFO 0x04000000

+

+///

+/// Display the timer entry and exit

+///

+#define DEBUG_VK_TIMER_ENTRY_EXIT 0x00100000

+

+///

+/// Signature

+///

+#define VK_SIGNATURE SIGNATURE_32 ('V', 'K', 'e', 'y')

+#define VK_NOTIFY_SIGNATURE SIGNATURE_32 ('V', 'K', 'n', 's')

+

+///

+/// Poll interval

+///

+#define VK_POLL_INTERVAL (1000 * 1000)

+

+///

+/// Define the touch timeout in poll intervals

+///

+#define VK_REPEAT_TIMEOUT 5

+

+///

+/// TPL used to synchronize add/remove from list

+///

+#define TPL_VK_SYNC TPL_NOTIFY

+

+///

+/// Dimension of an array ( number of elements )

+///

+#define DIM(x) ( sizeof ( x ) / sizeof ( x [ 0 ]))

+

+///

+/// Define Key buffer

+///

+#define MAX_KEY_BUF_SIZE 64

+

+///

+/// Define Transparent Weight

+///

+#define TRANSPARENCY_WEIGHT 50

+

+typedef struct _VK_CONTEXT VK_CONTEXT;

+

+typedef enum _VK_KEY_TYPE {

+ VkKeyNull = 0x0000 | CHAR_NULL,

+ VkKeyBackspace = 0x0000 | CHAR_BACKSPACE,

+ VkKeyTab = 0x0000 | CHAR_TAB,

+ VkKeyEnter = 0x0000 | CHAR_CARRIAGE_RETURN,

+ VkKeyScanMask = 0x1000,

+ VkKeyEsc = 0x1000 | SCAN_ESC,

+ VkKeyLeft = 0x1000 | SCAN_LEFT,

+ VkKeyRight = 0x1000 | SCAN_RIGHT,

+ VkKeyUp = 0x1000 | SCAN_UP,

+ VkKeyDown = 0x1000 | SCAN_DOWN,

+ VkKeyF1 = 0x1000 | SCAN_F1,

+ VkKeyF2 = 0x1000 | SCAN_F2,

+ VkKeyF3 = 0x1000 | SCAN_F3,

+ VkKeyF4 = 0x1000 | SCAN_F4,

+ VkKeyF5 = 0x1000 | SCAN_F5,

+ VkKeyF6 = 0x1000 | SCAN_F6,

+ VkKeyF7 = 0x1000 | SCAN_F7,

+ VkKeyF8 = 0x1000 | SCAN_F8,

+ VkKeyF9 = 0x1000 | SCAN_F9,

+ VkKeyF10 = 0x1000 | SCAN_F10,

+ VkKeyF11 = 0x1000 | SCAN_F11,

+ VkKeyF12 = 0x1000 | SCAN_F12,

+ VkKeySpecificMask = 0x2000,

+ VkKeyShift = 0x2000 | 0x0000,

+ VkKeyCapslock = 0x2000 | 0x0001,

+ VkKeyTwoPage = 0x2000 | 0x0002,

+ VkKeyTypeMaximum = 0xFFFF

+} VK_KEY_TYPE;

+

+typedef enum _VK_PAGE_TYPE {

+ //

+ // +---+---+---+---+---+---+---+---+---+---+---+

+ // | q | w | e | r | t | y | u | i | o | p |<X|| Line 0

+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

+ // | | a | s | d | f | g | h | j | k | l | F2| | Line 1

+ // +-+---+---+---+---+---+---+---+---+---+---+-+

+ // |Caps | z | x | c | v | b | n | m |aU |Enter| Line 2

+ // +-----+---+---+---+---+---+---+---+---+---+-+

+ // | Esc |12#| Space |aL |aD |aR | | Line 3

+ // +-----+---+-------------------+---+---+---+-+

+ //

+ VkPage0,

+

+ //

+ // +---+---+---+---+---+---+---+---+---+---+---+

+ // | Q | W | E | R | T | Y | U | I | O | P |<X|| Line 0

+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

+ // | | A | S | D | F | G | H | J | K | L | F2| | Line 1

+ // +-+---+---+---+---+---+---+---+---+---+---+-+

+ // |Caps | Z | X | C | V | B | N | M |aU |Enter| Line 2

+ // +-----+---+---+---+---+---+---+---+---+---+-+

+ // | Esc |12#| Space |aL |aD |aR | | Line 3

+ // +-----+---+-------------------+---+---+---+-+

+ //

+ VkPage1,

+

+ //

+ // +---+---+---+---+---+---+---+---+---+---+---+

+ // | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 |<X|| Line 0

+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

+ // | |F1 |F2 |F3 |F4 |F5 |F6 |F7 |F8 |F9 |F10| | Line 1

+ // +-+---+---+---+---+---+---+---+---+---+---+-+

+ // |Shift| . | ; | ' | , | . | / |F11|F12|Enter| Line 2

+ // +-----+---+---+---+---+---+---+---+---+---+-+

+ // | Esc |12#| Space | \ | - | = | | Line 3

+ // +-----+---+-------------------+---+---+---+-+

+ //

+ VkPage2,

+

+ //

+ // +---+---+---+---+---+---+---+---+---+---+---+

+ // | ! | @ | # | $ | % | ^ | & | * | ( | ) |<X|| Line 0

+ // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

+ // | |F1 |F2 |F3 |F4 |F5 |F6 |F7 |F8 |F9 |F10| | Line 1

+ // +-+---+---+---+---+---+---+---+---+---+---+-+

+ // |Shift| ~ | : | " | < | > | ? |F11|F12|Enter| Line 2

+ // +-----+---+---+---+---+---+---+---+---+---+-+

+ // | Esc |12#| Space | | | _ | + | | Line 3

+ // +-----+---+-------------------+---+---+---+-+

+ //

+ VkPage3,

+ VkPageMaximum

+} VK_PAGE_TYPE;

+

+typedef enum VK_DISPLAY_ATTRIBUTE {

+ VkDisplayAttributeNone, /// No keyboard displayed

+ VkDisplayAttributeFullTop, /// Full keyboard display at top

+ VkDisplayAttributeFullBottom, /// Full keyboard display at bottom

+ VkDisplayAttributeSimpleTop, /// Simple keyboard display at top

+ VkDisplayAttributeSimpleBottom, /// Simple keyboard display at bottom

+ VkDisplayAttributeMaximum

+} VK_DISPLAY_ATTRIBUTE;

+

+typedef struct _VK_STRUCT {

+ UINT16 DisStartX;

+ UINT16 DisStartY;

+ UINT16 DisEndX;

+ UINT16 DisEndY;

+ VK_KEY_TYPE PageFont[VkPageMaximum];

+} VK_STRUCT;

+

+typedef struct _VK_NOTIFY {

+ UINTN Signature;

+ EFI_KEY_DATA KeyData;

+ EFI_KEY_NOTIFY_FUNCTION KeyNotificationFn;

+ LIST_ENTRY NotifyEntry;

+} VK_NOTIFY;

+

+///

+/// Virtual Keyboard context

+///

+struct _VK_CONTEXT {

+ ///

+ /// Structure identification

+ ///

+ UINTN Signature;

+

+ ///

+ /// Controller Handle

+ ///

+ EFI_HANDLE Controller;

+

+ ///

+ /// Upper level API

+ ///

+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL SimpleTextIn;

+

+ ///

+ /// Simple Text In EX

+ ///

+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL SimpleTextInEx;

+

+ ///

+ /// Lower level APIs

+ ///

+ EFI_ABSOLUTE_POINTER_PROTOCOL *AbsolutePointer;

+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;

+

+ ///

+ /// Flag when the last poll indicated a touch event

+ ///

+ BOOLEAN TouchActive;

+

+ ///

+ /// Time to poll for touch input

+ ///

+ EFI_EVENT TimerEvent;

+

+ ///

+ /// HII handle to get image data used

+ ///

+ EFI_HII_HANDLE HiiHandle;

+ EFI_HII_IMAGE_EX_PROTOCOL *HiiImageEx;

+

+ ///

+ /// Keyboard body background buffer information

+ ///

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VkBodyBackgroundBltBuffer;

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *VkBodyCompoundBltBuffer;

+ UINTN VkBodyBltSize;

+ UINTN VkBodyBltStartX;

+ UINTN VkBodyBltStartY;

+ UINTN VkBodyBltHeight;

+ UINTN VkBodyBltWidth;

+ BOOLEAN IsBackgroundChanged;

+

+ ///

+ /// Icon buffer information

+ ///

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *IconBltBuffer;

+ UINTN IconBltSize;

+ UINTN IconBltHeight;

+ UINTN IconBltWidth;

+

+ ///

+ /// Full icon background buffer information

+ ///

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *FullIconBackBuffer;

+ UINTN FullIconBackStartX;

+ UINTN FullIconBackStartY;

+ UINTN FullIconBackHeight;

+ UINTN FullIconBackWidth;

+ UINTN FullIconBackSize;

+ BOOLEAN FullIconUpdatedFlag;

+

+ ///

+ /// Simple icon background buffer information

+ ///

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *SimIconBackBuffer;

+ UINTN SimIconBackStartX;

+ UINTN SimIconBackStartY;

+ UINTN SimIconBackHeight;

+ UINTN SimIconBackWidth;

+ UINTN SimIconBackSize;

+ BOOLEAN SimIconUpdatedFlag;

+

+ ///

+ /// Small Icon

+ ///

+ EFI_IMAGE_INPUT *SmallIcon;

+

+ ///

+ /// Full Icon

+ ///

+ EFI_IMAGE_INPUT *FullIcon;

+

+ ///

+ /// Simple Key body

+ ///

+ EFI_IMAGE_INPUT *SimKeyBody;

+

+ ///

+ /// Digital key body

+ ///

+ EFI_IMAGE_INPUT *DigKeyBody;

+

+ ///

+ /// Capital Letter Key board

+ ///

+ EFI_IMAGE_INPUT *CapLeKeyBody;

+

+ ///

+ /// Screen check buffer.

+ /// This is used to check if screen is kept scrolling up.

+ ///

+ EFI_GRAPHICS_OUTPUT_BLT_PIXEL *ScreenCheckBuffer;

+ UINTN ScreenCheckBufferSize;

+

+ ///

+ /// Key state

+ ///

+ BOOLEAN KeyPressed;

+

+ ///

+ /// Keyboard display status

+ ///

+ VK_DISPLAY_ATTRIBUTE CurrentKeyboardDisplay;

+ VK_DISPLAY_ATTRIBUTE TargetKeyboardDisplay;

+

+ ///

+ /// Keyboard icon display status

+ ///

+ BOOLEAN IsIconShowed;

+ UINT8 IconReDrawCheck;

+

+ ///

+ /// Keyboard body Image address

+ /// Size of KeyboardBodyPtr must larger than mFullKeyboardBody

+ ///

+ UINT32 NumOfKeysInfo;

+ VK_STRUCT KeyboardBodyPtr[50];

+

+ ///

+ /// KeyBuffer

+ ///

+ EFI_EVENT KeyNotifyProcessEvent;

+ EFI_KEY_TOGGLE_STATE KeyToggleState;

+ EFI_KEY_DATA Keybuffer[MAX_KEY_BUF_SIZE];

+ UINT8 KeyStartIndex;

+ UINT8 KeyEndIndex;

+ UINT16 KeyTouchedTimeOut;

+ BOOLEAN IsShiftKeyFlag;

+ BOOLEAN IsCapsLockFlag;

+ BOOLEAN IsSupportPartialKey;

+ BOOLEAN IsRedrawUpdateUI;

+ VK_PAGE_TYPE PageNumber;

+ LIST_ENTRY NotifyList;

+};

+

+///

+/// Locate VK_CONTEXT from protocol

+///

+#define VK_CONTEXT_FROM_PROTOCOL(a) CR (a, VK_CONTEXT, SimpleTextIn, VK_SIGNATURE)

+#define VK_CONTEXT_FROM_SIMPLETEXTINEX_PROTOCOL(a) CR (a, VK_CONTEXT, SimpleTextInEx, VK_SIGNATURE)

+#define VK_CONTEXT_FROM_VKBD_PROTOCOL(a) CR (a, VK_CONTEXT, VkbdProtocol, VK_SIGNATURE)

+

+/**

+ Start the virtual keyboard driver

+

+ This routine allocates the necessary resources for the driver.

+

+ This routine is called by VirtualKeyboardDriverStart to complete the driver

+ initialization.

+

+ @param[in, out] VkContext Address of an VK_CONTEXT structure

+ @param[in] Controller Handle of device to work with.

+

+ @retval EFI_SUCCESS Driver API properly initialized

+

+**/

+EFI_STATUS

+VkApiStart (

+ IN VK_CONTEXT *VkContext,

+ IN EFI_HANDLE Controller

+ );

+

+/**

+ Stop the virtual keyboard driver

+

+ This routine releases the resources allocated by VKApiStart.

+

+ This routine is called by VirtualKeyboardDriverStop to initiate the driver

+ shutdown.

+

+ @param[in] VkContext Address of an VK_CONTEXT structure

+

+**/

+VOID

+VkApiStop (

+ IN VK_CONTEXT *VkContext

+ );

+

+/**

+ Resets the input device hardware.

+

+ The Reset() function resets the input device hardware. As part

+ of initialization process, the firmware/device will make a quick

+ but reasonable attempt to verify that the device is functioning.

+ If the ExtendedVerification flag is TRUE the firmware may take

+ an extended amount of time to verify the device is operating on

+ reset. Otherwise the reset operation is to occur as quickly as

+ possible. The hardware verification process is not defined by

+ this specification and is left up to the platform firmware or

+ driver to implement.

+

+ @param[in] This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.

+

+ @param[in] ExtendedVerification Indicates that the driver may perform a more exhaustive

+ verification operation of the device during reset.

+

+ @retval EFI_SUCCESS The device was reset.

+ @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset.

+

+**/

+EFI_STATUS

+EFIAPI

+VkKeyboardReset (

+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,

+ IN BOOLEAN ExtendedVerification

+ );

+

+/**

+ Reads the next keystroke from the input device. The WaitForKey Event can

+ be used to test for existence of a keystroke via WaitForEvent () call.

+

+ @param[in] This Protocol instance pointer.

+ @param[out] Key Driver may perform diagnostics on reset.

+

+ @retval EFI_SUCCESS The keystroke information was returned.

+ @retval EFI_NOT_READY There was no keystroke data available.

+ @retval EFI_DEVICE_ERROR The keystroke information was not returned due to

+ hardware errors.

+

+**/

+EFI_STATUS

+EFIAPI

+VkKeyboardReadKeyStroke (

+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,

+ OUT EFI_INPUT_KEY *Key

+ );

+

+/**

+ Resets the input device hardware.

+

+ The Reset() function resets the input device hardware. As part

+ of initialization process, the firmware/device will make a quick

+ but reasonable attempt to verify that the device is functioning.

+ If the ExtendedVerification flag is TRUE the firmware may take

+ an extended amount of time to verify the device is operating on

+ reset. Otherwise the reset operation is to occur as quickly as

+ possible. The hardware verification process is not defined by

+ this specification and is left up to the platform firmware or

+ driver to implement.

+

+ @param[in] This A pointer to the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL instance.

+

+ @param[in] ExtendedVerification Indicates that the driver may perform a more exhaustive

+ verification operation of the device during reset.

+

+ @retval EFI_SUCCESS The device was reset.

+ @retval EFI_DEVICE_ERROR The device is not functioning correctly and could not be reset.

+

+**/

+EFI_STATUS

+EFIAPI

+VkKeyboardResetEx (

+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,

+ IN BOOLEAN ExtendedVerification

+ );

+

+/**

+ Reads the next keystroke from the input device.

+

+ @param[in] This Protocol instance pointer.

+ @param[out] KeyData A pointer to a buffer that is filled in with the keystroke

+ state data for the key that was pressed.

+

+ @retval EFI_SUCCESS The keystroke information was returned.

+ @retval EFI_NOT_READY There was no keystroke data available.

+ @retval EFI_INVALID_PARAMETER This or KeyData is NULL.

+

+**/

+EFI_STATUS

+EFIAPI

+VkKeyboardReadKeyStrokeEx (

+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,

+ OUT EFI_KEY_DATA *KeyData

+ );

+

+/**

+ Set certain state for the input device.

+

+ @param[in] This Protocol instance pointer.

+ @param[in] KeyToggleState A pointer to the EFI_KEY_TOGGLE_STATE to set the

+ state for the input device.

+

+ @retval EFI_SUCCESS The device state was set appropriately.

+ @retval EFI_INVALID_PARAMETER This or KeyToggleState is NULL.

+

+**/

+EFI_STATUS

+EFIAPI

+VkKeyboardSetState (

+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,

+ IN EFI_KEY_TOGGLE_STATE *KeyToggleState

+ );

+

+/**

+ Register a notification function for a particular keystroke for the input device.

+

+ @param[in] This Protocol instance pointer.

+ @param[in] KeyData A pointer to a buffer that is filled in with the keystroke

+ information data for the key that was pressed.

+ @param[in] KeyNotificationFunction Points to the function to be called when the key

+ sequence is typed specified by KeyData.

+ @param[out] NotifyHandle Points to the unique handle assigned to the registered notification.

+

+ @retval EFI_SUCCESS The notification function was registered successfully.

+ @retval EFI_OUT_OF_RESOURCES Unable to allocate resources for necessary data structures.

+ @retval EFI_INVALID_PARAMETER KeyData or NotifyHandle or KeyNotificationFunction is NULL.

+

+**/

+EFI_STATUS

+EFIAPI

+VkKeyboardRegisterKeyNotify (

+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,

+ IN EFI_KEY_DATA *KeyData,

+ IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction,

+ OUT EFI_HANDLE *NotifyHandle

+ );

+

+/**

+ Remove a registered notification function from a particular keystroke.

+

+ @param[in] This Protocol instance pointer.

+ @param[in] NotificationHandle The handle of the notification function being unregistered.

+

+ @retval EFI_SUCCESS The notification function was unregistered successfully.

+ @retval EFI_INVALID_PARAMETER The NotificationHandle is invalid

+

+**/

+EFI_STATUS

+EFIAPI

+VkKeyboardUnregisterKeyNotify (

+ IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This,

+ IN EFI_HANDLE NotificationHandle

+ );

+

+/**

+ Draw key board on the display

+

+ @param[in] VkContext Graphic Protocol for draw the alphabet.

+

+ @retval EFI_SUCCESS Draw keyboard was done.

+ @retval EFI_UNSUPPORTED Did not get key mapping table.

+

+**/

+EFI_STATUS

+DrawKeyboardLayout (

+ IN VK_CONTEXT *VkContext

+ );

+

+/**

+ Clear the keyboard body

+

+ @param[in] VkContext Code context.

+

+ @retval EFI_SUCCESS Clear rectangle is done.

+

+**/

+EFI_STATUS

+HideVkBody (

+ IN VK_CONTEXT *VkContext

+ );

+

+/**

+ Clear the keyboard icon

+

+ @param[in] VkContext Code context.

+

+ @retval EFI_SUCCESS Clear rectangle is done.

+

+**/

+EFI_STATUS

+HideVkIcon (

+ IN VK_CONTEXT *VkContext

+ );

+

+/**

+ Use to draw the keyboard icon.

+

+ @param[in] VkContext Pointer to virtual keyboard's context

+ @param[in] VkImage Image of keyboard to display on the screen.

+ @param[in] Attribute Attribute of keyboard to display on the screen.

+

+ @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and keyboard icon displayed.

+ @retval EFI_UNSUPPORTED KeyboardFile not found

+ @retval EFI_INVALID_PARAMETER Attribute is unknown.

+

+**/

+EFI_STATUS

+EFIAPI

+DrawVkIcon (

+ IN VK_CONTEXT *VkContext,

+ IN EFI_IMAGE_INPUT *VkImage,

+ IN VK_DISPLAY_ATTRIBUTE Attribute

+ );

+

+/**

+ Use to draw the keyboard.

+

+ @param[in] VkContext Pointer to virtual keyboard's context

+ @param[in] VkImage Image of keyboard to display on the screen.

+ @param[in] Attribute Attribute of keyboard to display on the screen.

+

+ @retval EFI_SUCCESS ConsoleControl has been flipped to graphics and keyboard displayed.

+ @retval EFI_UNSUPPORTED KeyboardFile not found

+ @retval EFI_INVALID_PARAMETER Attribute is unknown.

+

+**/

+EFI_STATUS

+EFIAPI

+DrawVkBody (

+ IN VK_CONTEXT *VkContext,

+ IN EFI_IMAGE_INPUT *VkImage,

+ IN VK_DISPLAY_ATTRIBUTE Attribute

+ );

+

+/**

+ Get unicode by VkContext->PageNumber and VkContext->KeyboardBodyPtr.

+

+ @param[in] VkContext Address of an VK_CONTEXT structure.

+ @param[in] KeyItem Key Item.

+ @param[out] FontPtr Follow VkContext->PageNumber to translate

+ font unicode.

+

+ @retval EFI_SUCCESS Finish translating FontPtr.

+ @retval EFI_INVALID_PARAMETER VkContext or FontPtr is NULL.

+

+**/

+EFI_STATUS

+VkGetMappingFont (

+ IN VK_CONTEXT *VkContext,

+ IN VK_STRUCT KeyItem,

+ OUT UINT32 *FontPtr

+ );

+

+/**

+ This routine is used to check if icon has been cleared.

+

+ @param[in] VkContext Pointer to virtual keyboard's context

+

+ @retval EFI_SUCCESS Function completed.

+

+**/

+EFI_STATUS

+CheckIconCleared (

+ IN VK_CONTEXT *VkContext

+ );

+

+/**

+ ConvertCoordinate - Convert the touch panel's coordinate to display's coordinate.

+

+ @param[in] VkContext Virtual Keyboard context.

+ @param[in] Point The coordinate reported from touch panel.

+ @param[out] TouchX The coordinate X converted to display panel.

+ @param[out] TouchY The coordinate Y converted to display panel..

+

+ @retval EFI_SUCCESS Convert success.

+

+**/

+EFI_STATUS

+ConvertCoordinate (

+ IN VK_CONTEXT *VkContext,

+ IN EFI_ABSOLUTE_POINTER_STATE Point,

+ OUT UINT32 *TouchX,

+ OUT UINT32 *TouchY

+ );

+

+/**

+ This routine is used to check if screen has been cleared.

+

+ @param[in] VkContext Pointer to virtual keyboard's context

+

+ @retval EFI_SUCCESS Function completed.

+

+**/

+EFI_STATUS

+CheckScreenCleared (

+ IN VK_CONTEXT *VkContext

+ );

+

+/**

+ This routine is used to check if background beneath virtual keyboard has been cleared.

+

+ @param[in] VkContext Pointer to virtual keyboard's context

+

+ @retval EFI_SUCCESS Function completed.

+

+**/

+EFI_STATUS

+CheckBackgroundChanged (

+ IN VK_CONTEXT *VkContext

+ );

+

+/**

+ To prevent screen keyboard layout occur scroll up

+

+ @param[in] VkContext Address of an VK_CONTEXT structure.

+

+**/

+VOID

+PreventScreenScrollUp (

+ IN OUT VK_CONTEXT *VkContext

+ );

+

+EFI_STATUS

+SetCharacterPosition (

+ IN VK_CONTEXT *VkContext,

+ IN UINT32 DestX,

+ IN UINT32 DestY

+ );

+

+EFI_STATUS

+KeyboardLayoutHandler (

+ IN VK_CONTEXT *VkContext,

+ IN UINT32 Index

+ );

+

+EFI_STATUS

+EFIAPI

+SaveVkBodyBackgroundBltBuffer (

+ IN VK_CONTEXT *VkContext,

+ IN UINTN BltSize

+ );

+

+EFI_STATUS

+EFIAPI

+RestoreVkBodyBackgroundBltBuffer (

+ IN VK_CONTEXT *VkContext

+ );

+

+EFI_STATUS

+EFIAPI

+SaveVkIconBackgroundBltBuffer (

+ IN VK_CONTEXT *VkContext,

+ IN VK_DISPLAY_ATTRIBUTE IconType

+ );

+#endif

diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboardDriver.c
b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboardDriver.c
new file mode 100644
index 0000000000..42ad493a9f
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboardDriver.c
@@ -0,0 +1,541 @@
+/** @file

+ Virtual Keyboard driver.

+

+ Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.<BR>

+ SPDX-License-Identifier: BSD-2-Clause-Patent

+

+**/

+

+#include "VirtualKeyboard.h"

+

+UINT32 mOrigConOutRow = 0;

+UINT32 mOrigSetupConOutRow = 0;

+EFI_HII_HANDLE mHiiHandle = NULL;

+

+EFI_STATUS

+EFIAPI

+VirtualKeyboardDriverSupported (

+ IN EFI_DRIVER_BINDING_PROTOCOL *This,

+ IN EFI_HANDLE Controller,

+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath

+ );

+

+EFI_STATUS

+EFIAPI

+VirtualKeyboardDriverStart (

+ IN EFI_DRIVER_BINDING_PROTOCOL *This,

+ IN EFI_HANDLE Controller,

+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath

+ );

+

+EFI_STATUS

+EFIAPI

+VirtualKeyboardDriverStop (

+ IN EFI_DRIVER_BINDING_PROTOCOL *This,

+ IN EFI_HANDLE Controller,

+ IN UINTN NumberOfChildren,

+ IN EFI_HANDLE *ChildHandleBuffer

+ );

+

+EFI_DRIVER_BINDING_PROTOCOL gVirtualKeyboardDriverBinding = {

+ VirtualKeyboardDriverSupported,

+ VirtualKeyboardDriverStart,

+ VirtualKeyboardDriverStop,

+ 0x10,

+ NULL,

+ NULL

+};

+

+/**

+ This is the declaration of an EFI image entry point. This entry point is

+ the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including

+ both device drivers and bus drivers.

+

+ @param ImageHandle The firmware allocated handle for the UEFI image.

+ @param SystemTable A pointer to the EFI System Table.

+

+ @retval EFI_SUCCESS The operation completed successfully.

+ @retval Others An unexpected error occurred.

+

+**/

+EFI_STATUS

+EFIAPI

+VirtualKeyboardDriverEntryPoint (

+ IN EFI_HANDLE ImageHandle,

+ IN EFI_SYSTEM_TABLE *SystemTable

+ )

+{

+ EFI_STATUS Status;

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverEntryPoint Start\n"));

+ //

+ // Install UEFI Driver Model protocol(s).

+ //

+ Status = EfiLibInstallDriverBindingComponentName2 (

+ ImageHandle,

+ SystemTable,

+ &gVirtualKeyboardDriverBinding,

+ ImageHandle,

+ &gVirtualKeyboardComponentName,

+ &gVirtualKeyboardComponentName2

+ );

+ ASSERT_EFI_ERROR (Status);

+

+ mHiiHandle = HiiAddPackages (

+ &gEfiCallerIdGuid,

+ NULL,

+ VirtualKeyboardDxeImages,

+ NULL

+ );

+ ASSERT (mHiiHandle != NULL);

+

+ mOrigConOutRow = PcdGet32 (PcdConOutRow);

+ mOrigSetupConOutRow = PcdGet32 (PcdSetupConOutRow);

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverEntryPoint End\n"));

+ return Status;

+}

+

+/**

+ Verify the controller type

+

+ This routine determines if the pointer and GOP are available.

+

+ This routine is called by the UEFI driver framework during connect

+ processing.

+

+ @param[in] DriverBinding Protocol instance pointer.

+ @param[in] Controller Handle of device to test.

+ @param[in] RemainingDevicePath Not used.

+

+ @retval EFI_SUCCESS This driver supports this device.

+ @retval other This driver does not support this device.

+

+**/

+EFI_STATUS

+EFIAPI

+VirtualKeyboardDriverSupported (

+ IN EFI_DRIVER_BINDING_PROTOCOL *This,

+ IN EFI_HANDLE Controller,

+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath

+ )

+{

+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;

+ EFI_STATUS Status;

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverSupported Start\n"));

+

+ //

+ // Verify that the driver is not already started

+ //

+ Status = gBS->OpenProtocol (

+ Controller,

+ &gEfiCallerIdGuid,

+ NULL,

+ This->DriverBindingHandle,

+ Controller,

+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL

+ );

+ if (!EFI_ERROR (Status)) {

+ Status = EFI_ALREADY_STARTED;

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - VK has already initialized\n"));

+ goto Error;

+ }

+

+ //

+ // Determine if the pointer protocol is available.

+ // This should be installed in touch driver.

+ //

+ Status = gBS->OpenProtocol (

+ Controller,

+ &gEfiAbsolutePointerProtocolGuid,

+ NULL,

+ This->DriverBindingHandle,

+ Controller,

+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - VK Absolute pointer protocol not found\n"));

+ goto Error;

+ }

+

+ Status = gBS->OpenProtocol (

+ Controller,

+ &gEfiTouchPanelGuid,

+ NULL,

+ This->DriverBindingHandle,

+ Controller,

+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - VK Touch Panel Guid not found\n"));

+ goto Error;

+ }

+

+ //

+ // Determine if the graphics output protocol is available

+ //

+ Status = gBS->HandleProtocol (

+ gST->ConsoleOutHandle,

+ &gEfiGraphicsOutputProtocolGuid,

+ (VOID **)&GraphicsOutput

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - VK Graphics output protocol not found\n"));

+ goto Error;

+ }

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_INFO, "VirtualKeyboardDriverSupported Success, Status: %r\n",
Status));

+ goto End;

+

+Error:

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverSupported Failed, Status: %r\n", Status));

+

+End:

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverSupported End\n"));

+ return Status;

+}

+

+/**

+ Connect to the controller

+

+ This routine initializes an instance of the virutal keyboard driver for this

+ controller.

+

+ This routine is called by the UEFI driver framework during connect

+ processing if the controller passes the tests in I2cBusDriverSupported.

+

+ @param[in] DriverBinding Protocol instance pointer.

+ @param[in] Controller Handle of device to work with.

+ @param[in] RemainingDevicePath Not used, always produce all possible children.

+

+ @retval EFI_SUCCESS This driver is added to Controller.

+ @retval other This driver does not support this device.

+

+**/

+EFI_STATUS

+EFIAPI

+VirtualKeyboardDriverStart (

+ IN EFI_DRIVER_BINDING_PROTOCOL *This,

+ IN EFI_HANDLE Controller,

+ IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath

+ )

+{

+ VK_CONTEXT *VkContext;

+ EFI_STATUS Status;

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_INFO, "VirtualKeyboardDriverStart Start\n"));

+

+ VkContext = AllocateZeroPool (sizeof (VK_CONTEXT));

+ if (VkContext == NULL) {

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - No memory for virtual keyboard driver\n"));

+ Status = EFI_OUT_OF_RESOURCES;

+ ASSERT_EFI_ERROR (Status);

+ goto Error;

+ }

+

+ Status = gBS->OpenProtocol (

+ Controller,

+ &gEfiAbsolutePointerProtocolGuid,

+ (VOID**) &VkContext->AbsolutePointer,

+ This->DriverBindingHandle,

+ Controller,

+ EFI_OPEN_PROTOCOL_BY_DRIVER

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to open absolute pointer protocol,
Status: %r\n", Status));

+ goto Error;

+ }

+

+ Status = gBS->OpenProtocol (

+ Controller,

+ &gEfiTouchPanelGuid,

+ NULL,

+ This->DriverBindingHandle,

+ Controller,

+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - TouchPanel GUID not found, Status: %r\n",
Status));

+ goto Error;

+ }

+

+ Status = gBS->HandleProtocol (

+ gST->ConsoleOutHandle,

+ &gEfiGraphicsOutputProtocolGuid,

+ (VOID**) &VkContext->GraphicsOutput

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Graphics output protocol not available,
Status: %r\n", Status));

+ goto Error;

+ }

+

+ VkContext->HiiHandle = mHiiHandle;

+ Status = VkApiStart (VkContext, Controller);

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to VkApiStart, Status: %r\n", Status));

+ goto Error;

+ }

+

+ Status = gBS->InstallMultipleProtocolInterfaces (

+ &Controller,

+ &gEfiCallerIdGuid,

+ VkContext,

+ &gEfiSimpleTextInProtocolGuid,

+ &VkContext->SimpleTextIn,

+ &gEfiSimpleTextInputExProtocolGuid,

+ &VkContext->SimpleTextInEx,

+ &gEfiConsoleInDeviceGuid,

+ NULL,

+ NULL

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_ERROR, "ERROR - Failed to install VK protocols, Status: %r\n",
Status));

+ ASSERT_EFI_ERROR (Status);

+ goto Error;

+ }

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT | DEBUG_INFO, "VirtualKeyboardDriverStart Success, Status: %r\n", Status));

+ goto End;

+

+Error:

+ if (VkContext != NULL) {

+ FreePool (VkContext);

+ }

+

+ gBS->CloseProtocol (

+ Controller,

+ &gEfiAbsolutePointerProtocolGuid,

+ This->DriverBindingHandle,

+ Controller

+ );

+

+ //

+ // Restore setting if connect device fail.

+ //

+ PcdSet32S (PcdConOutRow, mOrigConOutRow);

+ PcdSet32S (PcdSetupConOutRow, mOrigSetupConOutRow);

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverStart Failed, Status: %r\n", Status));

+

+End:

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverStart End\n"));

+

+ return Status;

+}

+

+/**

+ Disconnect from the controller.

+

+ This routine disconnects from the controller.

+

+ This routine is called by DriverUnload when the I2C bus driver

+ is being unloaded.

+

+ @param[in] DriverBinding Protocol instance pointer.

+ @param[in] Controller Handle of device to stop driver on.

+ @param[in] NumberOfChildren How many children need to be stopped.

+ @param[in] ChildHandleBuffer Not used.

+

+ @retval EFI_SUCCESS This driver is removed Controller.

+ @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.

+ @retval other This driver was not removed from this device.

+

+**/

+EFI_STATUS

+EFIAPI

+VirtualKeyboardDriverStop (

+ IN EFI_DRIVER_BINDING_PROTOCOL *This,

+ IN EFI_HANDLE Controller,

+ IN UINTN NumberOfChildren,

+ IN EFI_HANDLE *ChildHandleBuffer

+ )

+{

+ VK_CONTEXT *VkContext;

+ EFI_STATUS Status;

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverStop Start\n"));

+

+ Status = gBS->OpenProtocol (

+ Controller,

+ &gEfiCallerIdGuid,

+ (VOID**)&VkContext,

+ This->DriverBindingHandle,

+ Controller,

+ EFI_OPEN_PROTOCOL_BY_DRIVER | EFI_OPEN_PROTOCOL_EXCLUSIVE

+ );

+ if (EFI_ERROR (Status)) {

+ Status = EFI_SUCCESS;

+ goto Success;

+ }

+

+ //

+ // Done with the driver protocol

+ //

+ Status = gBS->CloseProtocol (

+ Controller,

+ &gEfiCallerIdGuid,

+ This->DriverBindingHandle,

+ Controller

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - Failed to close the VK protocol, Status: %r\n", Status));

+ goto Error;

+ }

+

+ //

+ // Remove ConsoleIn protocols first to close the link in ConSplitter

+ //

+ Status = gBS->OpenProtocol (

+ Controller,

+ &gEfiConsoleInDeviceGuid,

+ NULL,

+ This->DriverBindingHandle,

+ Controller,

+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - Failed to uninstall the protocols, Status: %r\n", Status));

+ goto Error;

+ }

+

+ //

+ // Remove the remaining protocols

+ //

+ Status = gBS->UninstallMultipleProtocolInterfaces (

+ Controller,

+ &gEfiCallerIdGuid,

+ VkContext,

+ &gEfiSimpleTextInProtocolGuid,

+ &VkContext->SimpleTextIn,

+ &gEfiSimpleTextInputExProtocolGuid,

+ &VkContext->SimpleTextInEx,

+ &gEfiConsoleInDeviceGuid,

+ NULL,

+ NULL

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - Failed to uninstall the protocols, Status: %r\n", Status));

+ goto Error;

+ }

+

+ //

+ // Stop the driver

+ //

+ VkApiStop (VkContext);

+

+ //

+ // Release the pointer protocol upon failure

+ //

+ Status = gBS->CloseProtocol (

+ Controller,

+ &gEfiAbsolutePointerProtocolGuid,

+ This->DriverBindingHandle,

+ Controller

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - Failed to close absolute pointer protocol, Status: %r\n", Status));

+ goto Error;

+ }

+

+ //

+ // Release VkContext

+ //

+ if (VkContext != NULL) {

+ FreePool (VkContext);

+ }

+

+Success:

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverStop Success, Status: %r\n", Status));

+ goto End;

+

+Error:

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverStop Failed, Status: %r\n", Status));

+

+End:

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverStop End\n"));

+ return Status;

+}

+

+/**

+ Unloads an image.

+

+ @param[in] ImageHandle Handle that identifies the image to be unloaded.

+

+ @retval EFI_SUCCESS The image has been unloaded.

+ @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.

+

+**/

+EFI_STATUS

+EFIAPI

+VirtualKeyboardDriverUnload (

+ IN EFI_HANDLE ImageHandle

+ )

+{

+ EFI_STATUS Status;

+ EFI_HANDLE *HandleBuffer;

+ UINTN HandleCount;

+ UINTN Index;

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverUnload Start\n"));

+

+ //

+ // Retrieve array of all handles in the handle database

+ //

+ Status = gBS->LocateHandleBuffer (

+ AllHandles,

+ NULL,

+ NULL,

+ &HandleCount,

+ &HandleBuffer

+ );

+ if (EFI_ERROR (Status)) {

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "ERROR - Failed to locate handle buffer, Status: %r\n", Status));

+ ASSERT_EFI_ERROR (Status);

+ goto Error;

+ }

+

+ //

+ // Disconnect the current driver from handles in the handle database

+ //

+ for (Index = 0; Index < HandleCount; Index++) {

+ gBS->DisconnectController (HandleBuffer[Index], ImageHandle, NULL);

+ }

+

+ //

+ // Free the array of handles

+ //

+ if (HandleBuffer != NULL) {

+ FreePool (HandleBuffer);

+ }

+

+ //

+ // Uninstall protocols installed in the driver entry point

+ //

+ Status = gBS->UninstallMultipleProtocolInterfaces (

+ ImageHandle,

+ &gEfiDriverBindingProtocolGuid,

+ &gVirtualKeyboardDriverBinding,

+ &gEfiComponentNameProtocolGuid,

+ &gVirtualKeyboardComponentName,

+ &gEfiComponentName2ProtocolGuid,

+ &gVirtualKeyboardComponentName2,

+ NULL

+ );

+ if (EFI_ERROR (Status)) {

+ ASSERT_EFI_ERROR (Status);

+ goto Error;

+ }

+

+ HiiRemovePackages (mHiiHandle);

+

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverUnload Success, Status: %r\n", Status));

+ goto End;

+

+Error:

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverUnload Failed, Status: %r\n", Status));

+

+End:

+ DEBUG ((DEBUG_VK_ROUTINE_ENTRY_EXIT, "VirtualKeyboardDriverUnload End\n"));

+ return Status;

+}

diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboardDxe.inf
b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboardDxe.inf
new file mode 100644
index 0000000000..9ecc99d5a7
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardDxe/VirtualKeyboardDxe.inf
@@ -0,0 +1,77 @@
+## @file

+# Instance of virtual keyboard driver binding protocol.

+#

+# Compliant with efi driver model, 1. VirtualKeyboardDriverSupported

+# determines if the pointer and GOP are available. 2.

+# VirtualKeyboardDriverStart initializes an instance of the virtual

+# keyboard driver for a particular controller. 3.

+# VirtualKeyboardDriverStop is called by DriverUnload when the I2C bus

+# driver is being unload.

+#

+# Copyright (c) 2012 - 2020, Intel Corporation. All rights reserved.<BR>

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

+

+[Defines]

+ INF_VERSION = 0x00010017

+ BASE_NAME = VirtualKeyboardDxe

+ FILE_GUID = E4735AAC-9C27-493f-86EA-9EFF43D7ADCD

+ VERSION_STRING = 1.0

+ MODULE_TYPE = UEFI_DRIVER

+ ENTRY_POINT = VirtualKeyboardDriverEntryPoint

+ UNLOAD_IMAGE = VirtualKeyboardDriverUnload

+

+#

+# VALID_ARCHITECTURES = IA32 X64

+# DRIVER_BINDING = gVirtualKeyboardDriverBinding;

+# COMPONENT_NAME = gVirtualKeyboardComponentName;

+# COMPONENT_NAME2 = gVirtualKeyboardComponentName2;

+#

+

+[LibraryClasses]

+ BaseMemoryLib

+ DebugLib

+ MemoryAllocationLib

+ UefiBootServicesTableLib

+ UefiDriverEntryPoint

+ UefiLib

+ PcdLib

+ HiiLib

+

+[Packages]

+ MdePkg/MdePkg.dec

+ MdeModulePkg/MdeModulePkg.dec

+ UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardFeaturePkg.dec

+

+[Pcd]

+ gEfiMdeModulePkgTokenSpaceGuid.PcdConOutRow

+ gEfiMdeModulePkgTokenSpaceGuid.PcdSetupConOutRow

+

+[Sources]

+ CapitalLetterKeyboard.bmp

+ DigitKeyboard.bmp

+ FullIcon.bmp

+ SimpleIcon.bmp

+ SimpleKeyboard.bmp

+ KeyboardLayout.idf

+ KeyboardLayout.c

+ ComponentName.c

+ Keyboard.c

+ VirtualKeyboard.h

+ VirtualKeyboardDriver.c

+

+[Protocols]

+ gEfiAbsolutePointerProtocolGuid ## TO_START

+ gEfiDriverBindingProtocolGuid ## PRODUCES

+ gEfiGraphicsOutputProtocolGuid ## TO_START

+ gEfiSimpleTextInProtocolGuid ## BY_START

+ gEfiSimpleTextInputExProtocolGuid ## BY_START

+ gEfiHiiImageExProtocolGuid ## TO_START

+

+[Guids]

+ gEfiConsoleInDeviceGuid ## SOMETIMES_PRODUCES

+ gEfiTouchPanelGuid ## TO_START

+

+[Depex]

+ gEfiHiiDatabaseProtocolGuid

diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardFeaturePkg.dec
b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardFeaturePkg.dec
new file mode 100644
index 0000000000..2742a04a8f
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardFeaturePkg.dec
@@ -0,0 +1,26 @@
+## @file

+# This package provides advanced feature functionality for User Authentication support.

+# This package should only depend on EDK II Core packages, IntelSiliconPkg, and MinPlatformPkg.

+#

+# The DEC files are used by the utilities that parse DSC and

+# INF files to generate AutoGen.c and AutoGen.h files

+# for the build infrastructure.

+#

+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>

+#

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

+

+[Defines]

+ DEC_SPECIFICATION = 0x00010017

+ PACKAGE_NAME = VirtualKeyboardFeaturePkg

+ PACKAGE_GUID = A40DFD69-3552-40E8-8D3D-89741B03B9E1

+ PACKAGE_VERSION = 0.1

+

+[Includes]

+ Include

+

+[Guids]

+ ## GUID used for VirtualKeyboardDriver to open TouchPanel protocol.

+ gEfiTouchPanelGuid = { 0x91b1d27b, 0xe126, 0x48d1, { 0x82, 0x34, 0xd2, 0x8b, 0x81, 0xc8, 0x83, 0x62 }}

diff --git a/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardFeaturePkg.dsc
b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardFeaturePkg.dsc
new file mode 100644
index 0000000000..ab3605fa15
--- /dev/null
+++ b/Features/Intel/UserInterface/VirtualKeyboardFeaturePkg/VirtualKeyboardFeaturePkg.dsc
@@ -0,0 +1,30 @@
+## @file

+# This is a build description file for the User Authentication advanced feature.

+# This package should only depend on EDK II Core packages, IntelSiliconPkg, and MinPlatformPkg.

+#

+# The DEC files are used by the utilities that parse DSC and

+# INF files to generate AutoGen.c and AutoGen.h files

+# for the build infrastructure.

+#

+# Copyright (c) 2020, Intel Corporation. All rights reserved.<BR>

+#

+# SPDX-License-Identifier: BSD-2-Clause-Patent

+#

+##

+

+[Defines]

+ PLATFORM_NAME = VirtualKeyboardFeaturePkg

+ PLATFORM_GUID = 6D396683-C82B-41D5-84E7-BB6E13B7C2BF

+ PLATFORM_VERSION = 0.1

+ DSC_SPECIFICATION = 0x00010005

+ OUTPUT_DIRECTORY = Build/$(PLATFORM_NAME)

+ SUPPORTED_ARCHITECTURES = IA32|X64

+ BUILD_TARGETS = DEBUG|RELEASE|NOOPT

+ SKUID_IDENTIFIER = DEFAULT

+ PEI_ARCH = IA32

+ DXE_ARCH = X64

+

+#

+# This package always builds the feature.

+#

+!include Include/VirtualKeyboardFeature.dsc

--
2.24.0.windows.2


-=-=-=-=-=-=
Groups.io Links: You receive all messages sent to this group.

View/Reply Online (#56348): https://edk2.groups.io/g/devel/message/56348
Mute This Topic: https://groups.io/mt/72555278/1712937
Group Owner: devel+owner@edk2.groups.io
Unsubscribe: https://edk2.groups.io/g/devel/unsub [ray.ni@...]
-=-=-=-=-=-=


Re: [PATCH v1 1/1] INF Spec: Add file dependency to [Sources] syntax

Bob Feng
 

Hi Pierre,

I will review the spec and code change in this week.

Thanks,
Bob

-----Original Message-----
From: devel@edk2.groups.io [mailto:devel@edk2.groups.io] On Behalf Of PierreGondois
Sent: Monday, March 30, 2020 11:52 PM
To: devel@edk2.groups.io; Sami Mujawar <Sami.Mujawar@...>; Feng, Bob C <bob.c.feng@...>; Gao, Liming <liming.gao@...>
Cc: nd <nd@...>
Subject: Re: [edk2-devel] [PATCH v1 1/1] INF Spec: Add file dependency to [Sources] syntax

Hello Liming and Bob,
I couldn't find the list of maintainers for the specification files, but it seems Liming is a maintainer. If a maintainer is missing, please feel free to cc him,

Regards,
Pierre

-----Original Message-----
From: PierreGondois <pierre.gondois@...>
Sent: Monday, March 30, 2020 4:43 PM
To: devel@edk2.groups.io
Cc: Pierre Gondois <Pierre.Gondois@...>; liming.gao@...; sami.mujawar@...; nd <nd@...>
Subject: [PATCH v1 1/1] INF Spec: Add file dependency to [Sources] syntax

From: Pierre Gondois <Pierre.Gondois@...>

BZ: https://bugzilla.tianocore.org/show_bug.cgi?id=2464

When building an edk2 module, a C file was including a .hex file generated by the compilation of an ASL file.
To describe this dependency between an ASL file and a C file, the edk2 patch,
- named "BaseTools: Build ASL files before C files",
- discussed at: https://edk2.groups.io/g/devel/message/52550
has been created.
This patch allows to establish build dependencies in the [Sources] section, between files that are not of the same language.
E.g.:
[Sources]
FileName1.X
FileName2.Y : FileName1.X
FileName3.Z : FileName1.X FileName2.Y

Here:
* FileName1.X will be built prior to FileName2.Y.
* FileName1.X and FileName2.Y will be built prior to
FileName3.Z.

This patch updates the Inf specification accordingly.

Signed-off-by: Pierre Gondois <pierre.gondois@...>
---

The changes can be seen at https://github.com/PierreARM/edk2-InfSpecification/tree/Bugzilla_2464_Enable_Build_Dependencies_v1

Notes:
v1:
- Enable build dependencies in the [Sources] section

2_inf_overview/25_[sources]_section.md | 12 ++++++++++++
3_edk_ii_inf_file_format/32_component_inf_definition.md | 3 +++
3_edk_ii_inf_file_format/39_[sources]_sections.md | 6 ++++--
README.md | 1 +
4 files changed, 20 insertions(+), 2 deletions(-)

diff --git a/2_inf_overview/25_[sources]_section.md b/2_inf_overview/25_[sources]_section.md
index 54757e61e37268eed293a5288e607cf2c7cfacf6..5b9f0a8395ef2be4497d99197dc695625d841830 100644
--- a/2_inf_overview/25_[sources]_section.md
+++ b/2_inf_overview/25_[sources]_section.md
@@ -2,6 +2,7 @@
2.5 [Sources] Section

Copyright (c) 2007-2019, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2020, ARM Limited. All rights reserved.<BR>

Redistribution and use in source (original document form) and 'compiled'
forms (converted to PDF, epub, HTML and other formats) with or without @@ -94,6 +95,17 @@ The following is an example for sources sections.

```

+The following example depicts the syntax to establish dependencies
+between files of different source types. As shown in the example below,
+Dsdt.asl will be compiled before DadtHandler.c:
+
+```ini
+[Sources.common]
+ DsdtHandler.c : Dsdt.asl
+ DsdtHandler.h
+ Dsdt.asl
+```
+
All Unicode files must be listed in the source section. If a Unicode file, `A.uni`, has the statement: `#include B.uni`, and `B.uni` has a statement:
`#include C.uni`, both `B.uni` and `C.uni` files must be listed in the INF diff --git a/3_edk_ii_inf_file_format/32_component_inf_definition.md b/3_edk_ii_inf_file_format/32_component_inf_definition.md
index 164771cb4cfff6e81fbf762a67ff741c190cecde..d776714c24c0baf2348f53dc2576c9feb6f3cb5e 100644
--- a/3_edk_ii_inf_file_format/32_component_inf_definition.md
+++ b/3_edk_ii_inf_file_format/32_component_inf_definition.md
@@ -2,6 +2,7 @@
3.2 Component INF Definition

Copyright (c) 2007-2019, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2020, ARM Limited. All rights reserved.<BR>

Redistribution and use in source (original document form) and 'compiled'
forms (converted to PDF, epub, HTML and other formats) with or without @@ -133,6 +134,8 @@ The following are common definitions used by multiple section types.
<Eq> ::= <TS> "=" <TS>
<FieldSeparator> ::= "|"
<FS> ::= <TS> <FieldSeparator> <TS>
+<SrcDepSeperator> ::= ":"
+<DepS> ::= <TS> <SrcDepSeperator> <TS>
<Wildcard> ::= "*"
<CommaSpace> ::= "," <Space>*
<Cs> ::= "," <Space>*
diff --git a/3_edk_ii_inf_file_format/39_[sources]_sections.md b/3_edk_ii_inf_file_format/39_[sources]_sections.md
index 810995df26ba409ca2cf3ebe6238aa5d55cf81f1..ac966425101fd44a57b09d36f95a0f732eab1c59 100644
--- a/3_edk_ii_inf_file_format/39_[sources]_sections.md
+++ b/3_edk_ii_inf_file_format/39_[sources]_sections.md
@@ -2,6 +2,7 @@
3.9 [Sources] Sections

Copyright (c) 2007-2019, Intel Corporation. All rights reserved.<BR>
+ Copyright (c) 2020, ARM Limited. All rights reserved.<BR>

Redistribution and use in source (original document form) and 'compiled'
forms (converted to PDF, epub, HTML and other formats) with or without @@ -74,7 +75,8 @@ This section is not valid for a generated "As Built" binary INF file.
<Options> ::= <FS> [<Family>] [<opt1>]
<opt1> ::= <FS> [<TagName>] [<opt2>]
<opt2> ::= <FS> [<ToolCode>] [<opt3>]
-<opt3> ::= <FS> [<FeatureFlagExpress>]
+<opt3> ::= <FS> [<FeatureFlagExpress>] [<opt4>]
+<opt4> ::= <DepS> <FileNameDependency>+
<Family> ::= {"MSFT"} {"GCC"} {"INTEL"} {<Wildcard>}
<TagName> ::= {<ToolWord>} {"*"}
<ToolCode> ::= _CommandCode_
@@ -83,7 +85,7 @@ This section is not valid for a generated "As Built" binary INF file.

#### Parameters

-**_Filename_**
+**_Filename_, _FileNameDependency_**

Paths listed in the filename elements of the `[Sources]` section must be relative to the directory the INF file resides in. Use of "..", "." and "../"
diff --git a/README.md b/README.md
index 60fba19fd67fd8d3dd33199de23f9bfe20aea7c9..4f771fc0f6e4ff516be95b1879d58329ab3bbecc 100644
--- a/README.md
+++ b/README.md
@@ -203,3 +203,4 @@ Copyright (c) 2007-2017, Intel Corporation. All rights reserved.
| | [#1162](https://bugzilla.tianocore.org/show_bug.cgi?id=1162) Correct the item in Table 1 to align with 3.4 section | |
| 1.28 | [#1453](https://bugzilla.tianocore.org/show_bug.cgi?id=1453) Update INF spec to remove EDK related contents | Mar 2019 |
| 1.29 | [#1952](https://bugzilla.tianocore.org/show_bug.cgi?id=1952) Add new MODULE_TYPE HOST_APPLICATION | July 2019 |
+| | [#2646](https://bugzilla.tianocore.org/show_bug.cgi?id=2646) Add file dependency to [Sources] syntax | |
--
'Guid(CE165669-3EF3-493F-B85D-6190EE5B9759)'


Re: [PATCH] OvmfPkg/PvScsiDxe: Fix VS2019 build error because of implicit cast

Ard Biesheuvel
 

On Wed, 1 Apr 2020 at 10:37, Laszlo Ersek <lersek@...> wrote:

On 04/01/20 00:17, Liran Alon wrote:

I would also mention that there are some bizzare code in EDK2 that
defines it's own ASSERT() macro that just does CpuDeadLoop(). E.g.
ArmVirtPkg/Library/ArmVirtDxeHobLib/HobLib.c
This is a very special case.

Please see the justification in commit ad90df8ac018
("ArmPlatformPkg/ArmVirtualizationPkg: Add private HobLib implementation
for DXE phase", 2014-09-18).

The stock HobLib instance depends on DebugLib, for using the normal
ASSERT() macro.

Furthermore, the stock serial-based DebugLib instance depends on
SerialPortLib, for printing messages.

That produces a HobLib -> DebugLib -> SerialPortLib dependency chain.

But, in case of this particular platform, our SerialPortLib instance
depends on HobLib, for retrieving the particulars of the serial port.
This creates a dependency cycle:

HobLib -> DebugLib -> SerialPortLib -> HobLib

which makes the platform un-buildable.

We had to break the dependency cycle somewhere, and the best (or maybe
only -- I don't recall exactly anymore) link to break was the HobLib ->
DebugLib dependency. We introduced our own HobLib instance, which (IIRC)
was almost identical to the stock one, except that its (only) DebugLib
dependency, namely the ASSERT(), was reimplemented with a plain
CpuDeadLoop(). And so the dependency chain ended up as:

DebugLib -> SerialPortLib -> HobLib

Not circular any more.

and OvmfPkg/Library/XenConsoleSerialPortLib/XenConsoleSerialPortLib.c)
Very similar same case; here we even have a comment:

//
// We can't use DebugLib due to a constructor dependency cycle between DebugLib
// and ourselves.
//

The BaseDebugLibSerialPort instance depends on SerialPortLib, so a
SerialPortLib instance cannot "depend back" on DebugLib, in combination
with BaseDebugLibSerialPort.
There's an additional problem in EDK2 that we never fixed, which is
the fact that constructor dependencies are not transitive across
library implementations that don't have a constructor themselves. For
instance, in the following case

LibA (+)
depends on
LibB (-)
depends on
LibC (+)

where (+) means 'has constructor' and (-) means 'has no constructor',
the EDK2 build tools may emit the LibA and LibC constructor
invocations in any order. However, as soon as you try to fix this, we
end up with circular dependencies all over the place, and none of the
platforms can be built anymore.