Star,
Thanks for the suggestion. I agree that only starting to listen
AcpiTable change event after ReadyToBoot can reduce the ACPI
table parsing times. But the ACPI table parsing just walks through
n * 4 or n * 8 bytes where n is at most 20 or more. Comparing to
the performance the change gains, I prefer to keep the current
fix because it makes the code simpler to read (Your change
needs to hook ReadyToBoot event and hooks AcpiTable change
in ReadyToBoot event callback).

Regards,
Ray


-----Original Message-----
From: Zeng, Star 
Sent: Tuesday, December 22, 2015 12:43 PM
To: Ni, Ruiyu <[email protected]>; [email protected]
Subject: Re: [edk2] [Patch V2] PcAtChipsetPkg/Rtc: Fix a UEFI Win7 boot hang 
issue

On 2015/12/21 22:53, Ruiyu Ni wrote:
> The patch updates the Century value in CMOS location specified
> by FADT.Century to avoid UEFI Win7 hang during booting.
> Per the ACPI spec if the FADT.Century is zero, it's not needed
> to store the century value in CMOS. But UEFI Win7 treats the
> Century storage is optional only when FADT.Century is 0x80.
> While Linux strictly follows the ACPI spec and treats Century
> storage is optional when FADT.Century is 0.
> So if a platform wants to support both UEFI Win7 and Linux,
> it needs to report FADT.Century to a traditional value which
> doesn't equal to 0 or 0x80 (0x32 mostly). And RTC driver is
> enhanced to save the century value to the location specified
> by FADT.Century.
>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Ruiyu Ni <[email protected]>
> Cc: Star Zeng <[email protected]>
> ---
>   PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c | 110 
> +++++++++++++++++++++
>   PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.h |  22 ++++-
>   .../PcatRealTimeClockRuntimeDxe/PcRtcEntry.c       |  26 ++++-
>   .../PcatRealTimeClockRuntimeDxe.inf                |   4 +
>   4 files changed, 158 insertions(+), 4 deletions(-)

Reviewed-by: Star Zeng <[email protected]>

At the same time, in fact, I have a personal suggestion to register 
ReadyToBoot callback that is to get acpi table from configuration table 
and create acpi table event callback at the same for the following acpi 
table change, that can reduce the effort to parse acpi table before 
ReadyToBoot.

Up to you to adopt this suggestion.

