Platform/Intel: Add Cmos related modules to BoardModulePkg

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

Add Cmos related libraries to BoardModulePkg. Totally two
library have been added, one is CmosAccessLib and the other
is PlatformCmosAccessLib. PlatformCmosAccessLib will be used
by CmosAccessLib.

These two libraries provide the generic operations for CMOS
access.

APIs exports by PlatformCmosAccessLib include:
  PlatformCmosGetEntry
  PlatformCmosGetNmiState

APIs exports by CmosAccessLib include:
  CmosRead8
  CmosWrite8
  CmosRead16
  CmosWrite16
  CmosRead32
  CmosWrite32
  CmosInit

Cc: Michael Kubacki <michael.a.kubacki@intel.com>
Cc: Sai Chaganty <rangasai.v.chaganty@intel.com>
Cc: Oram Isaac W <isaac.w.oram@intel.com>
Sign-off-by: Eric Dong <eric.dong@intel.com>
Reviewed-by: Liming Gao <liming.gao@intel.com>
Signed-off-by: Eric Dong <eric.dong@intel.com>
This commit is contained in:
Eric Dong
2019-05-24 13:42:45 +08:00
parent e5ad5d1b6c
commit ffaa0b2bcd
9 changed files with 794 additions and 2 deletions

View File

@@ -21,6 +21,12 @@
[Includes]
Include
[LibraryClasses]
## @libraryclass Provide services to access CMOS area.
CmosAccessLib|Include/Library/CmosAccessLib.h
## @libraryclass Provide platform relevant services to access CMOS area.
PlatformCmosAccessLib|Include/Library/PlatformCmosAccessLib.h

View File

@@ -71,4 +71,5 @@
###################################################################################################
[Components]
BoardModulePkg/Library/CmosAccessLib/CmosAccessLib.inf
BoardModulePkg/Library/PlatformCmosAccessLibNull/PlatformCmosAccessLibNull.inf

View File

@@ -0,0 +1,106 @@
/** @file
CmosAccessLib header file.
Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef _CMOS_ACCESS_LIB_H_
#define _CMOS_ACCESS_LIB_H_
/**
Read a byte value from a CMOS address.
@param [in] Address Location to read from CMOS
@return The byte value read from the CMOS address.
**/
UINT8
EFIAPI
CmosRead8 (
IN UINT8 Address
);
/**
Write a byte value to a CMOS address.
@param [in] Address Location to write to CMOS.
@param [in] Data The byte value write to the CMOS address.
**/
VOID
EFIAPI
CmosWrite8 (
IN UINT8 Address,
IN UINT8 Data
);
/**
Read a word value from a CMOS address.
@param [in] Address Location to read from CMOS
@return The word value read from the CMOS address.
**/
UINT16
EFIAPI
CmosRead16 (
IN UINT8 Address
);
/**
Write a word value to a CMOS address.
@param [in] Address Location to write to CMOS.
@param [in] Data The word value write to the CMOS address.
**/
VOID
EFIAPI
CmosWrite16 (
IN UINT8 Address,
IN UINT16 Data
);
/**
Read a dword value from a CMOS address.
@param [in] Address Location to read from CMOS
@return The dword value read from the CMOS address.
**/
UINT32
EFIAPI
CmosRead32 (
IN UINT8 Address
);
/**
Write a dword value to a CMOS address.
@param [in] Address Location to write to CMOS.
@param [in] Data The dword value write to the CMOS address.
**/
VOID
EFIAPI
CmosWrite32 (
IN UINT8 Address,
IN UINT32 Data
);
/**
Initialize the CMOS.
It initialize the CMOS area when Force is TRUE or the checksum is incorrect.
@param[in] Force TRUE indicating initializing the CMOS area without checking the checksum.
@retval TRUE The CMOS is initialized to default value.
@retval FALSE The CMOS isn't initialized to default value.
**/
BOOLEAN
EFIAPI
CmosInit (
IN BOOLEAN Force
);
#endif // _CMOS_ACCESS_LIB_H_

View File

