Ryzen/AmdCbsPkg/Tools/CommonGen.pm
2022-12-23 15:14:44 +08:00

941 lines
33 KiB
Perl

#;*****************************************************************************
#;
#; Copyright 2012 - 2019 ADVANCED MICRO DEVICES, INC. All Rights Reserved.
#;
#; AMD is granting you permission to use this software and documentation (if
#; any) (collectively, the "Materials") pursuant to the terms and conditions of
#; the Software License Agreement included with the Materials. If you do not
#; have a copy of the Software License Agreement, contact your AMD
#; representative for a copy.
#;
#; You agree that you will not reverse engineer or decompile the Materials, in
#; whole or in part, except as allowed by applicable law.
#;
#; WARRANTY DISCLAIMER: THE MATERIALS ARE PROVIDED "AS IS" WITHOUT WARRANTY OF
#; ANY KIND. AMD DISCLAIMS ALL WARRANTIES, EXPRESS, IMPLIED, OR STATUTORY,
#; INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY,
#; FITNESS FOR A PARTICULAR PURPOSE, TITLE, NON-INFRINGEMENT, THAT THE
#; MATERIALS WILL RUN UNINTERRUPTED OR ERROR-FREE OR WARRANTIES ARISING FROM
#; CUSTOM OF TRADE OR COURSE OF USAGE. THE ENTIRE RISK ASSOCIATED WITH THE USE
#; OF THE MATERIAL IS ASSUMED BY YOU. Some jurisdictions do not allow the
#; exclusion of implied warranties, so the above exclusion may not apply to
#; You.
#;
#; LIMITATION OF LIABILITY AND INDEMNIFICATION: AMD AND ITS LICENSORS WILL
#; NOT, UNDER ANY CIRCUMSTANCES BE LIABLE TO YOU FOR ANY PUNITIVE, DIRECT,
#; INCIDENTAL, INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES ARISING FROM USE OF
#; THE MATERIALS OR THIS AGREEMENT EVEN IF AMD AND ITS LICENSORS HAVE BEEN
#; ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. In no event shall AMD's total
#; liability to You for all damages, losses, and causes of action (whether in
#; contract, tort (including negligence) or otherwise) exceed the amount of
#; $100 USD. You agree to defend, indemnify and hold harmless AMD and its
#; licensors, and any of their directors, officers, employees, affiliates or
#; agents from and against any and all loss, damage, liability and other
#; expenses (including reasonable attorneys' fees), resulting from Your use of
#; the Materials or violation of the terms and conditions of this Agreement.
#;
#; U.S. GOVERNMENT RESTRICTED RIGHTS: The Materials are provided with
#; "RESTRICTED RIGHTS." Use, duplication, or disclosure by the Government is
#; subject to the restrictions as set forth in FAR 52.227-14 and
#; DFAR252.227-7013, et seq., or its successor. Use of the Materials by the
#; Government constitutes acknowledgment of AMD's proprietary rights in them.
#;
#; EXPORT RESTRICTIONS: The Materials may be subject to export restrictions as
#; stated in the Software License Agreement.
#;*****************************************************************************
package CommonGen;
use strict;
use vars qw ($VERSION $XS_VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD);
require Exporter;
require AutoLoader;
@ISA = qw (Exporter AutoLoader);
@EXPORT = qw ();
@EXPORT_OK = qw ( generateUniFileStr
generateHFile
generateLableStr
generateKeyStr
generateVfrFile
generateBlankLine
genStrToken
attachUniStr
genLableToken
generateSetDefaultValueFile
);
#*----------------------------------------------------------
#* D E F I N E S
#*----------------------------------------------------------
#*
my $strPrefix = 'AMD_CBS_STR_'; # Prefix string
my $vfrStructName = 'AMD_SYSTEM_CONFIGURATION'; # Struct name
#*----------------------------------------------------------
#* E X P O R T E D F U N C T I O N S
#*----------------------------------------------------------
#*
#########################################################
#
# Generate UNI files
#
# IN : UNI file handle
# IN : Pointer to a CBS section or option
# IN : a hash to store exist UNI string
#
#########################################################
sub generateUniFileStr
{
my $uniFileStr = shift;
my $thisOption = shift;
my $uniExistHash = shift;
my $optionNameToken;
my $optionNameStr;
my $optionHelpToken;
my $optionHelpStr;
my $sectionNameToken;
if ($thisOption->{'Type'} =~ /^SECTION$/i) {
# This is a section
$sectionNameToken = &genStrToken($thisOption->{'Name'});
$sectionNameToken = $sectionNameToken.'_SECTION';
&outputStr($uniFileStr, $sectionNameToken, $thisOption->{'Name'}, $uniExistHash);
} elsif ($thisOption->{'Type'} =~ /^OPTION$/i) {
# This is an option
#
# Name string
#
# for 'Text' type, we want to show text which is in 'Additional_information'
if ($thisOption->{'Input_type'} =~ /^Text$/i) {
$optionNameToken = &genStrToken($thisOption->{'Name'});
$optionNameStr = $thisOption->{'Additional_information'};
&outputStr($uniFileStr, $optionNameToken, $optionNameStr, $uniExistHash);
} else {
$optionNameToken = &genStrToken($thisOption->{'Name'});
$optionNameStr = $thisOption->{'Name'};
$optionNameStr =~s/GRA\d/GRA/g;
&outputStr($uniFileStr, $optionNameToken, $optionNameStr, $uniExistHash);
}
#
# Help string
#
$optionHelpToken = "$optionNameToken".'_HELP';
if (ref($thisOption->{'Help_text'}) eq 'HASH') {
$optionHelpStr = 'No help string';
} else {
if ($thisOption->{'Help_text'} ne '') {
$optionHelpStr = $thisOption->{'Help_text'};
$optionHelpStr =~ s/GRA\d/GRA/g;
} else {
$optionHelpStr = 'No help string';
}
}
&outputStr($uniFileStr, $optionHelpToken, $optionHelpStr, $uniExistHash);
#
# Option item string
#
if ($thisOption->{'Input_type'} =~ /^Fixed$/i) {
foreach my $choice (@{$thisOption->{'OPTION_ITEM'}}) {
my $optionItemToken = &genStrToken($choice->{'Name'});
&outputStr($uniFileStr, $optionItemToken, $choice->{'Name'}, $uniExistHash);
}
}
}
}
#########################################################
#
# Generate Header files
#
# IN : Header file handle
# IN : Pointer to a CBS section or option
#
#########################################################
sub generateHFile
{
my $hFile = shift;
my $thisOption = shift;
if ($thisOption->{'Type'} =~ /^OPTION$/i) {
if ($thisOption->{'Nv_type'} =~ /^Byte$/i) {
printf $hFile " UINT8 %-50s///< $thisOption->{'Name'}\n", $thisOption->{'Variable_name'}.';';
} elsif ($thisOption->{'Nv_type'} =~ /^Word$/i) {
printf $hFile " UINT16 %-50s///< $thisOption->{'Name'}\n", $thisOption->{'Variable_name'}.';';
} elsif ($thisOption->{'Nv_type'} =~ /^DWord$/i) {
printf $hFile " UINT32 %-50s///< $thisOption->{'Name'}\n", $thisOption->{'Variable_name'}.';';
} elsif ($thisOption->{'Nv_type'} =~ /^QWord$/i) {
printf $hFile " UINT64 %-50s///< $thisOption->{'Name'}\n", $thisOption->{'Variable_name'}.';';
}
}
}
#########################################################
#
# Generate Lable string
#
# IN : FORM start ID for CBS
# IN : FORM ID will be output to .h file for CBS
# IN : Pointer to a CBS section or option
#
#########################################################
sub generateLableStr
{
my $lableStartID = shift;
my $lableIDOutput = shift;
my $thisOption = shift;
if ($thisOption->{'Type'} =~ /^SECTION$/i) {
if ($$lableIDOutput eq '') {
$$lableIDOutput .= "// Section ID\n";
}
my $lableToken = genLableToken ($thisOption->{'Name'});
$$lableIDOutput .= sprintf " #define %-70s 0x%X\n", $lableToken, $$lableStartID;
$$lableStartID++;
}
}
#########################################################
#
# Generate KEY string
#
# IN : FORM start ID for CBS
# IN : FORM ID will be output to .h file for CBS
# IN : Pointer to a CBS section or option
#
#########################################################
sub generateKeyStr
{
my $lableStartID = shift;
my $keyIDOutput = shift;
my $thisOption = shift;
if (($thisOption->{'Type'} =~ /^OPTION$/i) && ($thisOption->{'Key_function'} != 0)) {
if ($$keyIDOutput eq '') {
$$keyIDOutput .= "\n// KEY function ID\n";
}
my $keyToken = genKeyToken ($thisOption->{'Variable_name'});
$$keyIDOutput .= sprintf " #define %-70s 0x%X //%s\n", $keyToken, $$lableStartID, $thisOption->{'Variable_name'};
$$lableStartID++;
}
}
#########################################################
#
# Generate VFR files
#
# IN : VFR file handle
# IN : Pointer to a CBS section or option
# IN : Indent number
# IN : code base
# IN : Pointer to the CBS root section
# IN : a hash to store exist KEY ID
# IN : FORM start ID for CBS
# IN : FORM ID will be output to .h file for CBS
# IN : component (CPU/GNB/FCH)
#
#########################################################
sub generateVfrFile
{
my $vfrFile = shift;
my $thisOption = shift;
my $indentNum = shift;
my $rootSection = shift;
my $keyIDExistHash = shift;
my $lableStartID = shift;
my $keyIDOutput = shift;
my $component = shift;
$vfrStructName = 'CBS_CONFIG';
if ($thisOption->{'Type'} =~ /^SECTION$/i) {
# This is a section
generateVfrSection ($vfrFile, $thisOption, $indentNum, $rootSection, $component);
} elsif ($thisOption->{'Type'} =~ /^OPTION$/i) {
# This is an option
# check if we need split 'Display_condition' and have multi instance
my $multiInstance = checkForMultiInstance ($thisOption);
if ($multiInstance eq 'FALSE') {
# common options
generateVfrCommonOpt ($vfrFile, $thisOption, $indentNum, $rootSection, $keyIDExistHash);
} else {
# split 'Display_condition'
my @displayConditon = split (/\|/, $thisOption->{'Display_condition'});
foreach my $disConditon (@displayConditon) {
$thisOption->{'Display_condition'} = $disConditon;
$thisOption->{'Display_condition'} =~ s/\s*$//g;
generateVfrCommonOpt ($vfrFile, $thisOption, $indentNum, $rootSection, $keyIDExistHash);
}
}
}
}
#########################################################
#
# Generate string token
# adding prefix = 'AMD_CBS_STR_'
# replace `~!@$%^&*()-=+[]{}\/,<>?| white space with _
# replace . with DOT
# replace # with POUND
# IN : name string
#
# RETURN : a string token used for UNI file
#
#########################################################
sub genStrToken
{
my $str = shift;
$str = $strPrefix.uc($str);
$str = updateStr ($str);
return $str;
}
#########################################################
#
# Attach the str to Uni str
# IN : ref of UNI string
# IN : string been attached
#
# RETURN : NULL
#
#########################################################
sub attachUniStr
{
my $unistr = shift;
my $str = shift;
$$unistr .= $str;
}
#########################################################
#
# Generate lable token
# adding prefix = 'SETUP_'
# adding suffix = '_LABLE'
# replace `~!@$%^&*()-=+[]{}\/,<>?| white space with _
# replace . with DOT
# replace # with POUND
# IN : name string
#
# RETURN : a lable used for 'goto'
#
#########################################################
sub genLableToken
{
my $lable = shift;
$lable = 'SETUP_'.uc($lable).'_LABLE';
$lable = updateStr ($lable);
return $lable;
}
#########################################################
#
# Generate Key token
# adding prefix = 'KEY_'
# adding suffix = '_LABLE'
# replace `~!@$%^&*()-=+[]{}\/,<>?| white space with _
# replace . with DOT
# replace # with POUND
# IN : name string
#
# RETURN : a lable used for 'goto'
#
#########################################################
sub genKeyToken
{
my $lable = shift;
$lable =~ s/([A-Z][a-z])/_$1/g;
$lable =~ s/([a-z])([A-Z])/$1_$2/g;
$lable =~ s/SMU/SMU_/ig;
$lable = 'KEY_'.uc($lable);
$lable = updateStr ($lable);
return $lable;
}
#########################################################
#
# Generate a blank line in VFR file
#
# IN : VFR file handle
# IN : Indent number
# IN : code base
#
#########################################################
sub generateBlankLine
{
my $vfrFile = shift;
my $indentNum = shift;
my $StrToken = genStrToken ('BLANK');
print $vfrFile ' ' x $indentNum."text\n";
print $vfrFile ' ' x ($indentNum+1)."help = STRING_TOKEN \($StrToken\),\n";
print $vfrFile ' ' x ($indentNum+1)."text = STRING_TOKEN \($StrToken\);\n";
print $vfrFile "\n";
}
#*----------------------------------------------------------
#* L O C A L F U N C T I O N S
#*----------------------------------------------------------
#*
#########################################################
#
# Generate Section for VFR files
#
# IN : VFR file handle
# IN : Pointer to a CBS section or option
# IN : Indent number
# IN : code base
# IN : Pointer to the CBS root section
# IN : component (CPU/GNB/FCH)
#
#########################################################
sub generateVfrSection
{
my $vfrFile = shift;
my $thisOption = shift;
my $indentNum = shift;
my $rootSection = shift;
my $component = shift;
my $displayCondition;
my $grayoutCondition;
my $space;
my $lableToken;
my $strToken;
# 0, #define AMD_PROCESSOR/GNB/FCH
# if (($thisOption->{'Name'} =~ /AMD Processor Debug Options/i) || ($thisOption->{'Name'} =~ /AMD Processor Common Options/i)) {
# print $vfrFile ' ' x $indentNum."#ifdef AMD_CBS_CPU_SUPPORT\n";
# }
# if (($thisOption->{'Name'} =~ /AMD GNB Debug Options/i) || ($thisOption->{'Name'} =~ /AMD GNB Common Options/i)) {
# print $vfrFile ' ' x $indentNum."#ifdef AMD_CBS_GNB_SUPPORT\n";
# }
# if (($thisOption->{'Name'} =~ /AMD FCH Debug Options/i) || ($thisOption->{'Name'} =~ /AMD FCH Common Options/i)) {
# print $vfrFile ' ' x $indentNum."#ifdef AMD_CBS_FCH_SUPPORT\n";
# }
if (($thisOption->{'Name'} =~ /Promontory Debug Options/i) || ($thisOption->{'Name'} =~ /Promontory Common Options/i)) {
print $vfrFile ' ' x $indentNum."#ifdef PROMONTORY_SUPPORT\n";
}
# 1st, generate suppressif and grayoutif
if ((ref ($thisOption->{'Display_condition'}) ne 'HASH') || (ref ($thisOption->{'Active_condition'}) ne 'HASH')) {
# 1.1 comments
if (ref ($thisOption->{'Display_condition'}) ne 'HASH') {
printf $vfrFile ' ' x $indentNum."// Display Condition: $thisOption->{'Display_condition'}\n";
}
if (ref ($thisOption->{'Active_condition'}) ne 'HASH') {
printf $vfrFile ' ' x $indentNum."// Active Condition: $thisOption->{'Active_condition'}\n";
}
# 1.2 suppressif
if (ref ($thisOption->{'Display_condition'}) ne 'HASH') {
$displayCondition = findNegativeConditions ($thisOption->{'Display_condition'}, $rootSection);
$space = ' ' x $indentNum.' ';
$displayCondition =~ s/\tOR /$space OR /g;
$displayCondition =~ s/\tAND /$space AND /g;
printf $vfrFile ' ' x $indentNum."suppressif $displayCondition;\n";
}
# 1.3 grayoutif
if (ref ($thisOption->{'Active_condition'}) ne 'HASH') {
$grayoutCondition = findNegativeConditions ($thisOption->{'Active_condition'}, $rootSection);
$space = ' ' x $indentNum.' ';
$grayoutCondition =~ s/\tOR /$space OR /g;
$grayoutCondition =~ s/\tAND /$space AND /g;
printf $vfrFile ' ' x $indentNum."grayoutif $grayoutCondition;\n";
}
# 1.4 $indentNum++
$indentNum++;
}
# 2nd, generate form
$lableToken = genLableToken ($thisOption->{'Name'});
$strToken = &genStrToken($thisOption->{'Name'});
$strToken = $strToken.'_SECTION';
# Normally we always goto low level section
# but sometimes we want to goto up level section
# This is for legal disclaimer
if (exists $thisOption->{'GoTo_Section'}) {
if (ref ($thisOption->{'GoTo_Section'}) ne 'HASH') {
my $GotoSection = genLableToken ($thisOption->{'GoTo_Section'});
printf $vfrFile ' ' x $indentNum."goto $GotoSection,\n";
} else {
printf $vfrFile ' ' x $indentNum."goto $lableToken,\n";
}
} else {
printf $vfrFile ' ' x $indentNum."goto $lableToken,\n";
}
printf $vfrFile ' ' x ($indentNum+1)."prompt = STRING_TOKEN \($strToken\),\n";
printf $vfrFile ' ' x ($indentNum+1)."help = STRING_TOKEN \($strToken\);\n";
# 3rd, endif
if ((ref ($thisOption->{'Display_condition'}) ne 'HASH') || (ref ($thisOption->{'Active_condition'}) ne 'HASH')) {
$indentNum--;
printf $vfrFile ' ' x $indentNum."endif;\n";
if ((ref ($thisOption->{'Display_condition'}) ne 'HASH') && (ref ($thisOption->{'Active_condition'}) ne 'HASH')) {
printf $vfrFile ' ' x $indentNum."endif;\n";
}
}
# 4th #endif
# if (($thisOption->{'Name'} =~ /AMD Processor Debug Options/i) || ($thisOption->{'Name'} =~ /AMD Processor Common Options/i) ||
# ($thisOption->{'Name'} =~ /AMD GNB Debug Options/i) || ($thisOption->{'Name'} =~ /AMD GNB Common Options/i) ||
# ($thisOption->{'Name'} =~ /AMD FCH Debug Options/i) || ($thisOption->{'Name'} =~ /AMD FCH Common Options/i)) {
# print $vfrFile ' ' x $indentNum."#endif\n";
# }
if (($thisOption->{'Name'} =~ /Promontory Debug Options/i) || ($thisOption->{'Name'} =~ /Promontory Common Options/i)) {
print $vfrFile ' ' x $indentNum."#endif\n";
}
printf $vfrFile "\n";
}
#########################################################
#
# Check if we need split 'Display_condition' and have multi instance
#
# IN : Pointer to a CBS section or option
# OUT : TRUE --- we need have multi instance for this option
# FALSE --- one instance for this option is enough
#
#########################################################
sub checkForMultiInstance
{
my $thisOption = shift;
my $multiInstance = 'FALSE';
# (A&B&C) | (A&!B)
if ($thisOption->{'Display_condition'} =~ /\|/g) {
my @displayConditon = split (/\|/, $thisOption->{'Display_condition'});
foreach (@displayConditon) {
my @temp = split (/\,/, $_);
if (scalar @temp > 2) {
$multiInstance = 'TRUE';
}
}
}
return $multiInstance;
}
#########################################################
#
# Generate common options for VFR files
#
# IN : VFR file handle
# IN : Pointer to a CBS section or option
# IN : Indent number
# IN : code base
# IN : Pointer to the CBS root section
# IN : a hash to store exist KEY ID
#
#########################################################
sub generateVfrCommonOpt
{
my $vfrFile = shift;
my $thisOption = shift;
my $indentNum = shift;
my $rootSection = shift;
my $keyIDExistHash = shift;
my $optionNameToken;
my $optionHelpToken;
my $defaultValue;
my $keyFunction;
my $keyLable;
my $choice;
my $displayCondition;
my $grayoutCondition;
my $space;
my $Backslash = '';
my $FlagForKeyFunction;
# 1st, generate suppressif and grayoutif
if ((ref ($thisOption->{'Display_condition'}) ne 'HASH') || (ref ($thisOption->{'Active_condition'}) ne 'HASH')) {
# 1.1 comments
if (ref ($thisOption->{'Display_condition'}) ne 'HASH') {
printf $vfrFile ' ' x $indentNum."// Display Condition: $thisOption->{'Display_condition'}\n";
}
if (ref ($thisOption->{'Active_condition'}) ne 'HASH') {
printf $vfrFile ' ' x $indentNum."// Active Condition: $thisOption->{'Active_condition'}\n";
}
# 1.2 suppressif
if (ref ($thisOption->{'Display_condition'}) ne 'HASH') {
$displayCondition = findNegativeConditions ($thisOption->{'Display_condition'}, $rootSection);
$space = ' ' x $indentNum.' ';
$displayCondition =~ s/\tOR /$space OR /g;
$displayCondition =~ s/\tAND /$space AND /g;
printf $vfrFile ' ' x $indentNum."suppressif $displayCondition;\n";
}
# 1.3 grayoutif
if (ref ($thisOption->{'Active_condition'}) ne 'HASH') {
$grayoutCondition = findNegativeConditions ($thisOption->{'Active_condition'}, $rootSection);
$space = ' ' x $indentNum.' ';
$grayoutCondition =~ s/\tOR /$space OR /g;
$grayoutCondition =~ s/\tAND /$space AND /g;
printf $vfrFile ' ' x $indentNum."grayoutif $grayoutCondition;\n";
}
# 1.4 $indentNum++
$indentNum++;
}
# 2nd, generate oneof, numeric
$optionNameToken = &genStrToken($thisOption->{'Name'});
$optionHelpToken = "$optionNameToken".'_HELP';
printf $vfrFile ' ' x $indentNum."// $thisOption->{'Name'}$Backslash\n";
if (ref ($thisOption->{'Help_text'}) ne 'HASH') {
if ($thisOption->{'Help_text'} ne $thisOption->{'Name'}) {
printf $vfrFile ' ' x $indentNum."// $thisOption->{'Help_text'}$Backslash\n";
}
} else {
printf $vfrFile ' ' x $indentNum."// No help string$Backslash\n";
}
if ($thisOption->{'Input_type'} =~ /^Fixed$/i) {
# Fixed Options
printf $vfrFile ' ' x $indentNum."oneof$Backslash\n";
printf $vfrFile ' ' x ($indentNum+1)."varid = $vfrStructName.%s,$Backslash\n", $thisOption->{'Variable_name'};
# questionid = KEY_XXXX,
if ($thisOption->{'Key_function'} != 0) {
$keyLable = genKeyToken ($thisOption->{'Variable_name'});
printf $vfrFile ' ' x ($indentNum+1)."questionid = $keyLable,$Backslash\n";
}
printf $vfrFile ' ' x ($indentNum+1)."prompt = STRING_TOKEN (%s),$Backslash\n", $optionNameToken;
printf $vfrFile ' ' x ($indentNum+1)."help = STRING_TOKEN (%s),$Backslash\n", $optionHelpToken;
# flags = INTERACTIVE,
if ($thisOption->{'Key_function'} != 0) {
$keyLable = genKeyToken ($thisOption->{'Variable_name'});
}
my $first = 1;
foreach $choice (@{$thisOption->{'OPTION_ITEM'}}) {
# get DEFAULT flag
$defaultValue = '0 | RESET_REQUIRED';
if ($thisOption->{'BIOS_Default'} =~ /^$choice->{'Nv_storage'}$/i) {
$defaultValue = 'DEFAULT | RESET_REQUIRED';
}
# get INTERACTIVE flag
if ($thisOption->{'Key_function'} == 0) {
$keyFunction = '';
} else {
$keyFunction = ' | INTERACTIVE';
}
my $optionItemToken = &genStrToken($choice->{'Name'});
if ($thisOption->{'Key_function'} != 0) {
printf $vfrFile ' ' x ($indentNum+1)."option text = STRING_TOKEN %-30s value = %-5s flags = %-10s\n", '('.$optionItemToken.'),', $choice->{'Nv_storage'}.',', $defaultValue.$keyFunction.';';
} else {
printf $vfrFile ' ' x ($indentNum+1)."option text = STRING_TOKEN %-30s value = %-5s flags = %s\n", '('.$optionItemToken.'),', $choice->{'Nv_storage'}.',', $defaultValue.';';
}
}
printf $vfrFile ' ' x $indentNum."endoneof;\n";
} elsif ($thisOption->{'Input_type'} =~ /^Customed$/i) {
# Customed Options
printf $vfrFile ' ' x $indentNum."numeric$Backslash\n";
printf $vfrFile ' ' x ($indentNum+1)."varid = $vfrStructName.%s,$Backslash\n", $thisOption->{'Variable_name'};
# questionid = KEY_XXXX,
if ($thisOption->{'Key_function'} != 0) {
$FlagForKeyFunction = ' | INTERACTIVE';
$keyLable = genKeyToken ($thisOption->{'Variable_name'});
printf $vfrFile ' ' x ($indentNum+1)."questionid = $keyLable,$Backslash\n";
}
printf $vfrFile ' ' x ($indentNum+1)."prompt = STRING_TOKEN (%s),$Backslash\n", $optionNameToken;
printf $vfrFile ' ' x ($indentNum+1)."help = STRING_TOKEN (%s),$Backslash\n", $optionHelpToken;
if (ref ($thisOption->{'Additional_information'}) eq 'HASH') {
printf $vfrFile ' ' x ($indentNum+1)."flags = DISPLAY_UINT_HEX | RESET_REQUIRED$FlagForKeyFunction,$Backslash\n";
} elsif ($thisOption->{'Additional_information'} !~ /DECIMAL_INPUT\s*=\s*TRUE/ig) {
printf $vfrFile ' ' x ($indentNum+1)."flags = DISPLAY_UINT_HEX | RESET_REQUIRED$FlagForKeyFunction,$Backslash\n";
} else {
printf $vfrFile ' ' x ($indentNum+1)."flags = RESET_REQUIRED$FlagForKeyFunction,$Backslash\n";
}
$thisOption->{'OPTION_ITEM'}->[0]->{'Nv_storage'} =~ /(\w+)-(\w+)/;
printf $vfrFile ' ' x ($indentNum+1)."minimum = %s,$Backslash\n",$1;
printf $vfrFile ' ' x ($indentNum+1)."maximum = %s,$Backslash\n",$2;
printf $vfrFile ' ' x ($indentNum+1)."step = 0,$Backslash\n";
printf $vfrFile ' ' x ($indentNum+1)."default = %s,$Backslash\n", $thisOption->{'BIOS_Default'};
printf $vfrFile ' ' x $indentNum."endnumeric;\n";
} elsif ($thisOption->{'Input_type'} =~ /^Text$/i) {
if (ref ($thisOption->{'Additional_information'}) ne 'HASH') {
printf $vfrFile ' ' x $indentNum."text\n";
printf $vfrFile ' ' x ($indentNum+1)."help = STRING_TOKEN (%s),$Backslash\n", $optionHelpToken;
printf $vfrFile ' ' x ($indentNum+1)."text = STRING_TOKEN (%s);\n", $optionNameToken;
}
}
# 3rd, endif
if ((ref ($thisOption->{'Display_condition'}) ne 'HASH') || (ref ($thisOption->{'Active_condition'}) ne 'HASH')) {
$indentNum--;
printf $vfrFile ' ' x $indentNum."endif;$Backslash\n";
if ((ref ($thisOption->{'Display_condition'}) ne 'HASH') && (ref ($thisOption->{'Active_condition'}) ne 'HASH')) {
printf $vfrFile ' ' x $indentNum."endif;$Backslash\n";
}
}
printf $vfrFile "\n";
}
#########################################################
#
# Update string
# replace `~!@$%^&*()-=+[]{}\/,<>?| white space with _
# replace . with DOT
# replace # with POUND
# IN OUT : string
#
#########################################################
sub updateStr
{
my $str = shift;
$str =~ s/[`~!@\s\$\%\'\^&\*\(\)\[\]\{\}\-=+\\|\;:",\<>\/\?]+/_/g;
$str =~ s/\.+/_DOT_/g;
$str =~ s/#+/_POUND_/g;
$str =~ s/_{2,}/_/g;
$str =~ s/_*$//;
$str =~ s/GRA\d*/GRA/g;
return $str;
}
#########################################################
#
# Output string to UNI file str.
# IN : UNI file string
# IN : String token
# IN : String
# IN : a hash to store exist UNI string
#
#########################################################
sub outputStr
{
my $uniFilestr = shift;
my $str1 = shift;
my $str2 = shift;
my $uniExistHash = shift;
if (exists $uniExistHash->{"$str1"}) {
$uniExistHash->{"$str1"} += 1;
} else {
$uniExistHash->{"$str1"} = 1;
$str2 =~ s/"/'/g;
if ($str2 =~ /_Legal_Disclaimer_(\w+)$/i) {
$str2 = $1;
}
attachUniStr($uniFilestr, sprintf "#string %-70s #language en-US \"%s\"\n", $str1, $str2);
}
}
#########################################################
#
# Generate NV value of a given variable
#
# IN : variable name
# IN : NV value name
# IN : CBS section
#
# RETURN : NV value
#########################################################
sub getNvValue
{
my $variableName = shift;
my $nvValueName = shift;
my $cbsSection = shift;
my $nvValue = 'Not found';
# remove tailing space.
$variableName =~ s/\s*$//g;
$nvValueName =~ s/\s*$//g;
foreach my $thisOption (@{$cbsSection}) {
if ($thisOption->{'Type'} =~ /^SECTION$/i) {
$nvValue = getNvValue ($variableName, $nvValueName, $thisOption->{'ITEM'});
if ($nvValue ne 'Not found') {
return $nvValue;
}
} elsif ($thisOption->{'Type'} =~ /^OPTION$/i) {
if ($thisOption->{'Variable_name'} =~ /^$variableName$/i) {
if ($thisOption->{'Input_type'} =~ /^Fixed$/i) {
foreach my $choice (@{$thisOption->{'OPTION_ITEM'}}) {
if ($choice->{'Name'} =~ /^$nvValueName$/i) {
$nvValue = $choice->{'Nv_storage'};
return $nvValue;
}
}
} elsif ($thisOption->{'Input_type'} =~ /^Customed$/i) {
$nvValue = $nvValueName;
}
}
}
}
return $nvValue;
}
#########################################################
#
# return a group of strings in the form of
# "<VariableName>=<NvValue>"
# IN : Target option to be processed
# IN : ptr to the option groups
#
#########################################################
sub findNegativeConditions
{
my $displayCondition = shift;
my $sectionName = shift;
my $parentConditionsString;
my $vfrCondition = "";
my @vfrConditions = ();
my $parentOptionFound = 0;
my $parentOptionChoiceFound = 0;
my $nvValue;
# remove preceding space
$displayCondition =~ s/^\s*//g;
# Collect all the parent conditions in @parentConditions
if (defined $displayCondition && $displayCondition ne "") {
$parentConditionsString = $displayCondition;
}
# parse the complementary parent conditions
if ($parentConditionsString !~ /\|/) {
my @oredParentConditionStrings = split (/\s*\,\s*/, $parentConditionsString);
@vfrConditions = &parseNegativeCondition (\@oredParentConditionStrings, $sectionName);
$vfrCondition = join ("\n\tOR ", @vfrConditions);
} elsif ($parentConditionsString !~ /,/) {
my @andedParentConditionStrings = split (/\s*\|\s*/, $parentConditionsString);
@vfrConditions = &parseNegativeCondition (\@andedParentConditionStrings, $sectionName);
$vfrCondition = join ("\n\tAND ", @vfrConditions);
} else {
my @vfrAndedConditions = ();
my @vfrOredConditions = ();
my @andedParentConditionStrings0 = ();
my @andedParentConditionStrings1 = ();
$parentConditionsString = &formatAsABorAC ($parentConditionsString);
my @oredParentConditionStrings = split (/\s*\|\s*/, $parentConditionsString);
foreach my $oredParentConditionStrings (@oredParentConditionStrings) {
$oredParentConditionStrings =~ s/\(|\)//g;
my @andedParentConditionStrings = split (/\s*\,\s*/, $oredParentConditionStrings);
if (scalar @andedParentConditionStrings == 2) {
@andedParentConditionStrings1 = ($andedParentConditionStrings[1]);
@vfrAndedConditions = (@vfrAndedConditions, &parseNegativeCondition (\@andedParentConditionStrings1, $sectionName));
$vfrCondition = join ("\n\tAND ", @vfrAndedConditions);
if (!defined $andedParentConditionStrings0[0]) {
@andedParentConditionStrings0 = ($andedParentConditionStrings[0]);
} elsif ($andedParentConditionStrings0[0] ne $andedParentConditionStrings[0]) {
# The first condition must be common
die ("[ERROR1] Incorrect format of parent condition string\n\t\t".$parentConditionsString."\n");
}
} else {
die ("[ERROR2] Incorrect format of parent condition string\n\t\t".$parentConditionsString."\n");
}
}
@vfrOredConditions = (&parseNegativeCondition (\@andedParentConditionStrings0, $sectionName));
$vfrCondition = join ("\n\tOR ", @vfrOredConditions, $vfrCondition);
}
return $vfrCondition;
}
sub parseNegativeCondition
{
my $pConditions = shift;
my $sectionName = shift;
my $vfrCondition = "";
my @vfrConditions = ();
my $nvValue;
foreach my $condition (@$pConditions) {
# loop for all components
if ($condition =~ /\s*=\s*/) {
(my $variableName, my $choiceName) = split (/\s*=\s*/, $condition);
# match target with all the options
$nvValue = &getNvValue ($variableName, $choiceName, $sectionName);
push (@vfrConditions, sprintf "NOT ideqval $vfrStructName.%s == $nvValue", $variableName);
} else {
die ("[ERROR3] Incorrect format of parent condition string\n\t\t".$condition."\n");
}
}
return @vfrConditions;
}
sub formatAsABorAC
{
my $parentConditionString = shift;
my $option = shift;
my $numOredConditions = 0;
my %numConditions = ();
my $commonCondition = "";
my $formattedCondition = "";
my @oredParentConditionStrings = split (/\s*\|\s*/, $parentConditionString);
foreach my $oredParentConditionString (@oredParentConditionStrings) {
$numOredConditions ++;
my @andedParentConditions = split (/\s*,\s*/, $oredParentConditionString);
foreach my $condition (@andedParentConditions) {
# count the repeats of each condition
$condition =~ s/\s*=\s*/=/;
if (defined $numConditions{$condition}) {
$numConditions{$condition} ++;
} else {
$numConditions{$condition} = 1;
}
}
}
# find the common condition
foreach my $condition (keys %numConditions) {
if ($numConditions{$condition} == $numOredConditions) {
$commonCondition = $condition;
last;
}
}
if ($commonCondition =~ /^\s*$/) {
&logError ("[ERROR] No common condition found\n\t\t".$option->{"Name"}." : ".$parentConditionString."\n");
}
# format the parent condition
foreach my $oredParentConditionString (@oredParentConditionStrings) {
my @andedParentConditions = split (/\s*,\s*/, $oredParentConditionString);
if ($andedParentConditions[0] eq $commonCondition) {
$formattedCondition .= $commonCondition.",".$andedParentConditions[1];
} else {
$formattedCondition .= $commonCondition.",".$andedParentConditions[0];
}
$formattedCondition .= "|";
}
$formattedCondition =~ s/\|$//;
return $formattedCondition;
}
#*----------------------------------------------------------
#* D E V F U N C T I O N S
#*----------------------------------------------------------
#*
#########################################################
#
# set default value
# IN : set default value file handle
# IN : Pointer to a CBS section or option
#
#########################################################
sub generateSetDefaultValueFile
{
my $setDefaultValueFile = shift;
my $thisOption = shift;
my $temp;
if ($thisOption->{'Type'} =~ /^OPTION$/i) {
$temp = ' Setup_Config->'.$thisOption->{'Variable_name'}.' = '.$thisOption->{'BIOS_Default'}.';';
$temp = sprintf "%-70s // $thisOption->{'Name'}\n", $temp;
printf $setDefaultValueFile $temp;
}
}
1;