Thanks,
Star
>
> diff --git a/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c 
> b/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c
> index 5abb71c..e122ae1 100644
> --- a/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c
> +++ b/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.c
> @@ -500,6 +500,13 @@ PcRtcSetTime (
>     RegisterB.Bits.Set  = 1;
>     RtcWrite (RTC_ADDRESS_REGISTER_B, RegisterB.Data);
>
> +  //
> +  // Store the century value to RTC before converting to BCD format.
> +  //
> +  if (Global->CenturyRtcAddress != 0) {
> +    RtcWrite (Global->CenturyRtcAddress, DecimalToBcd8 ((UINT8) 
> (RtcTime.Year / 100)));
> +  }
> +
>     ConvertEfiTimeToRtcTime (&RtcTime, RegisterB);
>
>     RtcWrite (RTC_ADDRESS_SECONDS, RtcTime.Second);
> @@ -1198,3 +1205,106 @@ IsWithinOneDay (
>     return Adjacent;
>   }
>
> +/**
> +  This function find ACPI table with the specified signature in RSDT or XSDT.
> +
> +  @param Sdt              ACPI RSDT or XSDT.
> +  @param Signature        ACPI table signature.
> +  @param TablePointerSize Size of table pointer: 4 or 8.
> +
> +  @return ACPI table or NULL if not found.
> +**/
> +VOID *
> +ScanTableInSDT (
> +  IN EFI_ACPI_DESCRIPTION_HEADER    *Sdt,
> +  IN UINT32                         Signature,
> +  IN UINTN                          TablePointerSize
> +  )
> +{
> +  UINTN                          Index;
> +  UINTN                          EntryCount;
> +  UINTN                          EntryBase;
> +  EFI_ACPI_DESCRIPTION_HEADER    *Table;
> +
> +  EntryCount = (Sdt->Length - sizeof (EFI_ACPI_DESCRIPTION_HEADER)) / 
> TablePointerSize;
> +
> +  EntryBase = (UINTN) (Sdt + 1);
> +  for (Index = 0; Index < EntryCount; Index++) {
> +    //
> +    // When TablePointerSize is 4 while sizeof (VOID *) is 8, make sure the 
> upper 4 bytes are zero.
> +    //
> +    Table = 0;
> +    CopyMem (&Table, (VOID *) (EntryBase + Index * TablePointerSize), 
> TablePointerSize);
> +    if (Table->Signature == Signature) {
> +      return Table;
> +    }
> +  }
> +
> +  return NULL;
> +}
> +
> +/**
> +  Notification function of ACPI Table change.
> +
> +  This is a notification function registered on ACPI Table change event.
> +  It saves the Century address stored in ACPI FADT table.
> +
> +  @param  Event        Event whose notification function is being invoked.
> +  @param  Context      Pointer to the notification function's context.
> +
> +**/
> +VOID
> +EFIAPI
> +PcRtcAcpiTableChangeCallback (
> +  IN EFI_EVENT        Event,
> +  IN VOID             *Context
> +  )
> +{
> +  EFI_STATUS                                    Status;
> +  EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER  *Rsdp;
> +  EFI_ACPI_DESCRIPTION_HEADER                   *Rsdt;
> +  EFI_ACPI_DESCRIPTION_HEADER                   *Xsdt;
> +  EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE     *Fadt;
> +  EFI_TIME                                      Time;
> +  UINT8                                         Century;
> +
> +  Status = EfiGetSystemConfigurationTable (&gEfiAcpiTableGuid, (VOID **) 
> &Rsdp);
> +  if (EFI_ERROR (Status)) {
> +    Status = EfiGetSystemConfigurationTable (&gEfiAcpi10TableGuid, (VOID **) 
> &Rsdp);
> +  }
> +
> +  if (EFI_ERROR (Status)) {
> +    return;
> +  }
> +
> +  //
> +  // Find FADT in XSDT
> +  //
> +  Fadt = NULL;
> +  if (Rsdp->Revision >= 
> EFI_ACPI_2_0_ROOT_SYSTEM_DESCRIPTION_POINTER_REVISION) {
> +    Xsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->XsdtAddress;
> +    Fadt = ScanTableInSDT (Xsdt, 
> EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, sizeof (UINT64));
> +  }
> +
> +  if (Fadt == NULL) {
> +    //
> +    // Find FADT in RSDT
> +    //
> +    Rsdt = (EFI_ACPI_DESCRIPTION_HEADER *) (UINTN) Rsdp->RsdtAddress;
> +    Fadt = ScanTableInSDT (Rsdt, 
> EFI_ACPI_2_0_FIXED_ACPI_DESCRIPTION_TABLE_SIGNATURE, sizeof (UINT32));
> +  }
> +
> +  if ((Fadt != NULL) &&
> +      (Fadt->Century > RTC_ADDRESS_REGISTER_D) && (Fadt->Century < 0x80) &&
> +      (mModuleGlobal.CenturyRtcAddress != Fadt->Century)
> +      ) {
> +    mModuleGlobal.CenturyRtcAddress = Fadt->Century;
> +    Status = PcRtcGetTime (&Time, NULL, &mModuleGlobal);
> +    if (!EFI_ERROR (Status)) {
> +      Century = (UINT8) (Time.Year / 100);
> +      Century = DecimalToBcd8 (Century);
> +      DEBUG ((EFI_D_INFO, "PcRtc: Write 0x%x to CMOS location 0x%x\n", 
> Century, mModuleGlobal.CenturyRtcAddress));
> +      RtcWrite (mModuleGlobal.CenturyRtcAddress, Century);
> +    }
> +  }
> +}
> diff --git a/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.h 
> b/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.h
> index 026c108..7fc19f9 100644
> --- a/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.h
> +++ b/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtc.h
> @@ -19,6 +19,8 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER 
> EXPRESS OR IMPLIED.
>
>   #include <Uefi.h>
>
> +#include <Guid/Acpi.h>
> +
>   #include <Protocol/RealTimeClock.h>
>
>   #include <Library/BaseLib.h>
> @@ -34,13 +36,15 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER 
> EXPRESS OR IMPLIED.
>   #include <Library/PcdLib.h>
>   #include <Library/ReportStatusCodeLib.h>
>
> -
>   typedef struct {
>     EFI_LOCK  RtcLock;
>     INT16     SavedTimeZone;
>     UINT8     Daylight;
> +  UINT8     CenturyRtcAddress;
>   } PC_RTC_MODULE_GLOBALS;
>
> +extern PC_RTC_MODULE_GLOBALS  mModuleGlobal;
> +
>   #define PCAT_RTC_ADDRESS_REGISTER 0x70
>   #define PCAT_RTC_DATA_REGISTER    0x71
>
> @@ -355,4 +359,20 @@ IsLeapYear (
>     IN EFI_TIME   *Time
>     );
>
> +/**
> +  Notification function of ACPI Table change.
> +
> +  This is a notification function registered on ACPI Table change event.
> +  It saves the Century address stored in ACPI FADT table.
> +
> +  @param  Event        Event whose notification function is being invoked.
> +  @param  Context      Pointer to the notification function's context.
> +
> +**/
> +VOID
> +EFIAPI
> +PcRtcAcpiTableChangeCallback (
> +  IN EFI_EVENT        Event,
> +  IN VOID             *Context
> +  );
>   #endif
> diff --git a/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcEntry.c 
> b/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcEntry.c
> index 9cf3988..6f2a987 100644
> --- a/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcEntry.c
> +++ b/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcRtcEntry.c
> @@ -1,7 +1,7 @@
>   /** @file
>     Provides Set/Get time operations.
>
> -Copyright (c) 2006 - 2008, Intel Corporation. All rights reserved.<BR>
> +Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
>   This program and the accompanying materials
>   are licensed and made available under the terms and conditions of the BSD 
> License
>   which accompanies this distribution.  The full text of the license may be 
> found at
> @@ -14,11 +14,10 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER 
> EXPRESS OR IMPLIED.
>
>   #include "PcRtc.h"
>
> -PC_RTC_MODULE_GLOBALS  mModuleGlobal;
> +PC_RTC_MODULE_GLOBALS  mModuleGlobal = { 0 };
>
>   EFI_HANDLE             mHandle = NULL;
>
> -
>   /**
>     Returns the current time and date information, and the time-keeping 
> capabilities
>     of the hardware platform.
> @@ -133,11 +132,32 @@ InitializePcRtc (
>     )
>   {
>     EFI_STATUS  Status;
> +  EFI_EVENT   Event;
>
>     EfiInitializeLock (&mModuleGlobal.RtcLock, TPL_CALLBACK);
>
>     Status = PcRtcInit (&mModuleGlobal);
>     ASSERT_EFI_ERROR (Status);
> +
> +  Status = gBS->CreateEventEx (
> +                  EVT_NOTIFY_SIGNAL,
> +                  TPL_CALLBACK,
> +                  PcRtcAcpiTableChangeCallback,
> +                  NULL,
> +                  &gEfiAcpi10TableGuid,
> +                  &Event
> +                  );
> +  ASSERT_EFI_ERROR (Status);
> +
> +  Status = gBS->CreateEventEx (
> +                  EVT_NOTIFY_SIGNAL,
> +                  TPL_CALLBACK,
> +                  PcRtcAcpiTableChangeCallback,
> +                  NULL,
> +                  &gEfiAcpiTableGuid,
> +                  &Event
> +                  );
> +  ASSERT_EFI_ERROR (Status);
>
>     gRT->GetTime       = PcRtcEfiGetTime;
>     gRT->SetTime       = PcRtcEfiSetTime;
> diff --git 
> a/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf 
> b/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
> index 9e5faf7..94596ce 100644
> --- 
> a/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
> +++ 
> b/PcAtChipsetPkg/PcatRealTimeClockRuntimeDxe/PcatRealTimeClockRuntimeDxe.inf
> @@ -57,6 +57,10 @@
>   [Protocols]
>     gEfiRealTimeClockArchProtocolGuid             ## PRODUCES
>
> +[Guids]
> +  gEfiAcpi10TableGuid                           ## CONSUMES
> +  gEfiAcpiTableGuid                             ## CONSUMES
> +
>   [Depex]
>     gEfiVariableArchProtocolGuid AND gEfiVariableWriteArchProtocolGuid
>
>

_______________________________________________
edk2-devel mailing list
[email protected]
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to