@@ -0,0 +1,68 @@
/** @file
Platform CMOS Access Library Header File.
Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef _PLATFORM_CMOS_ACCESS_LIB_H_
#define _PLATFORM_CMOS_ACCESS_LIB_H_
///
/// Flag indicating checksum calculation doesn't include this location.
/// NOTE: If a location isn't shown in platform CMOS entry table,
/// it means checksum calculation doesn't include the location.
///
#define CMOS_EXCLUDE_FROM_CHECKSUM BIT0
///
/// Flag indicating initialization doesn't cover this location.
/// NOTE: If a location isn't shown in platform CMOS entry table,
/// it means the location is initialized with CMOS_DEFAULT_VALUE (0).
///
#define CMOS_EXCLUDE_FROM_INIT_DATA BIT1
///
/// Flag indicating the location cannot be accessed.
/// NOTE: 0x0 ~ 0xD is implictly inaccessible.
///
#define CMOS_EXCLUDE_FROM_ACCESS (BIT3 | CMOS_EXCLUDE_FROM_CHECKSUM | CMOS_EXCLUDE_FROM_INIT_DATA)
///
/// Flag indicating the checksum location
/// NOTE: At most two entries can have this flag set.
///
#define CMOS_CHECKSUM_LOCATION (BIT2 | CMOS_EXCLUDE_FROM_CHECKSUM | CMOS_EXCLUDE_FROM_INIT_DATA)
#define CMOS_DEFAULT_VALUE 0x00
typedef struct {
UINT8 Address;
UINT8 DefaultValue;
UINT8 Attributes;
} CMOS_ENTRY;
/**
Return the platform CMOS entries.
@param [out] EntryCount Return the count of platform CMOS entries.
@return Platform CMOS entries.
**/
CMOS_ENTRY *
EFIAPI
PlatformCmosGetEntry (
OUT UINTN *EntryCount
);
/**
Return the NMI enable status.
**/
BOOLEAN
EFIAPI
PlatformCmosGetNmiState (
VOID
);
#endif // _PLATFORM_CMOS_ACCESS_LIB_H_

View File

