summaryrefslogtreecommitdiff
path: root/Core/EM/SMBIOS/SmbiosDMIEditSupport/SmbiosDMIEditFunc.c
diff options
context:
space:
mode:
Diffstat (limited to 'Core/EM/SMBIOS/SmbiosDMIEditSupport/SmbiosDMIEditFunc.c')
-rw-r--r--Core/EM/SMBIOS/SmbiosDMIEditSupport/SmbiosDMIEditFunc.c4176
1 files changed, 4176 insertions, 0 deletions
diff --git a/Core/EM/SMBIOS/SmbiosDMIEditSupport/SmbiosDMIEditFunc.c b/Core/EM/SMBIOS/SmbiosDMIEditSupport/SmbiosDMIEditFunc.c
new file mode 100644
index 0000000..6c1af45
--- /dev/null
+++ b/Core/EM/SMBIOS/SmbiosDMIEditSupport/SmbiosDMIEditFunc.c
@@ -0,0 +1,4176 @@
+//**********************************************************************//
+//**********************************************************************//
+//** **//
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **//
+//** **//
+//** All Rights Reserved. **//
+//** **//
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **//
+//** **//
+//** Phone: (770)-246-8600 **//
+//** **//
+//**********************************************************************//
+//**********************************************************************//
+
+//**********************************************************************//
+// $Header: /Alaska/SOURCE/Modules/SMBIOS/SmbiosDMIEditSupport/SmbiosDMIEditFunc.c 69 4/07/16 6:03p Davidd $
+//
+// $Revision: 69 $
+//
+// $Date: 4/07/16 6:03p $
+//**********************************************************************//
+// Revision History
+// ----------------
+// $Log: /Alaska/SOURCE/Modules/SMBIOS/SmbiosDMIEditSupport/SmbiosDMIEditFunc.c $
+//
+// 69 4/07/16 6:03p Davidd
+// [TAG] EIP231162
+// [Category] New Feature
+// [Description] Merge Aptio V Smbios -09 changes for Aptio 4
+// 4.6.5.5_SMBIOS_40 release
+// [Files] Smbios.c
+// SmbiosDmiEdit.c
+// SmbiosDmiEditFunc.c
+//
+// 68 4/04/16 11:43a Davidd
+// [TAG] EIP262865
+// [Category] Improvement
+// [Description] [APTIO4][Smbios]DmiEdit needs changes as smiflash
+// protocol is being changed to deny calls with Smm buffer
+// [Files] SmbiosDMIEdit.mak
+// SmbiosDMIEdit.h
+// SmbiosDMIEdit.c
+// SmbiosDMIEditFunc.c
+//
+// 67 11/25/14 12:50p Davidd
+// [TAG] EIP193846
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Generic changes for EIP187631
+// [RootCause] Function isWriteOnce is called even when the input
+// control is zero case (for validating the parameters)
+// [Solution] Excecute function isWriteOnce only if input control is set
+// [Files] SmbiosDMIEditFunc.c
+//
+// 66 8/11/14 10:46a Davidd
+// [TAG] EIP177887
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Build error if token "SYS_CHASSIS_INFO" set to "0"
+// [RootCause] Build error caused by non-existence token when
+// SYS_CHASSIS_INFO is disabled
+// [Solution] Added preprocessor checks
+// [Files] Smbios.c - File version: 153
+// SmbiosDmiEditFunc.c
+//
+// 65 8/08/14 3:50p Davidd
+// [TAG] EIP180676
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] UUID Updated by 3rd party DMI/SMBIOS tools is not working.
+// [RootCause] UUID is updated 4 bytes at a time instead of 16
+// [Solution] Modified code to handle all update types (1, 2, or 4
+// bytes) as 16 bytes
+// [Files] SmbiosDMIEditFunc.c
+//
+// 64 12/05/13 12:05p Davidd
+//
+// 63 11/15/13 4:34p Davidd
+// [TAG] EIP143321
+// [Category] Improvement
+// [Description] Perform "CppCheck" on Smbios module for
+// '4.6.5.1_SMBIOS_36' release
+// [Files] SmbiosBoard.c
+// Smbios.c
+// SmbiosDMIEdit.c
+// SmbiosDMIEditFunc.c
+// SmbiosNvramFunc.c
+//
+// 62 10/07/13 1:23p Davidd
+// [TAG] EIP129122
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Purchase date is not updated in DMI Data area of NCB
+// [RootCause] Old data is not cleared when new data size is smaller
+// than existing one
+// [Solution] Clear old data when new data size is smaller than existing
+// one
+// [Files] SmbiosDMIEditFunc.c
+//
+// 61 9/25/13 2:51p Davidd
+// [TAG] EIP136093
+// [Category] New Feature
+// [Description] SMBIOS Type0 offest 04 can't update by AMIDEDOS
+// [Files] SmbiosDMIEditFunc.c
+//
+// 60 8/23/13 6:28p Davidd
+// [TAG] EIP132364
+// [Category] Improvement
+// [Description] DMIEdit fails to update in the following cases:
+// 1. When current string is NULL
+// 2. When structure is created by OEM
+// 3. When structure is created with strings not numbered sequentially
+// [Files] Smbios.c
+// SmbiosDMIEditFunc.c
+//
+// 59 6/03/13 6:26p Davidd
+// [TAG] EIP125665
+// [Category] New Feature
+// [Description] Request to Support multiple instances of SMBIOS Type 3
+// structure (merge EIP106206 into Aptio 4)
+// [Files] Smbdata.mac
+// SmbiosStaticData.sdl
+// Smbstruc.def
+// Smbios.c
+// SmbiosDMIEditFunc.c
+// Smbios.h
+//
+// 58 5/23/13 2:41p Davidd
+// [TAG] EIP104836
+// [Category] New Feature
+// [Description] DMIEdit support edit type 4
+// [Files] SmbiosBoard.c
+// SmbiosDMIEditBoard.sdl
+// Smbios.c
+// SmbiosDMIEditFunc.c
+// Smbios.h
+// SmbiosDynamicData.h
+//
+// 57 2/28/13 3:10p Davidd
+// [TAG] EIP115031
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] NVRAM data corruption
+// [RootCause] In UpdateSmbiosTable function, FlashDataOffset is
+// incorrectly calculated for certain case
+// [Solution] Corrected code.
+// [Files] SmbiosDMIEditFunc.c
+//
+// 56 1/16/13 10:49a Davidd
+// [TAG] EIP110905
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] AMI DMIEDIT_DOS tool issue (Type 11 fails to update)
+// [RootCause] Problem is caused by recent change for EIP96221 where a
+// line of code
+// was inadvertently left out when function SetType11 was
+// simplified
+// [Solution] Corrected missing code
+// [Files] SmbiosDMIEditFunc.c
+//
+// 55 8/02/12 12:45p Davidd
+// [TAG] EIP96064
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] SMBIOS: DmiEdit support creates NVRAM variables with names
+// of incorrect length
+// [RootCause] Swprintf_s function creates 15 characters variable name
+// with NULL terminator in last byte.
+// [Solution] Use Swprintf function instead
+// [Files] Smbios.c
+// SmbiosDMIEditFunc.c
+// SmbiosNvramFunc.c
+//
+// 54 7/27/12 2:56p Davidd
+// [TAG] EIP96221
+// [Category] Bug Fix
+// [Severity] Minor
+// [Symptom] Smbios DmiEdit: Nvram variables store extraneous data for
+// fixed-length structure change.
+// [RootCause] Input "DataLength" field is used for data size, but this
+// field is not valid for fixed-size data change
+// [Solution] Added code to determine data size based on input command
+// byte
+// [Files] SmbiosDMIEditFunc.c
+//
+// 53 6/12/12 3:54p Davidd
+// [TAG] EIP89994
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] UpdateSmbiosTable function in SmbiosDMIEdit.c seems have
+// problem to handle
+// [RootCause] Data not checked for cross boundary
+// [Solution] Added code to check for cross boundary and update flash
+// block accordingly.
+// [Files] SmbiosDMIEditFunc.c
+//
+// 52 6/12/12 11:30a Davidd
+// [TAG] EIP92073
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] "write once" not updating properly for multiple instances
+// of the same structure type using AMI DmiEdit tool
+// [RootCause] Write-once implementation only supported single instance
+// of a structure.
+// [Solution] Changes made to support more than one instance of a given
+// structure.
+// [Files] SmbiosDMIEdit.h
+// SmbiosDMIEditFunc.c
+//
+// 51 6/08/12 6:03p Davidd
+// [TAG] EIP88664
+// [Category] New Feature
+// [Description] Need tool to update smbios information
+// [Files] SmbiosDMIEdit.c
+// SmbiosDMIEdit.h
+// SmbiosDMIEdit.sdl
+// SmbiosDMIEditFunc.c
+//
+// 50 6/06/12 3:09p Davidd
+// [TAG] EIP81954
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] WriteOnceTable is not supported when
+// SMBIOS_DMIEDIT_DATA_LOC is 2
+// [RootCause] WriteOnce is not properly checked
+// [Solution] Changes added to check for WriteOnce status
+// [Files] SmbiosDMIEdit.c
+// SmbiosDMIEditFunc.c
+//
+// 49 4/17/12 10:39a Davidd
+// [TAG] EIP86776
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Build error if "OEM_STRING_INFO" token is set to "0"
+// [RootCause] SMBIOS_OEM_STRINGS_INFO definition is used even when
+// OEM_STRING_INFO is disabled.
+// [Solution] Removed reference to "SMBIOS_OEM_STRINGS_INFO" in
+// "GetStructureLength" function (not really needed).
+// [Files] Smbios.c
+// SmbiosDMIEditFunc.c
+//
+// 48 11/17/11 2:41p Davidd
+// [TAG] EIP74579
+// [Category] Improvement
+// [Description] Update SMBIOS moudule to let AMDELNX support SMBIOS
+// spec 2.7
+// (remove the 64 characters string limitation)
+// [Files] Smbios.h
+// SmbiosStaticData.sdl
+// Smbios.c
+// SMBios.dxs
+// SmbiosDMIEdit.sdl
+// SmbiosDMIEdit.h
+// SmbiosDMIEditFunc.c
+// SmbiosNvram.c
+// SmbiosFlashData.sdl
+//
+// 45 10/06/11 4:47p Davidd
+// EIP65648 extended change.
+//
+// 44 9/29/11 4:39p Davidd
+// [TAG] EIP68202
+// [Category] NEW FEATURE
+// [Description] Allow Smbios Type 2 Location field and Type 3 SKU
+// Number field
+// to be apdated by dmieditwingui tool
+// [Files] Smbios.c
+// SmbiosDMIEditFunc.c
+// Smbdata.mac
+//
+// 43 8/30/11 4:14p Davidd
+// [TAG] EIP65648
+// [Category] Improvement
+// [Description] Update SMBIOS eModules for uEFI 2.3.1 / PI 1.2
+// compliance
+// [Files] Smbios.c
+// Smbios.dxs
+// SmbiosDMIEdit.c
+// SmbiosDMIEditFunc.c
+// SmbiosGetFlashData.c
+// SmbiosGetFlashData.dxs
+//
+// 42 8/03/11 10:53a Davidd
+// [TAG] EIP64029
+// [Category] NEW FEATURE
+// [Description] Allow SMBIOS Type 22 to be modified using DMIEdit
+// [Files] Smbios.h
+// Smbios.c
+// SmbiosDmieditFunc.c
+//
+// 41 5/11/11 12:34p Davidd
+// [TAG] EIP58171
+// [Category] Bug Fix
+// [Severity] Important
+// [Symptom] TABLE_INFO structure of SmbiosDMIEdit is not backward
+// compatible for AFU preserve DMI structure feature.
+// [RootCause] TABLE_INFO structure of SmbiosDMIEdit is not backward
+// compatible.
+// [Solution] New TABLE_INFO structure defined for backward
+// compatibility and support added.
+// [Files] Smbios.c
+// SmbiosDMIEdit.h
+// SmbiosDMIEditFunc.c
+// SmbiosGetFlashData.c
+//
+// 40 5/04/11 3:19p Davidd
+// [TAG] EIP57144
+// [Category] NEW FEATURE
+// [Description] Allow SMBIOS Type 39 to be modified using DMIEdit
+// [Files] SmbiosBoard.c
+// Smbios.h
+// SmbiosDynamicData.h
+// Smbios.c
+// SmbiosDmieditFunc.c
+// SmbiosNvramFunc.c
+//
+// 39 3/16/11 3:37p Davidd
+// [TAG] EIP53939
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] SMBIOS DMIEdit Driver always assumes FLASH_BLOCK_SIZE =
+// 64KB
+// [RootCause] Block size was assumed to be 64K
+// [Solution] Problem has been fixed with code changes
+// [Files] SmbiosDMIEdit.c
+// SmbiosDMIEditFunc.c
+//
+// 38 3/02/11 11:45a Davidd
+// [TAG] EIP54264
+// [Category] Bug Fix
+// [Severity] Normal
+// [Symptom] Data is assumed valid without checking after some
+// GetVariable calls
+// [RootCause] No error checking
+// [Solution] Problem has been fixed with code changes
+// [Files] SmbiosNvramFunc.c
+// SmbiosDMIEditFunc.c
+//
+// 37 12/14/10 3:40p Davidd
+// Updated StringType_3 table to include SKU string field.
+//
+// 36 11/02/10 4:13p Davidd
+// [TAG] EIP42938
+// [Category] BUG FIX
+// [Severity] Critical
+// [Symptom] The SMBIOS string field cannot be successfully updated
+// if it was programmed to Null by the 3-party SMBIOS tool
+// [RootCause] BIOS did not have support for NULL strings
+// [Solution] Problem has been fixed with code changes
+// [Files]
+// Smbios.c
+// SmbiosDMIEditFunc.c
+// SmbiosGetFlashData.c
+// SmbiosDMIEdit.h
+// SmbiosFlashData.sdl
+//
+// 35 10/21/10 11:36a Davidd
+// [TAG] EIP46394
+// [Category] BUG FIX
+// [Severity] Important
+// [Symptom] Incorrect variable size for GetVariable() usage in
+// Smbios module
+// [RootCause] GetVariable is called with incorrect "DataSize" type.
+// [Solution] Corrected "DataSize" type in all GetVariable calls.
+// [Files]
+// Smbios.c
+// SmbiosDMIEditFunc.c
+// SmbiosNvramFunc.c
+//
+// 34 5/18/10 5:13p Davidd
+// Added PnP function 52h commands 3 and 4 support - EIP 38010.
+//
+// 33 3/08/10 3:48p Davidd
+// Corrected Type1 UUID update problem with customer utility (update by
+// dword instead of block command) - EIP 35486
+//
+// 32 2/12/10 3:59p Davidd
+// Added conditional compile switch for Type 12 - EIP 34631
+// Same were added for Type 2, 3, and 11.
+//
+// 31 11/23/09 5:51p Davidd
+// Corrected the DMIEdit data not updated after being updated 5-6 times
+// (when NVRAM is used to store DMIEdit data) - EIP 30837.
+//
+// 30 8/05/09 6:19p Davidd
+// Added DMIEDIT support for Type 0 and Type 12 structures - EIP 24878
+//
+// 29 6/02/09 11:21a Davidd
+// Updated function headers. (EIP 22180)
+//
+// 28 2/13/09 10:43a Davidd
+// Changes made to return the SMBIOS table size in dmiStorageSize for
+// SMBIOS PnP function 50h (EIP 19115)
+//
+// 27 2/02/09 4:36p Davidd
+// Fixed the problem updating the existing DMIEdit data when FV_MAIN is
+// used for storage.
+//
+// 26 1/28/09 11:53a Davidd
+// New changes added to support DMIEdit data storage location in flash
+// selectable via SMBIOS_DMIEDIT_DATA_LOC SDL token
+//
+// 25 12/16/08 2:24a Iminglin
+// (EIP17767) The function value of GetStructureByHandleThenUpdateHandle
+// for compliance.
+//
+// 24 11/14/08 3:29p Davidd
+// - Changed header blocks
+// - Corrected build error when NUMBER_OF_BLOCKS is a large number.
+//
+// 23 2/13/08 12:57p Davidd
+// Fixed getting SMBIOS structure type 127 problem.
+//
+// 22 1/03/08 12:30p Olegi
+// Fix in GET_SMBIOS_INFO structure for x64 projects.
+//
+// 21 11/26/07 11:39a Davidd
+// Changes added to allow "Asset Tag" in Type 2 structure to be updated
+// per EIP 11283.
+//
+// 20 9/06/07 10:55a Davidd
+// Undo the Rev. 18 check-in. UUID reversal problem is now corrected in
+// Smbios.c.
+//
+// 19 8/30/07 12:23p Davidd
+// Fixed bug writing to NVRAM with 1.5MB BIOS size.
+//
+// 18 8/10/07 12:44p Davidd
+// When updating the system UUID, new UUID is saved in NVRAM correctly but
+// the UUID is copied to memory in reverse order.
+//
+// 17 7/10/07 3:05p Davidd
+// Fixed bug for DMIEdit Type 12 support.
+//
+// 16 6/20/07 10:57a Pats
+// Modified to support editing of SMBIOS structure type 0, offsets 5 and
+// 8.
+//
+// 15 3/29/07 6:06p Davidd
+// Changed the year in the AMI banner and code cleanup.
+//
+// 14 2/21/07 4:30p Davidd
+// Fixed the hanging problem during updating DMI data using DMIEdit
+// (multiple times with long strings).
+//
+// 13 2/05/07 11:59a Davidd
+// Corrected resetting problem during updating DMI data with Dmiedit (seen
+// with Core 4.5.3).
+//
+// 12 12/15/06 5:46p Davidd
+// Code cleanup and reformatted to coding standard.
+//
+// 11 11/03/06 11:57a Davidd
+// Added code to make Type 1 SKU and Family fields editable by DMIEdit
+// utility.
+//
+// 10 10/27/06 3:12p Davidd
+// Corrected the problem getting the string index in GetType1StringIndex
+//
+// 9 10/05/06 4:52p Davidd
+// Changes added for 64 bit support. Also use generic funtion MemCpy
+// rather than SmbiosMemCpy.
+//
+// 8 3/03/06 2:27p Davidd
+// Fixed the random hanging problem when using GetFlashInfo to get the
+// flash block size.
+//
+// 7 3/03/06 1:20p Davidd
+// In UpdateSmbiosTable, set the flash block size to
+// FLASH_BLOCK_SIZE SDL token.
+//
+// 6 3/02/06 1:57p Davidd
+// Updated include path to SMBios.h. It has been moved to
+// Include\Protocol
+//
+// 5 3/02/06 11:27a Davidd
+// Made some changes in the Update SmbiosTable routine to get the
+// flash information by calling the SMIFlash GetFlashInfo protocol rather
+// than hardcoding.
+//
+// 4 2/24/06 3:47p Davidd
+// Corrected the UUID data updated in reverse order (type 1 structure).
+//
+// 3 8/15/05 1:02p Davidd
+// Fixed the issue of updating DMI data when Debug_Mode is set to 0.
+//
+// 2 8/10/05 10:48a Davidd
+// Code cleanup.
+//
+// 1 4/29/05 2:06p Davidd
+// Initial checkin.
+//
+//**********************************************************************//
+
+#include <AmiDxeLib.h>
+#include "SmbiosDMIEdit.h"
+#include "Protocol\Smbios.h"
+#include <Protocol\FlashProtocol.h>
+#include "AmiLib.h"
+
+#define FLASH_DEVICE_BASE (0xFFFFFFFF - FLASH_SIZE + 1)
+#define WRITE_ONCE_ENTRIES 0x10 // Maximum number of WRITE_ONCE_STATUS entries
+
+#if PI_SPECIFICATION_VERSION >= 0x0001000a && SMM_MINOR_VER >= 43
+ extern EFI_SMM_SYSTEM_TABLE2 *mSmst;
+#else
+ extern EFI_SMM_SYSTEM_TABLE *mSmst;
+#endif
+
+#if !defined(SMBIOS_DMIEDIT_DATA_LOC) || SMBIOS_DMIEDIT_DATA_LOC != 2
+#if defined(NonSmiDmiEdit_Support) && (NonSmiDmiEdit_Support == 1)
+extern FLASH_PROTOCOL *FlashProtocol;
+#endif // NonSmiDmiEdit_Support
+
+VOID *gFlashData;
+UINT32 gFlashDataSize;
+#else
+CHAR16 *DmiArrayVar = L"DmiArray";
+DMI_VAR DmiArray[DMI_ARRAY_COUNT] = {0};
+UINTN DmiArraySize = DMI_ARRAY_COUNT * sizeof(DMI_VAR);
+UINT8 *DmiData;
+UINTN DmiDataSize;
+CHAR16 *Var = L" ";
+UINT8 Index;
+#endif // SMBIOS_DMIEDIT_DATA_LOC
+
+EFI_GUID EfiSmbiosNvramGuid = EFI_SMBIOS_NVRAM_DATA_GUID;
+
+SMBIOS_TABLE_ENTRY_POINT *SmbiosTableEntryPoint = NULL;
+UINT8 *ScratchBufferPtr = NULL;
+UINT16 MaximumBufferSize;
+
+BOOLEAN SwSmiMethod;
+
+//
+// String type tables
+//
+STRING_TABLE StringType_0[] = {{0x04, 1, 1},
+ {0x05, 2, 2},
+ {0x08, 3, 3},
+ {0xff, 0, 0},
+ };
+
+STRING_TABLE StringType_1[] = {{0x04, 1, 1},
+ {0x05, 2, 2},
+ {0x06, 3, 3},
+ {0x07, 4, 4},
+ {0x19, 5, 5},
+ {0x1a, 6, 6},
+ {0xff, 0, 0},
+ };
+
+STRING_TABLE StringType_2[] = {{0x04, 1, 1},
+ {0x05, 2, 2},
+ {0x06, 3, 3},
+ {0x07, 4, 4},
+ {0x08, 5, 5},
+ {0x0a, 6, 6},
+ {0xff, 0, 0},
+ };
+
+#if (SYS_CHASSIS_INFO == 1)
+STRING_TABLE StringType_3[NUMBER_OF_SYSTEM_CHASSIS][6] =
+ {{{0x04, 1, 1},
+ {0x06, 2, 2},
+ {0x07, 3, 3},
+ {0x08, 4, 4},
+ {0x15 + (ELEMENT_COUNT_1 * ELEMENT_LEN_1), 5, 5},
+ {0xff, 0, 0},
+ },
+#if NUMBER_OF_SYSTEM_CHASSIS > 1
+ {
+ {0x04, 1, 1},
+ {0x06, 2, 2},
+ {0x07, 3, 3},
+ {0x08, 4, 4},
+ {0x15 + (ELEMENT_COUNT_2 * ELEMENT_LEN_2), 5, 5},
+ {0xff, 0, 0},
+ },
+#endif
+#if NUMBER_OF_SYSTEM_CHASSIS > 2
+ {
+ {0x04, 1, 1},
+ {0x06, 2, 2},
+ {0x07, 3, 3},
+ {0x08, 4, 4},
+ {0x15 + (ELEMENT_COUNT_3 * ELEMENT_LEN_3), 5, 5},
+ {0xff, 0, 0},
+ },
+#endif
+#if NUMBER_OF_SYSTEM_CHASSIS > 3
+ {
+ {0x04, 1, 1},
+ {0x06, 2, 2},
+ {0x07, 3, 3},
+ {0x08, 4, 4},
+ {0x15 + (ELEMENT_COUNT_4 * ELEMENT_LEN_4), 5, 5},
+ {0xff, 0, 0},
+ },
+#endif
+#if NUMBER_OF_SYSTEM_CHASSIS > 4
+ {
+ {0x04, 1, 1},
+ {0x06, 2, 2},
+ {0x07, 3, 3},
+ {0x08, 4, 4},
+ {0x15 + (ELEMENT_COUNT_5 * ELEMENT_LEN_5), 5, 5},
+ {0xff, 0, 0},
+ },
+#endif
+ };
+#endif // #if (SYS_CHASSIS_INFO == 1)
+
+STRING_TABLE StringType_4[] = {{0x04, 1, 1},
+ {0x07, 2, 2},
+ {0x10, 3, 3},
+ {0x20, 4, 4},
+ {0x21, 5, 5},
+ {0x22, 6, 6},
+ {0xff, 0, 0},
+ };
+
+STRING_TABLE StringType_22[] = {{0x04, 1, 1},
+ {0x05, 2, 2},
+ {0x06, 3, 3},
+ {0x07, 4, 4},
+ {0x08, 5, 5},
+ {0x0e, 6, 6},
+ {0x14, 7, 7},
+ {0xff, 0, 0},
+ };
+
+STRING_TABLE StringType_39[] = {{0x05, 1, 1},
+ {0x06, 2, 2},
+ {0x07, 3, 3},
+ {0x08, 4, 4},
+ {0x09, 5, 5},
+ {0x0a, 6, 6},
+ {0x0b, 7, 7},
+ {0xff, 0, 0},
+ };
+
+//
+// String table
+//
+VOID* StringTable[] = {&StringType_0, // 0
+ &StringType_1, // 1
+ &StringType_2, // 2
+#if (SYS_CHASSIS_INFO == 1)
+ &StringType_3, // 3
+#endif // #if (SYS_CHASSIS_INFO == 1)
+ &StringType_4, // 4
+ &StringType_22, // 5
+ &StringType_39, // 6
+ };
+
+//<AMI_THDR_START>
+//----------------------------------------------------------------------------
+// Name: WriteOnceTable
+//
+// Description: Table indicating which structure and offset can be written
+// only once or multiple times
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_THDR_END>
+WRITE_ONCE_TABLE WriteOnceTable[] = {
+ {1, 4, TRUE},
+ {2, 4, TRUE},
+ };
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: WriteOnceStatusInit
+//
+// Description: Initialize NVRAM variable holding WriteOnce statuses
+//
+// Input: None
+//
+// Output: None
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+WriteOnceStatusInit(VOID)
+{
+ EFI_STATUS Status;
+ WRITE_ONCE_STATUS *Buffer;
+ UINTN BufferSize;
+
+ BufferSize = WRITE_ONCE_ENTRIES * sizeof(WRITE_ONCE_STATUS);
+ pBS->AllocatePool(EfiBootServicesData, BufferSize, &Buffer);
+
+ // Create "WriteOnceStatus" variable if it does not exist
+ Status = pRS->GetVariable(L"WriteOnceStatus",
+ &EfiSmbiosNvramGuid,
+ NULL,
+ &BufferSize,
+ Buffer);
+
+ if (Status == EFI_NOT_FOUND) {
+ // WriteOnceStatus variable does not exist
+ // Create one with default value of Type 127
+ MemSet(Buffer, BufferSize, 127);
+
+ pRS->SetVariable(L"WriteOnceStatus",
+ &EfiSmbiosNvramGuid,
+ EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ BufferSize,
+ Buffer);
+ }
+
+ pBS->FreePool(Buffer);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: isWriteOnce
+//
+// Description: Determines if a given structure type and offset can only
+// be written once or multiple times.
+//
+// Input: IN UINT8 Type
+// IN UINT8 Offset
+//
+// Output: BOOLEAN - TRUE/FALSE for Write Once/Multiple
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN
+isWriteOnce(
+ IN UINT8 Type,
+ IN UINT8 Offset,
+ IN UINT16 Handle
+)
+{
+ EFI_STATUS Status;
+ BOOLEAN WriteOnce = FALSE;
+ UINT8 TableEntries = sizeof(WriteOnceTable)/sizeof(WRITE_ONCE_TABLE);
+ WRITE_ONCE_STATUS Buffer[WRITE_ONCE_ENTRIES];
+ UINTN BufferSize;
+ UINT8 i;
+ UINT8 j;
+
+ BufferSize = WRITE_ONCE_ENTRIES * sizeof(WRITE_ONCE_STATUS);
+ Status = pRS->GetVariable(L"WriteOnceStatus",
+ &EfiSmbiosNvramGuid,
+ NULL,
+ &BufferSize,
+ Buffer);
+
+ for (i = 0; i < TableEntries; ++i) {
+ // Check for WriteOnce condition in WriteOnce table
+ if (WriteOnceTable[i].Type == Type \
+ && WriteOnceTable[i].Offset == Offset \
+ && WriteOnceTable[i].WriteOnce) {
+ // WriteOnce is set for input Type and Offset,
+ // Check if WriteOnce was set already in WriteOnceStatus table
+ // If "WriteOnceStatus" variable was not found then assume
+ // WriteOnce was not set for this data field
+ if (Status == EFI_SUCCESS) {
+ for (j = 0; j < WRITE_ONCE_ENTRIES; ++j) {
+ if (Buffer[j].Type == 127) {
+ break;
+ }
+ if (Buffer[j].Type == Type && Buffer[j].Offset == Offset && Buffer[j].Handle == Handle) {
+ // WriteOnce was already set for input Type and Offset
+ WriteOnce = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (j < WRITE_ONCE_ENTRIES) { // Make sure we are still within the WRITE_ONCE_ENTRIES
+ // Create new WriteOnce entry if it did not exist for input Type and Offset
+ if (WriteOnce == FALSE) {
+ Buffer[j].Type = Type;
+ Buffer[j].Offset = Offset;
+ Buffer[j].Handle = Handle;
+
+ pRS->SetVariable(L"WriteOnceStatus",
+ &EfiSmbiosNvramGuid,
+ EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ BufferSize,
+ Buffer);
+ }
+ }
+ }
+ }
+
+ return WriteOnce;
+}
+
+#if !defined(SMBIOS_DMIEDIT_DATA_LOC) || SMBIOS_DMIEDIT_DATA_LOC != 2
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: WriteToFlash
+//
+// Description: Write to the flash part starting at "Address" for a length
+// of "Size".
+//
+// Input: IN VOID *Address,
+// IN VOID *Data,
+// IN UINTN Size
+//
+// Output: EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+WriteToFlash(
+ IN VOID *Address,
+ IN VOID *Data,
+ IN UINTN Size
+)
+{
+ EFI_STATUS Status;
+
+ Status = mFlash->DeviceWriteEnable();
+ if (EFI_ERROR(Status)) return Status;
+
+ Status = mFlash->Write(Address, Size, Data);
+
+ mFlash->DeviceWriteDisable();
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetFlashDataInfo
+//
+// Description: Searches the Flash Data Table for a record of Type and
+// Offset. If found, returns the location found, the data size,
+// and the end of data.
+//
+// Input: IN TABLE_INFO RecordInfo
+//
+// Output: FLASH_DATA_INFO
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+FLASH_DATA_INFO
+GetFlashDataInfo(
+ IN TABLE_INFO *RecordInfo
+)
+{
+ TABLE_INFO *FlashDataPtr = gFlashData;
+ FLASH_DATA_INFO FlashDataInfo = {0, 0, 0};
+
+ while (FlashDataPtr->Handle != 0xffff) {
+ if (FlashDataPtr->Type == RecordInfo->Type &&
+ FlashDataPtr->Handle == RecordInfo->Handle &&
+ FlashDataPtr->Offset == RecordInfo->Offset &&
+ FlashDataPtr->Flags == RecordInfo->Flags) {
+ FlashDataInfo.Location = (UINT8*)FlashDataPtr;
+ FlashDataInfo.Size = FlashDataPtr->Size;
+ }
+
+ FlashDataPtr = (TABLE_INFO*)((UINT8*)(FlashDataPtr + 1) + FlashDataPtr->Size);
+ }
+ FlashDataInfo.EndOfData = (UINT8*)FlashDataPtr;
+ return FlashDataInfo;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UpdateSmbiosTable
+//
+// Description: Searches the Flash Data Table for a record of Type and
+// Offset. If found, the existing data will be replaced with
+// the new data, else the data will be added as a new record.
+//
+// Input: IN TABLE_INFO TableInfo,
+// IN UINT8 *Data
+//
+// Output: EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16
+UpdateSmbiosTable(
+ IN TABLE_INFO *TableInfo,
+ IN UINT8 *Data
+)
+{
+ UINT16 i;
+ UINT8 *BufferPtr = NULL;
+ UINT16 BufferSize = 0;
+ UINT16 Count = 0;
+ UINT32 SpaceAvailable;
+ EFI_STATUS Status;
+ FLASH_DATA_INFO FlashDataInfo;
+ UINT8 *FlashDataPtr;
+ FUNC_BLOCK FuncBlock[2];
+ EFI_PHYSICAL_ADDRESS SmmBuffer;
+ EFI_PHYSICAL_ADDRESS Buffer;
+#if defined(NonSmiDmiEdit_Support) && (NonSmiDmiEdit_Support == 1)
+ EFI_PHYSICAL_ADDRESS FlashDataBlock;
+ UINT8 BlockCount;
+ UINT8 *DataBuffer;
+ UINTN RemainingSize;
+#endif // NonSmiDmiEdit_Support
+
+ FlashDataInfo = GetFlashDataInfo(TableInfo);
+
+ // Check Size
+ SpaceAvailable = (UINT32)((UINT8*)gFlashData + gFlashDataSize - FlashDataInfo.EndOfData);
+ if (FlashDataInfo.Location) SpaceAvailable += FlashDataInfo.Size + sizeof(TABLE_INFO);
+
+ if (sizeof(TABLE_INFO) + TableInfo->Size > SpaceAvailable) {
+ return DMI_ADD_STRUCTURE_FAILED;
+ }
+
+ if (SwSmiMethod) {
+ // Initialize FuncBlock
+ for (i = 0; i < 2; i++) {
+ FuncBlock[i].BufAddr = 0;
+ FuncBlock[i].BlockAddr = 0;
+ FuncBlock[i].BlockSize = 0;
+ FuncBlock[i].ErrorCode = 0;
+ }
+
+ // Allocate 4K working buffer in SMM.
+ Status = mSmst->SmmAllocatePages ( AllocateAnyPages, EfiRuntimeServicesData, 1, &Buffer);
+ if (EFI_ERROR(Status)) return DMI_ADD_STRUCTURE_FAILED;
+ BufferPtr = (UINT8*)Buffer;
+
+ // Update String;
+ *(TABLE_INFO *)BufferPtr = *TableInfo;
+ BufferPtr += sizeof(TABLE_INFO);
+
+ for(i = 0; i < TableInfo->Size; ++i) {
+ *BufferPtr++ = Data[i];
+ }
+
+ if (FlashDataInfo.Location) {
+ UINT32 FlashDataOffset;
+
+ // Allocate 64K GetFlashInfo buffer in SMM.
+ Status = mSmst->SmmAllocatePages ( AllocateAnyPages, \
+ EfiRuntimeServicesData, \
+ 16, \
+ &SmmBuffer);
+ if (EFI_ERROR(Status)) {
+ // Free buffer and return error.
+ mSmst->SmmFreePages (Buffer, 1);
+ return DMI_ADD_STRUCTURE_FAILED;
+ }
+
+ ((INFO_BLOCK*)SmmBuffer)->Length = 0x10000;
+
+ Status = mSmiFlash->GetFlashInfo((INFO_BLOCK*)SmmBuffer);
+
+ if (Status) {
+ // Free buffers and return error.
+ mSmst->SmmFreePages (Buffer, 1);
+ mSmst->SmmFreePages (SmmBuffer, 16);
+ return DMI_ADD_STRUCTURE_FAILED;
+ }
+
+ // Initialize FUNC_BLOCK structure for SMIFlash used.
+ for (i = 0, Count = 1; i < ((INFO_BLOCK*)SmmBuffer)->TotalBlocks; i++) {
+ if (((UINT32)FlashDataInfo.Location - FLASH_DEVICE_BASE) > \
+ (((INFO_BLOCK*)SmmBuffer)->Blocks[i].StartAddress + \
+ ((INFO_BLOCK*)SmmBuffer)->Blocks[i].BlockSize)) continue;
+ FuncBlock[0].BlockSize = \
+ ((INFO_BLOCK*)SmmBuffer)->Blocks[i].BlockSize;
+ FuncBlock[0].BlockAddr = \
+ ((INFO_BLOCK*)SmmBuffer)->Blocks[i].StartAddress;
+
+ // Check whether SmbiosFlashData exceeds the block boundary.
+ if (((UINT32)gFlashData + (UINT32)FLASHDATA_SIZE - FLASH_DEVICE_BASE) > \
+ (((INFO_BLOCK*)SmmBuffer)->Blocks[i+1].StartAddress)) {
+ Count = 2;
+ FuncBlock[1].BlockSize = \
+ ((INFO_BLOCK*)SmmBuffer)->Blocks[i+1].BlockSize;
+ FuncBlock[1].BlockAddr = \
+ ((INFO_BLOCK*)SmmBuffer)->Blocks[i+1].StartAddress;
+ }
+ break;
+ }
+
+ // Free the GetFlashInfo buffer.
+ Status = mSmst->SmmFreePages (SmmBuffer, 16);
+ ASSERT_EFI_ERROR(Status);
+
+ // Allocate the blocks buffer.
+ Status = mSmst->SmmAllocatePages ( \
+ AllocateAnyPages, \
+ EfiRuntimeServicesData, \
+ (FuncBlock[0].BlockSize * Count) / 0x1000, \
+ &SmmBuffer);
+ if (EFI_ERROR(Status)) {
+ // Free buffer and return error.
+ mSmst->SmmFreePages (Buffer, 1);
+ return DMI_ADD_STRUCTURE_FAILED;
+ }
+ FuncBlock[0].BufAddr = SmmBuffer;
+ FuncBlock[1].BufAddr = SmmBuffer + FuncBlock[0].BlockSize;
+
+ // Read the whole SmbiosFlashData Blocks.
+ for (i = 0; i < Count; i++) {
+ Status = mFlash->Read((VOID*)(FuncBlock[i].BlockAddr + FLASH_DEVICE_BASE), \
+ FuncBlock[i].BlockSize, (VOID*)FuncBlock[i].BufAddr);
+ if (Status) {
+ // Free buffer and return error.
+ mSmst->SmmFreePages (Buffer, 1);
+
+ mSmst->SmmFreePages ( \
+ SmmBuffer, \
+ (FuncBlock[0].BlockSize * Count) / 0x1000);
+ return DMI_ADD_STRUCTURE_FAILED;
+ }
+ }
+
+ // Initialize SmbiosFlashData buffer.
+ for (i = 0; i < FLASHDATA_SIZE; i++, *((UINT8*)Buffer + i) = 0xff);
+
+ // Re-collect the Smbios structures to SmbiosFlashData buffer.
+ FlashDataPtr = gFlashData;
+ BufferPtr = (UINT8*)Buffer;
+
+ while((((TABLE_INFO*)FlashDataPtr)->Size != 0xffff) &&
+ (((TABLE_INFO*)FlashDataPtr)->Size != 0)) {
+ if ((((TABLE_INFO*)FlashDataPtr)->Type == TableInfo->Type) && \
+ (((TABLE_INFO*)FlashDataPtr)->Handle == TableInfo->Handle) && \
+ (((TABLE_INFO*)FlashDataPtr)->Offset == TableInfo->Offset)) {
+ // Replace the structure with updated data.
+ MemCpy(BufferPtr, (UINT8*)TableInfo, sizeof(TABLE_INFO));
+ BufferSize = TableInfo->Size;
+ MemCpy (BufferPtr + sizeof(TABLE_INFO), Data, BufferSize);
+ BufferSize += sizeof(TABLE_INFO);
+ } else {
+ // Copy the structure.
+ BufferSize = (((TABLE_INFO*)FlashDataPtr)->Size + sizeof(TABLE_INFO));
+ MemCpy (BufferPtr, FlashDataPtr, BufferSize);
+ }
+
+ BufferPtr += BufferSize;
+ FlashDataPtr += (((TABLE_INFO*)FlashDataPtr)->Size + sizeof(TABLE_INFO));
+ }
+
+ // Copy the new SmbiosFlashData to read buffer.
+ FlashDataOffset = ((UINT32)FlashDataInfo.Location - \
+ FLASH_DEVICE_BASE - FuncBlock[0].BlockAddr);
+ BufferPtr = (UINT8*)Buffer + (UINT32)FlashDataInfo.Location - (UINT32)gFlashData;
+ MemCpy((UINT8*)(FuncBlock[0].BufAddr + FlashDataOffset),
+ (UINT8*)BufferPtr,
+ (UINT32)gFlashData + (UINT32)FLASHDATA_SIZE - (UINT32)FlashDataInfo.Location);
+
+ // Write the block buffer with updated SmbiosFlashData back.
+ if (!EFI_ERROR(Status)) {
+ for (i = 0; i < Count; i++) {
+ Status = mFlash->Update( \
+ (VOID*)(FuncBlock[i].BlockAddr + FLASH_DEVICE_BASE), \
+ FuncBlock[i].BlockSize, (VOID*)FuncBlock[i].BufAddr
+ );
+ if (EFI_ERROR(Status)) break;
+ }
+ }
+
+ // Free the Block Buffer in SMM.
+ mSmst->SmmFreePages ( SmmBuffer, \
+ (FuncBlock[0].BlockSize * Count) / 0x1000);
+ }
+ else {
+ UINT32 EndOfData;
+
+ EndOfData = (UINT32)FlashDataInfo.EndOfData & 0x0ffff;
+
+ if ((EndOfData + (UINT32)(BufferPtr - (UINT8*)Buffer)) > 0x10000) {
+ UINT32 NewOffsetOfData;
+ UINT32 ExtraSize;
+ UINT32 DataLength;
+
+ NewOffsetOfData = (UINT32)(((UINT32)FlashDataInfo.EndOfData & 0xffff0000) + 0x10000);
+ ExtraSize = EndOfData + (UINT32)(BufferPtr - (UINT8*)Buffer) - 0x10000;
+ DataLength = (UINT32)(BufferPtr - (UINT8*)Buffer);
+
+ Status = WriteToFlash(FlashDataInfo.EndOfData,
+ (UINT8*)Buffer,
+ DataLength - ExtraSize);
+ ASSERT_EFI_ERROR(Status);
+
+ Status = WriteToFlash( (VOID *)NewOffsetOfData,
+ (UINT8*)(Buffer + DataLength - ExtraSize),
+ ExtraSize);
+ ASSERT_EFI_ERROR(Status);
+ }
+ else {
+ Status = WriteToFlash(FlashDataInfo.EndOfData,
+ (UINT8*)Buffer,
+ BufferPtr - (UINT8*)Buffer);
+ }
+
+ mSmst->SmmFreePages (Buffer, 1);
+
+ if (Status) return DMI_ADD_STRUCTURE_FAILED;
+ }
+ } // SwSmiMethod
+#if defined(NonSmiDmiEdit_Support) && (NonSmiDmiEdit_Support == 1)
+ else { // Protocol Method
+ // Determine the base block that contains the DmiEdit data
+ FlashDataBlock = (UINTN)gFlashData & (0xFFFFFFFF - FLASH_BLOCK_SIZE + 1);
+
+ // Check to see if it spans more than one block
+ if (((UINTN)gFlashData + FLASHDATA_SIZE) > (FlashDataBlock + FLASH_BLOCK_SIZE)) {
+ BlockCount = 2;
+ }
+ else {
+ BlockCount = 1;
+ }
+
+ // Allocate Flash Data buffer and get the data
+ // Note: additional 4K reserved for data manipulation
+ pBS->AllocatePool(EfiBootServicesData, BlockCount * FLASH_BLOCK_SIZE, &DataBuffer);
+ FlashProtocol->Read((UINT8*)FlashDataBlock, BlockCount * FLASH_BLOCK_SIZE, DataBuffer);
+
+ if (FlashDataInfo.Location) {
+ // Some data is already present for input type
+ // Determine location of existing data
+ BufferPtr = DataBuffer + \
+ (UINTN)gFlashData - FlashDataBlock + \
+ (UINTN)FlashDataInfo.Location - (UINTN)gFlashData; // Existing DmiEdit data location
+
+ // Calculate remaining size from the existing data location
+ // to end of DmiEdit data storage block
+ RemainingSize = (UINTN)FlashDataInfo.EndOfData - \
+ (UINTN)FlashDataInfo.Location - \
+ (sizeof(TABLE_INFO) + ((TABLE_INFO*)BufferPtr)->Size);
+
+ // Copy the remaining data (without the existing data) to location
+ // after input data entry insertion
+ MemCpy(BufferPtr + sizeof(TABLE_INFO) + TableInfo->Size,
+ BufferPtr + sizeof(TABLE_INFO) + ((TABLE_INFO*)BufferPtr)->Size,
+ RemainingSize);
+
+ // In case new data size is smaller than existing one, clear old data
+ // from (EndOfData - size difference) to EndOfData to 0xff
+ if (((TABLE_INFO*)BufferPtr)->Size > TableInfo->Size) {
+ UINT8 *DataEndPtr;
+
+ RemainingSize = ((TABLE_INFO*)BufferPtr)->Size - TableInfo->Size;
+ DataEndPtr = DataBuffer + \
+ ((UINTN)FlashDataInfo.EndOfData - FlashDataBlock) - \
+ RemainingSize;
+
+ for (i = 0; i < RemainingSize; ++i) {
+ *DataEndPtr++ = 0xff;
+ }
+ }
+ }
+ else {
+ // Determine the end location of current DmiEdit data
+ BufferPtr = DataBuffer + \
+ (UINTN)gFlashData - FlashDataBlock + \
+ (UINTN)FlashDataInfo.EndOfData - (UINTN)gFlashData; // End of DmiEdit data
+ }
+
+ // Insert data
+ *(TABLE_INFO *)BufferPtr = *TableInfo;
+ BufferPtr += sizeof(TABLE_INFO);
+
+ for(i = 0; i < TableInfo->Size; ++i) {
+ *BufferPtr++ = Data[i];
+ }
+
+ // Update DmiEdit data block
+ FlashProtocol->Update((UINT8*)FlashDataBlock, BlockCount * FLASH_BLOCK_SIZE, DataBuffer);
+
+ pBS->FreePool(DataBuffer);
+ }
+#endif // NonSmiDmiEdit_Support
+
+ return 0;
+}
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetSmbiosInfo
+//
+// Description: Returns the SMBIOS information
+//
+// Input: IN OUT GET_SMBIOS_INFO *p
+//
+// Output: Returns 0
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16
+GetSmbiosInfo(
+ IN OUT GET_SMBIOS_INFO *p
+)
+{
+ if (!SmbiosTableEntryPoint) return DMI_FUNCTION_NOT_SUPPORTED;
+ p->DmiBiosRevision = SmbiosTableEntryPoint->SmbiosBCDRevision;
+ p->NumStructures = SmbiosTableEntryPoint->NumberOfSmbiosStructures;
+ p->StructureSize = SmbiosTableEntryPoint->MaxStructureSize;
+ p->pDmiStorageBase = SmbiosTableEntryPoint->TableAddress;
+ p->DmiStorageSize = MaximumBufferSize;
+
+ return 0;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetStructureByHandle
+//
+// Description: Searches the structure table for a record with its handle
+// equal to the input Handle.
+// Returns the pointer to the structure if found.
+// Returns NULL if not found
+//
+// Input: IN UINT16 *Handle
+//
+// Output: UINT8* - Pointer to structure found
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT8*
+GetStructureByHandle(
+ IN UINT16 *Handle
+)
+{
+ UINT8 *SmbiosTable = (UINT8*)((SMBIOS_TABLE_ENTRY_POINT*)SmbiosTableEntryPoint)->TableAddress;
+ UINT8 *SmbiosTableEnd = SmbiosTable + ((SMBIOS_TABLE_ENTRY_POINT*)SmbiosTableEntryPoint)->TableLength;
+ UINT8 *SmbiosTableNext;
+
+ while(SmbiosTable < SmbiosTableEnd && ((SMBIOS_STRUCTURE_HEADER*)SmbiosTable)->Type != 127) {
+ SmbiosTableNext = SmbiosTable + GetStructureLength(SmbiosTable);
+ if (((SMBIOS_STRUCTURE_HEADER*)SmbiosTable)->Handle == *Handle) {
+ return SmbiosTable;
+ }
+ SmbiosTable = SmbiosTableNext;
+ }
+ return NULL;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetStructureByHandleThenUpdateHandle
+//
+// Description: Searches the structure table for a record with its handle
+// equal to the input Handle.
+// Returns the pointer to the structure if found.
+// Returns NULL if not found
+//
+// Input: IN UINT16 *Handle
+//
+// Output: UINT8* - Pointer to structure found
+// Sets Handle to the handle of the next structure
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT8*
+GetStructureByHandleThenUpdateHandle(
+ IN UINT16 *Handle
+)
+{
+ UINT8 *SmbiosTable = (UINT8*)((SMBIOS_TABLE_ENTRY_POINT*)SmbiosTableEntryPoint)->TableAddress;
+ UINT8 *SmbiosTableEnd = SmbiosTable + ((SMBIOS_TABLE_ENTRY_POINT*)SmbiosTableEntryPoint)->TableLength;
+ UINT8 *SmbiosTableNext;
+
+ if (*Handle == 0) {
+ SmbiosTableNext = SmbiosTable + GetStructureLength(SmbiosTable);
+ if (SmbiosTableNext >= SmbiosTableEnd) *Handle = 0xffff; //Last handle?
+ else *Handle = ((DMI_STRUC*)SmbiosTableNext)->Handle; //Return next handle
+ return SmbiosTable;
+ }
+
+ while(SmbiosTable < SmbiosTableEnd) {
+ SmbiosTableNext = SmbiosTable + GetStructureLength(SmbiosTable);
+ if (((DMI_STRUC*)SmbiosTable)->Handle == *Handle) {
+ if (SmbiosTableNext >= SmbiosTableEnd || ((DMI_STRUC*)SmbiosTable)->Type == 127 ) *Handle = 0xffff; //Last handle?
+ else *Handle = ((DMI_STRUC*)SmbiosTableNext)->Handle; //Return next handle
+ return SmbiosTable;
+ }
+
+ SmbiosTable = SmbiosTableNext;
+ }
+
+ return NULL;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetSmbiosStructure
+//
+// Description: Searches the structure table for a record with its handle
+// equal to the input Handle and copies its content into
+// the provided buffer.
+//
+// Input: IN OUT GET_SMBIOS_STRUCTURE *p
+//
+// Output: GET_SMBIOS_STRUCTURE* - Input pointer "p" is loaded with
+// structure data.
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16
+GetSmbiosStructure(
+ IN OUT GET_SMBIOS_STRUCTURE *p
+)
+{
+ UINT8 *SmbStructurePtr;
+ UINT32 TableSize;
+ UINT8 *src, *dest;
+
+ if (!SmbiosTableEntryPoint) return DMI_FUNCTION_NOT_SUPPORTED;
+
+ SmbStructurePtr = GetStructureByHandleThenUpdateHandle((UINT16*)p->Handle32BitAddr);
+ if (!SmbStructurePtr) return DMI_INVALID_HANDLE;
+
+ TableSize = GetStructureLength(SmbStructurePtr);
+
+ src = SmbStructurePtr;
+ dest = (UINT8*)p->Buffer32BitAddr;
+ while(TableSize--) *dest++ = *src++; //Copy Table
+
+ return 0;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetStructureLength
+//
+// Description: Returns the length of the structure pointed by BufferStart
+// in bytes
+//
+// Input: IN UINT8 *BufferStart
+//
+// Output: UINT16 - Size of the structure
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16
+GetStructureLength(
+ IN UINT8 *BufferStart
+)
+{
+ UINT8 *BufferEnd = BufferStart;
+
+ BufferEnd += ((SMBIOS_STRUCTURE_HEADER*)BufferStart)->Length;
+
+ while(*(UINT16*)BufferEnd != 0) {
+ BufferEnd++;
+ }
+
+ return (UINT16)(BufferEnd + 2 - BufferStart); // +2 for double zero terminator
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetInstanceByTypeHandle
+//
+// Description: Returns the instance of the input structure type and its handle
+//
+// Input: IN UINT8 Type
+// IN UINT16 Handle
+//
+// Output: Instance number (1-based) if found, or 0 if not found
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT8
+GetInstanceByTypeHandle(
+ IN UINT8 Type,
+ IN UINT16 Handle
+)
+{
+ UINT8 *Table = (UINT8*)((SMBIOS_TABLE_ENTRY_POINT*)SmbiosTableEntryPoint)->TableAddress;
+ UINT8 *TableEnd = Table + ((SMBIOS_TABLE_ENTRY_POINT*)SmbiosTableEntryPoint)->TableLength;
+ UINT8 Instance = 0; // 1-based
+
+ while ((Table < TableEnd) && ((SMBIOS_STRUCTURE_HEADER*)Table)->Type != 127) {
+ if (((SMBIOS_STRUCTURE_HEADER*)Table)->Type == Type) {
+ Instance ++;
+ }
+
+ if (((SMBIOS_STRUCTURE_HEADER*)Table)->Handle == Handle) {
+ return Instance;
+ }
+
+ Table = Table + GetStructureLength(Table);
+ }
+
+ return 0; // Not found
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindStructureType
+//
+// Description: Find structure type starting from memory location pointed by
+// Buffer
+//
+// Input: IN OUT UINT8 **Buffer
+// IN OUT UINT8 **StructureFoundPtr
+// IN UINT8 SearchType
+// IN UINT8 Instance
+//
+// Output:
+// BOOLEAN
+// TRUE - Structure found
+// FALSE - Structure not found
+//
+// If SearchType is found:
+// UINT8 **Buffer - Points to the next structure
+// UINT8 **StructureFoundPtr - Points to the structure
+// that was found
+// If SearchType is not found:
+// UINT8 **Buffer - No change
+// UINT8 **StructureFoundPtr = NULL
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN
+FindStructureType(
+ IN OUT UINT8 **Buffer,
+ IN OUT UINT8 **StructureFoundPtr,
+ IN UINT8 SearchType,
+ IN UINT8 Instance // 1-based
+)
+{
+ UINT8 *BufferPtr = *Buffer;
+ BOOLEAN FindStatus = FALSE;
+
+ *StructureFoundPtr = NULL;
+ while (((SMBIOS_STRUCTURE_HEADER*)BufferPtr)->Type != 127) {
+ if (((SMBIOS_STRUCTURE_HEADER*)BufferPtr)->Type == SearchType) {
+ // If this instance, set the find status flag and update the Buffer pointer
+ if (--Instance == 0) {
+ FindStatus = TRUE;
+ *StructureFoundPtr = BufferPtr;
+ *Buffer = BufferPtr + GetStructureLength(BufferPtr);
+ break;
+ }
+ }
+ BufferPtr += GetStructureLength(BufferPtr);
+ }
+ if ((FindStatus == FALSE) & (SearchType == 127)) {
+ FindStatus = TRUE;
+ *StructureFoundPtr = BufferPtr;
+ *Buffer = BufferPtr + GetStructureLength(BufferPtr);
+ }
+ return FindStatus;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetStringTableIndex
+//
+// Description: Returns the string array index for a given Offset in
+// structure pointed by input StringTablePtr
+//
+// Input: STRING_TABLE *StringTablePtr
+// IN UINT8 Offset
+//
+// Output: UINT8 - String array index
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT8
+GetStringTableIndex(
+ STRING_TABLE *StringTablePtr,
+ IN UINT8 Offset
+)
+{
+ UINT8 i;
+
+ for (i = 0; StringTablePtr->Offset != 0xff; i++) {
+ if (StringTablePtr->Offset == Offset) break;
+ StringTablePtr++;
+ }
+
+ return i;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: StrLen
+//
+// Description: Returns the length of an input string
+//
+// Input: IN CHAR8 *Str
+//
+// Output: UINT8 - Length of the string (without zero terminator)
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16
+StrLen(
+ IN CHAR8 *Str
+)
+{
+ UINT16 Length = 0;
+
+ while (*Str++) Length++;
+
+ return Length;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetRemainingStructuresSize
+//
+// Description: Return the size from the Pointer Buffer to the last
+// structure 127.
+//
+// Input: IN UINT8 *Buffer
+//
+// Output: Size of remaining structure
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16
+GetRemainingStructuresSize(
+ IN UINT8 *Buffer
+)
+{
+ UINT16 Length = 0;
+ UINT16 BlockSize;
+
+ while (((SMBIOS_STRUCTURE_HEADER*)Buffer)->Type != 127) {
+ BlockSize = GetStructureLength(Buffer);
+ Length += BlockSize;
+ Buffer += BlockSize;
+ }
+ Length += GetStructureLength(Buffer);
+ return Length;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SmbiosCheckSum
+//
+// Description: Returns the checksum of "length" bytes starting from the
+// "*ChecksumSrc"
+//
+// Input: IN UINT8 *ChecksumSrc
+// IN UINT8 length
+//
+// Output: UINT8 - Checksum value
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT8
+SmbiosCheckSum(
+ IN UINT8 *ChecksumSrc,
+ IN UINT8 length
+)
+{
+ UINT8 Checksum = 0;
+ UINT8 i;
+
+ for (i= 0; i < length; i++) {
+ Checksum += *ChecksumSrc++;
+ }
+ return (0 - Checksum);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetLargestStructureSize
+//
+// Description: Returns the largest structure size
+//
+// Input: IN UINT8 *Buffer
+//
+// Output: UINT16 - Largest structure size
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16
+GetLargestStructureSize(
+ IN UINT8 *Buffer
+)
+{
+ UINT8 *BufferPtr = Buffer;
+ UINT16 LargestStructureSize = 0;
+ UINT16 CurrentStructureSize;
+
+ while (((SMBIOS_STRUCTURE_HEADER*)BufferPtr)->Type != 127) {
+ UINT8 *LastBufferPtr;
+
+ LastBufferPtr = BufferPtr;
+ BufferPtr += ((SMBIOS_STRUCTURE_HEADER*)BufferPtr)->Length;
+ while(TRUE) {
+ if ((*(UINT16*)BufferPtr) == 0) {
+ BufferPtr += 2;
+ break;
+ }
+ BufferPtr++;
+ }
+ CurrentStructureSize = (UINT16)(BufferPtr - LastBufferPtr);
+ if (CurrentStructureSize > LargestStructureSize) {
+ LargestStructureSize = CurrentStructureSize;
+ }
+ }
+ return LargestStructureSize;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UpdateHeaderInfo
+//
+// Description: Updates SMBIOS Entry Point Header
+//
+// Input: None
+//
+// Output: None
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+UpdateHeaderInfo(VOID)
+{
+ SmbiosTableEntryPoint->TableLength = GetRemainingStructuresSize((UINT8*)SmbiosTableEntryPoint->TableAddress);
+ SmbiosTableEntryPoint->IntermediateChecksum = 0;
+ SmbiosTableEntryPoint->IntermediateChecksum = SmbiosCheckSum((UINT8*)SmbiosTableEntryPoint + 0x10, 15);
+ SmbiosTableEntryPoint->MaxStructureSize = GetLargestStructureSize((UINT8*)SmbiosTableEntryPoint->TableAddress);
+ SmbiosTableEntryPoint->EntryPointStructureChecksum = 0;
+ SmbiosTableEntryPoint->EntryPointStructureChecksum = SmbiosCheckSum((UINT8*)SmbiosTableEntryPoint,
+ SmbiosTableEntryPoint->EntryPointLength);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetTypeTable
+//
+// Description: Return pointer to the input type string table
+//
+// Input: IN UINT8 Structure Type
+//
+// Output: Pointer to the input type string table
+// (or NULL if not found)
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID*
+GetTypeTable(
+ IN UINT8 StructType
+)
+{
+ UINT8 Index;
+
+ switch (StructType) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4: Index = StructType;
+ break;
+ case 22: Index = 5;
+ break;
+ case 39: Index = 6;
+ break;
+ default: Index = 0xff;
+ }
+
+ if (Index != 0xff) {
+ return StringTable[Index];
+ }
+ else {
+ return NULL;
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetStringOffset
+//
+// Description: Returns the string offset for StringNumber from input string
+// buffer BufferStart
+//
+// Input: IN UINT8 *BufferStart
+// IN UINT8 StringNumber (1-based)
+//
+// Output: UINT16 - Offset from BufferStart
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16
+GetStringOffset(
+ IN UINT8 *BufferStart,
+ IN UINT8 StringNumber // 1-based
+)
+{
+ UINT8 *BufferEnd = BufferStart;
+
+ while (--StringNumber) {
+ while(*BufferEnd != 0) {
+ BufferEnd++;
+ }
+ BufferEnd++;
+ }
+
+ return (UINT16)(BufferEnd - BufferStart);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindString
+//
+// Description: Returns pointer to the string number in structure BufferPtr
+//
+// Input: IN OUT UINT8 **BufferPtr
+// IN UINT8 StringNumber
+//
+// Output: UINT8 *BufferPtr = Pointer to the #StringNumber string
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+BOOLEAN
+FindString(
+ IN OUT UINT8 **BufferPtr,
+ IN UINT8 StringNumber // 1-based
+)
+{
+ *BufferPtr += ((SMBIOS_STRUCTURE_HEADER*)*BufferPtr)->Length;
+ *BufferPtr += GetStringOffset(*BufferPtr, StringNumber);
+ return TRUE;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: FindLargestStrNumber
+//
+// Description: Return the largest string number in a structure
+//
+// Input: IN UINT8 *StructPtr
+// IN UINT8 *StrTablePtr
+//
+// Output: String number (1-based)
+// (or 0 if not found)
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT8
+FindLargestStrNumber (
+ IN UINT8 *StructPtr,
+ IN STRING_TABLE *StrTablePtr
+)
+{
+ UINT8 Number;
+ UINT8 StrNumber = 0;
+
+ // Find largest string number from structure
+ while (StrTablePtr->Offset != 0xff) {
+ Number = *(StructPtr + StrTablePtr->Offset);
+ if (Number > StrNumber) {
+ StrNumber = Number;
+ }
+ StrTablePtr++;
+ }
+
+ return StrNumber; // 1-based
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetStrNumber
+//
+// Description: Return the string number for a structure "Type" at "Offset"
+//
+// Input: IN UINT8 Pointer to structure
+// IN UINT8 Type
+// IN UINT8 Offset
+//
+// Output: String number (1-based)
+// (or 0xff if not found)
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT8
+GetStrNumber(
+ IN UINT8 *StructPtr,
+ IN UINT8 Type,
+ UINT8 Offset
+)
+{
+ UINT8 *NextStructPtr = StructPtr;
+ UINT8 *TempPtr;
+
+ if (FindStructureType(&NextStructPtr, &TempPtr, Type, 1)) {
+ return *(TempPtr + Offset);
+ }
+ else {
+ return 0xff;
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DeleteStringNumber
+//
+// Description: Zero out the string number in StructPtr
+//
+// Input: IN UINT8 *StructurePtr
+// IN UINT8 StrNumber
+//
+// Output: None
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+DeleteStringNumber (
+ IN UINT8 *StructPtr,
+ IN UINT8 StrNumber
+)
+{
+ UINT8 Number;
+ STRING_TABLE *StrTablePtr;
+
+ StrTablePtr = GetTypeTable(((SMBIOS_STRUCTURE_HEADER*)StructPtr)->Type);
+
+ while (StrTablePtr->Offset != 0xff) {
+ Number = *(StructPtr + StrTablePtr->Offset);
+ if (Number > StrNumber) {
+ *(StructPtr + StrTablePtr->Offset) = Number - 1;
+ }
+ if (Number == StrNumber) {
+ *(StructPtr + StrTablePtr->Offset) = 0;
+ }
+ StrTablePtr++;
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DeleteString
+//
+// Description: Delete string at Offset
+//
+// Input: IN UINT8 *StructPtr
+// IN UINT8 Offset
+//
+// Output: None
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+DeleteString (
+ IN UINT8 *StructPtr,
+ IN UINT8 Offset
+)
+{
+ UINT8 StrNumber;
+ UINT8 *TempPtr;
+ UINT8 *StructEndPtr;
+ UINTN RemainingSize;
+
+ StrNumber = GetStrNumber(StructPtr, ((SMBIOS_STRUCTURE_HEADER*)StructPtr)->Type, Offset);
+
+ // Delete string number
+ DeleteStringNumber(StructPtr, StrNumber);
+
+ FindString(&StructPtr, StrNumber); // StructPtr = StrNumber string
+ TempPtr = StructPtr + StrLen(StructPtr) + 1; // Move pointer to next string
+
+ // Find end of structure
+ StructEndPtr = TempPtr;
+ while(*(UINT16*)StructEndPtr != 0) {
+ StructEndPtr++;
+ }
+
+ // Copy remaining strings
+ RemainingSize = StructEndPtr + 2 - TempPtr; // Including double NULL characters
+ MemCpy(StructPtr, TempPtr, RemainingSize);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: ReplaceString
+//
+// Description: Replace the #StringNum in the input buffer *DestStructPtr
+// with StringData
+//
+// Input: IN UINT8 *DestStructPtr Pointer to structure to be updated
+// IN UINT8 StringNum String number (1 based)
+// IN UINT8 *StringData String with NULL terminated character
+//
+// Output: EFI_STATUS
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+ReplaceString(
+ IN UINT8 *DestStructPtr,
+ IN UINT8 StringNum,
+ IN UINT8 *StringData
+)
+{
+ UINT8 StringSize = 0;
+ UINT8 *TempPtr;
+ UINT8 *NextStrPtr;
+ UINT8 *StructEndPtr;
+ UINTN RemainingSize;
+
+ FindString(&DestStructPtr, StringNum);
+ NextStrPtr = DestStructPtr;
+ StructEndPtr = DestStructPtr;
+
+ while(*NextStrPtr != 0) {
+ NextStrPtr++;
+ }
+
+ // NextStrPtr = Pointer to the next string
+ NextStrPtr++;
+
+ while(*(UINT16*)StructEndPtr != 0) {
+ StructEndPtr++;
+ }
+
+ RemainingSize = StructEndPtr + 2 - NextStrPtr; // Including double NULL characters
+
+ TempPtr = StringData;
+ while (*(TempPtr++) != 0) {
+ StringSize++;
+ }
+ StringSize++; // Including NULL character
+
+ // Copy remaining strings
+ MemCpy(DestStructPtr + StringSize, NextStrPtr, RemainingSize);
+
+ // Copy the string
+ MemCpy(DestStructPtr, StringData, StringSize);
+
+ return EFI_SUCCESS;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AddStringNumber
+//
+// Description: Add new string number for a structure "Type" at "Offset".
+// Return the string index, assuming all strings exist in the
+// structure according to the Smbios specification
+//
+// Input: IN UINT8 Pointer to SmbiosTable or Structure
+// IN UINT8 Type
+// IN UINT8 Offset
+//
+// Output: String index (0-based)
+// (0xff if not found)
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT8
+AddStringNumber(
+ IN UINT8 *SmbiosTable,
+ IN UINT8 Type,
+ UINT8 Offset
+)
+{
+ STRING_TABLE *StrTablePtr;
+ UINT8 *NextStructPtr = SmbiosTable;
+ UINT8 *TempPtr;
+ UINT8 Index = 0xff;
+ UINT8 StrNumber = 0;
+ UINT8 Number;
+
+ if (FindStructureType(&NextStructPtr, &TempPtr, Type, 1)) {
+ StrTablePtr = GetTypeTable(Type);
+ if (StrTablePtr != NULL) {
+ // Find largest string number from structure
+ while (StrTablePtr->Offset != 0xff) {
+ if (StrTablePtr->Offset == Offset) {
+ // String index in Smbios spec
+ Index = StrTablePtr->SpecStrNum - 1; // 0-based
+ }
+
+ Number = *(TempPtr + StrTablePtr->Offset);
+ if (Number > StrNumber) {
+ StrNumber = Number;
+ }
+ StrTablePtr++;
+ }
+
+ // Assign next string number to structure at input Offset
+ *(TempPtr + Offset) = ++StrNumber;
+
+ return Index; // 0-based
+ }
+ }
+
+ return 0xff;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: AddNullTerminator
+//
+// Description: Add NULL terminator to the end of the structure
+//
+// Input: IN UINT8 *StructPtr
+// IN UINT8 *StrTablePtr
+//
+// Output: None
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+AddNullTerminator (
+ IN UINT8 *StructPtr,
+ IN STRING_TABLE *StrTablePtr
+)
+{
+ UINT8 StrNumber;
+ UINT8 i;
+
+ // Find largest string number
+ StrNumber = FindLargestStrNumber(StructPtr, StrTablePtr);
+
+ // Skip to string section
+ StructPtr += ((SMBIOS_STRUCTURE_HEADER*)StructPtr)->Length;
+
+ // Move pointer to end of last string
+ for (i = 0; i < StrNumber; i++) {
+ while (*StructPtr != NULL) StructPtr++;
+ StructPtr++;
+ }
+
+ // Add NULL terminator
+ *StructPtr = 0;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: UpdateStrings
+//
+// Description: Updates strings in SMBIOS Structure with input Handle
+// in Runtime with DMI data
+//
+// Input: IN UINT16 Handle,
+// IN TABLE_INFO TableInfo,
+// IN UINT8 *Data
+//
+// Output: UINT8 - Status
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16
+UpdateStrings(
+ IN UINT16 Handle,
+ IN TABLE_INFO TableInfo,
+ IN UINT8 *Data
+)
+{
+ UINT8 *TablePtr;
+ UINT8 *TempBuffer;
+ UINT8 *StructPtr;
+ UINT8 i;
+ UINT16 BlockSize;
+ UINT16 AvailableBlkSize;
+ STRING_TABLE *StrTablePtr;
+ UINT8 StrNumber;
+ UINT8 Instance;
+
+ // Check if enough space
+ AvailableBlkSize = MaximumBufferSize - SmbiosTableEntryPoint->TableLength;
+ if (AvailableBlkSize < (StrLen(Data) + 1)) {
+ return DMI_BAD_PARAMETER; // Not enough space
+ }
+
+ // Get pointer to structure to be updated
+ StructPtr = GetStructureByHandle(&Handle);
+ if (StructPtr == NULL) {
+ return DMI_INVALID_HANDLE;
+ }
+
+ // Get pointer to the StringTable
+ StrTablePtr = GetTypeTable(((SMBIOS_STRUCTURE_HEADER*)StructPtr)->Type);
+ if (((SMBIOS_STRUCTURE_HEADER*)StructPtr)->Type == 3) {
+ Instance = GetInstanceByTypeHandle(3, Handle);
+ StrTablePtr += 6 * (Instance - 1);
+ }
+
+ if (StrTablePtr == NULL) return DMI_BAD_PARAMETER;
+
+ // Copy structure data
+ TempBuffer = ScratchBufferPtr;
+ BlockSize = GetStructureLength(StructPtr);
+ MemCpy(TempBuffer, StructPtr, BlockSize);
+
+ // Set TablePtr to next structure
+ TablePtr = StructPtr + BlockSize;
+
+
+ // Update String fields
+ for (i = 0; StrTablePtr[i].Offset != 0xff; i++) {
+ // Update string at input Offset
+ if (StrTablePtr[i].Offset == TableInfo.Offset) {
+ // Update string if input data not empty, else delete it
+ if (StrLen(Data)) {
+ BlockSize = StrLen(Data) + 1;
+ // Add string if does not exist, else replace it
+ StrNumber = GetStrNumber(TempBuffer, TableInfo.Type, TableInfo.Offset);
+ if (StrNumber == 0) {
+ AddStringNumber(TempBuffer, TableInfo.Type, TableInfo.Offset);
+ StrNumber = GetStrNumber(TempBuffer, TableInfo.Type, TableInfo.Offset);
+ }
+ ReplaceString(TempBuffer, StrNumber, Data);
+ }
+ else {
+ DeleteString(TempBuffer, TableInfo.Offset);
+ }
+ }
+ }
+
+ // Add structure terminator Null byte
+ AddNullTerminator(TempBuffer, StrTablePtr);
+
+ BlockSize = GetRemainingStructuresSize(TablePtr);
+ MemCpy(TempBuffer + GetStructureLength(TempBuffer), TablePtr, BlockSize);
+
+ // Replace all DMI data with TempBuffer
+ TempBuffer = ScratchBufferPtr;
+ BlockSize = GetRemainingStructuresSize(TempBuffer);
+ MemCpy(StructPtr, TempBuffer, BlockSize);
+
+ // Update SMBIOS Structure Table Entry Point - Structure Table Length, Intermediate checksum
+ UpdateHeaderInfo();
+
+ return DMI_SUCCESS;
+}
+
+#if OEM_STRING_INFO
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DynamicUpdateType11
+//
+// Description: Updates SMBIOS Type 11 Structure in Runtime with DMI data
+//
+// Input: IN UINT16 Handle,
+// IN TABLE_INFO TableInfo,
+// IN UINT8 *Data
+//
+// Output: UINT8 - Status
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT8
+DynamicUpdateType11(
+ IN UINT16 Handle,
+ IN TABLE_INFO TableInfo,
+ IN UINT8 *Data
+)
+{
+ UINT8 *TablePtr;
+ UINT8 *TempBuffer;
+ UINT8 *StructPtr;
+ UINT16 BlockSize;
+ UINT16 StringSize;
+ UINT8 i;
+ UINT16 AvailableBlkSize;
+ UINT8 Count;
+
+ StructPtr = GetStructureByHandle(&Handle);
+ if (StructPtr == NULL) {
+ return DMI_INVALID_HANDLE;
+ }
+
+ TablePtr = StructPtr;
+ TempBuffer = ScratchBufferPtr;
+
+ AvailableBlkSize = MaximumBufferSize - SmbiosTableEntryPoint->TableLength;
+ if (AvailableBlkSize < (StrLen(Data) + 1)) {
+ return DMI_BAD_PARAMETER; // Not enough space
+ }
+
+ // Copy structure data (without string data)
+ BlockSize = ((SMBIOS_STRUCTURE_HEADER*)TablePtr)->Length;
+ MemCpy(TempBuffer, TablePtr, BlockSize);
+ Count = ((SMBIOS_OEM_STRINGS_INFO*)TempBuffer)->Count;
+
+ TablePtr += BlockSize;
+ TempBuffer += BlockSize;
+
+ // string fields
+ for (i = 1; i < (Count + 1); i++) {
+ StringSize = StrLen(TablePtr) + 1; // Size including string NULL terminator
+ if (TableInfo.Offset == i) {
+ BlockSize = StrLen(Data) + 1;
+ MemCpy(TempBuffer, Data, BlockSize);
+ TempBuffer += BlockSize;
+ }
+ else {
+ MemCpy(TempBuffer, TablePtr, StringSize);
+ TempBuffer += StringSize;
+ }
+ TablePtr += StringSize;
+ }
+
+ // Add NULL byte for end of string-set
+ *TempBuffer = 0;
+ TempBuffer++;
+ TablePtr++;
+
+ BlockSize = GetRemainingStructuresSize(TablePtr);
+ MemCpy(TempBuffer, TablePtr, BlockSize);
+
+ // Replace all DMI data with TempBuffer
+ TempBuffer = ScratchBufferPtr;
+ BlockSize = GetRemainingStructuresSize(TempBuffer);
+ MemCpy(StructPtr, TempBuffer, BlockSize);
+
+ // Update SMBIOS Structure Table Entry Point - Structure Table Length, Intermediate checksum
+ UpdateHeaderInfo();
+
+ return DMI_SUCCESS;
+}
+#endif
+
+#if SYSTEM_CONFIG_OPTION_INFO
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: DynamicUpdateType12
+//
+// Description: Updates SMBIOS Type 12 Structure in Runtime with DMI data
+//
+// Input: IN UINT16 Handle,
+// IN TABLE_INFO TableInfo,
+// IN UINT8 *Data
+//
+// Output: UINT8 - Status
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT8
+DynamicUpdateType12(
+ IN UINT16 Handle,
+ IN TABLE_INFO TableInfo,
+ IN UINT8 *Data
+)
+{
+ UINT8 *TablePtr;
+ UINT8 *TempBuffer;
+ UINT8 *StructPtr;
+ UINT16 BlockSize;
+ UINT16 StringSize;
+ UINT8 i;
+ UINT16 AvailableBlkSize;
+ UINT8 Count;
+
+ StructPtr = GetStructureByHandle(&Handle);
+ if (StructPtr == NULL) {
+ return DMI_INVALID_HANDLE;
+ }
+
+ TablePtr = StructPtr;
+ TempBuffer = ScratchBufferPtr;
+
+ AvailableBlkSize = MaximumBufferSize - SmbiosTableEntryPoint->TableLength;
+ if (AvailableBlkSize < (StrLen(Data) + 1)) {
+ return DMI_BAD_PARAMETER; // Not enough space
+ }
+
+ // Copy structure data (without string data)
+ BlockSize = ((SMBIOS_STRUCTURE_HEADER*)TablePtr)->Length;
+ MemCpy(TempBuffer, TablePtr, BlockSize);
+ Count = ((SMBIOS_SYSTEM_CONFIG_INFO*)TempBuffer)->Count;
+
+ TablePtr += BlockSize;
+ TempBuffer += BlockSize;
+
+ // string fields
+ for (i = 1; i < (Count + 1); i++) {
+ StringSize = StrLen(TablePtr) + 1; // Size including string NULL terminator
+ if (TableInfo.Offset == i) {
+ BlockSize = StrLen(Data) + 1;
+ MemCpy(TempBuffer, Data, BlockSize);
+ TempBuffer += BlockSize;
+ }
+ else {
+ MemCpy(TempBuffer, TablePtr, StringSize);
+ TempBuffer += StringSize;
+ }
+ TablePtr += StringSize;
+ }
+
+ // Add NULL byte for end of string-set
+ *TempBuffer = 0;
+ TempBuffer++;
+ TablePtr++;
+
+ BlockSize = GetRemainingStructuresSize(TablePtr);
+ MemCpy(TempBuffer, TablePtr, BlockSize);
+
+ // Replace all DMI data with TempBuffer
+ TempBuffer = ScratchBufferPtr;
+ BlockSize = GetRemainingStructuresSize(TempBuffer);
+ MemCpy(StructPtr, TempBuffer, BlockSize);
+
+ // Update SMBIOS Structure Table Entry Point - Structure Table Length, Intermediate checksum
+ UpdateHeaderInfo();
+
+ return DMI_SUCCESS;
+}
+#endif
+
+/////////////////////////////////////////////
+// Worker function for setting structures. //
+/////////////////////////////////////////////
+
+#if !defined(SMBIOS_DMIEDIT_DATA_LOC) || SMBIOS_DMIEDIT_DATA_LOC == 2
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: StoreNvramData
+//
+// Description: Store DMIEdit data into input variable
+//
+// Input: IN CHAR16 *Var
+// IN VOID *Data
+// IN UINTN DataSize
+//
+// Global variable "DmiArray", "DmiArraySize",
+//
+// Output: UINT8 - Status
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+EFI_STATUS
+StoreNvramData(
+ IN CHAR16 *Var,
+ IN VOID *Data,
+ IN UINTN DataSize
+)
+{
+ EFI_STATUS Status;
+ UINTN Size;
+ UINT8 *Buffer;
+
+ // Check if variable already exists
+ //
+ // Size of zero is used to detect if the variable exists.
+ // If the variable exists, an error code of EFI_BUFFER_TOO_SMALL
+ // would be returned
+ Size = 0;
+ Status = pRS->GetVariable(
+ Var,
+ &EfiSmbiosNvramGuid,
+ NULL,
+ &Size,
+ &Buffer);
+
+ if (Status == EFI_NOT_FOUND) {
+ // Record not present, increment record count
+ DmiArray[0].Type += 1;
+
+ Status = pRS->SetVariable(
+ DmiArrayVar,
+ &EfiSmbiosNvramGuid,
+ EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ DmiArraySize,
+ &DmiArray);
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ // Update DMI data record if already exists,
+ // or store new record if total record count in DmiArray was successfully
+ // updated
+ if (Status == EFI_BUFFER_TOO_SMALL || Status == EFI_SUCCESS) {
+ Status = pRS->SetVariable(
+ Var,
+ &EfiSmbiosNvramGuid,
+ EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ DataSize,
+ Data);
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ return Status;
+}
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetDmiDataSize
+//
+// Description: Returns the data size for DMI Function 0x52
+//
+// Input: IN SET_SMBIOS_STRUCTURE_DATA *Data,
+//
+// Output: UINT16 - Data Size
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16
+GetDmiDataSize(
+ IN SET_SMBIOS_STRUCTURE_DATA *Data
+)
+{
+ switch(Data->Command) {
+ case 0:
+ return 1;
+ case 1:
+ return 2;
+ case 2:
+ return 4;
+ case 4:
+ return 0; // Delete command, size does not matter
+ default:
+ return Data->DataLength; // Add, String, or Block change command
+ }
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: GetInputDataInfo
+//
+// Description: Fills "TableInfo" with data from DMI Function 0x52
+//
+// Input: IN UINT16 Handle,
+// IN SET_SMBIOS_STRUCTURE_DATA *Data,
+// IN OUT TABLE_INFO *TableInfo
+//
+// Output: UINT16 - Data Size
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+VOID
+GetInputDataInfo(
+ IN UINT16 Handle,
+ IN SET_SMBIOS_STRUCTURE_DATA *Data,
+ IN OUT TABLE_INFO *TableInfo
+)
+{
+ TableInfo->Type = Data->StructureHeader.Type;
+ TableInfo->Offset = Data->FieldOffset;
+ TableInfo->Reserved = 0;
+ TableInfo->Flags = DMIEDIT_EXTENDED_HDR;
+ TableInfo->HdrLength = sizeof(TABLE_INFO);
+ TableInfo->Size = GetDmiDataSize(Data);
+ TableInfo->Handle = Handle;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SetType0
+//
+// Description: Updates Flash Data record with input DMI data
+// Updates SMBIOS Type 0 Structure in Runtime with DMI data
+//
+// Input: IN UINT16 Handle,
+// IN SET_SMBIOS_STRUCTURE_DATA *Data,
+// IN BOOLEAN Set
+//
+// Output: UINT8 - Status
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes: Type 0 Offset 8 (Release Date) is a fixed form string. This
+// function only checks for proper length. It is up to the DMI
+// editing utility to check for the proper format.
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16
+SetType0(
+ IN UINT16 Handle,
+ IN SET_SMBIOS_STRUCTURE_DATA *Data,
+ IN BOOLEAN Set
+)
+{
+ EFI_STATUS Status;
+ TABLE_INFO TableInfo;
+
+ if (Data->Command != 5) return DMI_BAD_PARAMETER;
+
+ if ( Data->FieldOffset != 4
+ && Data->FieldOffset != 5
+ && Data->FieldOffset != 8
+ ) return DMI_BAD_PARAMETER;
+
+ if ((Data->FieldOffset == 8) && (Data->DataLength != 11)) {
+ return DMI_BAD_PARAMETER; // Date string is fixed size
+ }
+
+ if (Set == FALSE) return DMI_SUCCESS;
+
+ if (isWriteOnce(0, Data->FieldOffset, Handle)) return DMI_READ_ONLY;
+
+ // Fill TableInfo with input data
+ GetInputDataInfo(Handle, Data, &TableInfo);
+
+#if !defined(SMBIOS_DMIEDIT_DATA_LOC) || SMBIOS_DMIEDIT_DATA_LOC != 2
+
+ Status = UpdateSmbiosTable(&TableInfo, Data->StructureData);
+
+#else
+{
+ //
+ // Get number of DMI data records in NVRAM
+ //
+ // Note: DMI data record actually starts with record #1,
+ // first record #0 holds total number of DMI data records
+ // instead of TABLE_INFO
+ // ===> DmiArray[0].Type = count
+ //
+ Status = pRS->GetVariable(
+ DmiArrayVar,
+ &EfiSmbiosNvramGuid,
+ NULL,
+ &DmiArraySize,
+ &DmiArray);
+
+ if (Status == EFI_SUCCESS) {
+ Index = DmiArray[0].Type; // Note: DmiArray[0] has count # instead of Type/Offset
+ ++Index;
+ }
+ else {
+ Index = 1;
+ }
+
+ DmiArray[Index].Type = 0;
+ DmiArray[Index].Handle = Handle;
+ DmiArray[Index].Offset = Data->FieldOffset;
+ DmiArray[Index].Flags = 0;
+
+ Swprintf(Var, L"DmiVar%02x%04x%02x%02x",
+ DmiArray[Index].Type,
+ DmiArray[Index].Handle,
+ DmiArray[Index].Offset,
+ DmiArray[Index].Flags);
+
+ if (Set == FALSE) return DMI_SUCCESS;
+
+ Status = StoreNvramData(Var, &Data->StructureData, (UINTN)TableInfo.Size);
+}
+#endif
+
+ if (Status) {
+ return (UINT16)Status;
+ }
+
+ // Dynamically update strings in Smbios table
+ return UpdateStrings(Handle, TableInfo, Data->StructureData);
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SetType1
+//
+// Description: Updates Flash Data record with input DMI data
+// Updates SMBIOS Type 1 Structure in Runtime with DMI data
+//
+// Input: IN UINT16 Handle,
+// IN SET_SMBIOS_STRUCTURE_DATA *Data,
+// IN BOOLEAN Set
+//
+// Output: UINT8 - Status
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16
+SetType1(
+ IN UINT16 Handle,
+ IN SET_SMBIOS_STRUCTURE_DATA *Data,
+ IN BOOLEAN Set
+)
+{
+ EFI_STATUS Status;
+ TABLE_INFO TableInfo;
+ UINT8 *UuidPtr;
+ UINT8 i;
+
+ // Fill TableInfo with input data
+ GetInputDataInfo(Handle, Data, &TableInfo);
+
+#if !defined(SMBIOS_DMIEDIT_DATA_LOC) || SMBIOS_DMIEDIT_DATA_LOC != 2
+ switch (Data->FieldOffset) {
+ case 0x04 :
+ case 0x05 :
+ case 0x06 :
+ case 0x07 :
+ case 0x19 :
+ case 0x1a : if (Data->Command != 5) return DMI_BAD_PARAMETER;
+
+ if (Set == FALSE) return DMI_SUCCESS;
+
+ if (isWriteOnce(1, Data->FieldOffset, Handle)) return DMI_READ_ONLY;
+
+ Status = UpdateSmbiosTable(&TableInfo, Data->StructureData);
+ break;
+
+ default: if ((Data->FieldOffset > 0x07) && (Data->FieldOffset < 0x18)) {
+ UINT8 *Ptr;
+
+ Ptr = GetStructureByHandle(&Handle);
+ UuidPtr = (UINT8*)&((SMBIOS_SYSTEM_INFO*)Ptr)->Uuid;
+ Ptr = UuidPtr + Data->FieldOffset - 8;
+
+ if (Data->Command < 3) {
+ if (Data->Command == 0) {
+ *Ptr &= (UINT8)Data->ChangeMask;
+ *Ptr |= (UINT8)Data->ChangeValue;
+ }
+ if (Data->Command == 1) {
+ *(UINT16*)Ptr &= (UINT16)Data->ChangeMask;
+ *(UINT16*)Ptr |= (UINT16)Data->ChangeValue;
+ }
+ if (Data->Command == 2) {
+ *(UINT32*)Ptr &= Data->ChangeMask;
+ *(UINT32*)Ptr |= Data->ChangeValue;
+ }
+ }
+ else if (Data->Command == 6) {
+ for (i = 0; i < (UINT8)TableInfo.Size; i++) {
+ Ptr[i] = Data->StructureData[i];
+ }
+ }
+ else {
+ return DMI_BAD_PARAMETER;
+ }
+
+ if (Set == FALSE) return DMI_SUCCESS;
+
+ if (isWriteOnce(1, Data->FieldOffset, Handle)) return DMI_READ_ONLY;
+
+ TableInfo.Offset = 8;
+ TableInfo.Size = sizeof(EFI_GUID);
+
+ Status = UpdateSmbiosTable(&TableInfo, UuidPtr);
+ }
+ else {
+ return DMI_BAD_PARAMETER;
+ }
+ }
+#else
+{
+ VOID *NvramData;
+
+ NvramData = &Data->StructureData;
+
+ //
+ // Get number of DMI data records in NVRAM
+ //
+ // Note: DMI data record actually starts with record #1,
+ // first record #0 holds total number of DMI data records
+ // instead of TABLE_INFO
+ // ===> DmiArray[0].Type = count
+ //
+ Status = pRS->GetVariable(
+ DmiArrayVar,
+ &EfiSmbiosNvramGuid,
+ NULL,
+ &DmiArraySize,
+ &DmiArray);
+
+ if (Status == EFI_SUCCESS) {
+ Index = DmiArray[0].Type; // Note: DmiArray[0] has count # instead of Type/Offset
+ ++Index;
+ }
+ else {
+ Index = 1;
+ }
+
+ DmiArray[Index].Type = 1;
+ DmiArray[Index].Handle = Handle;
+ DmiArray[Index].Offset = Data->FieldOffset;
+ DmiArray[Index].Flags = 0;
+
+ switch (Data->FieldOffset) {
+ case 0x04 :
+ case 0x05 :
+ case 0x06 :
+ case 0x07 :
+ case 0x19 :
+ case 0x1a : if (Data->Command != 5) return DMI_BAD_PARAMETER;
+ break;
+
+ default: if ((Data->FieldOffset > 0x07) && (Data->FieldOffset < 0x18)) {
+ UINT8 *Ptr;
+
+ Ptr = GetStructureByHandle(&Handle);
+ UuidPtr = (UINT8*)&((SMBIOS_SYSTEM_INFO*)Ptr)->Uuid;
+ Ptr = UuidPtr + Data->FieldOffset - 8;
+
+ if (Data->Command < 3) {
+ if (Data->Command == 0) {
+ *Ptr &= (UINT8)Data->ChangeMask;
+ *Ptr |= (UINT8)Data->ChangeValue;
+ }
+ if (Data->Command == 1) {
+ *(UINT16*)Ptr &= (UINT16)Data->ChangeMask;
+ *(UINT16*)Ptr |= (UINT16)Data->ChangeValue;
+ }
+ if (Data->Command == 2) {
+ *(UINT32*)Ptr &= Data->ChangeMask;
+ *(UINT32*)Ptr |= Data->ChangeValue;
+ }
+ }
+ else if (Data->Command == 6) {
+ for (i = 0; i < (UINT8)TableInfo.Size; i++) {
+ Ptr[i] = Data->StructureData[i];
+ }
+ }
+ else {
+ return DMI_BAD_PARAMETER;
+ }
+
+ DmiArray[Index].Offset = 0x08;
+ NvramData = UuidPtr;
+ TableInfo.Offset = 8;
+ TableInfo.Size = sizeof(EFI_GUID);
+ }
+ else {
+ return DMI_BAD_PARAMETER;
+ }
+ }
+
+ if (Set == FALSE) return DMI_SUCCESS;
+
+ if (isWriteOnce(1, Data->FieldOffset, Handle)) return DMI_READ_ONLY;
+
+ Swprintf(Var, L"DmiVar%02x%04x%02x%02x",
+ DmiArray[Index].Type,
+ DmiArray[Index].Handle,
+ DmiArray[Index].Offset,
+ DmiArray[Index].Flags);
+
+ Status = StoreNvramData(Var, NvramData, (UINTN)TableInfo.Size);
+}
+#endif
+
+ TRACE((-1, "Change structure. Type = %x, Handle = %x, Offset = %x\n",\
+ TableInfo.Type,\
+ TableInfo.Handle,\
+ TableInfo.Offset));
+
+ if (Status) {
+ return (UINT16)Status;
+ }
+
+ if ((Data->FieldOffset > 0x07) && (Data->FieldOffset < 0x18)) {
+ return DMI_SUCCESS;
+ }
+ else {
+ // Dynamically update strings in Smbios table
+ return UpdateStrings(Handle, TableInfo, Data->StructureData);
+ }
+}
+
+#if BASE_BOARD_INFO
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SetType2
+//
+// Description: Updates Flash Data record with input DMI data
+// Updates SMBIOS Type 2 Structure in Runtime with DMI data
+//
+// Input: IN UINT16 Handle,
+// IN SET_SMBIOS_STRUCTURE_DATA *Data,
+// IN BOOLEAN Set
+//
+// Output: UINT8 - Status
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16
+SetType2(
+ IN UINT16 Handle,
+ IN SET_SMBIOS_STRUCTURE_DATA *Data,
+ IN BOOLEAN Set
+)
+{
+ EFI_STATUS Status;
+ TABLE_INFO TableInfo;
+
+ if (Data->Command != 5) return DMI_BAD_PARAMETER;
+ if ( Data->FieldOffset != 4
+ && Data->FieldOffset != 5
+ && Data->FieldOffset != 6
+ && Data->FieldOffset != 7
+ && Data->FieldOffset != 8
+ && Data->FieldOffset != 0x0a
+ ) return DMI_BAD_PARAMETER;
+
+ if (Set == FALSE) return DMI_SUCCESS;
+
+ if (isWriteOnce(2, Data->FieldOffset, Handle)) return DMI_READ_ONLY;
+
+ // Fill TableInfo with input data
+ GetInputDataInfo(Handle, Data, &TableInfo);
+
+#if !defined(SMBIOS_DMIEDIT_DATA_LOC) || SMBIOS_DMIEDIT_DATA_LOC != 2
+
+ Status = UpdateSmbiosTable(&TableInfo, Data->StructureData);
+
+#else
+{
+ //
+ // Get number of DMI data records in NVRAM
+ //
+ // Note: DMI data record actually starts with record #1,
+ // first record #0 holds total number of DMI data records
+ // instead of TABLE_INFO
+ // ===> DmiArray[0].Type = count
+ //
+ Status = pRS->GetVariable(
+ DmiArrayVar,
+ &EfiSmbiosNvramGuid,
+ NULL,
+ &DmiArraySize,
+ &DmiArray);
+
+ if (Status == EFI_SUCCESS) {
+ Index = DmiArray[0].Type; // Note: DmiArray[0] has count # instead of Type/Offset
+ ++Index;
+ }
+ else {
+ Index = 1;
+ }
+
+ DmiArray[Index].Type = 2;
+ DmiArray[Index].Handle = Handle;
+ DmiArray[Index].Offset = Data->FieldOffset;
+ DmiArray[Index].Flags = 0;
+
+ Swprintf(Var, L"DmiVar%02x%04x%02x%02x",
+ DmiArray[Index].Type,
+ DmiArray[Index].Handle,
+ DmiArray[Index].Offset,
+ DmiArray[Index].Flags);
+
+ Status = StoreNvramData(Var, &Data->StructureData, (UINTN)TableInfo.Size);
+}
+#endif
+
+ if (Status) {
+ return (UINT16)Status;
+ }
+
+ // Dynamically update strings in Smbios table
+ return UpdateStrings(Handle, TableInfo, Data->StructureData);
+}
+#endif
+
+#if SYS_CHASSIS_INFO
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SetType3
+//
+// Description: Updates Flash Data record with input DMI data
+// Updates SMBIOS Type 3 Structure in Runtime with DMI data
+//
+// Input: IN UINT16 Handle,
+// IN SET_SMBIOS_STRUCTURE_DATA *Data,
+// IN BOOLEAN Set
+//
+// Output: UINT8 - Status
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16
+SetType3(
+ IN UINT16 Handle,
+ IN SET_SMBIOS_STRUCTURE_DATA *Data,
+ IN BOOLEAN Set
+)
+{
+ EFI_STATUS Status;
+ TABLE_INFO TableInfo;
+ UINT8 *StructPtr;
+ UINT8 Instance;
+ STRING_TABLE *StringTablePtr;
+
+ switch (Data->FieldOffset) {
+ case 4:
+ case 6:
+ case 7:
+ case 8: if (Data->Command != 5) return DMI_BAD_PARAMETER;
+ break;
+ case 5: if (Data->Command != 0) return DMI_BAD_PARAMETER;
+ break;
+ case 0x0d: if (Data->Command != 2) return DMI_BAD_PARAMETER;
+ break;
+ default: {
+ // Get instance number
+ Instance = GetInstanceByTypeHandle(3, Handle);
+ StringTablePtr = &StringType_3[0][0];
+ StringTablePtr += 6 * (Instance - 1);
+
+ while (StringTablePtr->Offset != 0xff) {
+ if (StringTablePtr->Offset == Data->FieldOffset) {
+ break;
+ }
+
+ StringTablePtr++;
+ };
+
+ if (StringTablePtr->Offset != 0xff) {
+ if (Data->Command != 0x5) {
+ return DMI_BAD_PARAMETER;
+ }
+ }
+ else {
+ return DMI_BAD_PARAMETER;
+ }
+ }
+ }
+
+ if (Set == FALSE) return DMI_SUCCESS;
+
+ if (isWriteOnce(3, Data->FieldOffset, Handle)) return DMI_READ_ONLY;
+
+ // Fill TableInfo with input data
+ GetInputDataInfo(Handle, Data, &TableInfo);
+
+#if !defined(SMBIOS_DMIEDIT_DATA_LOC) || SMBIOS_DMIEDIT_DATA_LOC != 2
+ if (Data->Command == 0 || Data->Command == 0x2)
+ *(UINT32*)Data->StructureData = Data->ChangeValue;
+
+ Status = UpdateSmbiosTable(&TableInfo, Data->StructureData);
+
+#else
+{
+ //
+ // Get number of DMI data records in NVRAM
+ //
+ // Note: DMI data record actually starts with record #1,
+ // first record #0 holds total number of DMI data records
+ // instead of TABLE_INFO
+ // ===> DmiArray[0].Type = count
+ //
+ Status = pRS->GetVariable(
+ DmiArrayVar,
+ &EfiSmbiosNvramGuid,
+ NULL,
+ &DmiArraySize,
+ &DmiArray);
+
+ if (Status == EFI_SUCCESS) {
+ Index = DmiArray[0].Type; // Note: DmiArray[0] has count # instead of Type/Offset
+ ++Index;
+ }
+ else {
+ Index = 1;
+ }
+
+ DmiArray[Index].Type = 3;
+ DmiArray[Index].Handle = Handle;
+ DmiArray[Index].Offset = Data->FieldOffset;
+ DmiArray[Index].Flags = 0;
+
+ Swprintf(Var, L"DmiVar%02x%04x%02x%02x",
+ DmiArray[Index].Type,
+ DmiArray[Index].Handle,
+ DmiArray[Index].Offset,
+ DmiArray[Index].Flags);
+
+ if (Data->Command == 0 || Data->Command == 0x2)
+ *(UINT32*)Data->StructureData = Data->ChangeValue;
+
+ Status = StoreNvramData(Var, &Data->StructureData, (UINTN)TableInfo.Size);
+}
+#endif
+
+ if (Status) {
+ return (UINT16)Status;
+ }
+
+ // Dynamically update the structure in the Smbios table
+ StructPtr = GetStructureByHandle(&Handle);
+ if (StructPtr != NULL) {
+ switch (Data->FieldOffset) {
+ case 0x05: ((SMBIOS_SYSTEM_ENCLOSURE_INFO*)StructPtr)->Type &= (UINT8)Data->ChangeMask;
+ ((SMBIOS_SYSTEM_ENCLOSURE_INFO*)StructPtr)->Type |= (UINT8)Data->ChangeValue;
+ break;
+ case 0x0d: ((SMBIOS_SYSTEM_ENCLOSURE_INFO*)StructPtr)->OemDefined &= (UINT32)Data->ChangeMask;
+ ((SMBIOS_SYSTEM_ENCLOSURE_INFO*)StructPtr)->OemDefined |= (UINT32)Data->ChangeValue;
+ }
+ }
+
+ return UpdateStrings(Handle, TableInfo, Data->StructureData);
+}
+#endif
+
+#if PROCESSOR_DMIEDIT_SUPPORT
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SetType4
+//
+// Description: Updates Flash Data record with input DMI data
+// Updates SMBIOS Type 4 Structure in Runtime with DMI data
+//
+// Input: IN UINT16 Handle,
+// IN SET_SMBIOS_STRUCTURE_DATA *Data,
+// IN BOOLEAN Set
+//
+// Output: UINT8 - Status
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16
+SetType4(
+ IN UINT16 Handle,
+ IN SET_SMBIOS_STRUCTURE_DATA *Data,
+ IN BOOLEAN Set
+)
+{
+ EFI_STATUS Status;
+ TABLE_INFO TableInfo;
+
+ switch (Data->FieldOffset) {
+ case 0x20:
+ case 0x21:
+ case 0x22: if (Data->Command != 0x5) return DMI_BAD_PARAMETER;
+ break;
+ default: return DMI_BAD_PARAMETER;
+ }
+
+ if (Set == FALSE) return DMI_SUCCESS;
+
+ // Fill TableInfo with input data
+ GetInputDataInfo(Handle, Data, &TableInfo);
+
+#if !defined(SMBIOS_DMIEDIT_DATA_LOC) || SMBIOS_DMIEDIT_DATA_LOC != 2
+ Status = UpdateSmbiosTable(&TableInfo, Data->StructureData);
+#else
+{
+ //
+ // Get number of DMI data records in NVRAM
+ //
+ // Note: DMI data record actually starts with record #1,
+ // first record #0 holds total number of DMI data records
+ // instead of TABLE_INFO
+ // ===> DmiArray[0].Type = count
+ //
+ Status = pRS->GetVariable(
+ DmiArrayVar,
+ &EfiSmbiosNvramGuid,
+ NULL,
+ &DmiArraySize,
+ &DmiArray);
+
+ if (Status == EFI_SUCCESS) {
+ Index = DmiArray[0].Type; // Note: DmiArray[0] has count # instead of Type/Offset
+ ++Index;
+ }
+ else {
+ Index = 1;
+ }
+
+ DmiArray[Index].Type = 4;
+ DmiArray[Index].Handle = Handle;
+ DmiArray[Index].Offset = Data->FieldOffset;
+ DmiArray[Index].Flags = 0;
+
+ Swprintf(Var, L"DmiVar%02x%04x%02x%02x",
+ DmiArray[Index].Type,
+ DmiArray[Index].Handle,
+ DmiArray[Index].Offset,
+ DmiArray[Index].Flags);
+
+ Status = StoreNvramData(Var, &Data->StructureData, (UINTN)TableInfo.Size);
+}
+#endif
+
+ if (Status) {
+ return (UINT16)Status;
+ }
+
+ // Dynamically update the structure in the Smbios table
+ return UpdateStrings(Handle, TableInfo, Data->StructureData);
+}
+#endif
+
+#if OEM_STRING_INFO
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SetType11
+//
+// Description: Updates Flash Data record with input DMI data
+// Updates SMBIOS Type 11 Structure in Runtime with DMI data
+//
+// Input: IN UINT16 Handle,
+// IN SET_SMBIOS_STRUCTURE_DATA *Data,
+// IN BOOLEAN Set
+//
+// Output: UINT8 - Status
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16
+SetType11(
+ IN UINT16 Handle,
+ IN SET_SMBIOS_STRUCTURE_DATA *Data,
+ IN BOOLEAN Set
+)
+{
+ EFI_STATUS Status;
+ TABLE_INFO TableInfo;
+ static UINT8 StringNumber = 0;
+
+ if (isWriteOnce(11, Data->FieldOffset, Handle)) return DMI_READ_ONLY;
+
+ // Fill TableInfo with input data
+ GetInputDataInfo(Handle, Data, &TableInfo);
+
+ if (Data->Command == 0) {
+ if (Data->FieldOffset != 4) return DMI_BAD_PARAMETER;
+ if (Set == FALSE) return DMI_SUCCESS;
+
+ StringNumber = (UINT8) Data->ChangeValue;
+ return DMI_SUCCESS;
+ }
+
+ if (Data->Command != 5) return DMI_BAD_PARAMETER;
+ if (Data->FieldOffset != 4) return DMI_BAD_PARAMETER;
+ if (!StringNumber) return DMI_BAD_PARAMETER;
+ if (Set == FALSE) return DMI_SUCCESS;
+
+ TableInfo.Offset = StringNumber;
+
+#if !defined(SMBIOS_DMIEDIT_DATA_LOC) || SMBIOS_DMIEDIT_DATA_LOC != 2
+
+ Status = UpdateSmbiosTable(&TableInfo, Data->StructureData);
+
+#else
+{
+ //
+ // Get number of DMI data records in NVRAM
+ //
+ // Note: DMI data record actually starts with record #1,
+ // first record #0 holds total number of DMI data records
+ // instead of TABLE_INFO
+ // ===> DmiArray[0].Type = count
+ //
+ Status = pRS->GetVariable(
+ DmiArrayVar,
+ &EfiSmbiosNvramGuid,
+ NULL,
+ &DmiArraySize,
+ &DmiArray);
+
+ if (Status == EFI_SUCCESS) {
+ Index = DmiArray[0].Type; // Note: DmiArray[0] has count # instead of Type/Offset
+ ++Index;
+ }
+ else {
+ Index = 1;
+ }
+
+ DmiArray[Index].Type = 11;
+ DmiArray[Index].Handle = Handle;
+ DmiArray[Index].Offset = StringNumber - 1;
+ DmiArray[Index].Flags = 0;
+
+ Swprintf(Var, L"DmiVar%02x%04x%02x%02x",
+ DmiArray[Index].Type,
+ DmiArray[Index].Handle,
+ DmiArray[Index].Offset,
+ DmiArray[Index].Flags);
+
+ Status = StoreNvramData(Var, &Data->StructureData, (UINTN)TableInfo.Size);
+}
+#endif
+
+ if (Status) {
+ return (UINT16)Status;
+ }
+ return DynamicUpdateType11(Handle, TableInfo, Data->StructureData);
+}
+#endif
+
+#if SYSTEM_CONFIG_OPTION_INFO
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SetType12
+//
+// Description: Updates Flash Data record with input DMI data
+// Updates SMBIOS Type 12 Structure in Runtime with DMI data
+//
+// Input: IN UINT16 Handle,
+// IN SET_SMBIOS_STRUCTURE_DATA *Data,
+// IN BOOLEAN Set
+//
+// Output: UINT8 - Status
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16
+SetType12(
+ UINT16 Handle,
+ SET_SMBIOS_STRUCTURE_DATA *Data,
+ BOOLEAN Set
+)
+{
+ EFI_STATUS Status;
+ TABLE_INFO TableInfo;
+ static UINT8 StringNumber = 0;
+
+ if (Data->Command == 0) {
+ if (Data->FieldOffset != 4) return DMI_BAD_PARAMETER;
+ if (Set == FALSE) return DMI_SUCCESS;
+
+ StringNumber = (UINT8) Data->ChangeValue;
+ return DMI_SUCCESS;
+ }
+
+ if (Data->Command != 5) return DMI_BAD_PARAMETER;
+ if (Data->FieldOffset != 4) return DMI_BAD_PARAMETER;
+ if (!StringNumber) return DMI_BAD_PARAMETER;
+ if (Set == FALSE) return DMI_SUCCESS;
+
+ if (isWriteOnce(12, Data->FieldOffset, Handle)) return DMI_READ_ONLY;
+
+ // Fill TableInfo with input data
+ GetInputDataInfo(Handle, Data, &TableInfo);
+
+ TableInfo.Offset = StringNumber;
+
+#if !defined(SMBIOS_DMIEDIT_DATA_LOC) || SMBIOS_DMIEDIT_DATA_LOC != 2
+ Status = UpdateSmbiosTable(&TableInfo, Data->StructureData);
+ if (Status != 0) {
+ return (UINT16)Status;
+ }
+#else
+{
+ //
+ // Get number of DMI data records in NVRAM
+ //
+ // Note: DMI data record actually starts with record #1,
+ // first record #0 holds total number of DMI data records
+ // instead of TABLE_INFO
+ // ===> DmiArray[0].Type = count
+ //
+ Status = pRS->GetVariable(
+ DmiArrayVar,
+ &EfiSmbiosNvramGuid,
+ NULL,
+ &DmiArraySize,
+ &DmiArray);
+
+ if (Status == EFI_SUCCESS) {
+ Index = DmiArray[0].Type; // Note: DmiArray[0] has count # instead of Type/Offset
+ ++Index;
+ }
+ else {
+ Index = 1;
+ }
+
+ DmiArray[Index].Type = 12;
+ DmiArray[Index].Handle = Handle;
+ DmiArray[Index].Offset = StringNumber - 1;
+ DmiArray[Index].Flags = 0;
+
+ Swprintf(Var, L"DmiVar%02x%04x%02x%02x",
+ DmiArray[Index].Type,
+ DmiArray[Index].Handle,
+ DmiArray[Index].Offset,
+ DmiArray[Index].Flags);
+
+ Status = StoreNvramData(Var, &Data->StructureData, (UINTN)TableInfo.Size);
+}
+#endif
+
+ if (Status) {
+ return (UINT16)Status;
+ }
+ return DynamicUpdateType12(Handle, TableInfo, Data->StructureData);
+}
+#endif
+
+#if PORTABLE_BATTERY_INFO
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SetType22
+//
+// Description: Updates Flash Data record with input DMI data
+// Updates SMBIOS Type 22 Structure in Runtime with DMI data
+//
+// Input: IN UINT16 Handle,
+// IN SET_SMBIOS_STRUCTURE_DATA *Data,
+// IN BOOLEAN Set
+//
+// Output: UINT8 - Status
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16
+SetType22(
+ IN UINT16 Handle,
+ IN SET_SMBIOS_STRUCTURE_DATA *Data,
+ IN BOOLEAN Set
+)
+{
+ EFI_STATUS Status;
+ TABLE_INFO TableInfo;
+ UINT8 *StructPtr;
+
+ switch (Data->FieldOffset) {
+ case 0x09:
+ case 0x0f:
+ case 0x15: if (Data->Command != 0) return DMI_BAD_PARAMETER;
+ break;
+ case 0x0a:
+ case 0x0c:
+ case 0x10:
+ case 0x12: if (Data->Command != 1) return DMI_BAD_PARAMETER;
+ break;
+ case 0x16: if (Data->Command != 2) return DMI_BAD_PARAMETER;
+ break;
+ case 0x04:
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ case 0x08:
+ case 0x0e:
+ case 0x14: if (Data->Command != 5) return DMI_BAD_PARAMETER;
+ break;
+ default: return DMI_BAD_PARAMETER;
+ }
+
+ if (Set == FALSE) return DMI_SUCCESS;
+
+ if (isWriteOnce(22, Data->FieldOffset, Handle)) return DMI_READ_ONLY;
+
+ // Fill TableInfo with input data
+ GetInputDataInfo(Handle, Data, &TableInfo);
+
+ if (Data->Command == 0 || Data->Command == 0x1 || Data->Command == 0x2)
+ *(UINT32*)Data->StructureData = Data->ChangeValue;
+
+#if !defined(SMBIOS_DMIEDIT_DATA_LOC) || SMBIOS_DMIEDIT_DATA_LOC != 2
+
+ Status = UpdateSmbiosTable(&TableInfo, Data->StructureData);
+
+#else
+ //
+ // Get number of DMI data records in NVRAM
+ //
+ // Note: DMI data record actually starts with record #1,
+ // first record #0 holds total number of DMI data records
+ // instead of TABLE_INFO
+ // ===> DmiArray[0].Type = count
+ //
+ Status = pRS->GetVariable(
+ DmiArrayVar,
+ &EfiSmbiosNvramGuid,
+ NULL,
+ &DmiArraySize,
+ &DmiArray);
+
+ if (Status == EFI_SUCCESS) {
+ Index = DmiArray[0].Type; // Note: DmiArray[0] has count # instead of Type/Offset
+ ++Index;
+ }
+ else {
+ Index = 1;
+ }
+
+ DmiArray[Index].Type = 22;
+ DmiArray[Index].Handle = Handle;
+ DmiArray[Index].Offset = Data->FieldOffset;
+ DmiArray[Index].Flags = 0;
+
+ Swprintf(Var, L"DmiVar%02x%04x%02x%02x",
+ DmiArray[Index].Type,
+ DmiArray[Index].Handle,
+ DmiArray[Index].Offset,
+ DmiArray[Index].Flags);
+
+ Status = StoreNvramData(Var, &Data->StructureData, (UINTN)TableInfo.Size);
+#endif
+
+ if (Status) {
+ return (UINT16)Status;
+ }
+
+ // Dynamically update the structure in the Smbios table
+ StructPtr = GetStructureByHandle(&Handle);
+ if (StructPtr != NULL) {
+ switch (Data->FieldOffset) {
+ case 0x09: ((SMBIOS_PORTABLE_BATTERY_INFO*)StructPtr)->DeviceChemistry &= (UINT8)Data->ChangeMask;
+ ((SMBIOS_PORTABLE_BATTERY_INFO*)StructPtr)->DeviceChemistry |= (UINT8)Data->ChangeValue;
+ break;
+ case 0x0a: ((SMBIOS_PORTABLE_BATTERY_INFO*)StructPtr)->DesignCapacity &= (UINT16)Data->ChangeMask;
+ ((SMBIOS_PORTABLE_BATTERY_INFO*)StructPtr)->DesignCapacity |= (UINT16)Data->ChangeValue;
+ break;
+ case 0x0c: ((SMBIOS_PORTABLE_BATTERY_INFO*)StructPtr)->DesignVoltage &= (UINT16)Data->ChangeMask;
+ ((SMBIOS_PORTABLE_BATTERY_INFO*)StructPtr)->DesignVoltage |= (UINT16)Data->ChangeValue;
+ break;
+ case 0x0f: ((SMBIOS_PORTABLE_BATTERY_INFO*)StructPtr)->MaxErrorInBatteryData &= (UINT16)Data->ChangeMask;
+ ((SMBIOS_PORTABLE_BATTERY_INFO*)StructPtr)->MaxErrorInBatteryData |= (UINT16)Data->ChangeValue;
+ break;
+ case 0x10: ((SMBIOS_PORTABLE_BATTERY_INFO*)StructPtr)->SBDSSerialNumber &= (UINT16)Data->ChangeMask;
+ ((SMBIOS_PORTABLE_BATTERY_INFO*)StructPtr)->SBDSSerialNumber |= (UINT16)Data->ChangeValue;
+ break;
+ case 0x12: ((SMBIOS_PORTABLE_BATTERY_INFO*)StructPtr)->SBDSManufacturerDate &= (UINT16)Data->ChangeMask;
+ ((SMBIOS_PORTABLE_BATTERY_INFO*)StructPtr)->SBDSManufacturerDate |= (UINT16)Data->ChangeValue;
+ break;
+ case 0x15: ((SMBIOS_PORTABLE_BATTERY_INFO*)StructPtr)->DesignCapabilityMult &= (UINT16)Data->ChangeMask;
+ ((SMBIOS_PORTABLE_BATTERY_INFO*)StructPtr)->DesignCapabilityMult |= (UINT16)Data->ChangeValue;
+ break;
+ case 0x16: ((SMBIOS_PORTABLE_BATTERY_INFO*)StructPtr)->OEMSpecific &= (UINT32)Data->ChangeMask;
+ ((SMBIOS_PORTABLE_BATTERY_INFO*)StructPtr)->OEMSpecific |= (UINT32)Data->ChangeValue;
+ break;
+ }
+ }
+
+ return UpdateStrings(Handle, TableInfo, Data->StructureData);
+}
+#endif
+
+#if SYSTEM_POWER_SUPPLY_INFO
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SetType39
+//
+// Description: Updates Flash Data record with input DMI data
+// Updates SMBIOS Type 39 Structure in Runtime with DMI data
+//
+// Input: IN UINT16 Handle,
+// IN SET_SMBIOS_STRUCTURE_DATA *Data,
+// IN BOOLEAN Set
+//
+// Output: UINT8 - Status
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16
+SetType39(
+ IN UINT16 Handle,
+ IN SET_SMBIOS_STRUCTURE_DATA *Data,
+ IN BOOLEAN Set
+)
+{
+ EFI_STATUS Status;
+ TABLE_INFO TableInfo;
+ UINT8 *StructPtr;
+
+ switch (Data->FieldOffset) {
+ case 0x04: if (Data->Command != 0) return DMI_BAD_PARAMETER;
+ break;
+ case 0x05:
+ case 0x06:
+ case 0x07:
+ case 0x08:
+ case 0x09:
+ case 0x0a:
+ case 0x0b: if (Data->Command != 5) return DMI_BAD_PARAMETER;
+ break;
+ case 0x0c:
+ case 0x0e:
+ case 0x10:
+ case 0x12:
+ case 0x14: if (Data->Command != 1) return DMI_BAD_PARAMETER;
+ break;
+ default: return DMI_BAD_PARAMETER;
+ }
+
+ if (Set == FALSE) return DMI_SUCCESS;
+
+ if (isWriteOnce(39, Data->FieldOffset, Handle)) return DMI_READ_ONLY;
+
+ // Fill TableInfo with input data
+ GetInputDataInfo(Handle, Data, &TableInfo);
+
+ if (Data->Command == 0 || Data->Command == 0x1)
+ *(UINT32*)Data->StructureData = Data->ChangeValue;
+
+#if !defined(SMBIOS_DMIEDIT_DATA_LOC) || SMBIOS_DMIEDIT_DATA_LOC != 2
+
+ Status = UpdateSmbiosTable(&TableInfo, Data->StructureData);
+
+#else
+{
+ //
+ // Get number of DMI data records in NVRAM
+ //
+ // Note: DMI data record actually starts with record #1,
+ // first record #0 holds total number of DMI data records
+ // instead of TABLE_INFO
+ // ===> DmiArray[0].Type = count
+ //
+ Status = pRS->GetVariable(
+ DmiArrayVar,
+ &EfiSmbiosNvramGuid,
+ NULL,
+ &DmiArraySize,
+ &DmiArray);
+
+ if (Status == EFI_SUCCESS) {
+ Index = DmiArray[0].Type; // Note: DmiArray[0] has count # instead of Type/Offset
+ ++Index;
+ }
+ else {
+ Index = 1;
+ }
+
+ DmiArray[Index].Type = 39;
+ DmiArray[Index].Handle = Handle;
+ DmiArray[Index].Offset = Data->FieldOffset;
+ DmiArray[Index].Flags = 0;
+
+ Swprintf(Var, L"DmiVar%02x%04x%02x%02x",
+ DmiArray[Index].Type,
+ DmiArray[Index].Handle,
+ DmiArray[Index].Offset,
+ DmiArray[Index].Flags);
+
+ Status = StoreNvramData(Var, &Data->StructureData, (UINTN)TableInfo.Size);
+}
+#endif
+
+ if (Status) {
+ return (UINT16)Status;
+ }
+
+ // Dynamically update the structure in the Smbios table
+ StructPtr = GetStructureByHandle(&Handle);
+ if (StructPtr != NULL) {
+ switch (Data->FieldOffset) {
+ case 0x04: ((SMBIOS_SYSTEM_PWR_SUPPY_INFO*)StructPtr)->PwrUnitGroup &= (UINT8)Data->ChangeMask;
+ ((SMBIOS_SYSTEM_PWR_SUPPY_INFO*)StructPtr)->PwrUnitGroup |= (UINT8)Data->ChangeValue;
+ break;
+ case 0x0c: ((SMBIOS_SYSTEM_PWR_SUPPY_INFO*)StructPtr)->MaxPwrCapacity &= (UINT16)Data->ChangeMask;
+ ((SMBIOS_SYSTEM_PWR_SUPPY_INFO*)StructPtr)->MaxPwrCapacity |= (UINT16)Data->ChangeValue;
+ break;
+ case 0x0e: ((SMBIOS_SYSTEM_PWR_SUPPY_INFO*)StructPtr)->PwrSupplyChar &= (UINT16)Data->ChangeMask;
+ ((SMBIOS_SYSTEM_PWR_SUPPY_INFO*)StructPtr)->PwrSupplyChar |= (UINT16)Data->ChangeValue;
+ break;
+ case 0x10: ((SMBIOS_SYSTEM_PWR_SUPPY_INFO*)StructPtr)->InputVoltProbeHandle &= (UINT16)Data->ChangeMask;
+ ((SMBIOS_SYSTEM_PWR_SUPPY_INFO*)StructPtr)->InputVoltProbeHandle |= (UINT16)Data->ChangeValue;
+ break;
+ case 0x12: ((SMBIOS_SYSTEM_PWR_SUPPY_INFO*)StructPtr)->CoolingDevHandle &= (UINT16)Data->ChangeMask;
+ ((SMBIOS_SYSTEM_PWR_SUPPY_INFO*)StructPtr)->CoolingDevHandle |= (UINT16)Data->ChangeValue;
+ break;
+ case 0x14: ((SMBIOS_SYSTEM_PWR_SUPPY_INFO*)StructPtr)->InputCurrentProbeHandle &= (UINT16)Data->ChangeMask;
+ ((SMBIOS_SYSTEM_PWR_SUPPY_INFO*)StructPtr)->InputCurrentProbeHandle |= (UINT16)Data->ChangeValue;
+ break;
+ }
+ }
+
+ return UpdateStrings(Handle, TableInfo, Data->StructureData);
+}
+#endif
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PnPFn52AddStructure
+//
+// Description: PnP function 52 Command 03: Add structure
+//
+// Input: IN SET_SMBIOS_STRUCTURE_DATA *dmiDataBuffer
+// IN BOOLEAN Set
+//
+// Output: UINT8 - Status
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16
+PnPFn52AddStructure (
+ IN SET_SMBIOS_STRUCTURE *p
+)
+{
+ UINT16 Status;
+ UINT8 *SmbiosTable = (UINT8*)((SMBIOS_TABLE_ENTRY_POINT*)SmbiosTableEntryPoint)->TableAddress;
+ UINT8 *SmbiosTableEnd = SmbiosTable + ((SMBIOS_TABLE_ENTRY_POINT*)SmbiosTableEntryPoint)->TableLength;
+ UINT8 *SrcPtr;
+ UINT8 *DestPtr;
+ UINT8 Type127Buffer[4];
+ SET_SMBIOS_STRUCTURE_DATA *dmiDataBuffer;
+ TABLE_INFO TableInfo;
+
+ dmiDataBuffer = (SET_SMBIOS_STRUCTURE_DATA*)p->Buffer32BitAddr;
+ DestPtr = GetStructureByHandle(&dmiDataBuffer->StructureHeader.Handle);
+
+ if (DestPtr) {
+ Status = DMI_INVALID_HANDLE;
+ }
+ else {
+ SrcPtr = SmbiosTable;
+ if (FindStructureType(&SrcPtr, &DestPtr, 127, 1)) {
+ if ((MaximumBufferSize - ((SMBIOS_TABLE_ENTRY_POINT*)SmbiosTableEntryPoint)->TableLength) >= dmiDataBuffer->DataLength) {
+ if (p->Control & 1) {
+ TableInfo.Type = dmiDataBuffer->StructureHeader.Type;
+ TableInfo.Offset = dmiDataBuffer->FieldOffset;
+ TableInfo.Reserved = 0;
+ TableInfo.Flags = DMIEDIT_ADD_STRUC | DMIEDIT_EXTENDED_HDR;
+ TableInfo.HdrLength = sizeof(TABLE_INFO);
+ TableInfo.Size = dmiDataBuffer->DataLength;
+ TableInfo.Handle = dmiDataBuffer->StructureHeader.Handle;
+
+#if !defined(SMBIOS_DMIEDIT_DATA_LOC) || SMBIOS_DMIEDIT_DATA_LOC != 2
+ Status = UpdateSmbiosTable(&TableInfo, (UINT8*)&dmiDataBuffer->StructureHeader);
+ if (Status != 0) {
+ return Status;
+ }
+#else
+{
+ EFI_STATUS Status;
+
+ Swprintf(Var, L"DmiVar%02x%04x%02x%02x",
+ TableInfo.Type,
+ TableInfo.Handle,
+ TableInfo.Offset,
+ TableInfo.Flags);
+
+ //
+ // Get number of DMI data records in NVRAM
+ //
+ // Note: DMI data record actually starts with record #1,
+ // first record #0 holds total number of DMI data records
+ // instead of TABLE_INFO
+ // ===> DmiArray[0].Type = count
+ //
+ Status = pRS->GetVariable(
+ DmiArrayVar,
+ &EfiSmbiosNvramGuid,
+ NULL,
+ &DmiArraySize,
+ &DmiArray);
+
+ if (Status == EFI_SUCCESS) {
+ Index = DmiArray[0].Type; // Note: DmiArray[0] has count # instead of Type/Offset
+ ++Index;
+ }
+ else {
+ Index = 1;
+ }
+
+ // Check if record already exists
+ //
+ // DmiDataSize can be anything since the purpose of this GetVariable
+ // call is to detect if the variable already exists or not. Its
+ // content is not used.
+ DmiDataSize = 0; // Dummy value
+ Status = pRS->GetVariable(
+ Var,
+ &EfiSmbiosNvramGuid,
+ NULL,
+ &DmiDataSize,
+ &DmiData);
+
+ if (Status == EFI_NOT_FOUND) {
+ // Record not present, increment record count
+ DmiArray[Index].Type = TableInfo.Type;
+ DmiArray[Index].Handle = TableInfo.Handle;
+ DmiArray[Index].Offset = TableInfo.Offset;
+ DmiArray[Index].Flags = TableInfo.Flags;
+
+ DmiArray[0].Type += 1; // Increment # variable counter
+
+ Status = pRS->SetVariable(
+ DmiArrayVar,
+ &EfiSmbiosNvramGuid,
+ EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ DmiArraySize,
+ &DmiArray);
+ ASSERT_EFI_ERROR(Status);
+ if (Status != 0) {
+ return (UINT16)Status;
+ }
+ }
+
+ // Update DMI data record if already exists,
+ // or store new record if total record count in DmiArray was successfully
+ // updated
+ if (Status == EFI_BUFFER_TOO_SMALL || Status == EFI_SUCCESS) {
+ DmiDataSize = (UINTN)dmiDataBuffer->DataLength;
+ Status = pRS->SetVariable(
+ Var,
+ &EfiSmbiosNvramGuid,
+ EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ DmiDataSize,
+ (UINT8*)&dmiDataBuffer->StructureHeader);
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ if (Status != 0) {
+ return (UINT16)Status;
+ }
+}
+#endif
+
+ // Copy Type 127
+ MemCpy(&Type127Buffer, DestPtr, 4);
+ MemCpy(DestPtr, (UINT8*)&dmiDataBuffer->StructureHeader, dmiDataBuffer->DataLength);
+ DestPtr = DestPtr + GetStructureLength(DestPtr);
+ MemCpy(DestPtr, &Type127Buffer, 4);
+
+ // Update SMBIOS Structure Table Entry Point - Structure Table Length, Intermediate checksum
+ UpdateHeaderInfo();
+ }
+
+ Status = DMI_SUCCESS;
+ }
+ else {
+ Status = DMI_ADD_STRUCTURE_FAILED;
+ }
+ }
+ else {
+ Status = DMI_ADD_STRUCTURE_FAILED;
+ }
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: PnPFn52DeleteStructure
+//
+// Description: PnP function 52 Command 04: Delete structure
+//
+// Input: IN SET_SMBIOS_STRUCTURE_DATA *dmiDataBuffer
+// IN BOOLEAN Set
+//
+// Output: UINT8 - Status
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16
+PnPFn52DeleteStructure (
+ IN SET_SMBIOS_STRUCTURE *p
+)
+{
+ UINT16 Status;
+ UINT8 *SmbiosTable = (UINT8*)((SMBIOS_TABLE_ENTRY_POINT*)SmbiosTableEntryPoint)->TableAddress;
+ UINT8 *SmbiosTableEnd = SmbiosTable + ((SMBIOS_TABLE_ENTRY_POINT*)SmbiosTableEntryPoint)->TableLength;
+ UINT8 *DestPtr;
+ UINT16 i;
+ UINT16 RemainingSize;
+ SET_SMBIOS_STRUCTURE_DATA *dmiDataBuffer;
+ TABLE_INFO TableInfo;
+
+ dmiDataBuffer = (SET_SMBIOS_STRUCTURE_DATA*)p->Buffer32BitAddr;
+ DestPtr = GetStructureByHandle(&((SET_SMBIOS_STRUCTURE_DATA*)dmiDataBuffer)->StructureHeader.Handle);
+ if (DestPtr) {
+ if (p->Control & 1) {
+ UINT8 *SrcPtr;
+
+ TableInfo.Type = dmiDataBuffer->StructureHeader.Type;
+ TableInfo.Offset = 0xff;
+ TableInfo.Reserved = 0;
+ TableInfo.Flags = DMIEDIT_DELETE_STRUC | DMIEDIT_EXTENDED_HDR;
+ TableInfo.HdrLength = sizeof(TABLE_INFO);
+ TableInfo.Size = 0;
+ TableInfo.Handle = dmiDataBuffer->StructureHeader.Handle;
+
+#if !defined(SMBIOS_DMIEDIT_DATA_LOC) || SMBIOS_DMIEDIT_DATA_LOC != 2
+ Status = UpdateSmbiosTable(&TableInfo, (UINT8*)&dmiDataBuffer->StructureHeader);
+ if (Status != 0) {
+ return Status;
+ }
+#else
+{
+ EFI_STATUS Status;
+
+ Swprintf(Var, L"DmiVar%02x%04x%02x%02x",
+ TableInfo.Type,
+ TableInfo.Handle,
+ TableInfo.Offset,
+ TableInfo.Flags);
+
+ //
+ // Get number of DMI data records in NVRAM
+ //
+ // Note: DMI data record actually starts with record #1,
+ // first record #0 holds total number of DMI data records
+ // instead of TABLE_INFO
+ // ===> DmiArray[0].Type = count
+ //
+ Status = pRS->GetVariable(
+ DmiArrayVar,
+ &EfiSmbiosNvramGuid,
+ NULL,
+ &DmiArraySize,
+ &DmiArray);
+
+ if (Status == EFI_SUCCESS) {
+ Index = DmiArray[0].Type; // Note: DmiArray[0] has count # instead of Type/Offset
+ ++Index;
+ }
+ else {
+ Index = 1;
+ }
+
+ // Check if record already exists
+ //
+ // DmiDataSize can be anything since the purpose of this GetVariable
+ // call is to detect if the variable already exists or not. Its
+ // content is not used.
+ DmiDataSize = 0; // Dummy value
+ Status = pRS->GetVariable(
+ Var,
+ &EfiSmbiosNvramGuid,
+ NULL,
+ &DmiDataSize,
+ &DmiData);
+
+ if (Status == EFI_NOT_FOUND) {
+ // Record not present, increment record count
+ DmiArray[Index].Type = TableInfo.Type;
+ DmiArray[Index].Handle = TableInfo.Handle;
+ DmiArray[Index].Offset = TableInfo.Offset;
+ DmiArray[Index].Flags = TableInfo.Flags;
+
+ DmiArray[0].Type += 1; // Increment # variable counter
+
+ Status = pRS->SetVariable(
+ DmiArrayVar,
+ &EfiSmbiosNvramGuid,
+ EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ DmiArraySize,
+ &DmiArray);
+ ASSERT_EFI_ERROR(Status);
+ if (Status != 0) {
+ return (UINT16)Status;
+ }
+ }
+
+ // Update DMI data record if already exists,
+ // or store new record if total record count in DmiArray was successfully
+ // updated
+ if (Status == EFI_BUFFER_TOO_SMALL || Status == EFI_SUCCESS) {
+ DmiDataSize = (UINTN)sizeof(TABLE_INFO);
+ Status = pRS->SetVariable(
+ Var,
+ &EfiSmbiosNvramGuid,
+ EFI_VARIABLE_RUNTIME_ACCESS | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,
+ DmiDataSize,
+ &TableInfo);
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ if (Status != 0) {
+ return (UINT16)Status;
+ }
+}
+#endif
+
+ // Copy / update the remaining structures in the Smbios Table
+ SrcPtr = DestPtr + GetStructureLength(DestPtr);
+ RemainingSize = (UINT16)(SmbiosTableEnd - SrcPtr);
+
+ for (i = 0; i < RemainingSize; i++) {
+ *DestPtr = *SrcPtr;
+ SrcPtr++;
+ DestPtr++;
+ }
+
+ // Update SMBIOS Structure Table Entry Point - Structure Table Length, Intermediate checksum
+ UpdateHeaderInfo();
+ }
+
+ Status = DMI_SUCCESS;
+ }
+ else {
+ Status = DMI_INVALID_HANDLE;
+ }
+
+ return Status;
+}
+
+//<AMI_PHDR_START>
+//----------------------------------------------------------------------------
+// Procedure: SetSmbiosStructure
+//
+// Description: DMIEdit function to update the structures and saves the
+// DMI data in the Flash Part for subsequent boot.
+//
+// Input: IN SET_SMBIOS_STRUCTURE *p
+//
+// Output: UINT8 - Status
+//
+// Modified:
+//
+// Referrals:
+//
+// Notes:
+//----------------------------------------------------------------------------
+//<AMI_PHDR_END>
+UINT16
+SetSmbiosStructure(
+ IN SET_SMBIOS_STRUCTURE *p
+)
+{
+ SET_SMBIOS_STRUCTURE_DATA *Data = (SET_SMBIOS_STRUCTURE_DATA *)p->Buffer32BitAddr;
+ UINT8 *SmbTable;
+ UINT16 Handle = Data->StructureHeader.Handle;
+
+ if (!SmbiosTableEntryPoint) return DMI_FUNCTION_NOT_SUPPORTED;
+
+ if (Data->Command == 3) { // Add structure
+ return PnPFn52AddStructure(p);
+ }
+
+ if (Data->Command == 4) { // Delete structure
+ return PnPFn52DeleteStructure(p);
+ }
+
+ SmbTable = GetStructureByHandle(&Handle);
+ if (!SmbTable) return DMI_INVALID_HANDLE;
+
+ // Verify header
+ if (*(UINT16*)&Data->StructureHeader != *(UINT16*)SmbTable) return DMI_BAD_PARAMETER;
+
+ // Currently only accept certain table types;
+ switch (Data->StructureHeader.Type) {
+ case 0:
+ return SetType0(Handle, Data, p->Control&1);
+ case 1:
+ return SetType1(Handle, Data, p->Control&1);
+#if BASE_BOARD_INFO
+ case 2:
+ return SetType2(Handle, Data, p->Control&1);
+#endif
+#if SYS_CHASSIS_INFO
+ case 3:
+ return SetType3(Handle, Data, p->Control&1);
+#endif
+#if PROCESSOR_DMIEDIT_SUPPORT
+ case 4:
+ return SetType4(Handle, Data, p->Control&1);
+#endif
+#if OEM_STRING_INFO
+ case 11:
+ return SetType11(Handle, Data, p->Control&1);
+#endif
+#if SYSTEM_CONFIG_OPTION_INFO
+ case 12:
+ return SetType12(Handle, Data, p->Control&1);
+#endif
+#if PORTABLE_BATTERY_INFO
+ case 22:
+ return SetType22(Handle, Data, p->Control&1);
+#endif
+#if SYSTEM_POWER_SUPPLY_INFO
+ case 39:
+ return SetType39(Handle, Data, p->Control&1);
+#endif
+ }
+ return DMI_BAD_PARAMETER;
+}
+
+//**********************************************************************//
+//**********************************************************************//
+//** **//
+//** (C)Copyright 1985-2016, American Megatrends, Inc. **//
+//** **//
+//** All Rights Reserved. **//
+//** **//
+//** 5555 Oakbrook Pkwy, Suite 200, Norcross, GA 30093 **//
+//** **//
+//** Phone: (770)-246-8600 **//
+//** **//
+//**********************************************************************//
+//**********************************************************************//