@@ -0,0 +1,486 @@
/** @file
CmosAccessLib implementation.
Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include "CmosAccessLibInternal.h"
/**
Return the entry for the specified address in entries returned
from platform.
@param [in] Address The CMOS address to find.
@return A pointer to CMOS_ENTRY for the specified address,
or NULL if not found.
**/
CMOS_ENTRY *
CmosAccessLibLocateEntry (
IN UINT8 Address
)
{
UINTN Index;
UINTN Count;
CMOS_ENTRY *Entries;
Entries = PlatformCmosGetEntry (&Count);
for (Index = 0; Index < Count; Index++) {
if (Entries[Index].Address == Address) {
return &Entries[Index];
}
}
return NULL;
}
/**
Test the attributes of the Entry and return ValueIfSet if test passes
or !ValueIfSet if test fails. It returns DefaultValue if the Entry is
NULL.
@param [in] Address The CMOS address.
@param [in] Attributes The attributes to test.
@param [in] ValueIfSet The value to return if test passes.
@param [in] DefaultValue The value to return if Entry is NULL.
@param [in] Entry Pointer to entry.
@retval ValueIfSet If test passes.
@retval !ValueIfSet If test fails.
@retval DefaultValue If the Entry is NULL.
**/
BOOLEAN
CmosAccessLibCheckAttribute (
IN UINT8 Address,
IN UINT8 Attributes,
IN BOOLEAN ValueIfSet,
IN BOOLEAN DefaultValue,
IN CMOS_ENTRY *Entry OPTIONAL
)
{
if (Entry != NULL) {
ASSERT (Entry->Address == Address);
if ((Entry->Attributes & Attributes) == Attributes) {
return ValueIfSet;
} else {
return !ValueIfSet;
}
}
return DefaultValue;
}
/**
Check if the CMOS address needs Checksum calculation.
@param [in] Address CMOS address to be checked
@param [in] Entry Pointer to entry.
@retval TRUE CMOS address needs Checksum calculation.
@retval FALSE CMOS address doesn't need Checksum calculation.
**/
BOOLEAN
CmosAccessLibNeedChecksum (
IN UINT8 Address,
IN CMOS_ENTRY *Entry OPTIONAL
)
{
return CmosAccessLibCheckAttribute (Address, CMOS_EXCLUDE_FROM_CHECKSUM, FALSE, FALSE, Entry);
}
/**
Check if the CMOS address needs to fill default data.
@param [in] Address CMOS address to be checked
@param [in] Entry Pointer to entry.
@retval TRUE CMOS address need to fill default data.
@retval FALSE CMOS address doesn't need to fill default data.
**/
BOOLEAN
CmosAccessLibNeedFillDefault (
IN UINT8 Address,
IN CMOS_ENTRY *Entry OPTIONAL
)
{
return CmosAccessLibCheckAttribute (Address, CMOS_EXCLUDE_FROM_INIT_DATA, FALSE, TRUE, Entry);
}
/**
Check if the CMOS address is accessible.
@param [in] Address CMOS address to be checked.
@param [in] Entry Pointer to entry.
@retval TRUE CMOS address is accessible.
@retval FALSE CMOS address isn't accessible.
**/
BOOLEAN
CmosAccessLibIsAccessible (
IN UINT8 Address,
IN CMOS_ENTRY *Entry OPTIONAL
)
{
//
// CMOS 0-9, A, B, C, D are for RTC.
//
if (Address <= 0xD) {
return FALSE;
}
return CmosAccessLibCheckAttribute (Address, CMOS_EXCLUDE_FROM_ACCESS, FALSE, TRUE, Entry);
}
/**
Return the CMOS location to store checksum.
@param [out] Location Return the CMOS location to store the checksum.
**/
VOID
CmosAccessLibGetChecksumLocation (
OUT CMOS_CHECKSUM_LOCATION_INFO *Location
)
{
UINTN Index;
UINTN Count;
CMOS_ENTRY *Entries;
Location->Length = 0;
Entries = PlatformCmosGetEntry (&Count);
for (Index = 0; Index < Count; Index++) {
if ((Entries[Index].Attributes & CMOS_CHECKSUM_LOCATION) == CMOS_CHECKSUM_LOCATION) {
Location->Length++;
if (Location->Length == 1) {
Location->LowByteAddress = Entries[Index].Address;
} else if (Location->Length == 2) {
Location->HighByteAddress = Entries[Index].Address;
break;
}
}
}
ASSERT (Location->Length <= 2);
}
/**
Calculate the sum of CMOS values who need checksum calculation.
@param [in] Location The CMOS location to store the checksum.
@return The sum.
**/
UINT16
CmosAccessLibCalculateSum (
IN CMOS_CHECKSUM_LOCATION_INFO *Location
)
{
UINT16 Sum;
UINTN Index;
UINTN Count;
CMOS_ENTRY *Entries;
if (Location->Length == 0) {
return 0;
}
Sum = 0;
Entries = PlatformCmosGetEntry (&Count);
for (Index = 0; Index < Count; Index++) {
if (CmosAccessLibNeedChecksum (Entries[Index].Address, &Entries[Index])) {
Sum += CmosRead8 (Entries[Index].Address);
}
}
if (Location->Length == 1) {
return (UINT8) Sum;
} else {
return Sum;
}
}
/**
Return the checksum value stored in CMOS.
@param [in] Location The CMOS location to store the checksum.
@return The checksum value.
**/
UINT16
CmosAccessLibReadChecksum (
IN CMOS_CHECKSUM_LOCATION_INFO *Location
)
{
UINT16 Checksum;
Checksum = 0;
switch (Location->Length) {
case 2:
Checksum = (CmosRead8 (Location->HighByteAddress) << 8);
//
// Fall to case 1 to get the low byte value
//
case 1:
Checksum += CmosRead8 (Location->LowByteAddress);
break;
default:
break;
}
return Checksum;
}
/**
Write the Checksum to appropriate address.
@param [in] Location The CMOS location to store the checksum.
@param [in] Checksum The checksum value.
**/
VOID
CmosAccessLibWriteChecksum (
CMOS_CHECKSUM_LOCATION_INFO *Location,
IN UINT16 Checksum
)
{
switch (Location->Length) {
case 0:
break;
case 2:
CmosWrite8 (Location->HighByteAddress, Checksum >> 8);
//
// Fall to case 1 to update low byte value
//
case 1:
CmosWrite8 (Location->LowByteAddress, (UINT8) Checksum);
break;
}
}
/**
Read a byte value from a CMOS address.
@param [in] Address Location to read from CMOS
@return The byte value read from the CMOS address.
**/
UINT8
EFIAPI
CmosRead8 (
IN UINT8 Address
)
{
if (!CmosAccessLibIsAccessible (Address, CmosAccessLibLocateEntry (Address))) {
return 0xFF;
}
if (Address <= CMOS_BANK0_LIMIT) {
if (PlatformCmosGetNmiState ()) {
Address |= BIT7;
}
IoWrite8 (PORT_70, Address);
return IoRead8 (PORT_71);
} else {
IoWrite8 (PORT_72, Address);
return IoRead8 (PORT_73);
}
}
/**
Write a byte value to a CMOS address.
It's an internal function that doesn't update the checksum.
@param [in] Address Location to write to CMOS.
@param [in] Data The byte value write to the CMOS address.
**/
VOID
CmosAccessLibICmosWrite8 (
IN UINT8 Address,
IN UINT8 Data
)
{
if (Address <= CMOS_BANK0_LIMIT) {
if (PlatformCmosGetNmiState ()) {
Address |= BIT7;
}
IoWrite8 (PORT_70, Address);
IoWrite8 (PORT_71, Data);
} else {
IoWrite8 (PORT_72, Address);
IoWrite8 (PORT_73, Data);
}
}
/**
Write a byte value to a CMOS address.
@param [in] Address Location to write to CMOS.
@param [in] Data The byte value write to the CMOS address.
**/
VOID
EFIAPI
CmosWrite8 (
IN UINT8 Address,
IN UINT8 Data
)
{
UINT8 OriginalData;
CMOS_ENTRY *Entry;
CMOS_CHECKSUM_LOCATION_INFO ChecksumLocation;
Entry = CmosAccessLibLocateEntry (Address);
if (!CmosAccessLibIsAccessible (Address, Entry)) {
return;
}
OriginalData = CmosRead8 (Address);
CmosAccessLibICmosWrite8 (Address, Data);
if (CmosAccessLibNeedChecksum (Address, Entry)) {
//
// Sum of Data + Checksum = New Sum of Data + New Checksum = 0
// New Sum of Data - Sum of Data = Checksum - New Checksum
// New Checksum = Checksum - (New Sum of Data - Sum of Data)
//
CmosAccessLibGetChecksumLocation (&ChecksumLocation);
CmosAccessLibWriteChecksum (
&ChecksumLocation,
CmosAccessLibReadChecksum (&ChecksumLocation) - (Data - OriginalData)
);
}
}
/**
Read a word value from a CMOS address.
@param [in] Address Location to read from CMOS
@return The word value read from the CMOS address.
**/
UINT16
EFIAPI
CmosRead16 (
IN UINT8 Address
)
{
return CmosRead8 (Address) + (CmosRead8 (Address + 1) << 8);
}
/**
Write a word value to a CMOS address.
@param [in] Address Location to write to CMOS.
@param [in] Data The word value write to the CMOS address.
**/
VOID
EFIAPI
CmosWrite16 (
IN UINT8 Address,
IN UINT16 Data
)
{
CmosWrite8 (Address, (UINT8) Data);
CmosWrite8 (Address + 1, (UINT8) (Data >> 8));
}
/**
Read a dword value from a CMOS address.
@param [in] Address Location to read from CMOS
@return The dword value read from the CMOS address.
**/
UINT32
EFIAPI
CmosRead32 (
IN UINT8 Address
)
{
return CmosRead16 (Address) + (CmosRead16 (Address + 2) << 16);
}
/**
Write a dword value to a CMOS address.
@param [in] Address Location to write to CMOS.
@param [in] Data The dword value write to the CMOS address.
**/
VOID
EFIAPI
CmosWrite32 (
IN UINT8 Address,
IN UINT32 Data
)
{
CmosWrite16 (Address, (UINT16) Data);
CmosWrite16 (Address + 2, (UINT16) (Data >> 16));
}
/**
Initialize the CMOS.
It initialize the CMOS area when Force is TRUE or the checksum is incorrect.
@param[in] Force TRUE indicating initializing the CMOS area without checking the checksum.
@retval TRUE The CMOS is initialized to default value.
@retval FALSE The CMOS isn't initialized to default value.
**/
BOOLEAN
EFIAPI
CmosInit (
IN BOOLEAN Force
)
{
UINTN Address;
CMOS_ENTRY *Entry;
CMOS_CHECKSUM_LOCATION_INFO ChecksumLocation;
UINT16 Checksum;
CmosAccessLibGetChecksumLocation (&ChecksumLocation);
if (!Force) {
//
// Initialize the CMOS area when checksum is incorrect.
//
Checksum = CmosAccessLibCalculateSum (&ChecksumLocation) + CmosAccessLibReadChecksum (&ChecksumLocation);
if (ChecksumLocation.Length == 1) {
Checksum = (UINT8) Checksum;
}
if (Checksum != 0) {
Force = TRUE;
}
}
if (Force) {
//
// Traverse through entire CMOS location and fill it with zero
//
for (Address = 0; Address <= CMOS_BANK1_LIMIT; Address++) {
Entry = CmosAccessLibLocateEntry ((UINT8) Address);
if (CmosAccessLibNeedFillDefault ((UINT8) Address, Entry)) {
CmosAccessLibICmosWrite8 ((UINT8) Address, (Entry == NULL) ? CMOS_DEFAULT_VALUE : Entry->DefaultValue);
}
}
//
// Write the New checksum to the Checksum field
//
CmosAccessLibWriteChecksum (
&ChecksumLocation,
(UINT16) (0x10000 - CmosAccessLibCalculateSum (&ChecksumLocation))
);
return TRUE;
}
return FALSE;
}

View File

@@ -0,0 +1,28 @@
### @file
# Library producing CMOS access functionality.
#
# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
###
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = CmosAccessLib
FILE_GUID = FF6B645D-C001-4ACE-9CA1-199F97C2D601
VERSION_STRING = 1.0
MODULE_TYPE = BASE
LIBRARY_CLASS = CmosAccessLib
[Sources]
CmosAccessLib.c
CmosAccessLibInternal.h
[LibraryClasses]
IoLib
DebugLib
PlatformCmosAccessLib
[Packages]
MdePkg/MdePkg.dec
BoardModulePkg/BoardModulePkg.dec

View File

@@ -0,0 +1,35 @@
/** @file
CmosAccessLib internal header file.
Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#ifndef _CMOS_ACCESS_LIB_INTERNALS_
#define _CMOS_ACCESS_LIB_INTERNALS_
#include <Base.h>
#include <Uefi.h>
#include <Library/IoLib.h>
#include <Library/DebugLib.h>
#include <Library/CmosAccessLib.h>
#include <Library/PlatformCmosAccessLib.h>
// CMOS access Port address
#define PORT_70 0x70
#define PORT_71 0x71
#define PORT_72 0x72
#define PORT_73 0x73
#define CMOS_BANK0_LIMIT 0x7F
#define CMOS_BANK1_LIMIT 0xFF
typedef struct {
UINT8 Length;
UINT8 LowByteAddress;
UINT8 HighByteAddress;
} CMOS_CHECKSUM_LOCATION_INFO;
#endif // _CMOS_ACCESS_LIB_INTERNALS_

View File

@@ -0,0 +1,39 @@
/** @file
Platform CMOS Access Library.
Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
**/
#include <Base.h>
#include <Library/PlatformCmosAccessLib.h>
/**
Return the platform CMOS entries.
@param [out] EntryCount Return the count of platform CMOS entries.
@return Platform CMOS entries.
**/
CMOS_ENTRY *
EFIAPI
PlatformCmosGetEntry (
OUT UINTN *EntryCount
)
{
*EntryCount = 0;
return NULL;
}
/**
Return the NMI enable status.
**/
BOOLEAN
EFIAPI
PlatformCmosGetNmiState (
VOID
)
{
return FALSE;
}

View File

@@ -0,0 +1,23 @@
### @file
# Library producing CMOS access functionalities are relevant to platform.
#
# Copyright (c) 2019, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#
###
[Defines]
INF_VERSION = 0x00010005
BASE_NAME = PlatformCmosAccessLib
FILE_GUID = C315A8B6-FF6C-41D1-A934-7330501F308C
VERSION_STRING = 1.0
MODULE_TYPE = BASE
LIBRARY_CLASS = PlatformCmosAccessLib
[Sources]
PlatformCmosAccessLibNull.c
[Packages]
MdePkg/MdePkg.dec
BoardModulePkg/BoardModulePkg.dec