summaryrefslogtreecommitdiff
path: root/Core
diff options
context:
space:
mode:
Diffstat (limited to 'Core')
-rw-r--r--Core/ShellPkg/Application/Shell/ConsoleLogger.c1233
-rw-r--r--Core/ShellPkg/Application/Shell/ConsoleLogger.h329
-rw-r--r--Core/ShellPkg/Application/Shell/ConsoleWrappers.c518
-rw-r--r--Core/ShellPkg/Application/Shell/ConsoleWrappers.h84
-rw-r--r--Core/ShellPkg/Application/Shell/FileHandleInternal.h68
-rw-r--r--Core/ShellPkg/Application/Shell/FileHandleWrappers.c1910
-rw-r--r--Core/ShellPkg/Application/Shell/FileHandleWrappers.h95
-rw-r--r--Core/ShellPkg/Application/Shell/Shell.c3131
-rw-r--r--Core/ShellPkg/Application/Shell/Shell.h408
-rw-r--r--Core/ShellPkg/Application/Shell/Shell.inf112
-rw-r--r--Core/ShellPkg/Application/Shell/Shell.uni58
-rw-r--r--Core/ShellPkg/Application/Shell/ShellEnvVar.c576
-rw-r--r--Core/ShellPkg/Application/Shell/ShellEnvVar.h292
-rw-r--r--Core/ShellPkg/Application/Shell/ShellManParser.c1013
-rw-r--r--Core/ShellPkg/Application/Shell/ShellManParser.h86
-rw-r--r--Core/ShellPkg/Application/Shell/ShellParametersProtocol.c1298
-rw-r--r--Core/ShellPkg/Application/Shell/ShellParametersProtocol.h194
-rw-r--r--Core/ShellPkg/Application/Shell/ShellProtocol.c3939
-rw-r--r--Core/ShellPkg/Application/Shell/ShellProtocol.h953
-rw-r--r--Core/ShellPkg/Application/ShellCTestApp/README.txt5
-rw-r--r--Core/ShellPkg/Application/ShellCTestApp/ShellCTestApp.c51
-rw-r--r--Core/ShellPkg/Application/ShellCTestApp/ShellCTestApp.inf39
-rw-r--r--Core/ShellPkg/Application/ShellCTestApp/TestArgv.logbin0 -> 3320 bytes
-rw-r--r--Core/ShellPkg/Application/ShellCTestApp/TestArgv.nsh64
-rw-r--r--Core/ShellPkg/Application/ShellExecTestApp/SA.c38
-rw-r--r--Core/ShellPkg/Application/ShellExecTestApp/SA.inf41
-rw-r--r--Core/ShellPkg/Application/ShellSortTestApp/ShellSortTestApp.c83
-rw-r--r--Core/ShellPkg/Application/ShellSortTestApp/ShellSortTestApp.inf42
-rw-r--r--Core/ShellPkg/Contributions.txt218
-rw-r--r--Core/ShellPkg/Include/Guid/ShellAliasGuid.h25
-rw-r--r--Core/ShellPkg/Include/Guid/ShellEnvironment2Ext.h25
-rw-r--r--Core/ShellPkg/Include/Guid/ShellLibHiiGuid.h86
-rw-r--r--Core/ShellPkg/Include/Guid/ShellMapGuid.h25
-rw-r--r--Core/ShellPkg/Include/Guid/ShellPkgTokenSpace.h25
-rw-r--r--Core/ShellPkg/Include/Guid/ShellVariableGuid.h25
-rw-r--r--Core/ShellPkg/Include/Library/BcfgCommandLib.h52
-rw-r--r--Core/ShellPkg/Include/Library/HandleParsingLib.h391
-rw-r--r--Core/ShellPkg/Include/Library/ShellCEntryLib.h40
-rw-r--r--Core/ShellPkg/Include/Library/ShellCommandLib.h790
-rw-r--r--Core/ShellPkg/Include/Library/ShellLib.h1400
-rw-r--r--Core/ShellPkg/Include/Protocol/EfiShell.h1138
-rw-r--r--Core/ShellPkg/Include/Protocol/EfiShellDynamicCommand.h86
-rw-r--r--Core/ShellPkg/Include/Protocol/EfiShellEnvironment2.h975
-rw-r--r--Core/ShellPkg/Include/Protocol/EfiShellInterface.h94
-rw-r--r--Core/ShellPkg/Include/Protocol/EfiShellParameters.h60
-rw-r--r--Core/ShellPkg/Include/ShellBase.h157
-rw-r--r--Core/ShellPkg/Library/UefiDpLib/Dp.c407
-rw-r--r--Core/ShellPkg/Library/UefiDpLib/Dp.h98
-rw-r--r--Core/ShellPkg/Library/UefiDpLib/DpInternal.h356
-rw-r--r--Core/ShellPkg/Library/UefiDpLib/DpProfile.c101
-rw-r--r--Core/ShellPkg/Library/UefiDpLib/DpTrace.c897
-rw-r--r--Core/ShellPkg/Library/UefiDpLib/DpUtilities.c405
-rw-r--r--Core/ShellPkg/Library/UefiDpLib/Literals.c23
-rw-r--r--Core/ShellPkg/Library/UefiDpLib/Literals.h26
-rw-r--r--Core/ShellPkg/Library/UefiDpLib/PerformanceTokens.h28
-rw-r--r--Core/ShellPkg/Library/UefiDpLib/Readme.txt2
-rw-r--r--Core/ShellPkg/Library/UefiDpLib/UefiDpLib.c101
-rw-r--r--Core/ShellPkg/Library/UefiDpLib/UefiDpLib.h65
-rw-r--r--Core/ShellPkg/Library/UefiDpLib/UefiDpLib.inf75
-rw-r--r--Core/ShellPkg/Library/UefiDpLib/UefiDpLib.uni130
-rw-r--r--Core/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c3080
-rw-r--r--Core/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.h298
-rw-r--r--Core/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf317
-rw-r--r--Core/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.uni463
-rw-r--r--Core/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c1560
-rw-r--r--Core/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf46
-rw-r--r--Core/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.uni158
-rw-r--r--Core/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.c99
-rw-r--r--Core/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf44
-rw-r--r--Core/ShellPkg/Library/UefiShellCommandLib/ConsistMapping.c1707
-rw-r--r--Core/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c2053
-rw-r--r--Core/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h71
-rw-r--r--Core/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf69
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Comp.c277
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Compress.c1417
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Compress.h40
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Dblk.c201
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Dmem.c235
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/DmpStore.c769
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Edit.c162
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.c3370
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.h263
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c1936
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.h77
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.c92
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.h52
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditStrings.uni75
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditor.h32
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditorTypes.h102
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditInputBar.c323
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditInputBar.h91
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditMenuBar.c196
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditMenuBar.h125
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditStatusBar.c237
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditStatusBar.h109
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditTitleBar.c210
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditTitleBar.h77
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EfiCompress.c164
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EfiDecompress.c186
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.c2484
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.h277
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.c112
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.h69
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.c420
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.h95
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.c403
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.h83
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEdit.c277
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditor.h41
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditorTypes.h126
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexeditStrings.uni76
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.c2318
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.h76
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.c345
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.h92
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.c262
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.h93
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/LoadPciRom.c411
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/MemMap.c312
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Mm.c649
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Mode.c128
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.c5927
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.h463
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SerMode.c372
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SetSize.c110
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SetVar.c302
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/EventLogInfo.c412
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/EventLogInfo.h117
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/LibSmbiosView.c373
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/LibSmbiosView.h159
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/PrintInfo.c3227
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/PrintInfo.h423
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/QueryTable.c4401
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/QueryTable.h782
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosView.c1013
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosView.h136
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosViewStrings.uni491
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.c574
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.h421
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf139
-rw-r--r--Core/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.uni1188
-rw-r--r--Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Connect.c552
-rw-r--r--Core/ShellPkg/Library/UefiShellDriver1CommandsLib/DevTree.c278
-rw-r--r--Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Devices.c270
-rw-r--r--Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Dh.c984
-rw-r--r--Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Disconnect.c189
-rw-r--r--Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Drivers.c321
-rw-r--r--Core/ShellPkg/Library/UefiShellDriver1CommandsLib/DrvCfg.c1414
-rw-r--r--Core/ShellPkg/Library/UefiShellDriver1CommandsLib/DrvDiag.c464
-rw-r--r--Core/ShellPkg/Library/UefiShellDriver1CommandsLib/OpenInfo.c217
-rw-r--r--Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Reconnect.c99
-rw-r--r--Core/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.c104
-rw-r--r--Core/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.h226
-rw-r--r--Core/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf73
-rw-r--r--Core/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.uni743
-rw-r--r--Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Unload.c149
-rw-r--r--Core/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.c59
-rw-r--r--Core/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf51
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel1CommandsLib/Exit.c97
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel1CommandsLib/For.c754
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel1CommandsLib/Goto.c105
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel1CommandsLib/If.c1117
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel1CommandsLib/Shift.c64
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel1CommandsLib/Stall.c84
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.c310
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.h211
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf58
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.uni504
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Attrib.c277
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c278
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c783
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Load.c281
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c758
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c1256
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel2CommandsLib/MkDir.c129
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Mv.c801
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Parse.c459
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Reset.c132
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c382
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Set.c175
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel2CommandsLib/TimeDate.c976
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c351
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h374
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf84
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.uni1088
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Vol.c314
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Alias.c195
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Cls.c133
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Echo.c102
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel3CommandsLib/GetMtc.c97
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Help.c478
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Pause.c107
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Touch.c294
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Type.c328
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.c101
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.h162
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf74
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.uni518
-rw-r--r--Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Ver.c147
-rw-r--r--Core/ShellPkg/Library/UefiShellLib/UefiShellLib.c4361
-rw-r--r--Core/ShellPkg/Library/UefiShellLib/UefiShellLib.h96
-rw-r--r--Core/ShellPkg/Library/UefiShellLib/UefiShellLib.inf69
-rw-r--r--Core/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c1426
-rw-r--r--Core/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c1619
-rw-r--r--Core/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.c90
-rw-r--r--Core/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.h77
-rw-r--r--Core/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf67
-rw-r--r--Core/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni179
-rw-r--r--Core/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ifconfig6.c1894
-rw-r--r--Core/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ping6.c1275
-rw-r--r--Core/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.c91
-rw-r--r--Core/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.h72
-rw-r--r--Core/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.inf63
-rw-r--r--Core/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.uni154
-rw-r--r--Core/ShellPkg/Library/UefiShellTftpCommandLib/Tftp.c1051
-rw-r--r--Core/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.c97
-rw-r--r--Core/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.h62
-rw-r--r--Core/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.inf61
-rw-r--r--Core/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.uni97
-rw-r--r--Core/ShellPkg/License.txt25
-rw-r--r--Core/ShellPkg/Readme.txt29
-rw-r--r--Core/ShellPkg/ShellPkg.dec138
-rw-r--r--Core/ShellPkg/ShellPkg.dsc124
223 files changed, 110296 insertions, 0 deletions
diff --git a/Core/ShellPkg/Application/Shell/ConsoleLogger.c b/Core/ShellPkg/Application/Shell/ConsoleLogger.c
new file mode 100644
index 0000000000..9b64303cf0
--- /dev/null
+++ b/Core/ShellPkg/Application/Shell/ConsoleLogger.c
@@ -0,0 +1,1233 @@
+/** @file
+ Provides interface to shell console logger.
+
+ (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include "Shell.h"
+
+/**
+ Install our intermediate ConOut into the system table to
+ keep a log of all the info that is displayed to the user.
+
+ @param[in] ScreensToSave Sets how many screen-worths of data to save.
+ @param[out] ConsoleInfo The object to pass into later functions.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @return other The operation failed.
+
+ @sa ConsoleLoggerResetBuffers
+ @sa InstallProtocolInterface
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerInstall(
+ IN CONST UINTN ScreensToSave,
+ OUT CONSOLE_LOGGER_PRIVATE_DATA **ConsoleInfo
+ )
+{
+ EFI_STATUS Status;
+ ASSERT(ConsoleInfo != NULL);
+
+ (*ConsoleInfo) = AllocateZeroPool(sizeof(CONSOLE_LOGGER_PRIVATE_DATA));
+ if ((*ConsoleInfo) == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ (*ConsoleInfo)->Signature = CONSOLE_LOGGER_PRIVATE_DATA_SIGNATURE;
+ (*ConsoleInfo)->OldConOut = gST->ConOut;
+ (*ConsoleInfo)->OldConHandle = gST->ConsoleOutHandle;
+ (*ConsoleInfo)->Buffer = NULL;
+ (*ConsoleInfo)->BufferSize = 0;
+ (*ConsoleInfo)->OriginalStartRow = 0;
+ (*ConsoleInfo)->CurrentStartRow = 0;
+ (*ConsoleInfo)->RowsPerScreen = 0;
+ (*ConsoleInfo)->ColsPerScreen = 0;
+ (*ConsoleInfo)->Attributes = NULL;
+ (*ConsoleInfo)->AttribSize = 0;
+ (*ConsoleInfo)->ScreenCount = ScreensToSave;
+ (*ConsoleInfo)->HistoryMode.MaxMode = 1;
+ (*ConsoleInfo)->HistoryMode.Mode = 0;
+ (*ConsoleInfo)->HistoryMode.Attribute = 0;
+ (*ConsoleInfo)->HistoryMode.CursorColumn = 0;
+ (*ConsoleInfo)->HistoryMode.CursorRow = 0;
+ (*ConsoleInfo)->HistoryMode.CursorVisible = FALSE;
+ (*ConsoleInfo)->OurConOut.Reset = ConsoleLoggerReset;
+ (*ConsoleInfo)->OurConOut.OutputString = ConsoleLoggerOutputString;
+ (*ConsoleInfo)->OurConOut.TestString = ConsoleLoggerTestString;
+ (*ConsoleInfo)->OurConOut.QueryMode = ConsoleLoggerQueryMode;
+ (*ConsoleInfo)->OurConOut.SetMode = ConsoleLoggerSetMode;
+ (*ConsoleInfo)->OurConOut.SetAttribute = ConsoleLoggerSetAttribute;
+ (*ConsoleInfo)->OurConOut.ClearScreen = ConsoleLoggerClearScreen;
+ (*ConsoleInfo)->OurConOut.SetCursorPosition = ConsoleLoggerSetCursorPosition;
+ (*ConsoleInfo)->OurConOut.EnableCursor = ConsoleLoggerEnableCursor;
+ (*ConsoleInfo)->OurConOut.Mode = gST->ConOut->Mode;
+ (*ConsoleInfo)->Enabled = TRUE;
+
+ Status = ConsoleLoggerResetBuffers(*ConsoleInfo);
+ if (EFI_ERROR(Status)) {
+ SHELL_FREE_NON_NULL((*ConsoleInfo));
+ *ConsoleInfo = NULL;
+ return (Status);
+ }
+
+ Status = gBS->InstallProtocolInterface(&gImageHandle, &gEfiSimpleTextOutProtocolGuid, EFI_NATIVE_INTERFACE, (VOID*)&((*ConsoleInfo)->OurConOut));
+ if (EFI_ERROR(Status)) {
+ SHELL_FREE_NON_NULL((*ConsoleInfo)->Buffer);
+ SHELL_FREE_NON_NULL((*ConsoleInfo)->Attributes);
+ SHELL_FREE_NON_NULL((*ConsoleInfo));
+ *ConsoleInfo = NULL;
+ return (Status);
+ }
+
+ gST->ConsoleOutHandle = gImageHandle;
+ gST->ConOut = &(*ConsoleInfo)->OurConOut;
+
+ return (Status);
+}
+
+/**
+ Return the system to the state it was before InstallConsoleLogger
+ was installed.
+
+ @param[in] ConsoleInfo The object from the install function.
+
+ @retval EFI_SUCCESS The operation was successful
+ @return other The operation failed. This was from UninstallProtocolInterface.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerUninstall(
+ IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
+ )
+{
+ ASSERT(ConsoleInfo != NULL);
+ ASSERT(ConsoleInfo->OldConOut != NULL);
+
+ if (ConsoleInfo->Buffer != NULL) {
+ FreePool(ConsoleInfo->Buffer);
+ DEBUG_CODE(ConsoleInfo->Buffer = NULL;);
+ DEBUG_CODE(ConsoleInfo->BufferSize = 0;);
+ }
+ if (ConsoleInfo->Attributes != NULL) {
+ FreePool(ConsoleInfo->Attributes);
+ DEBUG_CODE(ConsoleInfo->Attributes = NULL;);
+ DEBUG_CODE(ConsoleInfo->AttribSize = 0;);
+ }
+
+ gST->ConsoleOutHandle = ConsoleInfo->OldConHandle;
+ gST->ConOut = ConsoleInfo->OldConOut;
+
+ return (gBS->UninstallProtocolInterface(gImageHandle, &gEfiSimpleTextOutProtocolGuid, (VOID*)&ConsoleInfo->OurConOut));
+}
+
+/**
+ Displays previously logged output back to the screen.
+
+ This will scroll the screen forwards and backwards through the log of previous
+ output. If Rows is 0 then the size of 1/2 the screen will be scrolled. If Rows
+ is (UINTN)(-1) then the size of the screen will be scrolled.
+
+ @param[in] Forward If TRUE then the log will be displayed forwards (scroll to newer).
+ If FALSE then the log will be displayed backwards (scroll to older).
+ @param[in] Rows Determines how many rows the log should scroll.
+ @param[in] ConsoleInfo The pointer to the instance of the console logger information.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerDisplayHistory(
+ IN CONST BOOLEAN Forward,
+ IN CONST UINTN Rows,
+ IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
+ )
+{
+ UINTN RowChange;
+
+ ASSERT(ConsoleInfo != NULL);
+
+ //
+ // Calculate the row number change
+ //
+ switch (Rows) {
+ case ((UINTN)(-1)):
+ RowChange = ConsoleInfo->RowsPerScreen;
+ break;
+ case (0):
+ RowChange = ConsoleInfo->RowsPerScreen / 2;
+ break;
+ default:
+ RowChange = Rows;
+ break;
+ }
+
+ //
+ // Do the math for direction
+ //
+ if (Forward) {
+ if ((ConsoleInfo->OriginalStartRow - ConsoleInfo->CurrentStartRow) < RowChange) {
+ RowChange = ConsoleInfo->OriginalStartRow - ConsoleInfo->CurrentStartRow;
+ }
+ } else {
+ if (ConsoleInfo->CurrentStartRow < RowChange) {
+ RowChange = ConsoleInfo->CurrentStartRow;
+ }
+ }
+
+ //
+ // If we are already at one end or the other
+ //
+ if (RowChange == 0) {
+ return (EFI_SUCCESS);
+ }
+
+ //
+ // Clear the screen
+ //
+ ConsoleInfo->OldConOut->ClearScreen(ConsoleInfo->OldConOut);
+
+ //
+ // Set the new start row
+ //
+ if (Forward) {
+ ConsoleInfo->CurrentStartRow += RowChange;
+ } else {
+ ConsoleInfo->CurrentStartRow -= RowChange;
+ }
+
+ //
+ // Change the screen
+ //
+ return (UpdateDisplayFromHistory(ConsoleInfo));
+}
+
+/**
+ Function to return to normal output whent he scrolling is complete.
+ @param[in] ConsoleInfo The pointer to the instance of the console logger information.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @return other The operation failed. See UpdateDisplayFromHistory.
+
+ @sa UpdateDisplayFromHistory
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerStopHistory(
+ IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
+ )
+{
+ ASSERT(ConsoleInfo != NULL);
+ if (ConsoleInfo->CurrentStartRow == ConsoleInfo->OriginalStartRow) {
+ return (EFI_SUCCESS);
+ }
+
+ //
+ // Clear the screen
+ //
+ ConsoleInfo->OldConOut->ClearScreen(ConsoleInfo->OldConOut);
+
+ ConsoleInfo->CurrentStartRow = ConsoleInfo->OriginalStartRow;
+ return (UpdateDisplayFromHistory(ConsoleInfo));
+}
+
+/**
+ Updates the hidden ConOut to be displaying the correct stuff.
+ @param[in] ConsoleInfo The pointer to the instance of the console logger information.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @return other The operation failed.
+**/
+EFI_STATUS
+EFIAPI
+UpdateDisplayFromHistory(
+ IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS RetVal;
+ CHAR16 *Screen;
+ INT32 *Attributes;
+ UINTN CurrentRow;
+ CHAR16 TempCharHolder;
+ UINTN Column;
+ INT32 CurrentAttrib;
+ UINTN CurrentColumn;
+ CHAR16 *StringSegment;
+ CHAR16 *StringSegmentEnd;
+ CHAR16 StringSegmentEndChar;
+ INT32 OrigAttribute;
+
+ ASSERT(ConsoleInfo != NULL);
+ TempCharHolder = CHAR_NULL;
+ RetVal = EFI_SUCCESS;
+ OrigAttribute = ConsoleInfo->OldConOut->Mode->Attribute;
+
+ //
+ // Disable cursor visibility and move it to the top left corner
+ //
+ ConsoleInfo->OldConOut->EnableCursor (ConsoleInfo->OldConOut, FALSE);
+ ConsoleInfo->OldConOut->SetCursorPosition (ConsoleInfo->OldConOut, 0, 0);
+
+ Screen = &ConsoleInfo->Buffer[(ConsoleInfo->ColsPerScreen + 2) * ConsoleInfo->CurrentStartRow];
+ Attributes = &ConsoleInfo->Attributes[ConsoleInfo->ColsPerScreen * ConsoleInfo->CurrentStartRow];
+ for ( CurrentRow = 0
+ ; CurrentRow < ConsoleInfo->RowsPerScreen
+ ; CurrentRow++
+ , Screen += (ConsoleInfo->ColsPerScreen + 2)
+ , Attributes += ConsoleInfo->ColsPerScreen
+ ){
+ //
+ // dont use the last char - prevents screen scroll
+ //
+ if (CurrentRow == (ConsoleInfo->RowsPerScreen-1)){
+ TempCharHolder = Screen[ConsoleInfo->ColsPerScreen - 1];
+ Screen[ConsoleInfo->ColsPerScreen - 1] = CHAR_NULL;
+ }
+
+ for ( Column = 0
+ ; Column < ConsoleInfo->ColsPerScreen
+ ; Column++
+ ){
+ if (Screen[Column] != CHAR_NULL) {
+ CurrentAttrib = Attributes[Column];
+ CurrentColumn = Column;
+ StringSegment = &Screen[Column];
+
+ //
+ // Find the first char with a different arrribute and make that temporarily NULL
+ // so we can do fewer printout statements. (later) restore that one and we will
+ // start at that collumn on the next loop.
+ //
+ StringSegmentEndChar = CHAR_NULL;
+ for ( StringSegmentEnd = StringSegment
+ ; StringSegmentEnd != CHAR_NULL
+ ; StringSegmentEnd++
+ , Column++
+ ){
+ if (Attributes[Column] != CurrentAttrib) {
+ StringSegmentEndChar = *StringSegmentEnd;
+ *StringSegmentEnd = CHAR_NULL;
+ break;
+ }
+ } // StringSegmentEnd loop
+
+ //
+ // Now write out as much as had the same Attributes
+ //
+
+ ConsoleInfo->OldConOut->SetAttribute(ConsoleInfo->OldConOut, CurrentAttrib);
+ ConsoleInfo->OldConOut->SetCursorPosition(ConsoleInfo->OldConOut, CurrentColumn, CurrentRow);
+ Status = ConsoleInfo->OldConOut->OutputString(ConsoleInfo->OldConOut, StringSegment);
+
+ if (EFI_ERROR(Status)) {
+ ASSERT(FALSE);
+ RetVal = Status;
+ }
+
+ //
+ // If we found a change in attribute put the character back and decrement the column
+ // so when it increments it will point at that character and we will start printing
+ // a segment with that new attribute
+ //
+ if (StringSegmentEndChar != CHAR_NULL) {
+ *StringSegmentEnd = StringSegmentEndChar;
+ StringSegmentEndChar = CHAR_NULL;
+ Column--;
+ }
+ }
+ } // column for loop
+
+ //
+ // If we removed the last char and this was the last row put it back
+ //
+ if (TempCharHolder != CHAR_NULL) {
+ Screen[ConsoleInfo->ColsPerScreen - 1] = TempCharHolder;
+ TempCharHolder = CHAR_NULL;
+ }
+ } // row for loop
+
+ //
+ // If we are setting the screen back to original turn on the cursor and make it visible
+ // and set the attributes back to what they were
+ //
+ if (ConsoleInfo->CurrentStartRow == ConsoleInfo->OriginalStartRow) {
+ ConsoleInfo->OldConOut->SetAttribute (
+ ConsoleInfo->OldConOut,
+ ConsoleInfo->HistoryMode.Attribute
+ );
+ ConsoleInfo->OldConOut->SetCursorPosition (
+ ConsoleInfo->OldConOut,
+ ConsoleInfo->HistoryMode.CursorColumn,
+ ConsoleInfo->HistoryMode.CursorRow - ConsoleInfo->OriginalStartRow
+ );
+
+ Status = ConsoleInfo->OldConOut->EnableCursor (
+ ConsoleInfo->OldConOut,
+ ConsoleInfo->HistoryMode.CursorVisible
+ );
+ if (EFI_ERROR (Status)) {
+ RetVal = Status;
+ }
+ } else {
+ ConsoleInfo->OldConOut->SetAttribute (
+ ConsoleInfo->OldConOut,
+ OrigAttribute
+ );
+ }
+
+ return (RetVal);
+}
+
+/**
+ Reset the text output device hardware and optionaly run diagnostics
+
+ @param This pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
+ @param ExtendedVerification Indicates that a more extensive test may be performed
+
+ @retval EFI_SUCCESS The text output device was reset.
+ @retval EFI_DEVICE_ERROR The text output device is not functioning correctly and
+ could not be reset.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerReset (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ EFI_STATUS Status;
+ CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
+ ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
+
+ //
+ // Forward the request to the original ConOut
+ //
+ Status = ConsoleInfo->OldConOut->Reset (ConsoleInfo->OldConOut, ExtendedVerification);
+
+ //
+ // Check that the buffers are still correct for logging
+ //
+ if (!EFI_ERROR (Status)) {
+ ConsoleLoggerResetBuffers(ConsoleInfo);
+ if (ExtendedVerification) {
+ ConsoleInfo->OriginalStartRow = 0;
+ ConsoleInfo->CurrentStartRow = 0;
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Appends a string to the history buffer. If the buffer is full then the oldest
+ information in the buffer will be dropped. Information is added in a line by
+ line manner such that an empty line takes up just as much space as a full line.
+
+ @param[in] String String pointer to add.
+ @param[in] ConsoleInfo The pointer to the instance of the console logger information.
+**/
+EFI_STATUS
+EFIAPI
+AppendStringToHistory(
+ IN CONST CHAR16 *String,
+ IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
+ )
+{
+ CONST CHAR16 *Walker;
+ UINTN CopySize;
+ UINTN PrintIndex;
+ UINTN Index;
+
+ ASSERT(ConsoleInfo != NULL);
+
+ for ( Walker = String
+ ; Walker != NULL && *Walker != CHAR_NULL
+ ; Walker++
+ ){
+ switch (*Walker) {
+ case (CHAR_BACKSPACE):
+ if (ConsoleInfo->HistoryMode.CursorColumn > 0) {
+ ConsoleInfo->HistoryMode.CursorColumn--;
+ }
+ break;
+ case (CHAR_LINEFEED):
+ if (ConsoleInfo->HistoryMode.CursorRow >= (INT32)((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount)-1)) {
+ //
+ // Should never be bigger
+ //
+ ASSERT(ConsoleInfo->HistoryMode.CursorRow == (INT32)((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount)-1));
+
+ //
+ // scroll history attributes 'up' 1 row and set the last row to default attribute
+ //
+ CopySize = ConsoleInfo->ColsPerScreen
+ * ((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount) - 1)
+ * sizeof(ConsoleInfo->Attributes[0]);
+ ASSERT(CopySize < ConsoleInfo->AttribSize);
+ CopyMem(
+ ConsoleInfo->Attributes,
+ ConsoleInfo->Attributes + ConsoleInfo->ColsPerScreen,
+ CopySize
+ );
+
+ for ( Index = 0
+ ; Index < ConsoleInfo->ColsPerScreen
+ ; Index++
+ ){
+ *(ConsoleInfo->Attributes + (CopySize/sizeof(ConsoleInfo->Attributes[0])) + Index) = ConsoleInfo->HistoryMode.Attribute;
+ }
+
+ //
+ // scroll history buffer 'up' 1 row and set the last row to spaces (L' ')
+ //
+ CopySize = (ConsoleInfo->ColsPerScreen + 2)
+ * ((ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount) - 1)
+ * sizeof(ConsoleInfo->Buffer[0]);
+ ASSERT(CopySize < ConsoleInfo->BufferSize);
+ CopyMem(
+ ConsoleInfo->Buffer,
+ ConsoleInfo->Buffer + (ConsoleInfo->ColsPerScreen + 2),
+ CopySize
+ );
+
+ //
+ // Set that last row of chars to spaces
+ //
+ SetMem16(((UINT8*)ConsoleInfo->Buffer)+CopySize, ConsoleInfo->ColsPerScreen*sizeof(CHAR16), L' ');
+ } else {
+ //
+ // we are not on the last row
+ //
+
+ //
+ // We should not be scrolling history
+ //
+ ASSERT (ConsoleInfo->OriginalStartRow == ConsoleInfo->CurrentStartRow);
+ //
+ // are we at the end of a row?
+ //
+ if (ConsoleInfo->HistoryMode.CursorRow == (INT32) (ConsoleInfo->OriginalStartRow + ConsoleInfo->RowsPerScreen - 1)) {
+ ConsoleInfo->OriginalStartRow++;
+ ConsoleInfo->CurrentStartRow++;
+ }
+ ConsoleInfo->HistoryMode.CursorRow++;
+ }
+ break;
+ case (CHAR_CARRIAGE_RETURN):
+ //
+ // Move the cursor to the beginning of the current row.
+ //
+ ConsoleInfo->HistoryMode.CursorColumn = 0;
+ break;
+ default:
+ //
+ // Acrtually print characters into the history buffer
+ //
+
+ PrintIndex = ConsoleInfo->HistoryMode.CursorRow * ConsoleInfo->ColsPerScreen + ConsoleInfo->HistoryMode.CursorColumn;
+
+ for ( // no initializer needed
+ ; ConsoleInfo->HistoryMode.CursorColumn < (INT32) ConsoleInfo->ColsPerScreen
+ ; ConsoleInfo->HistoryMode.CursorColumn++
+ , PrintIndex++
+ , Walker++
+ ){
+ if (*Walker == CHAR_NULL
+ ||*Walker == CHAR_BACKSPACE
+ ||*Walker == CHAR_LINEFEED
+ ||*Walker == CHAR_CARRIAGE_RETURN
+ ){
+ Walker--;
+ break;
+ }
+ //
+ // The buffer is 2*CursorRow more since it has that many \r\n characters at the end of each row.
+ //
+
+ ASSERT(PrintIndex + ConsoleInfo->HistoryMode.CursorRow < ConsoleInfo->BufferSize);
+ ConsoleInfo->Buffer[PrintIndex + (2*ConsoleInfo->HistoryMode.CursorRow)] = *Walker;
+ ASSERT(PrintIndex < ConsoleInfo->AttribSize);
+ ConsoleInfo->Attributes[PrintIndex] = ConsoleInfo->HistoryMode.Attribute;
+ } // for loop
+
+ //
+ // Add the carriage return and line feed at the end of the lines
+ //
+ if (ConsoleInfo->HistoryMode.CursorColumn >= (INT32)ConsoleInfo->ColsPerScreen) {
+ AppendStringToHistory(L"\r\n", ConsoleInfo);
+ Walker--;
+ }
+
+ break;
+ } // switch for character
+ } // for loop
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Worker function to handle printing the output to the screen
+ and the history buffer
+
+ @param[in] String The string to output
+ @param[in] ConsoleInfo The pointer to the instance of the console logger information.
+
+ @retval EFI_SUCCESS The string was printed
+ @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
+ the text.
+ @retval EFI_UNSUPPORTED The output device's mode is not currently in a
+ defined text mode.
+ @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
+ characters in the Unicode string could not be
+ rendered and were skipped.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerOutputStringSplit(
+ IN CONST CHAR16 *String,
+ IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Forward the request to the original ConOut
+ //
+ Status = ConsoleInfo->OldConOut->OutputString (ConsoleInfo->OldConOut, (CHAR16*)String);
+
+ if (EFI_ERROR(Status)) {
+ return (Status);
+ }
+
+ return (AppendStringToHistory(String, ConsoleInfo));
+}
+
+/**
+ Function to handle page break mode.
+
+ This function will prompt for continue or break.
+
+ @retval EFI_SUCCESS Continue was choosen
+ @return other Break was choosen
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerDoPageBreak(
+ VOID
+ )
+{
+ SHELL_PROMPT_RESPONSE *Resp;
+ EFI_STATUS Status;
+
+ Resp = NULL;
+ ASSERT(ShellInfoObject.PageBreakEnabled);
+ ShellInfoObject.PageBreakEnabled = FALSE;
+ Status = ShellPromptForResponseHii(ShellPromptResponseTypeQuitContinue, STRING_TOKEN(STR_SHELL_QUIT_CONT), ShellInfoObject.HiiHandle, (VOID**)&Resp);
+ ShellInfoObject.PageBreakEnabled = TRUE;
+ ASSERT(Resp != NULL);
+ if (Resp == NULL) {
+ return (EFI_NOT_FOUND);
+ }
+ if (EFI_ERROR(Status)) {
+ if (Resp != NULL) {
+ FreePool(Resp);
+ }
+ return (Status);
+ }
+ if (*Resp == ShellPromptResponseContinue) {
+ FreePool(Resp);
+ ShellInfoObject.ConsoleInfo->RowCounter = 0;
+// ShellInfoObject.ConsoleInfo->OurConOut.Mode->CursorRow = 0;
+// ShellInfoObject.ConsoleInfo->OurConOut.Mode->CursorColumn = 0;
+
+ return (EFI_SUCCESS);
+ } else if (*Resp == ShellPromptResponseQuit) {
+ FreePool(Resp);
+ ShellInfoObject.ConsoleInfo->Enabled = FALSE;
+ //
+ // When user wants to quit, the shell should stop running the command.
+ //
+ gBS->SignalEvent (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak);
+ return (EFI_DEVICE_ERROR);
+ } else {
+ ASSERT(FALSE);
+ }
+ return (EFI_SUCCESS);
+}
+/**
+ Worker function to handle printing the output with page breaks.
+
+ @param[in] String The string to output
+ @param[in] ConsoleInfo The pointer to the instance of the console logger information.
+
+ @retval EFI_SUCCESS The string was printed
+ @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
+ the text.
+ @retval EFI_UNSUPPORTED The output device's mode is not currently in a
+ defined text mode.
+ @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
+ characters in the Unicode string could not be
+ rendered and were skipped.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerPrintWithPageBreak(
+ IN CONST CHAR16 *String,
+ IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
+ )
+{
+ CONST CHAR16 *Walker;
+ CONST CHAR16 *LineStart;
+ CHAR16 *StringCopy;
+ CHAR16 TempChar;
+
+ StringCopy = NULL;
+ StringCopy = StrnCatGrow(&StringCopy, NULL, String, 0);
+ if (StringCopy == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ for ( Walker = StringCopy
+ , LineStart = StringCopy
+ ; Walker != NULL && *Walker != CHAR_NULL
+ ; Walker++
+ ){
+ switch (*Walker) {
+ case (CHAR_BACKSPACE):
+ if (ConsoleInfo->OurConOut.Mode->CursorColumn > 0) {
+ ConsoleInfo->OurConOut.Mode->CursorColumn--;
+ }
+ break;
+ case (CHAR_LINEFEED):
+ //
+ // add a temp NULL terminator
+ //
+ TempChar = *(Walker + 1);
+ *((CHAR16*)(Walker+1)) = CHAR_NULL;
+
+ //
+ // output the string
+ //
+ ConsoleLoggerOutputStringSplit (LineStart, ConsoleInfo);
+
+ //
+ // restore the temp NULL terminator to it's original character
+ //
+ *((CHAR16*)(Walker+1)) = TempChar;
+
+ //
+ // Update LineStart Variable
+ //
+ LineStart = Walker + 1;
+
+ //
+ // increment row count
+ //
+ ShellInfoObject.ConsoleInfo->RowCounter++;
+ ConsoleInfo->OurConOut.Mode->CursorRow++;
+
+ break;
+ case (CHAR_CARRIAGE_RETURN):
+ //
+ // Move the cursor to the beginning of the current row.
+ //
+ ConsoleInfo->OurConOut.Mode->CursorColumn = 0;
+ break;
+ default:
+ //
+ // increment column count
+ //
+ ConsoleInfo->OurConOut.Mode->CursorColumn++;
+ //
+ // check if that is the last column
+ //
+ if ((INTN)ConsoleInfo->ColsPerScreen == ConsoleInfo->OurConOut.Mode->CursorColumn + 1) {
+ //
+ // output a line similar to the linefeed character.
+ //
+
+ //
+ // add a temp NULL terminator
+ //
+ TempChar = *(Walker + 1);
+ *((CHAR16*)(Walker+1)) = CHAR_NULL;
+
+ //
+ // output the string
+ //
+ ConsoleLoggerOutputStringSplit (LineStart, ConsoleInfo);
+
+ //
+ // restore the temp NULL terminator to it's original character
+ //
+ *((CHAR16*)(Walker+1)) = TempChar;
+
+ //
+ // Update LineStart Variable
+ //
+ LineStart = Walker + 1;
+
+ //
+ // increment row count and zero the column
+ //
+ ShellInfoObject.ConsoleInfo->RowCounter++;
+ ConsoleInfo->OurConOut.Mode->CursorRow++;
+ ConsoleInfo->OurConOut.Mode->CursorColumn = 0;
+ } // last column on line
+ break;
+ } // switch for character
+
+ //
+ // check if that was the last printable row. If yes handle PageBreak mode
+ //
+ if ((ConsoleInfo->RowsPerScreen) -1 == ShellInfoObject.ConsoleInfo->RowCounter) {
+ if (EFI_ERROR(ConsoleLoggerDoPageBreak())) {
+ //
+ // We got an error which means 'break' and halt the printing
+ //
+ SHELL_FREE_NON_NULL(StringCopy);
+ return (EFI_DEVICE_ERROR);
+ }
+ }
+ } // for loop
+
+ if (LineStart != NULL && *LineStart != CHAR_NULL) {
+ ConsoleLoggerOutputStringSplit (LineStart, ConsoleInfo);
+ }
+
+ SHELL_FREE_NON_NULL(StringCopy);
+ return (EFI_SUCCESS);
+}
+
+/**
+ Write a Unicode string to the output device.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] WString The NULL-terminated Unicode string to be displayed on the output
+ device(s). All output devices must also support the Unicode
+ drawing defined in this file.
+ @retval EFI_SUCCESS The string was output to the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
+ the text.
+ @retval EFI_UNSUPPORTED The output device's mode is not currently in a
+ defined text mode.
+ @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
+ characters in the Unicode string could not be
+ rendered and were skipped.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerOutputString (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN CHAR16 *WString
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TxtInEx;
+ EFI_KEY_DATA KeyData;
+ UINTN EventIndex;
+ CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
+
+ ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
+ if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) {
+ return (EFI_UNSUPPORTED);
+ }
+ ASSERT(ShellInfoObject.ConsoleInfo == ConsoleInfo);
+
+ Status = gBS->HandleProtocol (gST->ConsoleInHandle, &gEfiSimpleTextInputExProtocolGuid, (VOID **) &TxtInEx);
+ if (!EFI_ERROR (Status)) {
+ while (ShellInfoObject.HaltOutput) {
+
+ ShellInfoObject.HaltOutput = FALSE;
+ //
+ // just get some key
+ //
+ Status = gBS->WaitForEvent (1, &TxtInEx->WaitForKeyEx, &EventIndex);
+ ASSERT_EFI_ERROR (Status);
+ Status = TxtInEx->ReadKeyStrokeEx (TxtInEx, &KeyData);
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+
+ if ((KeyData.Key.UnicodeChar == L's') && (KeyData.Key.ScanCode == SCAN_NULL) &&
+ ((KeyData.KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID | EFI_LEFT_CONTROL_PRESSED)) ||
+ (KeyData.KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID | EFI_RIGHT_CONTROL_PRESSED))
+ )
+ ) {
+ ShellInfoObject.HaltOutput = TRUE;
+ }
+ }
+ }
+
+ if (!ShellInfoObject.ConsoleInfo->Enabled) {
+ return (EFI_DEVICE_ERROR);
+ } else if (ShellInfoObject.PageBreakEnabled) {
+ return (ConsoleLoggerPrintWithPageBreak(WString, ConsoleInfo));
+ } else {
+ return (ConsoleLoggerOutputStringSplit(WString, ConsoleInfo));
+ }
+}
+
+/**
+ Verifies that all characters in a Unicode string can be output to the
+ target device.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] WString The NULL-terminated Unicode string to be examined for the output
+ device(s).
+
+ @retval EFI_SUCCESS The device(s) are capable of rendering the output string.
+ @retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be
+ rendered by one or more of the output devices mapped
+ by the EFI handle.
+
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerTestString (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN CHAR16 *WString
+ )
+{
+ CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
+ ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
+ //
+ // Forward the request to the original ConOut
+ //
+ return (ConsoleInfo->OldConOut->TestString (ConsoleInfo->OldConOut, WString));
+}
+
+/**
+ Returns information for an available text mode that the output device(s)
+ supports.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] ModeNumber The mode number to return information on.
+ @param[out] Columns Upon return, the number of columns in the selected geometry
+ @param[out] Rows Upon return, the number of rows in the selected geometry
+
+ @retval EFI_SUCCESS The requested mode information was returned.
+ @retval EFI_DEVICE_ERROR The device had an error and could not
+ complete the request.
+ @retval EFI_UNSUPPORTED The mode number was not valid.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerQueryMode (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN ModeNumber,
+ OUT UINTN *Columns,
+ OUT UINTN *Rows
+ )
+{
+ CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
+ ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
+ //
+ // Forward the request to the original ConOut
+ //
+ return (ConsoleInfo->OldConOut->QueryMode (
+ ConsoleInfo->OldConOut,
+ ModeNumber,
+ Columns,
+ Rows
+ ));
+}
+
+/**
+ Sets the output device(s) to a specified mode.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] ModeNumber The mode number to set.
+
+
+ @retval EFI_SUCCESS The requested text mode was set.
+ @retval EFI_DEVICE_ERROR The device had an error and
+ could not complete the request.
+ @retval EFI_UNSUPPORTED The mode number was not valid.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerSetMode (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN ModeNumber
+ )
+{
+ EFI_STATUS Status;
+
+ CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
+ ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
+
+ //
+ // Forward the request to the original ConOut
+ //
+ Status = ConsoleInfo->OldConOut->SetMode (ConsoleInfo->OldConOut, ModeNumber);
+
+ //
+ // Check that the buffers are still correct for logging
+ //
+ if (!EFI_ERROR (Status)) {
+ ConsoleInfo->OurConOut.Mode = ConsoleInfo->OldConOut->Mode;
+ ConsoleLoggerResetBuffers(ConsoleInfo);
+ ConsoleInfo->OriginalStartRow = 0;
+ ConsoleInfo->CurrentStartRow = 0;
+ ConsoleInfo->OurConOut.ClearScreen (&ConsoleInfo->OurConOut);
+ }
+
+ return Status;
+}
+
+/**
+ Sets the background and foreground colors for the OutputString () and
+ ClearScreen () functions.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Attribute The attribute to set. Bits 0..3 are the foreground color, and
+ bits 4..6 are the background color. All other bits are undefined
+ and must be zero. The valid Attributes are defined in this file.
+
+ @retval EFI_SUCCESS The attribute was set.
+ @retval EFI_DEVICE_ERROR The device had an error and
+ could not complete the request.
+ @retval EFI_UNSUPPORTED The attribute requested is not defined.
+
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerSetAttribute (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN Attribute
+ )
+{
+ EFI_STATUS Status;
+
+ CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
+ ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
+
+ //
+ // Forward the request to the original ConOut
+ //
+ Status = ConsoleInfo->OldConOut->SetAttribute (ConsoleInfo->OldConOut, Attribute);
+
+ //
+ // Record console output history
+ //
+ if (!EFI_ERROR (Status)) {
+ ConsoleInfo->HistoryMode.Attribute = (INT32) Attribute;
+ }
+
+ return Status;
+}
+
+/**
+ Clears the output device(s) display to the currently selected background
+ color.
+
+ @param[in] This Protocol instance pointer.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_DEVICE_ERROR The device had an error and
+ could not complete the request.
+ @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerClearScreen (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *Screen;
+ INT32 *Attributes;
+ UINTN Row;
+ UINTN Column;
+ CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
+
+ if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) {
+ return (EFI_UNSUPPORTED);
+ }
+
+ ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
+
+ //
+ // Forward the request to the original ConOut
+ //
+ Status = ConsoleInfo->OldConOut->ClearScreen (ConsoleInfo->OldConOut);
+
+ //
+ // Record console output history
+ //
+ if (!EFI_ERROR (Status)) {
+ Screen = &ConsoleInfo->Buffer[(ConsoleInfo->ColsPerScreen + 2) * ConsoleInfo->CurrentStartRow];
+ Attributes = &ConsoleInfo->Attributes[ConsoleInfo->ColsPerScreen * ConsoleInfo->CurrentStartRow];
+ for ( Row = ConsoleInfo->OriginalStartRow
+ ; Row < (ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount)
+ ; Row++
+ ){
+ for ( Column = 0
+ ; Column < ConsoleInfo->ColsPerScreen
+ ; Column++
+ , Screen++
+ , Attributes++
+ ){
+ *Screen = L' ';
+ *Attributes = ConsoleInfo->OldConOut->Mode->Attribute;
+ }
+ //
+ // Skip the NULL on each column end in text buffer only
+ //
+ Screen += 2;
+ }
+ ConsoleInfo->HistoryMode.CursorColumn = 0;
+ ConsoleInfo->HistoryMode.CursorRow = 0;
+ }
+
+ return Status;
+}
+
+/**
+ Sets the current coordinates of the cursor position
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Column Column to put the cursor in. Must be between zero and Column returned from QueryMode
+ @param[in] Row Row to put the cursor in. Must be between zero and Row returned from QueryMode
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_DEVICE_ERROR The device had an error and
+ could not complete the request.
+ @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the
+ cursor position is invalid for the current mode.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerSetCursorPosition (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN Column,
+ IN UINTN Row
+ )
+{
+ EFI_STATUS Status;
+ CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
+
+ if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) {
+ return (EFI_UNSUPPORTED);
+ }
+
+ ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
+ //
+ // Forward the request to the original ConOut
+ //
+ Status = ConsoleInfo->OldConOut->SetCursorPosition (
+ ConsoleInfo->OldConOut,
+ Column,
+ Row
+ );
+
+ //
+ // Record console output history
+ //
+ if (!EFI_ERROR (Status)) {
+ ConsoleInfo->HistoryMode.CursorColumn = (INT32)Column;
+ ConsoleInfo->HistoryMode.CursorRow = (INT32)(ConsoleInfo->OriginalStartRow + Row);
+ }
+
+ return Status;
+}
+
+/**
+ Makes the cursor visible or invisible
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Visible If TRUE, the cursor is set to be visible. If FALSE, the cursor is
+ set to be invisible.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_DEVICE_ERROR The device had an error and could not complete the
+ request, or the device does not support changing
+ the cursor mode.
+ @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerEnableCursor (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN BOOLEAN Visible
+ )
+{
+ EFI_STATUS Status;
+
+ CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo;
+ ConsoleInfo = CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(This);
+ //
+ // Forward the request to the original ConOut
+ //
+ Status = ConsoleInfo->OldConOut->EnableCursor (ConsoleInfo->OldConOut, Visible);
+
+ //
+ // Record console output history
+ //
+ if (!EFI_ERROR (Status)) {
+ ConsoleInfo->HistoryMode.CursorVisible = Visible;
+ }
+
+ return Status;
+}
+
+/**
+ Function to update and verify that the current buffers are correct.
+
+ @param[in] ConsoleInfo The pointer to the instance of the console logger information.
+
+ This will be used when a mode has changed or a reset ocurred to verify all
+ history buffers.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerResetBuffers(
+ IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
+ )
+{
+ EFI_STATUS Status;
+
+ if (ConsoleInfo->Buffer != NULL) {
+ FreePool(ConsoleInfo->Buffer);
+ ConsoleInfo->Buffer = NULL;
+ ConsoleInfo->BufferSize = 0;
+ }
+ if (ConsoleInfo->Attributes != NULL) {
+ FreePool(ConsoleInfo->Attributes);
+ ConsoleInfo->Attributes = NULL;
+ ConsoleInfo->AttribSize = 0;
+ }
+
+ Status = gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &ConsoleInfo->ColsPerScreen, &ConsoleInfo->RowsPerScreen);
+ if (EFI_ERROR(Status)){
+ return (Status);
+ }
+
+ ConsoleInfo->BufferSize = (ConsoleInfo->ColsPerScreen + 2) * ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount * sizeof(ConsoleInfo->Buffer[0]);
+ ConsoleInfo->AttribSize = ConsoleInfo->ColsPerScreen * ConsoleInfo->RowsPerScreen * ConsoleInfo->ScreenCount * sizeof(ConsoleInfo->Attributes[0]);
+
+ ConsoleInfo->Buffer = (CHAR16*)AllocateZeroPool(ConsoleInfo->BufferSize);
+
+ if (ConsoleInfo->Buffer == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ ConsoleInfo->Attributes = (INT32*)AllocateZeroPool(ConsoleInfo->AttribSize);
+ if (ConsoleInfo->Attributes == NULL) {
+ FreePool(ConsoleInfo->Buffer);
+ ConsoleInfo->Buffer = NULL;
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ CopyMem (&ConsoleInfo->HistoryMode, ConsoleInfo->OldConOut->Mode, sizeof (EFI_SIMPLE_TEXT_OUTPUT_MODE));
+
+ return (EFI_SUCCESS);
+}
diff --git a/Core/ShellPkg/Application/Shell/ConsoleLogger.h b/Core/ShellPkg/Application/Shell/ConsoleLogger.h
new file mode 100644
index 0000000000..19034c9050
--- /dev/null
+++ b/Core/ShellPkg/Application/Shell/ConsoleLogger.h
@@ -0,0 +1,329 @@
+/** @file
+ Provides interface to shell console logger.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#ifndef _CONSOLE_LOGGER_HEADER_
+#define _CONSOLE_LOGGER_HEADER_
+
+#include "Shell.h"
+
+#define CONSOLE_LOGGER_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('c', 'o', 'P', 'D')
+
+typedef struct _CONSOLE_LOGGER_PRIVATE_DATA{
+ UINTN Signature;
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL OurConOut; ///< the protocol we installed onto the system table
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *OldConOut; ///< old protocol to reinstall upon exiting
+ EFI_HANDLE OldConHandle; ///< old protocol handle
+ UINTN ScreenCount; ///< How many screens worth of data to save
+ CHAR16 *Buffer; ///< Buffer to save data
+ UINTN BufferSize; ///< size of buffer in bytes
+
+ // start row is the top of the screen
+ UINTN OriginalStartRow; ///< What the originally visible start row was
+ UINTN CurrentStartRow; ///< what the currently visible start row is
+
+ UINTN RowsPerScreen; ///< how many rows the screen can display
+ UINTN ColsPerScreen; ///< how many columns the screen can display
+
+ INT32 *Attributes; ///< Buffer for Attribute to be saved for each character
+ UINTN AttribSize; ///< Size of Attributes in bytes
+
+ EFI_SIMPLE_TEXT_OUTPUT_MODE HistoryMode; ///< mode of the history log
+ BOOLEAN Enabled; ///< Set to FALSE when a break is requested.
+ UINTN RowCounter; ///< Initial row of each print job.
+} CONSOLE_LOGGER_PRIVATE_DATA;
+
+#define CONSOLE_LOGGER_PRIVATE_DATA_FROM_THIS(a) CR (a, CONSOLE_LOGGER_PRIVATE_DATA, OurConOut, CONSOLE_LOGGER_PRIVATE_DATA_SIGNATURE)
+
+/**
+ Install our intermediate ConOut into the system table to
+ keep a log of all the info that is displayed to the user.
+
+ @param[in] ScreensToSave Sets how many screen-worths of data to save.
+ @param[out] ConsoleInfo The object to pass into later functions.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @return other The operation failed.
+
+ @sa ConsoleLoggerResetBuffers
+ @sa InstallProtocolInterface
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerInstall(
+ IN CONST UINTN ScreensToSave,
+ OUT CONSOLE_LOGGER_PRIVATE_DATA **ConsoleInfo
+ );
+
+/**
+ Return the system to the state it was before InstallConsoleLogger
+ was installed.
+
+ @param[in, out] ConsoleInfo The object from the install function.
+
+ @retval EFI_SUCCESS The operation was successful
+ @return other The operation failed. This was from UninstallProtocolInterface.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerUninstall(
+ IN OUT CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
+ );
+
+/**
+ Displays previously logged output back to the screen.
+
+ This will scroll the screen forwards and backwards through the log of previous
+ output. If Rows is 0 then the size of 1/2 the screen will be scrolled. If Rows
+ is (UINTN)(-1) then the size of the screen will be scrolled.
+
+ @param[in] Forward If TRUE then the log will be displayed forwards (scroll to newer).
+ If FALSE then the log will be displayed backwards (scroll to older).
+ @param[in] Rows Determines how many rows the log should scroll.
+ @param[in] ConsoleInfo The pointer to the instance of the console logger information.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerDisplayHistory(
+ IN CONST BOOLEAN Forward,
+ IN CONST UINTN Rows,
+ IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
+ );
+
+/**
+ Function to return to normal output whent he scrolling is complete.
+ @param[in] ConsoleInfo The pointer to the instance of the console logger information.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @return other The operation failed. See UpdateDisplayFromHistory.
+
+ @sa UpdateDisplayFromHistory
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerStopHistory(
+ IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
+ );
+
+/**
+ Updates the hidden ConOut to be displaying the correct stuff.
+ @param[in] ConsoleInfo The pointer to the instance of the console logger information.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @return other The operation failed.
+**/
+EFI_STATUS
+EFIAPI
+UpdateDisplayFromHistory(
+ IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
+ );
+
+/**
+ Reset the text output device hardware and optionaly run diagnostics
+
+ @param This Pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
+ @param ExtendedVerification Indicates that a more extensive test may be performed
+
+ @retval EFI_SUCCESS The text output device was reset.
+ @retval EFI_DEVICE_ERROR The text output device is not functioning correctly and
+ could not be reset.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerReset (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ );
+
+/**
+ Write a Unicode string to the output device.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] WString The NULL-terminated Unicode string to be displayed on the output
+ device(s). All output devices must also support the Unicode
+ drawing defined in this file.
+ @retval EFI_SUCCESS The string was output to the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
+ the text.
+ @retval EFI_UNSUPPORTED The output device's mode is not currently in a
+ defined text mode.
+ @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
+ characters in the Unicode string could not be
+ rendered and were skipped.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerOutputString(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN CHAR16 *WString
+ );
+
+/**
+ Verifies that all characters in a Unicode string can be output to the
+ target device.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] WString The NULL-terminated Unicode string to be examined for the output
+ device(s).
+
+ @retval EFI_SUCCESS The device(s) are capable of rendering the output string.
+ @retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be
+ rendered by one or more of the output devices mapped
+ by the EFI handle.
+
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerTestString (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN CHAR16 *WString
+ );
+
+/**
+ Returns information for an available text mode that the output device(s)
+ supports.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] ModeNumber The mode number to return information on.
+ @param[out] Columns Upon return, the number of columns in the selected geometry
+ @param[out] Rows Upon return, the number of rows in the selected geometry
+
+ @retval EFI_SUCCESS The requested mode information was returned.
+ @retval EFI_DEVICE_ERROR The device had an error and could not
+ complete the request.
+ @retval EFI_UNSUPPORTED The mode number was not valid.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerQueryMode (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN ModeNumber,
+ OUT UINTN *Columns,
+ OUT UINTN *Rows
+ );
+
+/**
+ Sets the output device(s) to a specified mode.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] ModeNumber The mode number to set.
+
+
+ @retval EFI_SUCCESS The requested text mode was set.
+ @retval EFI_DEVICE_ERROR The device had an error and
+ could not complete the request.
+ @retval EFI_UNSUPPORTED The mode number was not valid.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerSetMode (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN ModeNumber
+ );
+
+/**
+ Sets the background and foreground colors for the OutputString () and
+ ClearScreen () functions.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Attribute The attribute to set. Bits 0..3 are the foreground color, and
+ bits 4..6 are the background color. All other bits are undefined
+ and must be zero. The valid Attributes are defined in this file.
+
+ @retval EFI_SUCCESS The attribute was set.
+ @retval EFI_DEVICE_ERROR The device had an error and
+ could not complete the request.
+ @retval EFI_UNSUPPORTED The attribute requested is not defined.
+
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerSetAttribute (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN Attribute
+ );
+
+/**
+ Clears the output device(s) display to the currently selected background
+ color.
+
+ @param[in] This Protocol instance pointer.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_DEVICE_ERROR The device had an error and
+ could not complete the request.
+ @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerClearScreen (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
+ );
+
+/**
+ Sets the current coordinates of the cursor position.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Column Column to put the cursor in. Must be between zero and Column returned from QueryMode
+ @param[in] Row Row to put the cursor in. Must be between zero and Row returned from QueryMode
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_DEVICE_ERROR The device had an error and
+ could not complete the request.
+ @retval EFI_UNSUPPORTED The output device is not in a valid text mode, or the
+ cursor position is invalid for the current mode.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerSetCursorPosition (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN Column,
+ IN UINTN Row
+ );
+
+/**
+ Makes the cursor visible or invisible
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Visible If TRUE, the cursor is set to be visible. If FALSE, the cursor is
+ set to be invisible.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+ @retval EFI_DEVICE_ERROR The device had an error and could not complete the
+ request, or the device does not support changing
+ the cursor mode.
+ @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
+
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerEnableCursor (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN BOOLEAN Visible
+ );
+
+/**
+ Function to update and verify that the current buffers are correct.
+
+ @param[in] ConsoleInfo The pointer to the instance of the console logger information.
+
+ This will be used when a mode has changed or a reset ocurred to verify all
+ history buffers.
+**/
+EFI_STATUS
+EFIAPI
+ConsoleLoggerResetBuffers(
+ IN CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo
+ );
+
+#endif //_CONSOLE_LOGGER_HEADER_
+
diff --git a/Core/ShellPkg/Application/Shell/ConsoleWrappers.c b/Core/ShellPkg/Application/Shell/ConsoleWrappers.c
new file mode 100644
index 0000000000..46af141eba
--- /dev/null
+++ b/Core/ShellPkg/Application/Shell/ConsoleWrappers.c
@@ -0,0 +1,518 @@
+/** @file
+ Function definitions for shell simple text in and out on top of file handles.
+
+ (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Shell.h"
+
+extern BOOLEAN AsciiRedirection;
+
+typedef struct {
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL SimpleTextIn;
+ SHELL_FILE_HANDLE FileHandle;
+ EFI_HANDLE TheHandle;
+ UINT64 RemainingBytesOfInputFile;
+} SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL;
+
+typedef struct {
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL SimpleTextOut;
+ SHELL_FILE_HANDLE FileHandle;
+ EFI_HANDLE TheHandle;
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *OriginalSimpleTextOut;
+} SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL;
+
+/**
+ Event notification function for EFI_SIMPLE_TEXT_INPUT_PROTOCOL.WaitForKey event
+ Signal the event if there is key available
+
+ @param Event Indicates the event that invoke this function.
+ @param Context Indicates the calling context.
+
+**/
+VOID
+EFIAPI
+ConInWaitForKey (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ gBS->SignalEvent (Event);
+}
+
+/**
+ Reset function for the fake simple text input.
+
+ @param[in] This A pointer to the SimpleTextIn structure.
+ @param[in] ExtendedVerification TRUE for extra validation, FALSE otherwise.
+
+ @retval EFI_SUCCESS The reset was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBasedSimpleTextInReset(
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ return (EFI_SUCCESS);
+}
+
+/**
+ ReadKeyStroke function for the fake simple text input.
+
+ @param[in] This A pointer to the SimpleTextIn structure.
+ @param[in, out] Key A pointer to the Key structure to fill.
+
+ @retval EFI_SUCCESS The read was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBasedSimpleTextInReadKeyStroke(
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
+ IN OUT EFI_INPUT_KEY *Key
+ )
+{
+ UINTN Size;
+ UINTN CharSize;
+
+ //
+ // Verify the parameters
+ //
+ if (Key == NULL || This == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ //
+ // Check if we have any characters left in the stream.
+ //
+ if (((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)This)->RemainingBytesOfInputFile == 0) {
+ return (EFI_NOT_READY);
+ }
+
+ Size = sizeof(CHAR16);
+
+ if(!AsciiRedirection) {
+ CharSize = sizeof(CHAR16);
+ } else {
+ CharSize = sizeof(CHAR8);
+ }
+ //
+ // Decrement the amount of free space by Size or set to zero (for odd length files)
+ //
+ if (((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)This)->RemainingBytesOfInputFile > CharSize) {
+ ((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)This)->RemainingBytesOfInputFile -= CharSize;
+ } else {
+ ((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)This)->RemainingBytesOfInputFile = 0;
+ }
+
+ Key->ScanCode = 0;
+ return (ShellInfoObject.NewEfiShellProtocol->ReadFile(
+ ((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)This)->FileHandle,
+ &Size,
+ &Key->UnicodeChar));
+}
+
+/**
+ Function to create a EFI_SIMPLE_TEXT_INPUT_PROTOCOL on top of a
+ SHELL_FILE_HANDLE to support redirecting input from a file.
+
+ @param[in] FileHandleToUse The pointer to the SHELL_FILE_HANDLE to use.
+ @param[in] HandleLocation The pointer of a location to copy handle with protocol to.
+
+ @retval NULL There was insufficient memory available.
+ @return A pointer to the allocated protocol structure;
+**/
+EFI_SIMPLE_TEXT_INPUT_PROTOCOL*
+EFIAPI
+CreateSimpleTextInOnFile(
+ IN SHELL_FILE_HANDLE FileHandleToUse,
+ IN EFI_HANDLE *HandleLocation
+ )
+{
+ SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ProtocolToReturn;
+ EFI_STATUS Status;
+ UINT64 CurrentPosition;
+ UINT64 FileSize;
+
+ if (HandleLocation == NULL || FileHandleToUse == NULL) {
+ return (NULL);
+ }
+
+ ProtocolToReturn = AllocateZeroPool(sizeof(SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL));
+ if (ProtocolToReturn == NULL) {
+ return (NULL);
+ }
+
+ ShellGetFileSize (FileHandleToUse, &FileSize);
+ ShellGetFilePosition(FileHandleToUse, &CurrentPosition);
+
+ //
+ // Initialize the protocol members
+ //
+ ProtocolToReturn->RemainingBytesOfInputFile = FileSize - CurrentPosition;
+ ProtocolToReturn->FileHandle = FileHandleToUse;
+ ProtocolToReturn->SimpleTextIn.Reset = FileBasedSimpleTextInReset;
+ ProtocolToReturn->SimpleTextIn.ReadKeyStroke = FileBasedSimpleTextInReadKeyStroke;
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_WAIT,
+ TPL_NOTIFY,
+ ConInWaitForKey,
+ &ProtocolToReturn->SimpleTextIn,
+ &ProtocolToReturn->SimpleTextIn.WaitForKey
+ );
+
+ if (EFI_ERROR(Status)) {
+ FreePool(ProtocolToReturn);
+ return (NULL);
+ }
+ ///@todo possibly also install SimpleTextInputEx on the handle at this point.
+ Status = gBS->InstallProtocolInterface(
+ &(ProtocolToReturn->TheHandle),
+ &gEfiSimpleTextInProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &(ProtocolToReturn->SimpleTextIn));
+ if (!EFI_ERROR(Status)) {
+ *HandleLocation = ProtocolToReturn->TheHandle;
+ return ((EFI_SIMPLE_TEXT_INPUT_PROTOCOL*)ProtocolToReturn);
+ } else {
+ FreePool(ProtocolToReturn);
+ return (NULL);
+ }
+}
+
+/**
+ Function to close a EFI_SIMPLE_TEXT_INPUT_PROTOCOL on top of a
+ SHELL_FILE_HANDLE to support redirecting input from a file.
+
+ @param[in] SimpleTextIn The pointer to the SimpleTextIn to close.
+
+ @retval EFI_SUCCESS The object was closed.
+**/
+EFI_STATUS
+EFIAPI
+CloseSimpleTextInOnFile(
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleTextIn
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS Status1;
+
+ if (SimpleTextIn == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ Status = gBS->CloseEvent(((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL *)SimpleTextIn)->SimpleTextIn.WaitForKey);
+
+ Status1 = gBS->UninstallProtocolInterface(
+ ((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL*)SimpleTextIn)->TheHandle,
+ &gEfiSimpleTextInProtocolGuid,
+ &(((SHELL_EFI_SIMPLE_TEXT_INPUT_PROTOCOL*)SimpleTextIn)->SimpleTextIn));
+
+ FreePool(SimpleTextIn);
+ if (!EFI_ERROR(Status)) {
+ return (Status1);
+ } else {
+ return (Status);
+ }
+}
+
+/**
+ Reset the text output device hardware and optionaly run diagnostics.
+
+ @param This pointer to EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
+ @param ExtendedVerification Indicates that a more extensive test may be performed
+
+ @retval EFI_SUCCESS The text output device was reset.
+**/
+EFI_STATUS
+EFIAPI
+FileBasedSimpleTextOutReset (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN BOOLEAN ExtendedVerification
+ )
+{
+ return (EFI_SUCCESS);
+}
+
+/**
+ Verifies that all characters in a Unicode string can be output to the
+ target device.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] WString The NULL-terminated Unicode string to be examined.
+
+ @retval EFI_SUCCESS The device(s) are capable of rendering the output string.
+**/
+EFI_STATUS
+EFIAPI
+FileBasedSimpleTextOutTestString (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN CHAR16 *WString
+ )
+{
+ return (EFI_SUCCESS);
+}
+
+/**
+ Returns information for an available text mode that the output device(s)
+ supports.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] ModeNumber The mode number to return information on.
+ @param[out] Columns Upon return, the number of columns in the selected geometry
+ @param[out] Rows Upon return, the number of rows in the selected geometry
+
+ @retval EFI_UNSUPPORTED The mode number was not valid.
+**/
+EFI_STATUS
+EFIAPI
+FileBasedSimpleTextOutQueryMode (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN ModeNumber,
+ OUT UINTN *Columns,
+ OUT UINTN *Rows
+ )
+{
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *PassThruProtocol;
+
+ PassThruProtocol = ((SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)This)->OriginalSimpleTextOut;
+
+ // Pass the QueryMode call thru to the original SimpleTextOutProtocol
+ return (PassThruProtocol->QueryMode(
+ PassThruProtocol,
+ ModeNumber,
+ Columns,
+ Rows));
+}
+
+/**
+ Sets the output device(s) to a specified mode.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] ModeNumber The mode number to set.
+
+ @retval EFI_UNSUPPORTED The mode number was not valid.
+**/
+EFI_STATUS
+EFIAPI
+FileBasedSimpleTextOutSetMode (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN ModeNumber
+ )
+{
+ return (EFI_UNSUPPORTED);
+}
+
+/**
+ Sets the background and foreground colors for the OutputString () and
+ ClearScreen () functions.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Attribute The attribute to set. Bits 0..3 are the foreground color, and
+ bits 4..6 are the background color. All other bits are undefined
+ and must be zero. The valid Attributes are defined in this file.
+
+ @retval EFI_SUCCESS The attribute was set.
+**/
+EFI_STATUS
+EFIAPI
+FileBasedSimpleTextOutSetAttribute (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN Attribute
+ )
+{
+ return (EFI_SUCCESS);
+}
+
+/**
+ Clears the output device(s) display to the currently selected background
+ color.
+
+ @param[in] This Protocol instance pointer.
+
+ @retval EFI_UNSUPPORTED The output device is not in a valid text mode.
+**/
+EFI_STATUS
+EFIAPI
+FileBasedSimpleTextOutClearScreen (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
+ )
+{
+ return (EFI_SUCCESS);
+}
+
+/**
+ Sets the current coordinates of the cursor position
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Column Column to put the cursor in. Must be between zero and Column returned from QueryMode
+ @param[in] Row Row to put the cursor in. Must be between zero and Row returned from QueryMode
+
+ @retval EFI_SUCCESS The operation completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+FileBasedSimpleTextOutSetCursorPosition (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN UINTN Column,
+ IN UINTN Row
+ )
+{
+ return (EFI_SUCCESS);
+}
+
+/**
+ Makes the cursor visible or invisible
+
+ @param[in] This Protocol instance pointer.
+ @param[in] Visible If TRUE, the cursor is set to be visible. If FALSE, the cursor is
+ set to be invisible.
+
+ @retval EFI_SUCCESS The operation completed successfully.
+**/
+EFI_STATUS
+EFIAPI
+FileBasedSimpleTextOutEnableCursor (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN BOOLEAN Visible
+ )
+{
+ return (EFI_SUCCESS);
+}
+
+/**
+ Write a Unicode string to the output device.
+
+ @param[in] This Protocol instance pointer.
+ @param[in] WString The NULL-terminated Unicode string to be displayed on the output
+ device(s). All output devices must also support the Unicode
+ drawing defined in this file.
+ @retval EFI_SUCCESS The string was output to the device.
+ @retval EFI_DEVICE_ERROR The device reported an error while attempting to output
+ the text.
+ @retval EFI_UNSUPPORTED The output device's mode is not currently in a
+ defined text mode.
+ @retval EFI_WARN_UNKNOWN_GLYPH This warning code indicates that some of the
+ characters in the Unicode string could not be
+ rendered and were skipped.
+**/
+EFI_STATUS
+EFIAPI
+FileBasedSimpleTextOutOutputString (
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
+ IN CHAR16 *WString
+ )
+{
+ UINTN Size;
+ Size = StrLen(WString) * sizeof(CHAR16);
+ return (ShellInfoObject.NewEfiShellProtocol->WriteFile(
+ ((SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *)This)->FileHandle,
+ &Size,
+ WString));
+}
+
+/**
+ Function to create a EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL on top of a
+ SHELL_FILE_HANDLE to support redirecting output from a file.
+
+ @param[in] FileHandleToUse The pointer to the SHELL_FILE_HANDLE to use.
+ @param[in] HandleLocation The pointer of a location to copy handle with protocol to.
+ @param[in] OriginalProtocol The pointer to the original output protocol for pass thru of functions.
+
+ @retval NULL There was insufficient memory available.
+ @return A pointer to the allocated protocol structure;
+**/
+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL*
+EFIAPI
+CreateSimpleTextOutOnFile(
+ IN SHELL_FILE_HANDLE FileHandleToUse,
+ IN EFI_HANDLE *HandleLocation,
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *OriginalProtocol
+ )
+{
+ SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ProtocolToReturn;
+ EFI_STATUS Status;
+
+ if (HandleLocation == NULL || FileHandleToUse == NULL) {
+ return (NULL);
+ }
+
+ ProtocolToReturn = AllocateZeroPool(sizeof(SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL));
+ if (ProtocolToReturn == NULL) {
+ return (NULL);
+ }
+ ProtocolToReturn->FileHandle = FileHandleToUse;
+ ProtocolToReturn->OriginalSimpleTextOut = OriginalProtocol;
+ ProtocolToReturn->SimpleTextOut.Reset = FileBasedSimpleTextOutReset;
+ ProtocolToReturn->SimpleTextOut.TestString = FileBasedSimpleTextOutTestString;
+ ProtocolToReturn->SimpleTextOut.QueryMode = FileBasedSimpleTextOutQueryMode;
+ ProtocolToReturn->SimpleTextOut.SetMode = FileBasedSimpleTextOutSetMode;
+ ProtocolToReturn->SimpleTextOut.SetAttribute = FileBasedSimpleTextOutSetAttribute;
+ ProtocolToReturn->SimpleTextOut.ClearScreen = FileBasedSimpleTextOutClearScreen;
+ ProtocolToReturn->SimpleTextOut.SetCursorPosition = FileBasedSimpleTextOutSetCursorPosition;
+ ProtocolToReturn->SimpleTextOut.EnableCursor = FileBasedSimpleTextOutEnableCursor;
+ ProtocolToReturn->SimpleTextOut.OutputString = FileBasedSimpleTextOutOutputString;
+ ProtocolToReturn->SimpleTextOut.Mode = AllocateZeroPool(sizeof(EFI_SIMPLE_TEXT_OUTPUT_MODE));
+ if (ProtocolToReturn->SimpleTextOut.Mode == NULL) {
+ FreePool(ProtocolToReturn);
+ return (NULL);
+ }
+ ProtocolToReturn->SimpleTextOut.Mode->MaxMode = OriginalProtocol->Mode->MaxMode;
+ ProtocolToReturn->SimpleTextOut.Mode->Mode = OriginalProtocol->Mode->Mode;
+ ProtocolToReturn->SimpleTextOut.Mode->Attribute = OriginalProtocol->Mode->Attribute;
+ ProtocolToReturn->SimpleTextOut.Mode->CursorColumn = OriginalProtocol->Mode->CursorColumn;
+ ProtocolToReturn->SimpleTextOut.Mode->CursorRow = OriginalProtocol->Mode->CursorRow;
+ ProtocolToReturn->SimpleTextOut.Mode->CursorVisible = OriginalProtocol->Mode->CursorVisible;
+
+ Status = gBS->InstallProtocolInterface(
+ &(ProtocolToReturn->TheHandle),
+ &gEfiSimpleTextOutProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &(ProtocolToReturn->SimpleTextOut));
+ if (!EFI_ERROR(Status)) {
+ *HandleLocation = ProtocolToReturn->TheHandle;
+ return ((EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL*)ProtocolToReturn);
+ } else {
+ SHELL_FREE_NON_NULL(ProtocolToReturn->SimpleTextOut.Mode);
+ SHELL_FREE_NON_NULL(ProtocolToReturn);
+ return (NULL);
+ }
+}
+
+/**
+ Function to close a EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL on top of a
+ SHELL_FILE_HANDLE to support redirecting output from a file.
+
+ @param[in] SimpleTextOut The pointer to the SimpleTextOUT to close.
+
+ @retval EFI_SUCCESS The object was closed.
+**/
+EFI_STATUS
+EFIAPI
+CloseSimpleTextOutOnFile(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut
+ )
+{
+ EFI_STATUS Status;
+ if (SimpleTextOut == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+ Status = gBS->UninstallProtocolInterface(
+ ((SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL*)SimpleTextOut)->TheHandle,
+ &gEfiSimpleTextOutProtocolGuid,
+ &(((SHELL_EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL*)SimpleTextOut)->SimpleTextOut));
+ FreePool(SimpleTextOut->Mode);
+ FreePool(SimpleTextOut);
+ return (Status);
+}
diff --git a/Core/ShellPkg/Application/Shell/ConsoleWrappers.h b/Core/ShellPkg/Application/Shell/ConsoleWrappers.h
new file mode 100644
index 0000000000..ecd99a863d
--- /dev/null
+++ b/Core/ShellPkg/Application/Shell/ConsoleWrappers.h
@@ -0,0 +1,84 @@
+/** @file
+ Function definitions for shell simple text in and out on top of file handles.
+
+ (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SHELL_CONSOLE_WRAPPERS_HEADER_
+#define _SHELL_CONSOLE_WRAPPERS_HEADER_
+
+/**
+ Function to create a EFI_SIMPLE_TEXT_INPUT_PROTOCOL on top of a
+ SHELL_FILE_HANDLE to support redirecting input from a file.
+
+ @param[in] FileHandleToUse The pointer to the SHELL_FILE_HANDLE to use.
+ @param[in] HandleLocation The pointer of a location to copy handle with protocol to.
+
+ @retval NULL There was insufficient memory available.
+ @return A pointer to the allocated protocol structure;
+**/
+EFI_SIMPLE_TEXT_INPUT_PROTOCOL*
+EFIAPI
+CreateSimpleTextInOnFile(
+ IN SHELL_FILE_HANDLE FileHandleToUse,
+ IN EFI_HANDLE *HandleLocation
+ );
+
+/**
+ Function to close a EFI_SIMPLE_TEXT_INPUT_PROTOCOL on top of a
+ SHELL_FILE_HANDLE to support redirecting input from a file.
+
+ @param[in] SimpleTextIn The pointer to the SimpleTextIn to close.
+
+ @retval EFI_SUCCESS The object was closed.
+**/
+EFI_STATUS
+EFIAPI
+CloseSimpleTextInOnFile(
+ IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *SimpleTextIn
+ );
+
+/**
+ Function to create a EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL on top of a
+ SHELL_FILE_HANDLE to support redirecting output from a file.
+
+ @param[in] FileHandleToUse The pointer to the SHELL_FILE_HANDLE to use.
+ @param[in] HandleLocation The pointer of a location to copy handle with protocol to.
+ @param[in] OriginalProtocol The pointer to the original output protocol for pass thru of functions.
+
+ @retval NULL There was insufficient memory available.
+ @return A pointer to the allocated protocol structure;
+**/
+EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL*
+EFIAPI
+CreateSimpleTextOutOnFile(
+ IN SHELL_FILE_HANDLE FileHandleToUse,
+ IN EFI_HANDLE *HandleLocation,
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *OriginalProtocol
+ );
+
+/**
+ Function to close a EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL on top of a
+ SHELL_FILE_HANDLE to support redirecting output from a file.
+
+ @param[in] SimpleTextOut The pointer to the SimpleTextOUT to close.
+
+ @retval EFI_SUCCESS The object was closed.
+**/
+EFI_STATUS
+EFIAPI
+CloseSimpleTextOutOnFile(
+ IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *SimpleTextOut
+ );
+
+#endif //_SHELL_CONSOLE_WRAPPERS_HEADER_
+
diff --git a/Core/ShellPkg/Application/Shell/FileHandleInternal.h b/Core/ShellPkg/Application/Shell/FileHandleInternal.h
new file mode 100644
index 0000000000..11b490267c
--- /dev/null
+++ b/Core/ShellPkg/Application/Shell/FileHandleInternal.h
@@ -0,0 +1,68 @@
+/** @file
+ internal worker functions for FileHandleWrappers to use
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _FILE_HANDLE_INTERNAL_HEADER_
+#define _FILE_HANDLE_INTERNAL_HEADER_
+
+/**
+ Move the cursor position one character backward.
+
+ @param[in] LineLength Length of a line. Get it by calling QueryMode
+ @param[in, out] Column Current column of the cursor position
+ @param[in, out] Row Current row of the cursor position
+**/
+VOID
+EFIAPI
+MoveCursorBackward (
+ IN UINTN LineLength,
+ IN OUT UINTN *Column,
+ IN OUT UINTN *Row
+ );
+
+/**
+ Move the cursor position one character forward.
+
+ @param[in] LineLength Length of a line.
+ @param[in] TotalRow Total row of a screen
+ @param[in, out] Column Current column of the cursor position
+ @param[in, out] Row Current row of the cursor position
+**/
+VOID
+EFIAPI
+MoveCursorForward (
+ IN UINTN LineLength,
+ IN UINTN TotalRow,
+ IN OUT UINTN *Column,
+ IN OUT UINTN *Row
+ );
+
+/**
+ Prints out each previously typed command in the command list history log.
+
+ When each screen is full it will pause for a key before continuing.
+
+ @param[in] TotalCols How many columns are on the screen
+ @param[in] TotalRows How many rows are on the screen
+ @param[in] StartColumn which column to start at
+**/
+VOID
+EFIAPI
+PrintCommandHistory (
+ IN CONST UINTN TotalCols,
+ IN CONST UINTN TotalRows,
+ IN CONST UINTN StartColumn
+ );
+
+#endif //_FILE_HANDLE_INTERNAL_HEADER_
+
diff --git a/Core/ShellPkg/Application/Shell/FileHandleWrappers.c b/Core/ShellPkg/Application/Shell/FileHandleWrappers.c
new file mode 100644
index 0000000000..f6a82ee3c7
--- /dev/null
+++ b/Core/ShellPkg/Application/Shell/FileHandleWrappers.c
@@ -0,0 +1,1910 @@
+/** @file
+ EFI_FILE_PROTOCOL wrappers for other items (Like Environment Variables,
+ StdIn, StdOut, StdErr, etc...).
+
+ Copyright 2016 Dell Inc.
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Shell.h"
+#include "FileHandleInternal.h"
+
+#define MEM_WRITE_REALLOC_OVERHEAD 1024
+
+/**
+ File style interface for console (Open).
+
+ @param[in] This Ignored.
+ @param[out] NewHandle Ignored.
+ @param[in] FileName Ignored.
+ @param[in] OpenMode Ignored.
+ @param[in] Attributes Ignored.
+
+ @retval EFI_NOT_FOUND
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceOpenNotFound(
+ IN EFI_FILE_PROTOCOL *This,
+ OUT EFI_FILE_PROTOCOL **NewHandle,
+ IN CHAR16 *FileName,
+ IN UINT64 OpenMode,
+ IN UINT64 Attributes
+ )
+{
+ return (EFI_NOT_FOUND);
+}
+
+/**
+ File style interface for console (Close, Delete, & Flush)
+
+ @param[in] This Ignored.
+
+ @retval EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceNopGeneric(
+ IN EFI_FILE_PROTOCOL *This
+ )
+{
+ return (EFI_SUCCESS);
+}
+
+/**
+ File style interface for console (GetPosition).
+
+ @param[in] This Ignored.
+ @param[out] Position Ignored.
+
+ @retval EFI_UNSUPPORTED
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceNopGetPosition(
+ IN EFI_FILE_PROTOCOL *This,
+ OUT UINT64 *Position
+ )
+{
+ return (EFI_UNSUPPORTED);
+}
+
+/**
+ File style interface for console (SetPosition).
+
+ @param[in] This Ignored.
+ @param[in] Position Ignored.
+
+ @retval EFI_UNSUPPORTED
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceNopSetPosition(
+ IN EFI_FILE_PROTOCOL *This,
+ IN UINT64 Position
+ )
+{
+ return (EFI_UNSUPPORTED);
+}
+
+/**
+ File style interface for console (GetInfo).
+
+ @param[in] This Ignored.
+ @param[in] InformationType Ignored.
+ @param[in, out] BufferSize Ignored.
+ @param[out] Buffer Ignored.
+
+ @retval EFI_UNSUPPORTED
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceNopGetInfo(
+ IN EFI_FILE_PROTOCOL *This,
+ IN EFI_GUID *InformationType,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ return (EFI_UNSUPPORTED);
+}
+
+/**
+ File style interface for console (SetInfo).
+
+ @param[in] This Ignored.
+ @param[in] InformationType Ignored.
+ @param[in] BufferSize Ignored.
+ @param[in] Buffer Ignored.
+
+ @retval EFI_UNSUPPORTED
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceNopSetInfo(
+ IN EFI_FILE_PROTOCOL *This,
+ IN EFI_GUID *InformationType,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ return (EFI_UNSUPPORTED);
+}
+
+/**
+ File style interface for StdOut (Write).
+
+ Writes data to the screen.
+
+ @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
+ @param[in, out] BufferSize Size in bytes of Buffer.
+ @param[in] Buffer The pointer to the buffer to write.
+
+ @retval EFI_UNSUPPORTED No output console is supported.
+ @return A return value from gST->ConOut->OutputString.
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceStdOutWrite(
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ )
+{
+ if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut) {
+ return (EFI_UNSUPPORTED);
+ }
+ if (*((CHAR16 *)Buffer) == gUnicodeFileTag) {
+ return (gST->ConOut->OutputString(gST->ConOut, (CHAR16 *)Buffer + 1));
+ }
+ return (gST->ConOut->OutputString(gST->ConOut, Buffer));
+}
+
+/**
+ File style interface for StdIn (Write).
+
+ @param[in] This Ignored.
+ @param[in, out] BufferSize Ignored.
+ @param[in] Buffer Ignored.
+
+ @retval EFI_UNSUPPORTED
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceStdInWrite(
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ )
+{
+ return (EFI_UNSUPPORTED);
+}
+
+/**
+ File style interface for console StdErr (Write).
+
+ Writes error to the error output.
+
+ @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
+ @param[in, out] BufferSize Size in bytes of Buffer.
+ @param[in] Buffer The pointer to the buffer to write.
+
+ @return A return value from gST->StdErr->OutputString.
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceStdErrWrite(
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ )
+{
+ return (gST->StdErr->OutputString(gST->StdErr, Buffer));
+}
+
+/**
+ File style interface for console StdOut (Read).
+
+ @param[in] This Ignored.
+ @param[in, out] BufferSize Ignored.
+ @param[out] Buffer Ignored.
+
+ @retval EFI_UNSUPPORTED
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceStdOutRead(
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ return (EFI_UNSUPPORTED);
+}
+
+/**
+ File style interface for console StdErr (Read).
+
+ @param[in] This Ignored.
+ @param[in, out] BufferSize Ignored.
+ @param[out] Buffer Ignored.
+
+ @retval EFI_UNSUPPORTED Always.
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceStdErrRead(
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ return (EFI_UNSUPPORTED);
+}
+
+/**
+ File style interface for NUL file (Read).
+
+ @param[in] This Ignored.
+ @param[in, out] BufferSize Poiner to 0 upon return.
+ @param[out] Buffer Ignored.
+
+ @retval EFI_SUCCESS Always.
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceNulRead(
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ *BufferSize = 0;
+ return (EFI_SUCCESS);
+}
+
+/**
+ File style interface for NUL file (Write).
+
+ @param[in] This Ignored.
+ @param[in, out] BufferSize Ignored.
+ @param[in] Buffer Ignored.
+
+ @retval EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceNulWrite(
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ )
+{
+ return (EFI_SUCCESS);
+}
+
+/**
+ File style interface for console (Read).
+
+ This will return a single line of input from the console.
+
+ @param This A pointer to the EFI_FILE_PROTOCOL instance that is the
+ file handle to read data from. Not used.
+ @param BufferSize On input, the size of the Buffer. On output, the amount
+ of data returned in Buffer. In both cases, the size is
+ measured in bytes.
+ @param Buffer The buffer into which the data is read.
+
+
+ @retval EFI_SUCCESS The data was read.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_DEVICE_ERROR An attempt was made to read from a deleted file.
+ @retval EFI_DEVICE_ERROR On entry, the current file position is beyond the end of the file.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_BUFFER_TOO_SMALL The BufferSize is too small to read the current directory
+ entry. BufferSize has been updated with the size
+ needed to complete the request.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceStdInRead(
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ CHAR16 *CurrentString;
+ BOOLEAN Done;
+ UINTN Column; // Column of current cursor
+ UINTN Row; // Row of current cursor
+ UINTN StartColumn; // Column at the beginning of the line
+ UINTN Update; // Line index for update
+ UINTN Delete; // Num of chars to delete from console after update
+ UINTN StringLen; // Total length of the line
+ UINTN StringCurPos; // Line index corresponding to the cursor
+ UINTN MaxStr; // Maximum possible line length
+ UINTN Index;
+ UINTN TotalColumn; // Num of columns in the console
+ UINTN TotalRow; // Num of rows in the console
+ UINTN SkipLength;
+ UINTN OutputLength; // Length of the update string
+ UINTN TailRow; // Row of end of line
+ UINTN TailColumn; // Column of end of line
+ EFI_INPUT_KEY Key;
+
+ BUFFER_LIST *LinePos;
+ BUFFER_LIST *NewPos;
+ BOOLEAN InScrolling;
+ EFI_STATUS Status;
+ BOOLEAN InTabScrolling; // Whether in TAB-completion state
+ EFI_SHELL_FILE_INFO *FoundFileList;
+ EFI_SHELL_FILE_INFO *TabLinePos;
+ EFI_SHELL_FILE_INFO *TempPos;
+ CHAR16 *TabStr;
+ CHAR16 *TabOutputStr;
+ BOOLEAN InQuotationMode;
+ CHAR16 *TempStr;
+ UINTN TabPos; // Start index of the string to search for TAB completion.
+ UINTN TabUpdatePos; // Start index of the string updated by TAB stroke
+// UINTN Count;
+ UINTN EventIndex;
+ CONST CHAR16 *Cwd;
+
+ //
+ // If buffer is not large enough to hold a CHAR16, return minimum buffer size
+ //
+ if (*BufferSize < sizeof (CHAR16) * 2) {
+ *BufferSize = sizeof (CHAR16) * 2;
+ return (EFI_BUFFER_TOO_SMALL);
+ }
+
+ Done = FALSE;
+ CurrentString = Buffer;
+ StringLen = 0;
+ StringCurPos = 0;
+ OutputLength = 0;
+ Update = 0;
+ Delete = 0;
+ LinePos = NewPos = (BUFFER_LIST*)(&ShellInfoObject.ViewingSettings.CommandHistory);
+ InScrolling = FALSE;
+ InTabScrolling = FALSE;
+ Status = EFI_SUCCESS;
+ TabLinePos = NULL;
+ FoundFileList = NULL;
+ TempPos = NULL;
+ TabPos = 0;
+ TabUpdatePos = 0;
+
+ //
+ // Allocate buffers
+ //
+ TabStr = AllocateZeroPool (*BufferSize);
+ if (TabStr == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ TabOutputStr = AllocateZeroPool (*BufferSize);
+ if (TabOutputStr == NULL) {
+ FreePool(TabStr);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Get the screen setting and the current cursor location
+ //
+ Column = StartColumn = gST->ConOut->Mode->CursorColumn;
+ Row = gST->ConOut->Mode->CursorRow;
+ gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &TotalColumn, &TotalRow);
+
+ //
+ // Limit the line length to the buffer size or the minimun size of the
+ // screen. (The smaller takes effect)
+ //
+ MaxStr = TotalColumn * (TotalRow - 1) - StartColumn;
+ if (MaxStr > *BufferSize / sizeof (CHAR16)) {
+ MaxStr = *BufferSize / sizeof (CHAR16);
+ }
+ ZeroMem (CurrentString, MaxStr * sizeof (CHAR16));
+ do {
+ //
+ // Read a key
+ //
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ if (EFI_ERROR (Status)) {
+
+ if (Status == EFI_NOT_READY)
+ continue;
+
+ ZeroMem (CurrentString, MaxStr * sizeof(CHAR16));
+ StringLen = 0;
+ break;
+ }
+
+ //
+ // Press PageUp or PageDown to scroll the history screen up or down.
+ // Press any other key to quit scrolling.
+ //
+ if (Key.UnicodeChar == 0 && (Key.ScanCode == SCAN_PAGE_UP || Key.ScanCode == SCAN_PAGE_DOWN)) {
+ if (Key.ScanCode == SCAN_PAGE_UP) {
+ ConsoleLoggerDisplayHistory(FALSE, 0, ShellInfoObject.ConsoleInfo);
+ } else if (Key.ScanCode == SCAN_PAGE_DOWN) {
+ ConsoleLoggerDisplayHistory(TRUE, 0, ShellInfoObject.ConsoleInfo);
+ }
+
+ InScrolling = TRUE;
+ } else {
+ if (InScrolling) {
+ ConsoleLoggerStopHistory(ShellInfoObject.ConsoleInfo);
+ InScrolling = FALSE;
+ }
+ }
+
+ //
+ // If we are quitting TAB scrolling...
+ //
+ if (InTabScrolling && Key.UnicodeChar != CHAR_TAB) {
+ if (FoundFileList != NULL) {
+ ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FoundFileList);
+ DEBUG_CODE(FoundFileList = NULL;);
+ }
+ InTabScrolling = FALSE;
+ }
+
+ switch (Key.UnicodeChar) {
+ case CHAR_CARRIAGE_RETURN:
+ //
+ // All done, print a newline at the end of the string
+ //
+ TailRow = Row + (StringLen - StringCurPos + Column) / TotalColumn;
+ TailColumn = (StringLen - StringCurPos + Column) % TotalColumn;
+ ShellPrintEx ((INT32)TailColumn, (INT32)TailRow, L"%N\n");
+ Done = TRUE;
+ break;
+
+ case CHAR_BACKSPACE:
+ if (StringCurPos != 0) {
+ //
+ // If not move back beyond string beginning, move all characters behind
+ // the current position one character forward
+ //
+ StringCurPos--;
+ Update = StringCurPos;
+ Delete = 1;
+ CopyMem (CurrentString + StringCurPos, CurrentString + StringCurPos + 1, sizeof (CHAR16) * (StringLen - StringCurPos));
+
+ //
+ // Adjust the current column and row
+ //
+ MoveCursorBackward (TotalColumn, &Column, &Row);
+ }
+ break;
+
+ case CHAR_TAB:
+ //
+ // handle auto complete of file and directory names...
+ //
+ if (InTabScrolling) {
+ ASSERT(FoundFileList != NULL);
+ ASSERT(TabLinePos != NULL);
+ TabLinePos = (EFI_SHELL_FILE_INFO*)GetNextNode(&(FoundFileList->Link), &TabLinePos->Link);
+ if (IsNull(&(FoundFileList->Link), &TabLinePos->Link)) {
+ TabLinePos = (EFI_SHELL_FILE_INFO*)GetNextNode(&(FoundFileList->Link), &TabLinePos->Link);
+ }
+ } else {
+ TabPos = 0;
+ TabUpdatePos = 0;
+ InQuotationMode = FALSE;
+ for (Index = 0; Index < StringLen; Index++) {
+ if (CurrentString[Index] == L'\"') {
+ InQuotationMode = (BOOLEAN)(!InQuotationMode);
+ }
+ if (CurrentString[Index] == L' ' && !InQuotationMode) {
+ TabPos = Index + 1;
+ TabUpdatePos = Index + 1;
+ }
+ if (CurrentString[Index] == L'\\') {
+ TabUpdatePos = Index + 1;
+ }
+ }
+ if (StrStr(CurrentString + TabPos, L":") == NULL) {
+ Cwd = ShellInfoObject.NewEfiShellProtocol->GetCurDir(NULL);
+ if (Cwd != NULL) {
+ StrnCpyS(TabStr, (*BufferSize)/sizeof(CHAR16), Cwd, (*BufferSize)/sizeof(CHAR16) - 1);
+ StrCatS(TabStr, (*BufferSize)/sizeof(CHAR16), L"\\");
+ if (TabStr[StrLen(TabStr)-1] == L'\\' && *(CurrentString + TabPos) == L'\\' ) {
+ TabStr[StrLen(TabStr)-1] = CHAR_NULL;
+ }
+ StrnCatS( TabStr,
+ (*BufferSize)/sizeof(CHAR16),
+ CurrentString + TabPos,
+ StringLen - TabPos
+ );
+ } else {
+ *TabStr = CHAR_NULL;
+ StrnCatS(TabStr, (*BufferSize)/sizeof(CHAR16), CurrentString + TabPos, StringLen - TabPos);
+ }
+ } else {
+ StrnCpyS(TabStr, (*BufferSize)/sizeof(CHAR16), CurrentString + TabPos, (*BufferSize)/sizeof(CHAR16) - 1);
+ }
+ StrnCatS(TabStr, (*BufferSize)/sizeof(CHAR16), L"*", (*BufferSize)/sizeof(CHAR16) - 1 - StrLen(TabStr));
+ FoundFileList = NULL;
+ Status = ShellInfoObject.NewEfiShellProtocol->FindFiles(TabStr, &FoundFileList);
+ for ( TempStr = CurrentString
+ ; *TempStr == L' '
+ ; TempStr++); // note the ';'... empty for loop
+ //
+ // make sure we have a list before we do anything more...
+ //
+ if (EFI_ERROR (Status) || FoundFileList == NULL) {
+ InTabScrolling = FALSE;
+ TabLinePos = NULL;
+ continue;
+ } else {
+ //
+ // enumerate through the list of files
+ //
+ for ( TempPos = (EFI_SHELL_FILE_INFO*)GetFirstNode(&(FoundFileList->Link))
+ ; !IsNull(&FoundFileList->Link, &TempPos->Link)
+ ; TempPos = (EFI_SHELL_FILE_INFO*)GetNextNode(&(FoundFileList->Link), &(TempPos->Link))
+ ){
+ //
+ // If "cd" is typed, only directory name will be auto-complete filled
+ // in either case . and .. will be removed.
+ //
+ if ((((TempStr[0] == L'c' || TempStr[0] == L'C') &&
+ (TempStr[1] == L'd' || TempStr[1] == L'D')
+ ) && ((ShellIsDirectory(TempPos->FullName) != EFI_SUCCESS)
+ ||(StrCmp(TempPos->FileName, L".") == 0)
+ ||(StrCmp(TempPos->FileName, L"..") == 0)
+ )) || ((StrCmp(TempPos->FileName, L".") == 0)
+ ||(StrCmp(TempPos->FileName, L"..") == 0))){
+ TabLinePos = TempPos;
+ TempPos = (EFI_SHELL_FILE_INFO*)(RemoveEntryList(&(TempPos->Link))->BackLink);
+ InternalFreeShellFileInfoNode(TabLinePos);
+ }
+ }
+ if (FoundFileList != NULL && !IsListEmpty(&FoundFileList->Link)) {
+ TabLinePos = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FoundFileList->Link);
+ InTabScrolling = TRUE;
+ } else {
+ ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FoundFileList);
+ }
+ }
+ }
+ break;
+
+ default:
+ if (Key.UnicodeChar >= ' ') {
+ //
+ // If we are at the buffer's end, drop the key
+ //
+ if (StringLen == MaxStr - 1 && (ShellInfoObject.ViewingSettings.InsertMode || StringCurPos == StringLen)) {
+ break;
+ }
+ //
+ // If in insert mode, make space by moving each other character 1
+ // space higher in the array
+ //
+ if (ShellInfoObject.ViewingSettings.InsertMode) {
+ CopyMem(CurrentString + StringCurPos + 1, CurrentString + StringCurPos, (StringLen - StringCurPos)*sizeof(CurrentString[0]));
+ }
+
+ CurrentString[StringCurPos] = Key.UnicodeChar;
+ Update = StringCurPos;
+
+ StringCurPos += 1;
+ OutputLength = 1;
+ }
+ break;
+
+ case 0:
+ switch (Key.ScanCode) {
+ case SCAN_DELETE:
+ //
+ // Move characters behind current position one character forward
+ //
+ if (StringLen != 0) {
+ Update = StringCurPos;
+ Delete = 1;
+ CopyMem (CurrentString + StringCurPos, CurrentString + StringCurPos + 1, sizeof (CHAR16) * (StringLen - StringCurPos));
+ }
+ break;
+
+ case SCAN_UP:
+ //
+ // Prepare to print the previous command
+ //
+ NewPos = (BUFFER_LIST*)GetPreviousNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link);
+ if (IsNull(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link)) {
+ NewPos = (BUFFER_LIST*)GetPreviousNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link);
+ }
+ break;
+
+ case SCAN_DOWN:
+ //
+ // Prepare to print the next command
+ //
+ NewPos = (BUFFER_LIST*)GetNextNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link);
+ if (NewPos == (BUFFER_LIST*)(&ShellInfoObject.ViewingSettings.CommandHistory)) {
+ NewPos = (BUFFER_LIST*)GetNextNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &LinePos->Link);
+ }
+ break;
+
+ case SCAN_LEFT:
+ //
+ // Adjust current cursor position
+ //
+ if (StringCurPos != 0) {
+ --StringCurPos;
+ MoveCursorBackward (TotalColumn, &Column, &Row);
+ }
+ break;
+
+ case SCAN_RIGHT:
+ //
+ // Adjust current cursor position
+ //
+ if (StringCurPos < StringLen) {
+ ++StringCurPos;
+ MoveCursorForward (TotalColumn, TotalRow, &Column, &Row);
+ }
+ break;
+
+ case SCAN_HOME:
+ //
+ // Move current cursor position to the beginning of the command line
+ //
+ Row -= (StringCurPos + StartColumn) / TotalColumn;
+ Column = StartColumn;
+ StringCurPos = 0;
+ break;
+
+ case SCAN_END:
+ //
+ // Move current cursor position to the end of the command line
+ //
+ TailRow = Row + (StringLen - StringCurPos + Column) / TotalColumn;
+ TailColumn = (StringLen - StringCurPos + Column) % TotalColumn;
+ Row = TailRow;
+ Column = TailColumn;
+ StringCurPos = StringLen;
+ break;
+
+ case SCAN_ESC:
+ //
+ // Prepare to clear the current command line
+ //
+ CurrentString[0] = 0;
+ Update = 0;
+ Delete = StringLen;
+ Row -= (StringCurPos + StartColumn) / TotalColumn;
+ Column = StartColumn;
+ OutputLength = 0;
+ break;
+
+ case SCAN_INSERT:
+ //
+ // Toggle the SEnvInsertMode flag
+ //
+ ShellInfoObject.ViewingSettings.InsertMode = (BOOLEAN)!ShellInfoObject.ViewingSettings.InsertMode;
+ break;
+
+ case SCAN_F7:
+ //
+ // Print command history
+ //
+ PrintCommandHistory (TotalColumn, TotalRow, 4);
+ *CurrentString = CHAR_NULL;
+ Done = TRUE;
+ break;
+ }
+ }
+
+ if (Done) {
+ break;
+ }
+
+ //
+ // If we are in auto-complete mode, we are preparing to print
+ // the next file or directory name
+ //
+ if (InTabScrolling) {
+ //
+ // Adjust the column and row to the start of TAB-completion string.
+ //
+ Column = (StartColumn + TabUpdatePos) % TotalColumn;
+ Row -= (StartColumn + StringCurPos) / TotalColumn - (StartColumn + TabUpdatePos) / TotalColumn;
+ OutputLength = StrLen (TabLinePos->FileName);
+ //
+ // if the output string contains blank space, quotation marks L'\"'
+ // should be added to the output.
+ //
+ if (StrStr(TabLinePos->FileName, L" ") != NULL){
+ TabOutputStr[0] = L'\"';
+ CopyMem (TabOutputStr + 1, TabLinePos->FileName, OutputLength * sizeof (CHAR16));
+ TabOutputStr[OutputLength + 1] = L'\"';
+ TabOutputStr[OutputLength + 2] = CHAR_NULL;
+ } else {
+ CopyMem (TabOutputStr, TabLinePos->FileName, OutputLength * sizeof (CHAR16));
+ TabOutputStr[OutputLength] = CHAR_NULL;
+ }
+ OutputLength = StrLen (TabOutputStr) < MaxStr - 1 ? StrLen (TabOutputStr) : MaxStr - 1;
+ CopyMem (CurrentString + TabUpdatePos, TabOutputStr, OutputLength * sizeof (CHAR16));
+ CurrentString[TabUpdatePos + OutputLength] = CHAR_NULL;
+ StringCurPos = TabUpdatePos + OutputLength;
+ Update = TabUpdatePos;
+ if (StringLen > TabUpdatePos + OutputLength) {
+ Delete = StringLen - TabUpdatePos - OutputLength;
+ }
+ }
+
+ //
+ // If we have a new position, we are preparing to print a previous or
+ // next command.
+ //
+ if (NewPos != (BUFFER_LIST*)(&ShellInfoObject.ViewingSettings.CommandHistory)) {
+ Column = StartColumn;
+ Row -= (StringCurPos + StartColumn) / TotalColumn;
+
+ LinePos = NewPos;
+ NewPos = (BUFFER_LIST*)(&ShellInfoObject.ViewingSettings.CommandHistory);
+
+ OutputLength = StrLen (LinePos->Buffer) < MaxStr - 1 ? StrLen (LinePos->Buffer) : MaxStr - 1;
+ CopyMem (CurrentString, LinePos->Buffer, OutputLength * sizeof (CHAR16));
+ CurrentString[OutputLength] = CHAR_NULL;
+
+ StringCurPos = OutputLength;
+
+ //
+ // Draw new input string
+ //
+ Update = 0;
+ if (StringLen > OutputLength) {
+ //
+ // If old string was longer, blank its tail
+ //
+ Delete = StringLen - OutputLength;
+ }
+ }
+ //
+ // If we need to update the output do so now
+ //
+ if (Update != (UINTN) -1) {
+ ShellPrintEx ((INT32)Column, (INT32)Row, L"%s%.*s", CurrentString + Update, Delete, L"");
+ StringLen = StrLen (CurrentString);
+
+ if (Delete != 0) {
+ SetMem (CurrentString + StringLen, Delete * sizeof (CHAR16), CHAR_NULL);
+ }
+
+ if (StringCurPos > StringLen) {
+ StringCurPos = StringLen;
+ }
+
+ Update = (UINTN) -1;
+
+ //
+ // After using print to reflect newly updates, if we're not using
+ // BACKSPACE and DELETE, we need to move the cursor position forward,
+ // so adjust row and column here.
+ //
+ if (Key.UnicodeChar != CHAR_BACKSPACE && !(Key.UnicodeChar == 0 && Key.ScanCode == SCAN_DELETE)) {
+ //
+ // Calulate row and column of the tail of current string
+ //
+ TailRow = Row + (StringLen - StringCurPos + Column + OutputLength) / TotalColumn;
+ TailColumn = (StringLen - StringCurPos + Column + OutputLength) % TotalColumn;
+
+ //
+ // If the tail of string reaches screen end, screen rolls up, so if
+ // Row does not equal TailRow, Row should be decremented
+ //
+ // (if we are recalling commands using UPPER and DOWN key, and if the
+ // old command is too long to fit the screen, TailColumn must be 79.
+ //
+ if (TailColumn == 0 && TailRow >= TotalRow && Row != TailRow) {
+ Row--;
+ }
+ //
+ // Calculate the cursor position after current operation. If cursor
+ // reaches line end, update both row and column, otherwise, only
+ // column will be changed.
+ //
+ if (Column + OutputLength >= TotalColumn) {
+ SkipLength = OutputLength - (TotalColumn - Column);
+
+ Row += SkipLength / TotalColumn + 1;
+ if (Row > TotalRow - 1) {
+ Row = TotalRow - 1;
+ }
+
+ Column = SkipLength % TotalColumn;
+ } else {
+ Column += OutputLength;
+ }
+ }
+
+ Delete = 0;
+ }
+ //
+ // Set the cursor position for this key
+ //
+ gST->ConOut->SetCursorPosition (gST->ConOut, Column, Row);
+ } while (!Done);
+
+ if (CurrentString != NULL && StrLen(CurrentString) > 0) {
+ //
+ // add the line to the history buffer
+ //
+ AddLineToCommandHistory(CurrentString);
+ }
+
+ FreePool (TabStr);
+ FreePool (TabOutputStr);
+ //
+ // Return the data to the caller
+ //
+ *BufferSize = StringLen * sizeof (CHAR16);
+
+ //
+ // if this was used it should be deallocated by now...
+ // prevent memory leaks...
+ //
+ if (FoundFileList != NULL) {
+ ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FoundFileList);
+ }
+ ASSERT(FoundFileList == NULL);
+
+ return Status;
+}
+
+//
+// FILE sytle interfaces for StdIn/StdOut/StdErr
+//
+EFI_FILE_PROTOCOL FileInterfaceStdIn = {
+ EFI_FILE_REVISION,
+ FileInterfaceOpenNotFound,
+ FileInterfaceNopGeneric,
+ FileInterfaceNopGeneric,
+ FileInterfaceStdInRead,
+ FileInterfaceStdInWrite,
+ FileInterfaceNopGetPosition,
+ FileInterfaceNopSetPosition,
+ FileInterfaceNopGetInfo,
+ FileInterfaceNopSetInfo,
+ FileInterfaceNopGeneric
+};
+
+EFI_FILE_PROTOCOL FileInterfaceStdOut = {
+ EFI_FILE_REVISION,
+ FileInterfaceOpenNotFound,
+ FileInterfaceNopGeneric,
+ FileInterfaceNopGeneric,
+ FileInterfaceStdOutRead,
+ FileInterfaceStdOutWrite,
+ FileInterfaceNopGetPosition,
+ FileInterfaceNopSetPosition,
+ FileInterfaceNopGetInfo,
+ FileInterfaceNopSetInfo,
+ FileInterfaceNopGeneric
+};
+
+EFI_FILE_PROTOCOL FileInterfaceStdErr = {
+ EFI_FILE_REVISION,
+ FileInterfaceOpenNotFound,
+ FileInterfaceNopGeneric,
+ FileInterfaceNopGeneric,
+ FileInterfaceStdErrRead,
+ FileInterfaceStdErrWrite,
+ FileInterfaceNopGetPosition,
+ FileInterfaceNopSetPosition,
+ FileInterfaceNopGetInfo,
+ FileInterfaceNopSetInfo,
+ FileInterfaceNopGeneric
+};
+
+EFI_FILE_PROTOCOL FileInterfaceNulFile = {
+ EFI_FILE_REVISION,
+ FileInterfaceOpenNotFound,
+ FileInterfaceNopGeneric,
+ FileInterfaceNopGeneric,
+ FileInterfaceNulRead,
+ FileInterfaceNulWrite,
+ FileInterfaceNopGetPosition,
+ FileInterfaceNopSetPosition,
+ FileInterfaceNopGetInfo,
+ FileInterfaceNopSetInfo,
+ FileInterfaceNopGeneric
+};
+
+
+
+
+//
+// This is identical to EFI_FILE_PROTOCOL except for the additional member
+// for the name.
+//
+
+typedef struct {
+ UINT64 Revision;
+ EFI_FILE_OPEN Open;
+ EFI_FILE_CLOSE Close;
+ EFI_FILE_DELETE Delete;
+ EFI_FILE_READ Read;
+ EFI_FILE_WRITE Write;
+ EFI_FILE_GET_POSITION GetPosition;
+ EFI_FILE_SET_POSITION SetPosition;
+ EFI_FILE_GET_INFO GetInfo;
+ EFI_FILE_SET_INFO SetInfo;
+ EFI_FILE_FLUSH Flush;
+ CHAR16 Name[1];
+} EFI_FILE_PROTOCOL_ENVIRONMENT;
+//ANSI compliance helper to get size of the struct.
+#define SIZE_OF_EFI_FILE_PROTOCOL_ENVIRONMENT EFI_FIELD_OFFSET (EFI_FILE_PROTOCOL_ENVIRONMENT, Name)
+
+/**
+ File style interface for Environment Variable (Close).
+
+ Frees the memory for this object.
+
+ @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
+
+ @retval EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceEnvClose(
+ IN EFI_FILE_PROTOCOL *This
+ )
+{
+ VOID* NewBuffer;
+ UINTN NewSize;
+ EFI_STATUS Status;
+ BOOLEAN Volatile;
+
+ //
+ // Most if not all UEFI commands will have an '\r\n' at the end of any output.
+ // Since the output was redirected to a variable, it does not make sense to
+ // keep this. So, before closing, strip the trailing '\r\n' from the variable
+ // if it exists.
+ //
+ NewBuffer = NULL;
+ NewSize = 0;
+
+ Status = IsVolatileEnv (((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &Volatile);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ NewBuffer = AllocateZeroPool(NewSize + sizeof(CHAR16));
+ if (NewBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);
+ }
+
+ if (!EFI_ERROR(Status) && NewBuffer != NULL) {
+
+ if (StrSize(NewBuffer) > 6)
+ {
+ if ((((CHAR16*)NewBuffer)[(StrSize(NewBuffer)/2) - 2] == CHAR_LINEFEED)
+ && (((CHAR16*)NewBuffer)[(StrSize(NewBuffer)/2) - 3] == CHAR_CARRIAGE_RETURN)) {
+ ((CHAR16*)NewBuffer)[(StrSize(NewBuffer)/2) - 3] = CHAR_NULL;
+ }
+
+ if (Volatile) {
+ Status = SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, StrSize(NewBuffer), NewBuffer);
+ } else {
+ Status = SHELL_SET_ENVIRONMENT_VARIABLE_NV(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, StrSize(NewBuffer), NewBuffer);
+ }
+ }
+ }
+
+ SHELL_FREE_NON_NULL(NewBuffer);
+ FreePool((EFI_FILE_PROTOCOL_ENVIRONMENT*)This);
+ return (Status);
+}
+
+/**
+ File style interface for Environment Variable (Delete).
+
+ @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
+
+ @retval The return value from FileInterfaceEnvClose().
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceEnvDelete(
+ IN EFI_FILE_PROTOCOL *This
+ )
+{
+ SHELL_DELETE_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name);
+ return (FileInterfaceEnvClose(This));
+}
+
+/**
+ File style interface for Environment Variable (Read).
+
+ @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
+ @param[in, out] BufferSize Size in bytes of Buffer.
+ @param[out] Buffer The pointer to the buffer to fill.
+
+ @retval EFI_SUCCESS The data was read.
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceEnvRead(
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ return (SHELL_GET_ENVIRONMENT_VARIABLE(
+ ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name,
+ BufferSize,
+ Buffer));
+}
+
+/**
+ File style interface for Volatile Environment Variable (Write).
+
+ @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
+ @param[in, out] BufferSize Size in bytes of Buffer.
+ @param[in] Buffer The pointer to the buffer to write.
+
+ @retval EFI_SUCCESS The data was read.
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceEnvVolWrite(
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ )
+{
+ VOID* NewBuffer;
+ UINTN NewSize;
+ EFI_STATUS Status;
+
+ NewBuffer = NULL;
+ NewSize = 0;
+
+ Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);
+ if (Status == EFI_BUFFER_TOO_SMALL){
+ NewBuffer = AllocateZeroPool(NewSize + *BufferSize + sizeof(CHAR16));
+ Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);
+ }
+ if (!EFI_ERROR(Status) && NewBuffer != NULL) {
+ while (((CHAR16*)NewBuffer)[NewSize/2] == CHAR_NULL) {
+ //
+ // We want to overwrite the CHAR_NULL
+ //
+ NewSize -= 2;
+ }
+ CopyMem((UINT8*)NewBuffer + NewSize + 2, Buffer, *BufferSize);
+ Status = SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, StrSize(NewBuffer), NewBuffer);
+ FreePool(NewBuffer);
+ return (Status);
+ } else {
+ SHELL_FREE_NON_NULL(NewBuffer);
+ return (SHELL_SET_ENVIRONMENT_VARIABLE_V(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, *BufferSize, Buffer));
+ }
+}
+
+
+/**
+ File style interface for Non Volatile Environment Variable (Write).
+
+ @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
+ @param[in, out] BufferSize Size in bytes of Buffer.
+ @param[in] Buffer The pointer to the buffer to write.
+
+ @retval EFI_SUCCESS The data was read.
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceEnvNonVolWrite(
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ )
+{
+ VOID* NewBuffer;
+ UINTN NewSize;
+ EFI_STATUS Status;
+
+ NewBuffer = NULL;
+ NewSize = 0;
+
+ Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);
+ if (Status == EFI_BUFFER_TOO_SMALL){
+ NewBuffer = AllocateZeroPool(NewSize + *BufferSize);
+ Status = SHELL_GET_ENVIRONMENT_VARIABLE(((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name, &NewSize, NewBuffer);
+ }
+ if (!EFI_ERROR(Status)) {
+ CopyMem((UINT8*)NewBuffer + NewSize, Buffer, *BufferSize);
+ return (SHELL_SET_ENVIRONMENT_VARIABLE_NV(
+ ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name,
+ NewSize + *BufferSize,
+ NewBuffer));
+ } else {
+ return (SHELL_SET_ENVIRONMENT_VARIABLE_NV(
+ ((EFI_FILE_PROTOCOL_ENVIRONMENT*)This)->Name,
+ *BufferSize,
+ Buffer));
+ }
+}
+
+/**
+ Creates a EFI_FILE_PROTOCOL (almost) object for using to access
+ environment variables through file operations.
+
+ @param EnvName The name of the Environment Variable to be operated on.
+
+ @retval NULL Memory could not be allocated.
+ @return other a pointer to an EFI_FILE_PROTOCOL structure
+**/
+EFI_FILE_PROTOCOL*
+EFIAPI
+CreateFileInterfaceEnv(
+ IN CONST CHAR16 *EnvName
+ )
+{
+ EFI_STATUS Status;
+ EFI_FILE_PROTOCOL_ENVIRONMENT *EnvFileInterface;
+ UINTN EnvNameSize;
+ BOOLEAN Volatile;
+
+ if (EnvName == NULL) {
+ return (NULL);
+ }
+
+ Status = IsVolatileEnv (EnvName, &Volatile);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ //
+ // Get some memory
+ //
+ EnvNameSize = StrSize(EnvName);
+ EnvFileInterface = AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_ENVIRONMENT)+EnvNameSize);
+ if (EnvFileInterface == NULL){
+ return (NULL);
+ }
+
+ //
+ // Assign the generic members
+ //
+ EnvFileInterface->Revision = EFI_FILE_REVISION;
+ EnvFileInterface->Open = FileInterfaceOpenNotFound;
+ EnvFileInterface->Close = FileInterfaceEnvClose;
+ EnvFileInterface->GetPosition = FileInterfaceNopGetPosition;
+ EnvFileInterface->SetPosition = FileInterfaceNopSetPosition;
+ EnvFileInterface->GetInfo = FileInterfaceNopGetInfo;
+ EnvFileInterface->SetInfo = FileInterfaceNopSetInfo;
+ EnvFileInterface->Flush = FileInterfaceNopGeneric;
+ EnvFileInterface->Delete = FileInterfaceEnvDelete;
+ EnvFileInterface->Read = FileInterfaceEnvRead;
+
+ CopyMem(EnvFileInterface->Name, EnvName, EnvNameSize);
+
+ //
+ // Assign the different members for Volatile and Non-Volatile variables
+ //
+ if (Volatile) {
+ EnvFileInterface->Write = FileInterfaceEnvVolWrite;
+ } else {
+ EnvFileInterface->Write = FileInterfaceEnvNonVolWrite;
+ }
+ return ((EFI_FILE_PROTOCOL *)EnvFileInterface);
+}
+
+/**
+ Move the cursor position one character backward.
+
+ @param[in] LineLength Length of a line. Get it by calling QueryMode
+ @param[in, out] Column Current column of the cursor position
+ @param[in, out] Row Current row of the cursor position
+**/
+VOID
+EFIAPI
+MoveCursorBackward (
+ IN UINTN LineLength,
+ IN OUT UINTN *Column,
+ IN OUT UINTN *Row
+ )
+{
+ //
+ // If current column is 0, move to the last column of the previous line,
+ // otherwise, just decrement column.
+ //
+ if (*Column == 0) {
+ *Column = LineLength - 1;
+ if (*Row > 0) {
+ (*Row)--;
+ }
+ return;
+ }
+ (*Column)--;
+}
+
+/**
+ Move the cursor position one character forward.
+
+ @param[in] LineLength Length of a line.
+ @param[in] TotalRow Total row of a screen
+ @param[in, out] Column Current column of the cursor position
+ @param[in, out] Row Current row of the cursor position
+**/
+VOID
+EFIAPI
+MoveCursorForward (
+ IN UINTN LineLength,
+ IN UINTN TotalRow,
+ IN OUT UINTN *Column,
+ IN OUT UINTN *Row
+ )
+{
+ //
+ // Increment Column.
+ // If this puts column past the end of the line, move to first column
+ // of the next row.
+ //
+ (*Column)++;
+ if (*Column >= LineLength) {
+ (*Column) = 0;
+ if ((*Row) < TotalRow - 1) {
+ (*Row)++;
+ }
+ }
+}
+
+/**
+ Prints out each previously typed command in the command list history log.
+
+ When each screen is full it will pause for a key before continuing.
+
+ @param[in] TotalCols How many columns are on the screen
+ @param[in] TotalRows How many rows are on the screen
+ @param[in] StartColumn which column to start at
+**/
+VOID
+EFIAPI
+PrintCommandHistory (
+ IN CONST UINTN TotalCols,
+ IN CONST UINTN TotalRows,
+ IN CONST UINTN StartColumn
+ )
+{
+ BUFFER_LIST *Node;
+ UINTN Index;
+ UINTN LineNumber;
+ UINTN LineCount;
+
+ ShellPrintEx (-1, -1, L"\n");
+ Index = 0;
+ LineNumber = 0;
+ //
+ // go through history list...
+ //
+ for ( Node = (BUFFER_LIST*)GetFirstNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link)
+ ; !IsNull(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link)
+ ; Node = (BUFFER_LIST*)GetNextNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link)
+ ){
+ Index++;
+ LineCount = ((StrLen (Node->Buffer) + StartColumn + 1) / TotalCols) + 1;
+
+ if (LineNumber + LineCount >= TotalRows) {
+ ShellPromptForResponseHii(
+ ShellPromptResponseTypeEnterContinue,
+ STRING_TOKEN (STR_SHELL_ENTER_TO_CONT),
+ ShellInfoObject.HiiHandle,
+ NULL
+ );
+ LineNumber = 0;
+ }
+ ShellPrintEx (-1, -1, L"%2d. %s\n", Index, Node->Buffer);
+ LineNumber += LineCount;
+ }
+}
+
+
+
+
+
+
+//
+// This is identical to EFI_FILE_PROTOCOL except for the additional members
+// for the buffer, size, and position.
+//
+
+typedef struct {
+ UINT64 Revision;
+ EFI_FILE_OPEN Open;
+ EFI_FILE_CLOSE Close;
+ EFI_FILE_DELETE Delete;
+ EFI_FILE_READ Read;
+ EFI_FILE_WRITE Write;
+ EFI_FILE_GET_POSITION GetPosition;
+ EFI_FILE_SET_POSITION SetPosition;
+ EFI_FILE_GET_INFO GetInfo;
+ EFI_FILE_SET_INFO SetInfo;
+ EFI_FILE_FLUSH Flush;
+ VOID *Buffer;
+ UINT64 Position;
+ UINT64 BufferSize;
+ BOOLEAN Unicode;
+ UINT64 FileSize;
+} EFI_FILE_PROTOCOL_MEM;
+
+/**
+ File style interface for Mem (SetPosition).
+
+ @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
+ @param[out] Position The position to set.
+
+ @retval EFI_SUCCESS The position was successfully changed.
+ @retval EFI_INVALID_PARAMETER The Position was invalid.
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceMemSetPosition(
+ IN EFI_FILE_PROTOCOL *This,
+ OUT UINT64 Position
+ )
+{
+ if (Position <= ((EFI_FILE_PROTOCOL_MEM*)This)->FileSize) {
+ ((EFI_FILE_PROTOCOL_MEM*)This)->Position = Position;
+ return (EFI_SUCCESS);
+ } else {
+ return (EFI_INVALID_PARAMETER);
+ }
+}
+
+/**
+ File style interface for Mem (GetPosition).
+
+ @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
+ @param[out] Position The pointer to the position.
+
+ @retval EFI_SUCCESS The position was retrieved.
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceMemGetPosition(
+ IN EFI_FILE_PROTOCOL *This,
+ OUT UINT64 *Position
+ )
+{
+ *Position = ((EFI_FILE_PROTOCOL_MEM*)This)->Position;
+ return (EFI_SUCCESS);
+}
+
+/**
+ File style interface for Mem (Write).
+
+ @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
+ @param[in, out] BufferSize Size in bytes of Buffer.
+ @param[in] Buffer The pointer to the buffer to write.
+
+ @retval EFI_OUT_OF_RESOURCES The operation failed due to lack of resources.
+ @retval EFI_SUCCESS The data was written.
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceMemWrite(
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ )
+{
+ CHAR8 *AsciiBuffer;
+ EFI_FILE_PROTOCOL_MEM *MemFile;
+
+ MemFile = (EFI_FILE_PROTOCOL_MEM *) This;
+ if (MemFile->Unicode) {
+ //
+ // Unicode
+ //
+ if ((UINTN)(MemFile->Position + (*BufferSize)) > (UINTN)(MemFile->BufferSize)) {
+ MemFile->Buffer = ReallocatePool((UINTN)(MemFile->BufferSize), (UINTN)(MemFile->BufferSize) + (*BufferSize) + MEM_WRITE_REALLOC_OVERHEAD, MemFile->Buffer);
+ MemFile->BufferSize += (*BufferSize) + MEM_WRITE_REALLOC_OVERHEAD;
+ }
+ CopyMem(((UINT8*)MemFile->Buffer) + MemFile->Position, Buffer, *BufferSize);
+ MemFile->Position += (*BufferSize);
+ MemFile->FileSize = MemFile->Position;
+ return (EFI_SUCCESS);
+ } else {
+ //
+ // Ascii
+ //
+ AsciiBuffer = AllocateZeroPool(*BufferSize);
+ if (AsciiBuffer == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ AsciiSPrint(AsciiBuffer, *BufferSize, "%S", Buffer);
+ if ((UINTN)(MemFile->Position + AsciiStrSize(AsciiBuffer)) > (UINTN)(MemFile->BufferSize)) {
+ MemFile->Buffer = ReallocatePool((UINTN)(MemFile->BufferSize), (UINTN)(MemFile->BufferSize) + AsciiStrSize(AsciiBuffer) + MEM_WRITE_REALLOC_OVERHEAD, MemFile->Buffer);
+ MemFile->BufferSize += AsciiStrSize(AsciiBuffer) + MEM_WRITE_REALLOC_OVERHEAD;
+ }
+ CopyMem(((UINT8*)MemFile->Buffer) + MemFile->Position, AsciiBuffer, AsciiStrSize(AsciiBuffer));
+ MemFile->Position += (*BufferSize / sizeof(CHAR16));
+ MemFile->FileSize = MemFile->Position;
+ FreePool(AsciiBuffer);
+ return (EFI_SUCCESS);
+ }
+}
+
+/**
+ File style interface for Mem (Read).
+
+ @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
+ @param[in, out] BufferSize Size in bytes of Buffer.
+ @param[in] Buffer The pointer to the buffer to fill.
+
+ @retval EFI_SUCCESS The data was read.
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceMemRead(
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ )
+{
+ EFI_FILE_PROTOCOL_MEM *MemFile;
+
+ MemFile = (EFI_FILE_PROTOCOL_MEM *) This;
+ if (*BufferSize > (UINTN)((MemFile->FileSize) - (UINTN)(MemFile->Position))) {
+ (*BufferSize) = (UINTN)((MemFile->FileSize) - (UINTN)(MemFile->Position));
+ }
+ CopyMem(Buffer, ((UINT8*)MemFile->Buffer) + MemFile->Position, (*BufferSize));
+ MemFile->Position = MemFile->Position + (*BufferSize);
+ return (EFI_SUCCESS);
+}
+
+/**
+ File style interface for Mem (Close).
+
+ Frees all memory associated with this object.
+
+ @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
+
+ @retval EFI_SUCCESS The 'file' was closed.
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceMemClose(
+ IN EFI_FILE_PROTOCOL *This
+ )
+{
+ SHELL_FREE_NON_NULL(((EFI_FILE_PROTOCOL_MEM*)This)->Buffer);
+ SHELL_FREE_NON_NULL(This);
+ return (EFI_SUCCESS);
+}
+
+/**
+ Creates a EFI_FILE_PROTOCOL (almost) object for using to access
+ a file entirely in memory through file operations.
+
+ @param[in] Unicode Boolean value with TRUE for Unicode and FALSE for Ascii.
+
+ @retval NULL Memory could not be allocated.
+ @return other A pointer to an EFI_FILE_PROTOCOL structure.
+**/
+EFI_FILE_PROTOCOL*
+EFIAPI
+CreateFileInterfaceMem(
+ IN CONST BOOLEAN Unicode
+ )
+{
+ EFI_FILE_PROTOCOL_MEM *FileInterface;
+
+ //
+ // Get some memory
+ //
+ FileInterface = AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_MEM));
+ if (FileInterface == NULL){
+ return (NULL);
+ }
+
+ //
+ // Assign the generic members
+ //
+ FileInterface->Revision = EFI_FILE_REVISION;
+ FileInterface->Open = FileInterfaceOpenNotFound;
+ FileInterface->Close = FileInterfaceMemClose;
+ FileInterface->GetPosition = FileInterfaceMemGetPosition;
+ FileInterface->SetPosition = FileInterfaceMemSetPosition;
+ FileInterface->GetInfo = FileInterfaceNopGetInfo;
+ FileInterface->SetInfo = FileInterfaceNopSetInfo;
+ FileInterface->Flush = FileInterfaceNopGeneric;
+ FileInterface->Delete = FileInterfaceNopGeneric;
+ FileInterface->Read = FileInterfaceMemRead;
+ FileInterface->Write = FileInterfaceMemWrite;
+ FileInterface->Unicode = Unicode;
+
+ ASSERT(FileInterface->Buffer == NULL);
+ ASSERT(FileInterface->BufferSize == 0);
+ ASSERT(FileInterface->Position == 0);
+
+ if (Unicode) {
+ FileInterface->Buffer = AllocateZeroPool(sizeof(gUnicodeFileTag));
+ if (FileInterface->Buffer == NULL) {
+ FreePool (FileInterface);
+ return NULL;
+ }
+ *((CHAR16 *) (FileInterface->Buffer)) = EFI_UNICODE_BYTE_ORDER_MARK;
+ FileInterface->BufferSize = 2;
+ FileInterface->Position = 2;
+ }
+
+ return ((EFI_FILE_PROTOCOL *)FileInterface);
+}
+
+typedef struct {
+ UINT64 Revision;
+ EFI_FILE_OPEN Open;
+ EFI_FILE_CLOSE Close;
+ EFI_FILE_DELETE Delete;
+ EFI_FILE_READ Read;
+ EFI_FILE_WRITE Write;
+ EFI_FILE_GET_POSITION GetPosition;
+ EFI_FILE_SET_POSITION SetPosition;
+ EFI_FILE_GET_INFO GetInfo;
+ EFI_FILE_SET_INFO SetInfo;
+ EFI_FILE_FLUSH Flush;
+ BOOLEAN Unicode;
+ EFI_FILE_PROTOCOL *Orig;
+} EFI_FILE_PROTOCOL_FILE;
+
+/**
+ Set a files current position
+
+ @param This Protocol instance pointer.
+ @param Position Byte position from the start of the file.
+
+ @retval EFI_SUCCESS Data was written.
+ @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.
+
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceFileSetPosition(
+ IN EFI_FILE_PROTOCOL *This,
+ IN UINT64 Position
+ )
+{
+ return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->SetPosition(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, Position);
+}
+
+/**
+ Get a file's current position
+
+ @param This Protocol instance pointer.
+ @param Position Byte position from the start of the file.
+
+ @retval EFI_SUCCESS Data was written.
+ @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open..
+
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceFileGetPosition(
+ IN EFI_FILE_PROTOCOL *This,
+ OUT UINT64 *Position
+ )
+{
+ return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->GetPosition(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, Position);
+}
+
+/**
+ Get information about a file.
+
+ @param This Protocol instance pointer.
+ @param InformationType Type of information to return in Buffer.
+ @param BufferSize On input size of buffer, on output amount of data in buffer.
+ @param Buffer The buffer to return data.
+
+ @retval EFI_SUCCESS Data was returned.
+ @retval EFI_UNSUPPORT InformationType is not supported.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The device is write protected.
+ @retval EFI_ACCESS_DENIED The file was open for read only.
+ @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize.
+
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceFileGetInfo(
+ IN EFI_FILE_PROTOCOL *This,
+ IN EFI_GUID *InformationType,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->GetInfo(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, InformationType, BufferSize, Buffer);
+}
+
+/**
+ Set information about a file
+
+ @param This Protocol instance pointer.
+ @param InformationType Type of information in Buffer.
+ @param BufferSize Size of buffer.
+ @param Buffer The data to write.
+
+ @retval EFI_SUCCESS Data was returned.
+ @retval EFI_UNSUPPORT InformationType is not supported.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The device is write protected.
+ @retval EFI_ACCESS_DENIED The file was open for read only.
+
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceFileSetInfo(
+ IN EFI_FILE_PROTOCOL *This,
+ IN EFI_GUID *InformationType,
+ IN UINTN BufferSize,
+ IN VOID *Buffer
+ )
+{
+ return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->SetInfo(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, InformationType, BufferSize, Buffer);
+}
+
+/**
+ Flush data back for the file handle.
+
+ @param This Protocol instance pointer.
+
+ @retval EFI_SUCCESS Data was written.
+ @retval EFI_UNSUPPORT Writes to Open directory are not supported.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The device is write protected.
+ @retval EFI_ACCESS_DENIED The file was open for read only.
+ @retval EFI_VOLUME_FULL The volume is full.
+
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceFileFlush(
+ IN EFI_FILE_PROTOCOL *This
+ )
+{
+ return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Flush(((EFI_FILE_PROTOCOL_FILE*)This)->Orig);
+}
+
+/**
+ Read data from the file.
+
+ @param This Protocol instance pointer.
+ @param BufferSize On input size of buffer, on output amount of data in buffer.
+ @param Buffer The buffer in which data is read.
+
+ @retval EFI_SUCCESS Data was read.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_BUFFER_TO_SMALL BufferSize is too small. BufferSize contains required size.
+
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceFileRead(
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ CHAR8 *AsciiStrBuffer;
+ CHAR16 *UscStrBuffer;
+ UINTN Size;
+ UINTN CharNum;
+ EFI_STATUS Status;
+ if (((EFI_FILE_PROTOCOL_FILE*)This)->Unicode) {
+ //
+ // Unicode
+ //
+ return (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Read(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, BufferSize, Buffer));
+ } else {
+ //
+ // Ascii
+ //
+ Size = (*BufferSize) / sizeof(CHAR16);
+ AsciiStrBuffer = AllocateZeroPool(Size + sizeof(CHAR8));
+ if (AsciiStrBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ UscStrBuffer = AllocateZeroPool(*BufferSize + sizeof(CHAR16));
+ if (UscStrBuffer== NULL) {
+ SHELL_FREE_NON_NULL(AsciiStrBuffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Read(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, &Size, AsciiStrBuffer));
+ if (!EFI_ERROR(Status)) {
+ CharNum = UnicodeSPrint(UscStrBuffer, *BufferSize + sizeof(CHAR16), L"%a", AsciiStrBuffer);
+ if (CharNum == Size) {
+ CopyMem (Buffer, UscStrBuffer, *BufferSize);
+ } else {
+ Status = EFI_UNSUPPORTED;
+ }
+ }
+ SHELL_FREE_NON_NULL(AsciiStrBuffer);
+ SHELL_FREE_NON_NULL(UscStrBuffer);
+ return (Status);
+ }
+}
+
+/**
+ Opens a new file relative to the source file's location.
+
+ @param[in] This The protocol instance pointer.
+ @param[out] NewHandle Returns File Handle for FileName.
+ @param[in] FileName Null terminated string. "\", ".", and ".." are supported.
+ @param[in] OpenMode Open mode for file.
+ @param[in] Attributes Only used for EFI_FILE_MODE_CREATE.
+
+ @retval EFI_SUCCESS The device was opened.
+ @retval EFI_NOT_FOUND The specified file could not be found on the device.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_MEDIA_CHANGED The media has changed.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_ACCESS_DENIED The service denied access to the file.
+ @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
+ @retval EFI_VOLUME_FULL The volume is full.
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceFileOpen (
+ IN EFI_FILE_PROTOCOL *This,
+ OUT EFI_FILE_PROTOCOL **NewHandle,
+ IN CHAR16 *FileName,
+ IN UINT64 OpenMode,
+ IN UINT64 Attributes
+ )
+{
+ return ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Open(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, NewHandle, FileName, OpenMode, Attributes);
+}
+
+/**
+ Close and delete the file handle.
+
+ @param This Protocol instance pointer.
+
+ @retval EFI_SUCCESS The device was opened.
+ @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted.
+
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceFileDelete(
+ IN EFI_FILE_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status;
+ Status = ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Delete(((EFI_FILE_PROTOCOL_FILE*)This)->Orig);
+ FreePool(This);
+ return (Status);
+}
+
+/**
+ File style interface for File (Close).
+
+ @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
+
+ @retval EFI_SUCCESS The file was closed.
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceFileClose(
+ IN EFI_FILE_PROTOCOL *This
+ )
+{
+ EFI_STATUS Status;
+ Status = ((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Close(((EFI_FILE_PROTOCOL_FILE*)This)->Orig);
+ FreePool(This);
+ return (Status);
+}
+
+/**
+ File style interface for File (Write).
+
+ If the file was opened with ASCII mode the data will be processed through
+ AsciiSPrint before writing.
+
+ @param[in] This The pointer to the EFI_FILE_PROTOCOL object.
+ @param[in, out] BufferSize Size in bytes of Buffer.
+ @param[in] Buffer The pointer to the buffer to write.
+
+ @retval EFI_SUCCESS The data was written.
+**/
+EFI_STATUS
+EFIAPI
+FileInterfaceFileWrite(
+ IN EFI_FILE_PROTOCOL *This,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ )
+{
+ CHAR8 *AsciiBuffer;
+ UINTN Size;
+ EFI_STATUS Status;
+ if (((EFI_FILE_PROTOCOL_FILE*)This)->Unicode) {
+ //
+ // Unicode
+ //
+ return (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Write(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, BufferSize, Buffer));
+ } else {
+ //
+ // Ascii
+ //
+ AsciiBuffer = AllocateZeroPool(*BufferSize);
+ AsciiSPrint(AsciiBuffer, *BufferSize, "%S", Buffer);
+ Size = AsciiStrSize(AsciiBuffer) - 1; // (we dont need the null terminator)
+ Status = (((EFI_FILE_PROTOCOL_FILE*)This)->Orig->Write(((EFI_FILE_PROTOCOL_FILE*)This)->Orig, &Size, AsciiBuffer));
+ FreePool(AsciiBuffer);
+ return (Status);
+ }
+}
+
+/**
+ Create a file interface with unicode information.
+
+ This will create a new EFI_FILE_PROTOCOL identical to the Templace
+ except that the new one has Unicode and Ascii knowledge.
+
+ @param[in] Template A pointer to the EFI_FILE_PROTOCOL object.
+ @param[in] Unicode TRUE for UCS-2, FALSE for ASCII.
+
+ @return a new EFI_FILE_PROTOCOL object to be used instead of the template.
+**/
+EFI_FILE_PROTOCOL*
+CreateFileInterfaceFile(
+ IN CONST EFI_FILE_PROTOCOL *Template,
+ IN CONST BOOLEAN Unicode
+ )
+{
+ EFI_FILE_PROTOCOL_FILE *NewOne;
+
+ NewOne = AllocateZeroPool(sizeof(EFI_FILE_PROTOCOL_FILE));
+ if (NewOne == NULL) {
+ return (NULL);
+ }
+ CopyMem(NewOne, Template, sizeof(EFI_FILE_PROTOCOL_FILE));
+ NewOne->Orig = (EFI_FILE_PROTOCOL *)Template;
+ NewOne->Unicode = Unicode;
+ NewOne->Open = FileInterfaceFileOpen;
+ NewOne->Close = FileInterfaceFileClose;
+ NewOne->Delete = FileInterfaceFileDelete;
+ NewOne->Read = FileInterfaceFileRead;
+ NewOne->Write = FileInterfaceFileWrite;
+ NewOne->GetPosition = FileInterfaceFileGetPosition;
+ NewOne->SetPosition = FileInterfaceFileSetPosition;
+ NewOne->GetInfo = FileInterfaceFileGetInfo;
+ NewOne->SetInfo = FileInterfaceFileSetInfo;
+ NewOne->Flush = FileInterfaceFileFlush;
+
+ return ((EFI_FILE_PROTOCOL *)NewOne);
+}
diff --git a/Core/ShellPkg/Application/Shell/FileHandleWrappers.h b/Core/ShellPkg/Application/Shell/FileHandleWrappers.h
new file mode 100644
index 0000000000..af133b0963
--- /dev/null
+++ b/Core/ShellPkg/Application/Shell/FileHandleWrappers.h
@@ -0,0 +1,95 @@
+/** @file
+ EFI_FILE_PROTOCOL wrappers for other items (Like Environment Variables, StdIn, StdOut, StdErr, etc...)
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SHELL_FILE_HANDLE_WRAPPERS_HEADER_
+#define _SHELL_FILE_HANDLE_WRAPPERS_HEADER_
+
+typedef struct {
+ LIST_ENTRY Link;
+ CHAR16* Buffer;
+} SHELL_LINE_LIST;
+
+typedef struct {
+ UINTN LogCount;
+ SHELL_LINE_LIST *Log;
+} SHELL_LINE_LOG;
+
+///
+/// FILE sytle interfaces for StdIn.
+///
+extern EFI_FILE_PROTOCOL FileInterfaceStdIn;
+
+///
+/// FILE sytle interfaces for StdOut.
+///
+extern EFI_FILE_PROTOCOL FileInterfaceStdOut;
+
+///
+/// FILE sytle interfaces for StdErr.
+///
+extern EFI_FILE_PROTOCOL FileInterfaceStdErr;
+
+///
+/// FILE style interface for NUL file.
+///
+extern EFI_FILE_PROTOCOL FileInterfaceNulFile;
+
+/**
+ Creates a EFI_FILE_PROTOCOL (almost) object for using to access
+ environment variables through file operations.
+
+ @param EnvName The name of the Environment Variable to be operated on.
+
+ @retval NULL Memory could not be allocated.
+ @return other a pointer to an EFI_FILE_PROTOCOL structure
+**/
+EFI_FILE_PROTOCOL*
+EFIAPI
+CreateFileInterfaceEnv(
+ CONST CHAR16 *EnvName
+ );
+
+/**
+ Creates a EFI_FILE_PROTOCOL (almost) object for using to access
+ a file entirely in memory through file operations.
+
+ @param[in] Unicode TRUE if the data is UNICODE, FALSE otherwise.
+
+ @retval NULL Memory could not be allocated.
+ @return other a pointer to an EFI_FILE_PROTOCOL structure
+**/
+EFI_FILE_PROTOCOL*
+EFIAPI
+CreateFileInterfaceMem(
+ IN CONST BOOLEAN Unicode
+ );
+
+/**
+ Creates a EFI_FILE_PROTOCOL (almost) object for using to access
+ a file entirely with unicode awareness through file operations.
+
+ @param[in] Template The pointer to the handle to start with.
+ @param[in] Unicode TRUE if the data is UNICODE, FALSE otherwise.
+
+ @retval NULL Memory could not be allocated.
+ @return other a pointer to an EFI_FILE_PROTOCOL structure
+**/
+EFI_FILE_PROTOCOL*
+CreateFileInterfaceFile(
+ IN CONST EFI_FILE_PROTOCOL *Template,
+ IN CONST BOOLEAN Unicode
+ );
+
+#endif //_SHELL_FILE_HANDLE_WRAPPERS_HEADER_
+
diff --git a/Core/ShellPkg/Application/Shell/Shell.c b/Core/ShellPkg/Application/Shell/Shell.c
new file mode 100644
index 0000000000..3080a1644f
--- /dev/null
+++ b/Core/ShellPkg/Application/Shell/Shell.c
@@ -0,0 +1,3131 @@
+/** @file
+ This is THE shell (application)
+
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2013-2014 Hewlett-Packard Development Company, L.P.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Shell.h"
+
+//
+// Initialize the global structure
+//
+SHELL_INFO ShellInfoObject = {
+ NULL,
+ NULL,
+ FALSE,
+ FALSE,
+ {
+ {{
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ }},
+ 0,
+ NULL,
+ NULL
+ },
+ {{NULL, NULL}, NULL},
+ {
+ {{NULL, NULL}, NULL},
+ 0,
+ 0,
+ TRUE
+ },
+ NULL,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ {{NULL, NULL}, NULL, NULL},
+ {{NULL, NULL}, NULL, NULL},
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ FALSE
+};
+
+STATIC CONST CHAR16 mScriptExtension[] = L".NSH";
+STATIC CONST CHAR16 mExecutableExtensions[] = L".NSH;.EFI";
+STATIC CONST CHAR16 mStartupScript[] = L"startup.nsh";
+CONST CHAR16 mNoNestingEnvVarName[] = L"nonesting";
+CONST CHAR16 mNoNestingTrue[] = L"True";
+CONST CHAR16 mNoNestingFalse[] = L"False";
+
+/**
+ Cleans off leading and trailing spaces and tabs.
+
+ @param[in] String pointer to the string to trim them off.
+**/
+EFI_STATUS
+EFIAPI
+TrimSpaces(
+ IN CHAR16 **String
+ )
+{
+ ASSERT(String != NULL);
+ ASSERT(*String!= NULL);
+ //
+ // Remove any spaces and tabs at the beginning of the (*String).
+ //
+ while (((*String)[0] == L' ') || ((*String)[0] == L'\t')) {
+ CopyMem((*String), (*String)+1, StrSize((*String)) - sizeof((*String)[0]));
+ }
+
+ //
+ // Remove any spaces and tabs at the end of the (*String).
+ //
+ while ((StrLen (*String) > 0) && (((*String)[StrLen((*String))-1] == L' ') || ((*String)[StrLen((*String))-1] == L'\t'))) {
+ (*String)[StrLen((*String))-1] = CHAR_NULL;
+ }
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Parse for the next instance of one string within another string. Can optionally make sure that
+ the string was not escaped (^ character) per the shell specification.
+
+ @param[in] SourceString The string to search within
+ @param[in] FindString The string to look for
+ @param[in] CheckForEscapeCharacter TRUE to skip escaped instances of FinfString, otherwise will return even escaped instances
+**/
+CHAR16*
+EFIAPI
+FindNextInstance(
+ IN CONST CHAR16 *SourceString,
+ IN CONST CHAR16 *FindString,
+ IN CONST BOOLEAN CheckForEscapeCharacter
+ )
+{
+ CHAR16 *Temp;
+ if (SourceString == NULL) {
+ return (NULL);
+ }
+ Temp = StrStr(SourceString, FindString);
+
+ //
+ // If nothing found, or we don't care about escape characters
+ //
+ if (Temp == NULL || !CheckForEscapeCharacter) {
+ return (Temp);
+ }
+
+ //
+ // If we found an escaped character, try again on the remainder of the string
+ //
+ if ((Temp > (SourceString)) && *(Temp-1) == L'^') {
+ return FindNextInstance(Temp+1, FindString, CheckForEscapeCharacter);
+ }
+
+ //
+ // we found the right character
+ //
+ return (Temp);
+}
+
+/**
+ Check whether the string between a pair of % is a valid environment variable name.
+
+ @param[in] BeginPercent pointer to the first percent.
+ @param[in] EndPercent pointer to the last percent.
+
+ @retval TRUE is a valid environment variable name.
+ @retval FALSE is NOT a valid environment variable name.
+**/
+BOOLEAN
+IsValidEnvironmentVariableName(
+ IN CONST CHAR16 *BeginPercent,
+ IN CONST CHAR16 *EndPercent
+ )
+{
+ CONST CHAR16 *Walker;
+
+ Walker = NULL;
+
+ ASSERT (BeginPercent != NULL);
+ ASSERT (EndPercent != NULL);
+ ASSERT (BeginPercent < EndPercent);
+
+ if ((BeginPercent + 1) == EndPercent) {
+ return FALSE;
+ }
+
+ for (Walker = BeginPercent + 1; Walker < EndPercent; Walker++) {
+ if (
+ (*Walker >= L'0' && *Walker <= L'9') ||
+ (*Walker >= L'A' && *Walker <= L'Z') ||
+ (*Walker >= L'a' && *Walker <= L'z') ||
+ (*Walker == L'_')
+ ) {
+ if (Walker == BeginPercent + 1 && (*Walker >= L'0' && *Walker <= L'9')) {
+ return FALSE;
+ } else {
+ continue;
+ }
+ } else {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ Determine if a command line contains a split operation
+
+ @param[in] CmdLine The command line to parse.
+
+ @retval TRUE CmdLine has a valid split.
+ @retval FALSE CmdLine does not have a valid split.
+**/
+BOOLEAN
+EFIAPI
+ContainsSplit(
+ IN CONST CHAR16 *CmdLine
+ )
+{
+ CONST CHAR16 *TempSpot;
+ CONST CHAR16 *FirstQuote;
+ CONST CHAR16 *SecondQuote;
+
+ FirstQuote = FindNextInstance (CmdLine, L"\"", TRUE);
+ SecondQuote = NULL;
+ TempSpot = ShellFindFirstCharacter(CmdLine, L"|", TRUE);
+
+ if (FirstQuote == NULL ||
+ TempSpot == NULL ||
+ TempSpot == CHAR_NULL ||
+ FirstQuote > TempSpot
+ ) {
+ return (BOOLEAN) ((TempSpot != NULL) && (*TempSpot != CHAR_NULL));
+ }
+
+ while ((TempSpot != NULL) && (*TempSpot != CHAR_NULL)) {
+ if (FirstQuote == NULL || FirstQuote > TempSpot) {
+ break;
+ }
+ SecondQuote = FindNextInstance (FirstQuote + 1, L"\"", TRUE);
+ if (SecondQuote == NULL) {
+ break;
+ }
+ if (SecondQuote < TempSpot) {
+ FirstQuote = FindNextInstance (SecondQuote + 1, L"\"", TRUE);
+ continue;
+ } else {
+ FirstQuote = FindNextInstance (SecondQuote + 1, L"\"", TRUE);
+ TempSpot = ShellFindFirstCharacter(TempSpot + 1, L"|", TRUE);
+ continue;
+ }
+ }
+
+ return (BOOLEAN) ((TempSpot != NULL) && (*TempSpot != CHAR_NULL));
+}
+
+/**
+ Function to start monitoring for CTRL-S using SimpleTextInputEx. This
+ feature's enabled state was not known when the shell initially launched.
+
+ @retval EFI_SUCCESS The feature is enabled.
+ @retval EFI_OUT_OF_RESOURCES There is not enough memory available.
+**/
+EFI_STATUS
+EFIAPI
+InternalEfiShellStartCtrlSMonitor(
+ VOID
+ )
+{
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;
+ EFI_KEY_DATA KeyData;
+ EFI_STATUS Status;
+
+ Status = gBS->OpenProtocol(
+ gST->ConsoleInHandle,
+ &gEfiSimpleTextInputExProtocolGuid,
+ (VOID**)&SimpleEx,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_SHELL_NO_IN_EX),
+ ShellInfoObject.HiiHandle);
+ return (EFI_SUCCESS);
+ }
+
+ KeyData.KeyState.KeyToggleState = 0;
+ KeyData.Key.ScanCode = 0;
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED;
+ KeyData.Key.UnicodeChar = L's';
+
+ Status = SimpleEx->RegisterKeyNotify(
+ SimpleEx,
+ &KeyData,
+ NotificationFunction,
+ &ShellInfoObject.CtrlSNotifyHandle1);
+
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;
+ if (!EFI_ERROR(Status)) {
+ Status = SimpleEx->RegisterKeyNotify(
+ SimpleEx,
+ &KeyData,
+ NotificationFunction,
+ &ShellInfoObject.CtrlSNotifyHandle2);
+ }
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED;
+ KeyData.Key.UnicodeChar = 19;
+
+ if (!EFI_ERROR(Status)) {
+ Status = SimpleEx->RegisterKeyNotify(
+ SimpleEx,
+ &KeyData,
+ NotificationFunction,
+ &ShellInfoObject.CtrlSNotifyHandle3);
+ }
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;
+ if (!EFI_ERROR(Status)) {
+ Status = SimpleEx->RegisterKeyNotify(
+ SimpleEx,
+ &KeyData,
+ NotificationFunction,
+ &ShellInfoObject.CtrlSNotifyHandle4);
+ }
+ return (Status);
+}
+
+
+
+/**
+ The entry point for the application.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+UefiMain (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *TempString;
+ UINTN Size;
+ EFI_HANDLE ConInHandle;
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL *OldConIn;
+ SPLIT_LIST *Split;
+
+ if (PcdGet8(PcdShellSupportLevel) > 3) {
+ return (EFI_UNSUPPORTED);
+ }
+
+ //
+ // Clear the screen
+ //
+ Status = gST->ConOut->ClearScreen(gST->ConOut);
+ if (EFI_ERROR(Status)) {
+ return (Status);
+ }
+
+ //
+ // Populate the global structure from PCDs
+ //
+ ShellInfoObject.ImageDevPath = NULL;
+ ShellInfoObject.FileDevPath = NULL;
+ ShellInfoObject.PageBreakEnabled = PcdGetBool(PcdShellPageBreakDefault);
+ ShellInfoObject.ViewingSettings.InsertMode = PcdGetBool(PcdShellInsertModeDefault);
+ ShellInfoObject.LogScreenCount = PcdGet8 (PcdShellScreenLogCount );
+
+ //
+ // verify we dont allow for spec violation
+ //
+ ASSERT(ShellInfoObject.LogScreenCount >= 3);
+
+ //
+ // Initialize the LIST ENTRY objects...
+ //
+ InitializeListHead(&ShellInfoObject.BufferToFreeList.Link);
+ InitializeListHead(&ShellInfoObject.ViewingSettings.CommandHistory.Link);
+ InitializeListHead(&ShellInfoObject.SplitList.Link);
+
+ //
+ // Check PCDs for optional features that are not implemented yet.
+ //
+ if ( PcdGetBool(PcdShellSupportOldProtocols)
+ || !FeaturePcdGet(PcdShellRequireHiiPlatform)
+ || FeaturePcdGet(PcdShellSupportFrameworkHii)
+ ) {
+ return (EFI_UNSUPPORTED);
+ }
+
+ //
+ // turn off the watchdog timer
+ //
+ gBS->SetWatchdogTimer (0, 0, 0, NULL);
+
+ //
+ // install our console logger. This will keep a log of the output for back-browsing
+ //
+ Status = ConsoleLoggerInstall(ShellInfoObject.LogScreenCount, &ShellInfoObject.ConsoleInfo);
+ if (!EFI_ERROR(Status)) {
+ //
+ // Enable the cursor to be visible
+ //
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+
+ //
+ // If supporting EFI 1.1 we need to install HII protocol
+ // only do this if PcdShellRequireHiiPlatform == FALSE
+ //
+ // remove EFI_UNSUPPORTED check above when complete.
+ ///@todo add support for Framework HII
+
+ //
+ // install our (solitary) HII package
+ //
+ ShellInfoObject.HiiHandle = HiiAddPackages (&gEfiCallerIdGuid, gImageHandle, ShellStrings, NULL);
+ if (ShellInfoObject.HiiHandle == NULL) {
+ if (PcdGetBool(PcdShellSupportFrameworkHii)) {
+ ///@todo Add our package into Framework HII
+ }
+ if (ShellInfoObject.HiiHandle == NULL) {
+ Status = EFI_NOT_STARTED;
+ goto FreeResources;
+ }
+ }
+
+ //
+ // create and install the EfiShellParametersProtocol
+ //
+ Status = CreatePopulateInstallShellParametersProtocol(&ShellInfoObject.NewShellParametersProtocol, &ShellInfoObject.RootShellInstance);
+ ASSERT_EFI_ERROR(Status);
+ ASSERT(ShellInfoObject.NewShellParametersProtocol != NULL);
+
+ //
+ // create and install the EfiShellProtocol
+ //
+ Status = CreatePopulateInstallShellProtocol(&ShellInfoObject.NewEfiShellProtocol);
+ ASSERT_EFI_ERROR(Status);
+ ASSERT(ShellInfoObject.NewEfiShellProtocol != NULL);
+
+ //
+ // Now initialize the shell library (it requires Shell Parameters protocol)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = ShellInitEnvVarList ();
+
+ //
+ // Check the command line
+ //
+ Status = ProcessCommandLine ();
+ if (EFI_ERROR (Status)) {
+ goto FreeResources;
+ }
+
+ //
+ // If shell support level is >= 1 create the mappings and paths
+ //
+ if (PcdGet8(PcdShellSupportLevel) >= 1) {
+ Status = ShellCommandCreateInitialMappingsAndPaths();
+ }
+
+ //
+ // Set the environment variable for nesting support
+ //
+ Size = 0;
+ TempString = NULL;
+ if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest) {
+ //
+ // No change. require nesting in Shell Protocol Execute()
+ //
+ StrnCatGrow(&TempString,
+ &Size,
+ L"False",
+ 0);
+ } else {
+ StrnCatGrow(&TempString,
+ &Size,
+ mNoNestingTrue,
+ 0);
+ }
+ Status = InternalEfiShellSetEnv(mNoNestingEnvVarName, TempString, TRUE);
+ SHELL_FREE_NON_NULL(TempString);
+ Size = 0;
+
+ //
+ // save the device path for the loaded image and the device path for the filepath (under loaded image)
+ // These are where to look for the startup.nsh file
+ //
+ Status = GetDevicePathsForImageAndFile(&ShellInfoObject.ImageDevPath, &ShellInfoObject.FileDevPath);
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Display the version
+ //
+ if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion) {
+ ShellPrintHiiEx (
+ 0,
+ gST->ConOut->Mode->CursorRow,
+ NULL,
+ STRING_TOKEN (STR_VER_OUTPUT_MAIN_SHELL),
+ ShellInfoObject.HiiHandle,
+ SupportLevel[PcdGet8(PcdShellSupportLevel)],
+ gEfiShellProtocol->MajorVersion,
+ gEfiShellProtocol->MinorVersion
+ );
+
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_VER_OUTPUT_MAIN_SUPPLIER),
+ ShellInfoObject.HiiHandle,
+ (CHAR16 *) PcdGetPtr (PcdShellSupplier)
+ );
+
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_VER_OUTPUT_MAIN_UEFI),
+ ShellInfoObject.HiiHandle,
+ (gST->Hdr.Revision&0xffff0000)>>16,
+ (gST->Hdr.Revision&0x0000ffff),
+ gST->FirmwareVendor,
+ gST->FirmwareRevision
+ );
+ }
+
+ //
+ // Display the mapping
+ //
+ if (PcdGet8(PcdShellSupportLevel) >= 2 && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoMap) {
+ Status = RunCommand(L"map");
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ //
+ // init all the built in alias'
+ //
+ Status = SetBuiltInAlias();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Initialize environment variables
+ //
+ if (ShellCommandGetProfileList() != NULL) {
+ Status = InternalEfiShellSetEnv(L"profiles", ShellCommandGetProfileList(), TRUE);
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ Size = 100;
+ TempString = AllocateZeroPool(Size);
+
+ UnicodeSPrint(TempString, Size, L"%d", PcdGet8(PcdShellSupportLevel));
+ Status = InternalEfiShellSetEnv(L"uefishellsupport", TempString, TRUE);
+ ASSERT_EFI_ERROR(Status);
+
+ UnicodeSPrint(TempString, Size, L"%d.%d", ShellInfoObject.NewEfiShellProtocol->MajorVersion, ShellInfoObject.NewEfiShellProtocol->MinorVersion);
+ Status = InternalEfiShellSetEnv(L"uefishellversion", TempString, TRUE);
+ ASSERT_EFI_ERROR(Status);
+
+ UnicodeSPrint(TempString, Size, L"%d.%d", (gST->Hdr.Revision & 0xFFFF0000) >> 16, gST->Hdr.Revision & 0x0000FFFF);
+ Status = InternalEfiShellSetEnv(L"uefiversion", TempString, TRUE);
+ ASSERT_EFI_ERROR(Status);
+
+ FreePool(TempString);
+
+ if (!EFI_ERROR(Status)) {
+ if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt) {
+ //
+ // Set up the event for CTRL-C monitoring...
+ //
+ Status = InernalEfiShellStartMonitor();
+ }
+
+ if (!EFI_ERROR(Status) && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) {
+ //
+ // Set up the event for CTRL-S monitoring...
+ //
+ Status = InternalEfiShellStartCtrlSMonitor();
+ }
+
+ if (!EFI_ERROR(Status) && ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) {
+ //
+ // close off the gST->ConIn
+ //
+ OldConIn = gST->ConIn;
+ ConInHandle = gST->ConsoleInHandle;
+ gST->ConIn = CreateSimpleTextInOnFile((SHELL_FILE_HANDLE)&FileInterfaceNulFile, &gST->ConsoleInHandle);
+ } else {
+ OldConIn = NULL;
+ ConInHandle = NULL;
+ }
+
+ if (!EFI_ERROR(Status) && PcdGet8(PcdShellSupportLevel) >= 1) {
+ //
+ // process the startup script or launch the called app.
+ //
+ Status = DoStartupScript(ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath);
+ }
+
+ if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit && !ShellCommandGetExit() && (PcdGet8(PcdShellSupportLevel) >= 3 || PcdGetBool(PcdShellForceConsole)) && !EFI_ERROR(Status) && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) {
+ //
+ // begin the UI waiting loop
+ //
+ do {
+ //
+ // clean out all the memory allocated for CONST <something> * return values
+ // between each shell prompt presentation
+ //
+ if (!IsListEmpty(&ShellInfoObject.BufferToFreeList.Link)){
+ FreeBufferList(&ShellInfoObject.BufferToFreeList);
+ }
+
+ //
+ // Reset page break back to default.
+ //
+ ShellInfoObject.PageBreakEnabled = PcdGetBool(PcdShellPageBreakDefault);
+ ASSERT (ShellInfoObject.ConsoleInfo != NULL);
+ ShellInfoObject.ConsoleInfo->Enabled = TRUE;
+ ShellInfoObject.ConsoleInfo->RowCounter = 0;
+
+ //
+ // Reset the CTRL-C event (yes we ignore the return values)
+ //
+ Status = gBS->CheckEvent (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak);
+
+ //
+ // Display Prompt
+ //
+ Status = DoShellPrompt();
+ } while (!ShellCommandGetExit());
+ }
+ if (OldConIn != NULL && ConInHandle != NULL) {
+ CloseSimpleTextInOnFile (gST->ConIn);
+ gST->ConIn = OldConIn;
+ gST->ConsoleInHandle = ConInHandle;
+ }
+ }
+ }
+
+FreeResources:
+ //
+ // uninstall protocols / free memory / etc...
+ //
+ if (ShellInfoObject.UserBreakTimer != NULL) {
+ gBS->CloseEvent(ShellInfoObject.UserBreakTimer);
+ DEBUG_CODE(ShellInfoObject.UserBreakTimer = NULL;);
+ }
+ if (ShellInfoObject.ImageDevPath != NULL) {
+ FreePool(ShellInfoObject.ImageDevPath);
+ DEBUG_CODE(ShellInfoObject.ImageDevPath = NULL;);
+ }
+ if (ShellInfoObject.FileDevPath != NULL) {
+ FreePool(ShellInfoObject.FileDevPath);
+ DEBUG_CODE(ShellInfoObject.FileDevPath = NULL;);
+ }
+ if (ShellInfoObject.NewShellParametersProtocol != NULL) {
+ CleanUpShellParametersProtocol(ShellInfoObject.NewShellParametersProtocol);
+ DEBUG_CODE(ShellInfoObject.NewShellParametersProtocol = NULL;);
+ }
+ if (ShellInfoObject.NewEfiShellProtocol != NULL){
+ if (ShellInfoObject.NewEfiShellProtocol->IsRootShell()){
+ InternalEfiShellSetEnv(L"cwd", NULL, TRUE);
+ }
+ CleanUpShellEnvironment (ShellInfoObject.NewEfiShellProtocol);
+ DEBUG_CODE(ShellInfoObject.NewEfiShellProtocol = NULL;);
+ }
+
+ if (!IsListEmpty(&ShellInfoObject.BufferToFreeList.Link)){
+ FreeBufferList(&ShellInfoObject.BufferToFreeList);
+ }
+
+ if (!IsListEmpty(&ShellInfoObject.SplitList.Link)){
+ ASSERT(FALSE); ///@todo finish this de-allocation (free SplitStdIn/Out when needed).
+
+ for ( Split = (SPLIT_LIST*)GetFirstNode (&ShellInfoObject.SplitList.Link)
+ ; !IsNull (&ShellInfoObject.SplitList.Link, &Split->Link)
+ ; Split = (SPLIT_LIST *)GetNextNode (&ShellInfoObject.SplitList.Link, &Split->Link)
+ ) {
+ RemoveEntryList (&Split->Link);
+ FreePool (Split);
+ }
+
+ DEBUG_CODE (InitializeListHead (&ShellInfoObject.SplitList.Link););
+ }
+
+ if (ShellInfoObject.ShellInitSettings.FileName != NULL) {
+ FreePool(ShellInfoObject.ShellInitSettings.FileName);
+ DEBUG_CODE(ShellInfoObject.ShellInitSettings.FileName = NULL;);
+ }
+
+ if (ShellInfoObject.ShellInitSettings.FileOptions != NULL) {
+ FreePool(ShellInfoObject.ShellInitSettings.FileOptions);
+ DEBUG_CODE(ShellInfoObject.ShellInitSettings.FileOptions = NULL;);
+ }
+
+ if (ShellInfoObject.HiiHandle != NULL) {
+ HiiRemovePackages(ShellInfoObject.HiiHandle);
+ DEBUG_CODE(ShellInfoObject.HiiHandle = NULL;);
+ }
+
+ if (!IsListEmpty(&ShellInfoObject.ViewingSettings.CommandHistory.Link)){
+ FreeBufferList(&ShellInfoObject.ViewingSettings.CommandHistory);
+ }
+
+ ASSERT(ShellInfoObject.ConsoleInfo != NULL);
+ if (ShellInfoObject.ConsoleInfo != NULL) {
+ ConsoleLoggerUninstall(ShellInfoObject.ConsoleInfo);
+ FreePool(ShellInfoObject.ConsoleInfo);
+ DEBUG_CODE(ShellInfoObject.ConsoleInfo = NULL;);
+ }
+
+ ShellFreeEnvVarList ();
+ ShellSetRawCmdLine (NULL);
+
+ if (ShellCommandGetExit()) {
+ return ((EFI_STATUS)ShellCommandGetExitCode());
+ }
+ return (Status);
+}
+
+/**
+ Sets all the alias' that were registered with the ShellCommandLib library.
+
+ @retval EFI_SUCCESS all init commands were run successfully.
+**/
+EFI_STATUS
+EFIAPI
+SetBuiltInAlias(
+ )
+{
+ EFI_STATUS Status;
+ CONST ALIAS_LIST *List;
+ ALIAS_LIST *Node;
+
+ //
+ // Get all the commands we want to run
+ //
+ List = ShellCommandGetInitAliasList();
+
+ //
+ // for each command in the List
+ //
+ for ( Node = (ALIAS_LIST*)GetFirstNode(&List->Link)
+ ; !IsNull (&List->Link, &Node->Link)
+ ; Node = (ALIAS_LIST *)GetNextNode(&List->Link, &Node->Link)
+ ){
+ //
+ // install the alias'
+ //
+ Status = InternalSetAlias(Node->CommandString, Node->Alias, TRUE);
+ ASSERT_EFI_ERROR(Status);
+ }
+ return (EFI_SUCCESS);
+}
+
+/**
+ Internal function to determine if 2 command names are really the same.
+
+ @param[in] Command1 The pointer to the first command name.
+ @param[in] Command2 The pointer to the second command name.
+
+ @retval TRUE The 2 command names are the same.
+ @retval FALSE The 2 command names are not the same.
+**/
+BOOLEAN
+EFIAPI
+IsCommand(
+ IN CONST CHAR16 *Command1,
+ IN CONST CHAR16 *Command2
+ )
+{
+ if (StringNoCaseCompare(&Command1, &Command2) == 0) {
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/**
+ Internal function to determine if a command is a script only command.
+
+ @param[in] CommandName The pointer to the command name.
+
+ @retval TRUE The command is a script only command.
+ @retval FALSE The command is not a script only command.
+**/
+BOOLEAN
+EFIAPI
+IsScriptOnlyCommand(
+ IN CONST CHAR16 *CommandName
+ )
+{
+ if (IsCommand(CommandName, L"for")
+ ||IsCommand(CommandName, L"endfor")
+ ||IsCommand(CommandName, L"if")
+ ||IsCommand(CommandName, L"else")
+ ||IsCommand(CommandName, L"endif")
+ ||IsCommand(CommandName, L"goto")) {
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/**
+ This function will populate the 2 device path protocol parameters based on the
+ global gImageHandle. The DevPath will point to the device path for the handle that has
+ loaded image protocol installed on it. The FilePath will point to the device path
+ for the file that was loaded.
+
+ @param[in, out] DevPath On a successful return the device path to the loaded image.
+ @param[in, out] FilePath On a successful return the device path to the file.
+
+ @retval EFI_SUCCESS The 2 device paths were successfully returned.
+ @retval other A error from gBS->HandleProtocol.
+
+ @sa HandleProtocol
+**/
+EFI_STATUS
+EFIAPI
+GetDevicePathsForImageAndFile (
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevPath,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath;
+
+ ASSERT(DevPath != NULL);
+ ASSERT(FilePath != NULL);
+
+ Status = gBS->OpenProtocol (
+ gImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID**)&LoadedImage,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->OpenProtocol (
+ LoadedImage->DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID**)&ImageDevicePath,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ *DevPath = DuplicateDevicePath (ImageDevicePath);
+ *FilePath = DuplicateDevicePath (LoadedImage->FilePath);
+ gBS->CloseProtocol(
+ LoadedImage->DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ gImageHandle,
+ NULL);
+ }
+ gBS->CloseProtocol(
+ gImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ gImageHandle,
+ NULL);
+ }
+ return (Status);
+}
+
+/**
+ Process all Uefi Shell 2.0 command line options.
+
+ see Uefi Shell 2.0 section 3.2 for full details.
+
+ the command line must resemble the following:
+
+ shell.efi [ShellOpt-options] [options] [file-name [file-name-options]]
+
+ ShellOpt-options Options which control the initialization behavior of the shell.
+ These options are read from the EFI global variable "ShellOpt"
+ and are processed before options or file-name.
+
+ options Options which control the initialization behavior of the shell.
+
+ file-name The name of a UEFI shell application or script to be executed
+ after initialization is complete. By default, if file-name is
+ specified, then -nostartup is implied. Scripts are not supported
+ by level 0.
+
+ file-name-options The command-line options that are passed to file-name when it
+ is invoked.
+
+ This will initialize the ShellInfoObject.ShellInitSettings global variable.
+
+ @retval EFI_SUCCESS The variable is initialized.
+**/
+EFI_STATUS
+EFIAPI
+ProcessCommandLine(
+ VOID
+ )
+{
+ UINTN Size;
+ UINTN LoopVar;
+ CHAR16 *CurrentArg;
+ CHAR16 *DelayValueStr;
+ UINT64 DelayValue;
+ EFI_STATUS Status;
+ EFI_UNICODE_COLLATION_PROTOCOL *UnicodeCollation;
+
+ // `file-name-options` will contain arguments to `file-name` that we don't
+ // know about. This would cause ShellCommandLineParse to error, so we parse
+ // arguments manually, ignoring those after the first thing that doesn't look
+ // like a shell option (which is assumed to be `file-name`).
+
+ Status = gBS->LocateProtocol (
+ &gEfiUnicodeCollation2ProtocolGuid,
+ NULL,
+ (VOID **) &UnicodeCollation
+ );
+ if (EFI_ERROR (Status)) {
+ Status = gBS->LocateProtocol (
+ &gEfiUnicodeCollationProtocolGuid,
+ NULL,
+ (VOID **) &UnicodeCollation
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ // Set default options
+ ShellInfoObject.ShellInitSettings.BitUnion.Bits.Startup = FALSE;
+ ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = FALSE;
+ ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut = FALSE;
+ ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn = FALSE;
+ ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt = FALSE;
+ ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoMap = FALSE;
+ ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion = FALSE;
+ ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay = FALSE;
+ ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit = FALSE;
+ ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest = FALSE;
+ ShellInfoObject.ShellInitSettings.Delay = 5;
+
+ //
+ // Start LoopVar at 0 to parse only optional arguments at Argv[0]
+ // and parse other parameters from Argv[1]. This is for use case that
+ // UEFI Shell boot option is created, and OptionalData is provided
+ // that starts with shell command-line options.
+ //
+ for (LoopVar = 0 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) {
+ CurrentArg = gEfiShellParametersProtocol->Argv[LoopVar];
+ if (UnicodeCollation->StriColl (
+ UnicodeCollation,
+ L"-startup",
+ CurrentArg
+ ) == 0) {
+ ShellInfoObject.ShellInitSettings.BitUnion.Bits.Startup = TRUE;
+ }
+ else if (UnicodeCollation->StriColl (
+ UnicodeCollation,
+ L"-nostartup",
+ CurrentArg
+ ) == 0) {
+ ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = TRUE;
+ }
+ else if (UnicodeCollation->StriColl (
+ UnicodeCollation,
+ L"-noconsoleout",
+ CurrentArg
+ ) == 0) {
+ ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleOut = TRUE;
+ }
+ else if (UnicodeCollation->StriColl (
+ UnicodeCollation,
+ L"-noconsolein",
+ CurrentArg
+ ) == 0) {
+ ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn = TRUE;
+ }
+ else if (UnicodeCollation->StriColl (
+ UnicodeCollation,
+ L"-nointerrupt",
+ CurrentArg
+ ) == 0) {
+ ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt = TRUE;
+ }
+ else if (UnicodeCollation->StriColl (
+ UnicodeCollation,
+ L"-nomap",
+ CurrentArg
+ ) == 0) {
+ ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoMap = TRUE;
+ }
+ else if (UnicodeCollation->StriColl (
+ UnicodeCollation,
+ L"-noversion",
+ CurrentArg
+ ) == 0) {
+ ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion = TRUE;
+ }
+ else if (UnicodeCollation->StriColl (
+ UnicodeCollation,
+ L"-nonest",
+ CurrentArg
+ ) == 0) {
+ ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest = TRUE;
+ }
+ else if (UnicodeCollation->StriColl (
+ UnicodeCollation,
+ L"-delay",
+ CurrentArg
+ ) == 0) {
+ ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay = TRUE;
+ // Check for optional delay value following "-delay"
+ DelayValueStr = gEfiShellParametersProtocol->Argv[LoopVar + 1];
+ if (DelayValueStr != NULL){
+ if (*DelayValueStr == L':') {
+ DelayValueStr++;
+ }
+ if (!EFI_ERROR(ShellConvertStringToUint64 (
+ DelayValueStr,
+ &DelayValue,
+ FALSE,
+ FALSE
+ ))) {
+ ShellInfoObject.ShellInitSettings.Delay = (UINTN)DelayValue;
+ LoopVar++;
+ }
+ }
+ } else if (UnicodeCollation->StriColl (
+ UnicodeCollation,
+ L"-_exit",
+ CurrentArg
+ ) == 0) {
+ ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit = TRUE;
+ } else if (StrnCmp (L"-", CurrentArg, 1) == 0) {
+ // Unrecognized option
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_GEN_PROBLEM),
+ ShellInfoObject.HiiHandle,
+ CurrentArg
+ );
+ return EFI_INVALID_PARAMETER;
+ } else {
+ //
+ // First argument should be Shell.efi image name
+ //
+ if (LoopVar == 0) {
+ continue;
+ }
+
+ ShellInfoObject.ShellInitSettings.FileName = AllocateCopyPool(StrSize(CurrentArg), CurrentArg);
+ if (ShellInfoObject.ShellInitSettings.FileName == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ //
+ // We found `file-name`.
+ //
+ ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = 1;
+ LoopVar++;
+
+ // Add `file-name-options`
+ for (Size = 0 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) {
+ ASSERT((ShellInfoObject.ShellInitSettings.FileOptions == NULL && Size == 0) || (ShellInfoObject.ShellInitSettings.FileOptions != NULL));
+ StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions,
+ &Size,
+ L" ",
+ 0);
+ if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) {
+ SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName);
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions,
+ &Size,
+ gEfiShellParametersProtocol->Argv[LoopVar],
+ 0);
+ if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) {
+ SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName);
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ }
+ }
+ }
+
+ // "-nointerrupt" overrides "-delay"
+ if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt) {
+ ShellInfoObject.ShellInitSettings.Delay = 0;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Handles all interaction with the default startup script.
+
+ this will check that the correct command line parameters were passed, handle the delay, and then start running the script.
+
+ @param ImagePath the path to the image for shell. first place to look for the startup script
+ @param FilePath the path to the file for shell. second place to look for the startup script.
+
+ @retval EFI_SUCCESS the variable is initialized.
+**/
+EFI_STATUS
+EFIAPI
+DoStartupScript(
+ IN EFI_DEVICE_PATH_PROTOCOL *ImagePath,
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS CalleeStatus;
+ UINTN Delay;
+ EFI_INPUT_KEY Key;
+ SHELL_FILE_HANDLE FileHandle;
+ EFI_DEVICE_PATH_PROTOCOL *NewPath;
+ EFI_DEVICE_PATH_PROTOCOL *NamePath;
+ CHAR16 *FileStringPath;
+ CHAR16 *TempSpot;
+ UINTN NewSize;
+ CONST CHAR16 *MapName;
+
+ Key.UnicodeChar = CHAR_NULL;
+ Key.ScanCode = 0;
+ FileHandle = NULL;
+
+ if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.Startup && ShellInfoObject.ShellInitSettings.FileName != NULL) {
+ //
+ // launch something else instead
+ //
+ NewSize = StrSize(ShellInfoObject.ShellInitSettings.FileName);
+ if (ShellInfoObject.ShellInitSettings.FileOptions != NULL) {
+ NewSize += StrSize(ShellInfoObject.ShellInitSettings.FileOptions) + sizeof(CHAR16);
+ }
+ FileStringPath = AllocateZeroPool(NewSize);
+ if (FileStringPath == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ StrCpyS(FileStringPath, NewSize/sizeof(CHAR16), ShellInfoObject.ShellInitSettings.FileName);
+ if (ShellInfoObject.ShellInitSettings.FileOptions != NULL) {
+ StrnCatS(FileStringPath, NewSize/sizeof(CHAR16), L" ", NewSize/sizeof(CHAR16) - StrLen(FileStringPath) -1);
+ StrnCatS(FileStringPath, NewSize/sizeof(CHAR16), ShellInfoObject.ShellInitSettings.FileOptions, NewSize/sizeof(CHAR16) - StrLen(FileStringPath) -1);
+ }
+ Status = RunShellCommand(FileStringPath, &CalleeStatus);
+ if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit == TRUE) {
+ ShellCommandRegisterExit(gEfiShellProtocol->BatchIsActive(), (UINT64)CalleeStatus);
+ }
+ FreePool(FileStringPath);
+ return (Status);
+
+ }
+
+ //
+ // for shell level 0 we do no scripts
+ // Without the Startup bit overriding we allow for nostartup to prevent scripts
+ //
+ if ( (PcdGet8(PcdShellSupportLevel) < 1)
+ || (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.Startup)
+ ){
+ return (EFI_SUCCESS);
+ }
+
+ gST->ConOut->EnableCursor(gST->ConOut, FALSE);
+ //
+ // print out our warning and see if they press a key
+ //
+ for ( Status = EFI_UNSUPPORTED, Delay = ShellInfoObject.ShellInitSettings.Delay
+ ; Delay != 0 && EFI_ERROR(Status)
+ ; Delay--
+ ){
+ ShellPrintHiiEx(0, gST->ConOut->Mode->CursorRow, NULL, STRING_TOKEN (STR_SHELL_STARTUP_QUESTION), ShellInfoObject.HiiHandle, Delay);
+ gBS->Stall (1000000);
+ if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) {
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ }
+ }
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_CRLF), ShellInfoObject.HiiHandle);
+ gST->ConOut->EnableCursor(gST->ConOut, TRUE);
+
+ //
+ // ESC was pressed
+ //
+ if (Status == EFI_SUCCESS && Key.UnicodeChar == 0 && Key.ScanCode == SCAN_ESC) {
+ return (EFI_SUCCESS);
+ }
+
+ //
+ // Try the first location (must be file system)
+ //
+ MapName = ShellInfoObject.NewEfiShellProtocol->GetMapFromDevicePath(&ImagePath);
+ if (MapName != NULL) {
+ FileStringPath = NULL;
+ NewSize = 0;
+ FileStringPath = StrnCatGrow(&FileStringPath, &NewSize, MapName, 0);
+ if (FileStringPath == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ TempSpot = StrStr(FileStringPath, L";");
+ if (TempSpot != NULL) {
+ *TempSpot = CHAR_NULL;
+ }
+ FileStringPath = StrnCatGrow(&FileStringPath, &NewSize, ((FILEPATH_DEVICE_PATH*)FilePath)->PathName, 0);
+ PathRemoveLastItem(FileStringPath);
+ FileStringPath = StrnCatGrow(&FileStringPath, &NewSize, mStartupScript, 0);
+ Status = ShellInfoObject.NewEfiShellProtocol->OpenFileByName(FileStringPath, &FileHandle, EFI_FILE_MODE_READ);
+ FreePool(FileStringPath);
+ }
+ }
+ if (EFI_ERROR(Status)) {
+ NamePath = FileDevicePath (NULL, mStartupScript);
+ NewPath = AppendDevicePathNode (ImagePath, NamePath);
+ FreePool(NamePath);
+
+ //
+ // Try the location
+ //
+ Status = InternalOpenFileDevicePath(NewPath, &FileHandle, EFI_FILE_MODE_READ, 0);
+ FreePool(NewPath);
+ }
+ //
+ // If we got a file, run it
+ //
+ if (!EFI_ERROR(Status) && FileHandle != NULL) {
+ Status = RunScriptFile (mStartupScript, FileHandle, L"", ShellInfoObject.NewShellParametersProtocol);
+ ShellInfoObject.NewEfiShellProtocol->CloseFile(FileHandle);
+ } else {
+ FileStringPath = ShellFindFilePath(mStartupScript);
+ if (FileStringPath == NULL) {
+ //
+ // we return success since we don't need to have a startup script
+ //
+ Status = EFI_SUCCESS;
+ ASSERT(FileHandle == NULL);
+ } else {
+ Status = RunScriptFile(FileStringPath, NULL, L"", ShellInfoObject.NewShellParametersProtocol);
+ FreePool(FileStringPath);
+ }
+ }
+
+
+ return (Status);
+}
+
+/**
+ Function to perform the shell prompt looping. It will do a single prompt,
+ dispatch the result, and then return. It is expected that the caller will
+ call this function in a loop many times.
+
+ @retval EFI_SUCCESS
+ @retval RETURN_ABORTED
+**/
+EFI_STATUS
+EFIAPI
+DoShellPrompt (
+ VOID
+ )
+{
+ UINTN Column;
+ UINTN Row;
+ CHAR16 *CmdLine;
+ CONST CHAR16 *CurDir;
+ UINTN BufferSize;
+ EFI_STATUS Status;
+ LIST_ENTRY OldBufferList;
+
+ CurDir = NULL;
+
+ //
+ // Get screen setting to decide size of the command line buffer
+ //
+ gST->ConOut->QueryMode (gST->ConOut, gST->ConOut->Mode->Mode, &Column, &Row);
+ BufferSize = Column * Row * sizeof (CHAR16);
+ CmdLine = AllocateZeroPool (BufferSize);
+ if (CmdLine == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SaveBufferList(&OldBufferList);
+ CurDir = ShellInfoObject.NewEfiShellProtocol->GetEnv(L"cwd");
+
+ //
+ // Prompt for input
+ //
+ gST->ConOut->SetCursorPosition (gST->ConOut, 0, gST->ConOut->Mode->CursorRow);
+
+ if (CurDir != NULL && StrLen(CurDir) > 1) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_CURDIR), ShellInfoObject.HiiHandle, CurDir);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_SHELL), ShellInfoObject.HiiHandle);
+ }
+
+ //
+ // Read a line from the console
+ //
+ Status = ShellInfoObject.NewEfiShellProtocol->ReadFile(ShellInfoObject.NewShellParametersProtocol->StdIn, &BufferSize, CmdLine);
+
+ //
+ // Null terminate the string and parse it
+ //
+ if (!EFI_ERROR (Status)) {
+ CmdLine[BufferSize / sizeof (CHAR16)] = CHAR_NULL;
+ Status = RunCommand(CmdLine);
+ }
+
+ //
+ // Done with this command
+ //
+ RestoreBufferList(&OldBufferList);
+ FreePool (CmdLine);
+ return Status;
+}
+
+/**
+ Add a buffer to the Buffer To Free List for safely returning buffers to other
+ places without risking letting them modify internal shell information.
+
+ @param Buffer Something to pass to FreePool when the shell is exiting.
+**/
+VOID*
+EFIAPI
+AddBufferToFreeList (
+ VOID *Buffer
+ )
+{
+ BUFFER_LIST *BufferListEntry;
+
+ if (Buffer == NULL) {
+ return (NULL);
+ }
+
+ BufferListEntry = AllocateZeroPool (sizeof (BUFFER_LIST));
+ if (BufferListEntry == NULL) {
+ return NULL;
+ }
+
+ BufferListEntry->Buffer = Buffer;
+ InsertTailList (&ShellInfoObject.BufferToFreeList.Link, &BufferListEntry->Link);
+ return (Buffer);
+}
+
+
+/**
+ Create a new buffer list and stores the old one to OldBufferList
+
+ @param OldBufferList The temporary list head used to store the nodes in BufferToFreeList.
+**/
+VOID
+SaveBufferList (
+ OUT LIST_ENTRY *OldBufferList
+ )
+{
+ CopyMem (OldBufferList, &ShellInfoObject.BufferToFreeList.Link, sizeof (LIST_ENTRY));
+ InitializeListHead (&ShellInfoObject.BufferToFreeList.Link);
+}
+
+/**
+ Restore previous nodes into BufferToFreeList .
+
+ @param OldBufferList The temporary list head used to store the nodes in BufferToFreeList.
+**/
+VOID
+RestoreBufferList (
+ IN OUT LIST_ENTRY *OldBufferList
+ )
+{
+ FreeBufferList (&ShellInfoObject.BufferToFreeList);
+ CopyMem (&ShellInfoObject.BufferToFreeList.Link, OldBufferList, sizeof (LIST_ENTRY));
+}
+
+
+/**
+ Add a buffer to the Line History List
+
+ @param Buffer The line buffer to add.
+**/
+VOID
+EFIAPI
+AddLineToCommandHistory(
+ IN CONST CHAR16 *Buffer
+ )
+{
+ BUFFER_LIST *Node;
+ BUFFER_LIST *Walker;
+ UINT16 MaxHistoryCmdCount;
+ UINT16 Count;
+
+ Count = 0;
+ MaxHistoryCmdCount = PcdGet16(PcdShellMaxHistoryCommandCount);
+
+ if (MaxHistoryCmdCount == 0) {
+ return ;
+ }
+
+
+ Node = AllocateZeroPool(sizeof(BUFFER_LIST));
+ if (Node == NULL) {
+ return;
+ }
+
+ Node->Buffer = AllocateCopyPool (StrSize (Buffer), Buffer);
+ if (Node->Buffer == NULL) {
+ FreePool (Node);
+ return;
+ }
+
+ for ( Walker = (BUFFER_LIST*)GetFirstNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link)
+ ; !IsNull(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Walker->Link)
+ ; Walker = (BUFFER_LIST*)GetNextNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Walker->Link)
+ ){
+ Count++;
+ }
+ if (Count < MaxHistoryCmdCount){
+ InsertTailList(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link);
+ } else {
+ Walker = (BUFFER_LIST*)GetFirstNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link);
+ RemoveEntryList(&Walker->Link);
+ if (Walker->Buffer != NULL) {
+ FreePool(Walker->Buffer);
+ }
+ FreePool(Walker);
+ InsertTailList(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link);
+ }
+}
+
+/**
+ Checks if a string is an alias for another command. If yes, then it replaces the alias name
+ with the correct command name.
+
+ @param[in, out] CommandString Upon entry the potential alias. Upon return the
+ command name if it was an alias. If it was not
+ an alias it will be unchanged. This function may
+ change the buffer to fit the command name.
+
+ @retval EFI_SUCCESS The name was changed.
+ @retval EFI_SUCCESS The name was not an alias.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+ShellConvertAlias(
+ IN OUT CHAR16 **CommandString
+ )
+{
+ CONST CHAR16 *NewString;
+
+ NewString = ShellInfoObject.NewEfiShellProtocol->GetAlias(*CommandString, NULL);
+ if (NewString == NULL) {
+ return (EFI_SUCCESS);
+ }
+ FreePool(*CommandString);
+ *CommandString = AllocateCopyPool(StrSize(NewString), NewString);
+ if (*CommandString == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ return (EFI_SUCCESS);
+}
+
+/**
+ This function will eliminate unreplaced (and therefore non-found) environment variables.
+
+ @param[in,out] CmdLine The command line to update.
+**/
+EFI_STATUS
+EFIAPI
+StripUnreplacedEnvironmentVariables(
+ IN OUT CHAR16 *CmdLine
+ )
+{
+ CHAR16 *FirstPercent;
+ CHAR16 *FirstQuote;
+ CHAR16 *SecondPercent;
+ CHAR16 *SecondQuote;
+ CHAR16 *CurrentLocator;
+
+ for (CurrentLocator = CmdLine ; CurrentLocator != NULL ; ) {
+ FirstQuote = FindNextInstance(CurrentLocator, L"\"", TRUE);
+ FirstPercent = FindNextInstance(CurrentLocator, L"%", TRUE);
+ SecondPercent = FirstPercent!=NULL?FindNextInstance(FirstPercent+1, L"%", TRUE):NULL;
+ if (FirstPercent == NULL || SecondPercent == NULL) {
+ //
+ // If we ever don't have 2 % we are done.
+ //
+ break;
+ }
+
+ if (FirstQuote!= NULL && FirstQuote < FirstPercent) {
+ SecondQuote = FindNextInstance(FirstQuote+1, L"\"", TRUE);
+ //
+ // Quote is first found
+ //
+
+ if (SecondQuote < FirstPercent) {
+ //
+ // restart after the pair of "
+ //
+ CurrentLocator = SecondQuote + 1;
+ } else /* FirstPercent < SecondQuote */{
+ //
+ // Restart on the first percent
+ //
+ CurrentLocator = FirstPercent;
+ }
+ continue;
+ }
+
+ if (FirstQuote == NULL || SecondPercent < FirstQuote) {
+ if (IsValidEnvironmentVariableName(FirstPercent, SecondPercent)) {
+ //
+ // We need to remove from FirstPercent to SecondPercent
+ //
+ CopyMem(FirstPercent, SecondPercent + 1, StrSize(SecondPercent + 1));
+ //
+ // don't need to update the locator. both % characters are gone.
+ //
+ } else {
+ CurrentLocator = SecondPercent + 1;
+ }
+ continue;
+ }
+ CurrentLocator = FirstQuote;
+ }
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function allocates a new command line and replaces all instances of environment
+ variable names that are correctly preset to their values.
+
+ If the return value is not NULL the memory must be caller freed.
+
+ @param[in] OriginalCommandLine The original command line
+
+ @retval NULL An error occurred.
+ @return The new command line with no environment variables present.
+**/
+CHAR16*
+EFIAPI
+ShellConvertVariables (
+ IN CONST CHAR16 *OriginalCommandLine
+ )
+{
+ CONST CHAR16 *MasterEnvList;
+ UINTN NewSize;
+ CHAR16 *NewCommandLine1;
+ CHAR16 *NewCommandLine2;
+ CHAR16 *Temp;
+ UINTN ItemSize;
+ CHAR16 *ItemTemp;
+ SCRIPT_FILE *CurrentScriptFile;
+ ALIAS_LIST *AliasListNode;
+
+ ASSERT(OriginalCommandLine != NULL);
+
+ ItemSize = 0;
+ NewSize = StrSize(OriginalCommandLine);
+ CurrentScriptFile = ShellCommandGetCurrentScriptFile();
+ Temp = NULL;
+
+ ///@todo update this to handle the %0 - %9 for scripting only (borrow from line 1256 area) ? ? ?
+
+ //
+ // calculate the size required for the post-conversion string...
+ //
+ if (CurrentScriptFile != NULL) {
+ for (AliasListNode = (ALIAS_LIST*)GetFirstNode(&CurrentScriptFile->SubstList)
+ ; !IsNull(&CurrentScriptFile->SubstList, &AliasListNode->Link)
+ ; AliasListNode = (ALIAS_LIST*)GetNextNode(&CurrentScriptFile->SubstList, &AliasListNode->Link)
+ ){
+ for (Temp = StrStr(OriginalCommandLine, AliasListNode->Alias)
+ ; Temp != NULL
+ ; Temp = StrStr(Temp+1, AliasListNode->Alias)
+ ){
+ //
+ // we need a preceding and if there is space no ^ preceding (if no space ignore)
+ //
+ if ((((Temp-OriginalCommandLine)>2) && *(Temp-2) != L'^') || ((Temp-OriginalCommandLine)<=2)) {
+ NewSize += StrSize(AliasListNode->CommandString);
+ }
+ }
+ }
+ }
+
+ for (MasterEnvList = EfiShellGetEnv(NULL)
+ ; MasterEnvList != NULL && *MasterEnvList != CHAR_NULL //&& *(MasterEnvList+1) != CHAR_NULL
+ ; MasterEnvList += StrLen(MasterEnvList) + 1
+ ){
+ if (StrSize(MasterEnvList) > ItemSize) {
+ ItemSize = StrSize(MasterEnvList);
+ }
+ for (Temp = StrStr(OriginalCommandLine, MasterEnvList)
+ ; Temp != NULL
+ ; Temp = StrStr(Temp+1, MasterEnvList)
+ ){
+ //
+ // we need a preceding and following % and if there is space no ^ preceding (if no space ignore)
+ //
+ if (*(Temp-1) == L'%' && *(Temp+StrLen(MasterEnvList)) == L'%' &&
+ ((((Temp-OriginalCommandLine)>2) && *(Temp-2) != L'^') || ((Temp-OriginalCommandLine)<=2))) {
+ NewSize+=StrSize(EfiShellGetEnv(MasterEnvList));
+ }
+ }
+ }
+
+ //
+ // now do the replacements...
+ //
+ NewCommandLine1 = AllocateCopyPool(NewSize, OriginalCommandLine);
+ NewCommandLine2 = AllocateZeroPool(NewSize);
+ ItemTemp = AllocateZeroPool(ItemSize+(2*sizeof(CHAR16)));
+ if (NewCommandLine1 == NULL || NewCommandLine2 == NULL || ItemTemp == NULL) {
+ SHELL_FREE_NON_NULL(NewCommandLine1);
+ SHELL_FREE_NON_NULL(NewCommandLine2);
+ SHELL_FREE_NON_NULL(ItemTemp);
+ return (NULL);
+ }
+ for (MasterEnvList = EfiShellGetEnv(NULL)
+ ; MasterEnvList != NULL && *MasterEnvList != CHAR_NULL
+ ; MasterEnvList += StrLen(MasterEnvList) + 1
+ ){
+ StrCpyS( ItemTemp,
+ ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)),
+ L"%"
+ );
+ StrCatS( ItemTemp,
+ ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)),
+ MasterEnvList
+ );
+ StrCatS( ItemTemp,
+ ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)),
+ L"%"
+ );
+ ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, ItemTemp, EfiShellGetEnv(MasterEnvList), TRUE, FALSE);
+ StrCpyS(NewCommandLine1, NewSize/sizeof(CHAR16), NewCommandLine2);
+ }
+ if (CurrentScriptFile != NULL) {
+ for (AliasListNode = (ALIAS_LIST*)GetFirstNode(&CurrentScriptFile->SubstList)
+ ; !IsNull(&CurrentScriptFile->SubstList, &AliasListNode->Link)
+ ; AliasListNode = (ALIAS_LIST*)GetNextNode(&CurrentScriptFile->SubstList, &AliasListNode->Link)
+ ){
+ ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, AliasListNode->Alias, AliasListNode->CommandString, TRUE, FALSE);
+ StrCpyS(NewCommandLine1, NewSize/sizeof(CHAR16), NewCommandLine2);
+ }
+ }
+
+ //
+ // Remove non-existent environment variables
+ //
+ StripUnreplacedEnvironmentVariables(NewCommandLine1);
+
+ //
+ // Now cleanup any straggler intentionally ignored "%" characters
+ //
+ ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, L"^%", L"%", TRUE, FALSE);
+ StrCpyS(NewCommandLine1, NewSize/sizeof(CHAR16), NewCommandLine2);
+
+ FreePool(NewCommandLine2);
+ FreePool(ItemTemp);
+
+ return (NewCommandLine1);
+}
+
+/**
+ Internal function to run a command line with pipe usage.
+
+ @param[in] CmdLine The pointer to the command line.
+ @param[in] StdIn The pointer to the Standard input.
+ @param[in] StdOut The pointer to the Standard output.
+
+ @retval EFI_SUCCESS The split command is executed successfully.
+ @retval other Some error occurs when executing the split command.
+**/
+EFI_STATUS
+EFIAPI
+RunSplitCommand(
+ IN CONST CHAR16 *CmdLine,
+ IN SHELL_FILE_HANDLE *StdIn,
+ IN SHELL_FILE_HANDLE *StdOut
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *NextCommandLine;
+ CHAR16 *OurCommandLine;
+ UINTN Size1;
+ UINTN Size2;
+ SPLIT_LIST *Split;
+ SHELL_FILE_HANDLE *TempFileHandle;
+ BOOLEAN Unicode;
+
+ ASSERT(StdOut == NULL);
+
+ ASSERT(StrStr(CmdLine, L"|") != NULL);
+
+ Status = EFI_SUCCESS;
+ NextCommandLine = NULL;
+ OurCommandLine = NULL;
+ Size1 = 0;
+ Size2 = 0;
+
+ NextCommandLine = StrnCatGrow(&NextCommandLine, &Size1, StrStr(CmdLine, L"|")+1, 0);
+ OurCommandLine = StrnCatGrow(&OurCommandLine , &Size2, CmdLine , StrStr(CmdLine, L"|") - CmdLine);
+
+ if (NextCommandLine == NULL || OurCommandLine == NULL) {
+ SHELL_FREE_NON_NULL(OurCommandLine);
+ SHELL_FREE_NON_NULL(NextCommandLine);
+ return (EFI_OUT_OF_RESOURCES);
+ } else if (StrStr(OurCommandLine, L"|") != NULL || Size1 == 0 || Size2 == 0) {
+ SHELL_FREE_NON_NULL(OurCommandLine);
+ SHELL_FREE_NON_NULL(NextCommandLine);
+ return (EFI_INVALID_PARAMETER);
+ } else if (NextCommandLine[0] == L'a' &&
+ (NextCommandLine[1] == L' ' || NextCommandLine[1] == CHAR_NULL)
+ ){
+ CopyMem(NextCommandLine, NextCommandLine+1, StrSize(NextCommandLine) - sizeof(NextCommandLine[0]));
+ while (NextCommandLine[0] == L' ') {
+ CopyMem(NextCommandLine, NextCommandLine+1, StrSize(NextCommandLine) - sizeof(NextCommandLine[0]));
+ }
+ if (NextCommandLine[0] == CHAR_NULL) {
+ SHELL_FREE_NON_NULL(OurCommandLine);
+ SHELL_FREE_NON_NULL(NextCommandLine);
+ return (EFI_INVALID_PARAMETER);
+ }
+ Unicode = FALSE;
+ } else {
+ Unicode = TRUE;
+ }
+
+
+ //
+ // make a SPLIT_LIST item and add to list
+ //
+ Split = AllocateZeroPool(sizeof(SPLIT_LIST));
+ if (Split == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Split->SplitStdIn = StdIn;
+ Split->SplitStdOut = ConvertEfiFileProtocolToShellHandle(CreateFileInterfaceMem(Unicode), NULL);
+ ASSERT(Split->SplitStdOut != NULL);
+ InsertHeadList(&ShellInfoObject.SplitList.Link, &Split->Link);
+
+ Status = RunCommand(OurCommandLine);
+
+ //
+ // move the output from the first to the in to the second.
+ //
+ TempFileHandle = Split->SplitStdOut;
+ if (Split->SplitStdIn == StdIn) {
+ Split->SplitStdOut = NULL;
+ } else {
+ Split->SplitStdOut = Split->SplitStdIn;
+ }
+ Split->SplitStdIn = TempFileHandle;
+ ShellInfoObject.NewEfiShellProtocol->SetFilePosition(ConvertShellHandleToEfiFileProtocol(Split->SplitStdIn), 0);
+
+ if (!EFI_ERROR(Status)) {
+ Status = RunCommand(NextCommandLine);
+ }
+
+ //
+ // remove the top level from the ScriptList
+ //
+ ASSERT((SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link) == Split);
+ RemoveEntryList(&Split->Link);
+
+ //
+ // Note that the original StdIn is now the StdOut...
+ //
+ if (Split->SplitStdOut != NULL) {
+ ShellInfoObject.NewEfiShellProtocol->CloseFile(ConvertShellHandleToEfiFileProtocol(Split->SplitStdOut));
+ }
+ if (Split->SplitStdIn != NULL) {
+ ShellInfoObject.NewEfiShellProtocol->CloseFile(ConvertShellHandleToEfiFileProtocol(Split->SplitStdIn));
+ FreePool (Split->SplitStdIn);
+ }
+
+ FreePool(Split);
+ FreePool(NextCommandLine);
+ FreePool(OurCommandLine);
+
+ return (Status);
+}
+
+/**
+ Take the original command line, substitute any variables, free
+ the original string, return the modified copy.
+
+ @param[in] CmdLine pointer to the command line to update.
+
+ @retval EFI_SUCCESS the function was successful.
+ @retval EFI_OUT_OF_RESOURCES a memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+ShellSubstituteVariables(
+ IN CHAR16 **CmdLine
+ )
+{
+ CHAR16 *NewCmdLine;
+ NewCmdLine = ShellConvertVariables(*CmdLine);
+ SHELL_FREE_NON_NULL(*CmdLine);
+ if (NewCmdLine == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ *CmdLine = NewCmdLine;
+ return (EFI_SUCCESS);
+}
+
+/**
+ Take the original command line, substitute any alias in the first group of space delimited characters, free
+ the original string, return the modified copy.
+
+ @param[in] CmdLine pointer to the command line to update.
+
+ @retval EFI_SUCCESS the function was successful.
+ @retval EFI_OUT_OF_RESOURCES a memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+ShellSubstituteAliases(
+ IN CHAR16 **CmdLine
+ )
+{
+ CHAR16 *NewCmdLine;
+ CHAR16 *CommandName;
+ EFI_STATUS Status;
+ UINTN PostAliasSize;
+ ASSERT(CmdLine != NULL);
+ ASSERT(*CmdLine!= NULL);
+
+
+ CommandName = NULL;
+ if (StrStr((*CmdLine), L" ") == NULL){
+ StrnCatGrow(&CommandName, NULL, (*CmdLine), 0);
+ } else {
+ StrnCatGrow(&CommandName, NULL, (*CmdLine), StrStr((*CmdLine), L" ") - (*CmdLine));
+ }
+
+ //
+ // This cannot happen 'inline' since the CmdLine can need extra space.
+ //
+ NewCmdLine = NULL;
+ if (!ShellCommandIsCommandOnList(CommandName)) {
+ //
+ // Convert via alias
+ //
+ Status = ShellConvertAlias(&CommandName);
+ if (EFI_ERROR(Status)){
+ return (Status);
+ }
+ PostAliasSize = 0;
+ NewCmdLine = StrnCatGrow(&NewCmdLine, &PostAliasSize, CommandName, 0);
+ if (NewCmdLine == NULL) {
+ SHELL_FREE_NON_NULL(CommandName);
+ SHELL_FREE_NON_NULL(*CmdLine);
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ NewCmdLine = StrnCatGrow(&NewCmdLine, &PostAliasSize, StrStr((*CmdLine), L" "), 0);
+ if (NewCmdLine == NULL) {
+ SHELL_FREE_NON_NULL(CommandName);
+ SHELL_FREE_NON_NULL(*CmdLine);
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ } else {
+ NewCmdLine = StrnCatGrow(&NewCmdLine, NULL, (*CmdLine), 0);
+ }
+
+ SHELL_FREE_NON_NULL(*CmdLine);
+ SHELL_FREE_NON_NULL(CommandName);
+
+ //
+ // re-assign the passed in double pointer to point to our newly allocated buffer
+ //
+ *CmdLine = NewCmdLine;
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Takes the Argv[0] part of the command line and determine the meaning of it.
+
+ @param[in] CmdName pointer to the command line to update.
+
+ @retval Internal_Command The name is an internal command.
+ @retval File_Sys_Change the name is a file system change.
+ @retval Script_File_Name the name is a NSH script file.
+ @retval Unknown_Invalid the name is unknown.
+ @retval Efi_Application the name is an application (.EFI).
+**/
+SHELL_OPERATION_TYPES
+EFIAPI
+GetOperationType(
+ IN CONST CHAR16 *CmdName
+ )
+{
+ CHAR16* FileWithPath;
+ CONST CHAR16* TempLocation;
+ CONST CHAR16* TempLocation2;
+
+ FileWithPath = NULL;
+ //
+ // test for an internal command.
+ //
+ if (ShellCommandIsCommandOnList(CmdName)) {
+ return (Internal_Command);
+ }
+
+ //
+ // Test for file system change request. anything ending with first : and cant have spaces.
+ //
+ if (CmdName[(StrLen(CmdName)-1)] == L':') {
+ if ( StrStr(CmdName, L" ") != NULL
+ || StrLen(StrStr(CmdName, L":")) > 1
+ ) {
+ return (Unknown_Invalid);
+ }
+ return (File_Sys_Change);
+ }
+
+ //
+ // Test for a file
+ //
+ if ((FileWithPath = ShellFindFilePathEx(CmdName, mExecutableExtensions)) != NULL) {
+ //
+ // See if that file has a script file extension
+ //
+ if (StrLen(FileWithPath) > 4) {
+ TempLocation = FileWithPath+StrLen(FileWithPath)-4;
+ TempLocation2 = mScriptExtension;
+ if (StringNoCaseCompare((VOID*)(&TempLocation), (VOID*)(&TempLocation2)) == 0) {
+ SHELL_FREE_NON_NULL(FileWithPath);
+ return (Script_File_Name);
+ }
+ }
+
+ //
+ // Was a file, but not a script. we treat this as an application.
+ //
+ SHELL_FREE_NON_NULL(FileWithPath);
+ return (Efi_Application);
+ }
+
+ SHELL_FREE_NON_NULL(FileWithPath);
+ //
+ // No clue what this is... return invalid flag...
+ //
+ return (Unknown_Invalid);
+}
+
+/**
+ Determine if the first item in a command line is valid.
+
+ @param[in] CmdLine The command line to parse.
+
+ @retval EFI_SUCCESS The item is valid.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_NOT_FOUND The operation type is unknown or invalid.
+**/
+EFI_STATUS
+EFIAPI
+IsValidSplit(
+ IN CONST CHAR16 *CmdLine
+ )
+{
+ CHAR16 *Temp;
+ CHAR16 *FirstParameter;
+ CHAR16 *TempWalker;
+ EFI_STATUS Status;
+
+ Temp = NULL;
+
+ Temp = StrnCatGrow(&Temp, NULL, CmdLine, 0);
+ if (Temp == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ FirstParameter = StrStr(Temp, L"|");
+ if (FirstParameter != NULL) {
+ *FirstParameter = CHAR_NULL;
+ }
+
+ FirstParameter = NULL;
+
+ //
+ // Process the command line
+ //
+ Status = ProcessCommandLineToFinal(&Temp);
+
+ if (!EFI_ERROR(Status)) {
+ FirstParameter = AllocateZeroPool(StrSize(CmdLine));
+ if (FirstParameter == NULL) {
+ SHELL_FREE_NON_NULL(Temp);
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ TempWalker = (CHAR16*)Temp;
+ if (!EFI_ERROR (ShellGetNextParameter (&TempWalker, FirstParameter, StrSize(CmdLine), TRUE))) {
+ if (GetOperationType(FirstParameter) == Unknown_Invalid) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);
+ SetLastError(SHELL_NOT_FOUND);
+ Status = EFI_NOT_FOUND;
+ }
+ }
+ }
+
+ SHELL_FREE_NON_NULL(Temp);
+ SHELL_FREE_NON_NULL(FirstParameter);
+ return Status;
+}
+
+/**
+ Determine if a command line contains with a split contains only valid commands.
+
+ @param[in] CmdLine The command line to parse.
+
+ @retval EFI_SUCCESS CmdLine has only valid commands, application, or has no split.
+ @retval EFI_ABORTED CmdLine has at least one invalid command or application.
+**/
+EFI_STATUS
+EFIAPI
+VerifySplit(
+ IN CONST CHAR16 *CmdLine
+ )
+{
+ CONST CHAR16 *TempSpot;
+ EFI_STATUS Status;
+
+ //
+ // If this was the only item, then get out
+ //
+ if (!ContainsSplit(CmdLine)) {
+ return (EFI_SUCCESS);
+ }
+
+ //
+ // Verify up to the pipe or end character
+ //
+ Status = IsValidSplit(CmdLine);
+ if (EFI_ERROR(Status)) {
+ return (Status);
+ }
+
+ //
+ // recurse to verify the next item
+ //
+ TempSpot = ShellFindFirstCharacter(CmdLine, L"|", TRUE) + 1;
+ if (*TempSpot == L'a' &&
+ (*(TempSpot + 1) == L' ' || *(TempSpot + 1) == CHAR_NULL)
+ ) {
+ // If it's an ASCII pipe '|a'
+ TempSpot += 1;
+ }
+
+ return (VerifySplit(TempSpot));
+}
+
+/**
+ Process a split based operation.
+
+ @param[in] CmdLine pointer to the command line to process
+
+ @retval EFI_SUCCESS The operation was successful
+ @return an error occurred.
+**/
+EFI_STATUS
+EFIAPI
+ProcessNewSplitCommandLine(
+ IN CONST CHAR16 *CmdLine
+ )
+{
+ SPLIT_LIST *Split;
+ EFI_STATUS Status;
+
+ Status = VerifySplit(CmdLine);
+ if (EFI_ERROR(Status)) {
+ return (Status);
+ }
+
+ Split = NULL;
+
+ //
+ // are we in an existing split???
+ //
+ if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {
+ Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);
+ }
+
+ if (Split == NULL) {
+ Status = RunSplitCommand(CmdLine, NULL, NULL);
+ } else {
+ Status = RunSplitCommand(CmdLine, Split->SplitStdIn, Split->SplitStdOut);
+ }
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_SPLIT), ShellInfoObject.HiiHandle, CmdLine);
+ }
+ return (Status);
+}
+
+/**
+ Handle a request to change the current file system.
+
+ @param[in] CmdLine The passed in command line.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+ChangeMappedDrive(
+ IN CONST CHAR16 *CmdLine
+ )
+{
+ EFI_STATUS Status;
+ Status = EFI_SUCCESS;
+
+ //
+ // make sure we are the right operation
+ //
+ ASSERT(CmdLine[(StrLen(CmdLine)-1)] == L':' && StrStr(CmdLine, L" ") == NULL);
+
+ //
+ // Call the protocol API to do the work
+ //
+ Status = ShellInfoObject.NewEfiShellProtocol->SetCurDir(NULL, CmdLine);
+
+ //
+ // Report any errors
+ //
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_MAPPING), ShellInfoObject.HiiHandle, CmdLine);
+ }
+
+ return (Status);
+}
+
+/**
+ Reprocess the command line to direct all -? to the help command.
+
+ if found, will add "help" as argv[0], and move the rest later.
+
+ @param[in,out] CmdLine pointer to the command line to update
+**/
+EFI_STATUS
+EFIAPI
+DoHelpUpdate(
+ IN OUT CHAR16 **CmdLine
+ )
+{
+ CHAR16 *CurrentParameter;
+ CHAR16 *Walker;
+ CHAR16 *NewCommandLine;
+ EFI_STATUS Status;
+ UINTN NewCmdLineSize;
+
+ Status = EFI_SUCCESS;
+
+ CurrentParameter = AllocateZeroPool(StrSize(*CmdLine));
+ if (CurrentParameter == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ Walker = *CmdLine;
+ while(Walker != NULL && *Walker != CHAR_NULL) {
+ if (!EFI_ERROR (ShellGetNextParameter (&Walker, CurrentParameter, StrSize(*CmdLine), TRUE))) {
+ if (StrStr(CurrentParameter, L"-?") == CurrentParameter) {
+ CurrentParameter[0] = L' ';
+ CurrentParameter[1] = L' ';
+ NewCmdLineSize = StrSize(L"help ") + StrSize(*CmdLine);
+ NewCommandLine = AllocateZeroPool(NewCmdLineSize);
+ if (NewCommandLine == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ }
+
+ //
+ // We know the space is sufficient since we just calculated it.
+ //
+ StrnCpyS(NewCommandLine, NewCmdLineSize/sizeof(CHAR16), L"help ", 5);
+ StrnCatS(NewCommandLine, NewCmdLineSize/sizeof(CHAR16), *CmdLine, StrLen(*CmdLine));
+ SHELL_FREE_NON_NULL(*CmdLine);
+ *CmdLine = NewCommandLine;
+ break;
+ }
+ }
+ }
+
+ SHELL_FREE_NON_NULL(CurrentParameter);
+
+ return (Status);
+}
+
+/**
+ Function to update the shell variable "lasterror".
+
+ @param[in] ErrorCode the error code to put into lasterror.
+**/
+EFI_STATUS
+EFIAPI
+SetLastError(
+ IN CONST SHELL_STATUS ErrorCode
+ )
+{
+ CHAR16 LeString[19];
+ if (sizeof(EFI_STATUS) == sizeof(UINT64)) {
+ UnicodeSPrint(LeString, sizeof(LeString), L"0x%Lx", ErrorCode);
+ } else {
+ UnicodeSPrint(LeString, sizeof(LeString), L"0x%x", ErrorCode);
+ }
+ DEBUG_CODE(InternalEfiShellSetEnv(L"debuglasterror", LeString, TRUE););
+ InternalEfiShellSetEnv(L"lasterror", LeString, TRUE);
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Converts the command line to it's post-processed form. this replaces variables and alias' per UEFI Shell spec.
+
+ @param[in,out] CmdLine pointer to the command line to update
+
+ @retval EFI_SUCCESS The operation was successful
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @return some other error occurred
+**/
+EFI_STATUS
+EFIAPI
+ProcessCommandLineToFinal(
+ IN OUT CHAR16 **CmdLine
+ )
+{
+ EFI_STATUS Status;
+ TrimSpaces(CmdLine);
+
+ Status = ShellSubstituteAliases(CmdLine);
+ if (EFI_ERROR(Status)) {
+ return (Status);
+ }
+
+ TrimSpaces(CmdLine);
+
+ Status = ShellSubstituteVariables(CmdLine);
+ if (EFI_ERROR(Status)) {
+ return (Status);
+ }
+ ASSERT (*CmdLine != NULL);
+
+ TrimSpaces(CmdLine);
+
+ //
+ // update for help parsing
+ //
+ if (StrStr(*CmdLine, L"?") != NULL) {
+ //
+ // This may do nothing if the ? does not indicate help.
+ // Save all the details for in the API below.
+ //
+ Status = DoHelpUpdate(CmdLine);
+ }
+
+ TrimSpaces(CmdLine);
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Run an internal shell command.
+
+ This API will update the shell's environment since these commands are libraries.
+
+ @param[in] CmdLine the command line to run.
+ @param[in] FirstParameter the first parameter on the command line
+ @param[in] ParamProtocol the shell parameters protocol pointer
+ @param[out] CommandStatus the status from the command line.
+
+ @retval EFI_SUCCESS The command was completed.
+ @retval EFI_ABORTED The command's operation was aborted.
+**/
+EFI_STATUS
+EFIAPI
+RunInternalCommand(
+ IN CONST CHAR16 *CmdLine,
+ IN CHAR16 *FirstParameter,
+ IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol,
+ OUT EFI_STATUS *CommandStatus
+)
+{
+ EFI_STATUS Status;
+ UINTN Argc;
+ CHAR16 **Argv;
+ SHELL_STATUS CommandReturnedStatus;
+ BOOLEAN LastError;
+ CHAR16 *Walker;
+ CHAR16 *NewCmdLine;
+
+ NewCmdLine = AllocateCopyPool (StrSize (CmdLine), CmdLine);
+ if (NewCmdLine == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Walker = NewCmdLine; Walker != NULL && *Walker != CHAR_NULL ; Walker++) {
+ if (*Walker == L'^' && *(Walker+1) == L'#') {
+ CopyMem(Walker, Walker+1, StrSize(Walker) - sizeof(Walker[0]));
+ }
+ }
+
+ //
+ // get the argc and argv updated for internal commands
+ //
+ Status = UpdateArgcArgv(ParamProtocol, NewCmdLine, Internal_Command, &Argv, &Argc);
+ if (!EFI_ERROR(Status)) {
+ //
+ // Run the internal command.
+ //
+ Status = ShellCommandRunCommandHandler(FirstParameter, &CommandReturnedStatus, &LastError);
+
+ if (!EFI_ERROR(Status)) {
+ if (CommandStatus != NULL) {
+ if (CommandReturnedStatus != SHELL_SUCCESS) {
+ *CommandStatus = (EFI_STATUS)(CommandReturnedStatus | MAX_BIT);
+ } else {
+ *CommandStatus = EFI_SUCCESS;
+ }
+ }
+
+ //
+ // Update last error status.
+ // some commands do not update last error.
+ //
+ if (LastError) {
+ SetLastError(CommandReturnedStatus);
+ }
+
+ //
+ // Pass thru the exitcode from the app.
+ //
+ if (ShellCommandGetExit()) {
+ //
+ // An Exit was requested ("exit" command), pass its value up.
+ //
+ Status = CommandReturnedStatus;
+ } else if (CommandReturnedStatus != SHELL_SUCCESS && IsScriptOnlyCommand(FirstParameter)) {
+ //
+ // Always abort when a script only command fails for any reason
+ //
+ Status = EFI_ABORTED;
+ } else if (ShellCommandGetCurrentScriptFile() != NULL && CommandReturnedStatus == SHELL_ABORTED) {
+ //
+ // Abort when in a script and a command aborted
+ //
+ Status = EFI_ABORTED;
+ }
+ }
+ }
+
+ //
+ // This is guaranteed to be called after UpdateArgcArgv no matter what else happened.
+ // This is safe even if the update API failed. In this case, it may be a no-op.
+ //
+ RestoreArgcArgv(ParamProtocol, &Argv, &Argc);
+
+ //
+ // If a script is running and the command is not a script only command, then
+ // change return value to success so the script won't halt (unless aborted).
+ //
+ // Script only commands have to be able halt the script since the script will
+ // not operate if they are failing.
+ //
+ if ( ShellCommandGetCurrentScriptFile() != NULL
+ && !IsScriptOnlyCommand(FirstParameter)
+ && Status != EFI_ABORTED
+ ) {
+ Status = EFI_SUCCESS;
+ }
+
+ FreePool (NewCmdLine);
+ return (Status);
+}
+
+/**
+ Function to run the command or file.
+
+ @param[in] Type the type of operation being run.
+ @param[in] CmdLine the command line to run.
+ @param[in] FirstParameter the first parameter on the command line
+ @param[in] ParamProtocol the shell parameters protocol pointer
+ @param[out] CommandStatus the status from the command line.
+
+ @retval EFI_SUCCESS The command was completed.
+ @retval EFI_ABORTED The command's operation was aborted.
+**/
+EFI_STATUS
+EFIAPI
+RunCommandOrFile(
+ IN SHELL_OPERATION_TYPES Type,
+ IN CONST CHAR16 *CmdLine,
+ IN CHAR16 *FirstParameter,
+ IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol,
+ OUT EFI_STATUS *CommandStatus
+)
+{
+ EFI_STATUS Status;
+ EFI_STATUS StartStatus;
+ CHAR16 *CommandWithPath;
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+ SHELL_STATUS CalleeExitStatus;
+
+ Status = EFI_SUCCESS;
+ CommandWithPath = NULL;
+ DevPath = NULL;
+ CalleeExitStatus = SHELL_INVALID_PARAMETER;
+
+ switch (Type) {
+ case Internal_Command:
+ Status = RunInternalCommand(CmdLine, FirstParameter, ParamProtocol, CommandStatus);
+ break;
+ case Script_File_Name:
+ case Efi_Application:
+ //
+ // Process a fully qualified path
+ //
+ if (StrStr(FirstParameter, L":") != NULL) {
+ ASSERT (CommandWithPath == NULL);
+ if (ShellIsFile(FirstParameter) == EFI_SUCCESS) {
+ CommandWithPath = StrnCatGrow(&CommandWithPath, NULL, FirstParameter, 0);
+ }
+ }
+
+ //
+ // Process a relative path and also check in the path environment variable
+ //
+ if (CommandWithPath == NULL) {
+ CommandWithPath = ShellFindFilePathEx(FirstParameter, mExecutableExtensions);
+ }
+
+ //
+ // This should be impossible now.
+ //
+ ASSERT(CommandWithPath != NULL);
+
+ //
+ // Make sure that path is not just a directory (or not found)
+ //
+ if (!EFI_ERROR(ShellIsDirectory(CommandWithPath))) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);
+ SetLastError(SHELL_NOT_FOUND);
+ }
+ switch (Type) {
+ case Script_File_Name:
+ Status = RunScriptFile (CommandWithPath, NULL, CmdLine, ParamProtocol);
+ break;
+ case Efi_Application:
+ //
+ // Get the device path of the application image
+ //
+ DevPath = ShellInfoObject.NewEfiShellProtocol->GetDevicePathFromFilePath(CommandWithPath);
+ if (DevPath == NULL){
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ }
+
+ //
+ // Execute the device path
+ //
+ Status = InternalShellExecuteDevicePath(
+ &gImageHandle,
+ DevPath,
+ CmdLine,
+ NULL,
+ &StartStatus
+ );
+
+ SHELL_FREE_NON_NULL(DevPath);
+
+ if(EFI_ERROR (Status)) {
+ CalleeExitStatus = (SHELL_STATUS) (Status & (~MAX_BIT));
+ } else {
+ CalleeExitStatus = (SHELL_STATUS) StartStatus;
+ }
+
+ if (CommandStatus != NULL) {
+ *CommandStatus = CalleeExitStatus;
+ }
+
+ //
+ // Update last error status.
+ //
+ // Status is an EFI_STATUS. Clear top bit to convert to SHELL_STATUS
+ SetLastError(CalleeExitStatus);
+ break;
+ default:
+ //
+ // Do nothing.
+ //
+ break;
+ }
+ break;
+ default:
+ //
+ // Do nothing.
+ //
+ break;
+ }
+
+ SHELL_FREE_NON_NULL(CommandWithPath);
+
+ return (Status);
+}
+
+/**
+ Function to setup StdIn, StdErr, StdOut, and then run the command or file.
+
+ @param[in] Type the type of operation being run.
+ @param[in] CmdLine the command line to run.
+ @param[in] FirstParameter the first parameter on the command line.
+ @param[in] ParamProtocol the shell parameters protocol pointer
+ @param[out] CommandStatus the status from the command line.
+
+ @retval EFI_SUCCESS The command was completed.
+ @retval EFI_ABORTED The command's operation was aborted.
+**/
+EFI_STATUS
+EFIAPI
+SetupAndRunCommandOrFile(
+ IN SHELL_OPERATION_TYPES Type,
+ IN CHAR16 *CmdLine,
+ IN CHAR16 *FirstParameter,
+ IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol,
+ OUT EFI_STATUS *CommandStatus
+)
+{
+ EFI_STATUS Status;
+ SHELL_FILE_HANDLE OriginalStdIn;
+ SHELL_FILE_HANDLE OriginalStdOut;
+ SHELL_FILE_HANDLE OriginalStdErr;
+ SYSTEM_TABLE_INFO OriginalSystemTableInfo;
+ CONST SCRIPT_FILE *ConstScriptFile;
+
+ //
+ // Update the StdIn, StdOut, and StdErr for redirection to environment variables, files, etc... unicode and ASCII
+ //
+ Status = UpdateStdInStdOutStdErr(ParamProtocol, CmdLine, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr, &OriginalSystemTableInfo);
+
+ //
+ // The StdIn, StdOut, and StdErr are set up.
+ // Now run the command, script, or application
+ //
+ if (!EFI_ERROR(Status)) {
+ TrimSpaces(&CmdLine);
+ Status = RunCommandOrFile(Type, CmdLine, FirstParameter, ParamProtocol, CommandStatus);
+ }
+
+ //
+ // Now print errors
+ //
+ if (EFI_ERROR(Status)) {
+ ConstScriptFile = ShellCommandGetCurrentScriptFile();
+ if (ConstScriptFile == NULL || ConstScriptFile->CurrentCommand == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_ERROR), ShellInfoObject.HiiHandle, (VOID*)(Status));
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_ERROR_SCRIPT), ShellInfoObject.HiiHandle, (VOID*)(Status), ConstScriptFile->CurrentCommand->Line);
+ }
+ }
+
+ //
+ // put back the original StdIn, StdOut, and StdErr
+ //
+ RestoreStdInStdOutStdErr(ParamProtocol, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr, &OriginalSystemTableInfo);
+
+ return (Status);
+}
+
+/**
+ Function will process and run a command line.
+
+ This will determine if the command line represents an internal shell
+ command or dispatch an external application.
+
+ @param[in] CmdLine The command line to parse.
+ @param[out] CommandStatus The status from the command line.
+
+ @retval EFI_SUCCESS The command was completed.
+ @retval EFI_ABORTED The command's operation was aborted.
+**/
+EFI_STATUS
+EFIAPI
+RunShellCommand(
+ IN CONST CHAR16 *CmdLine,
+ OUT EFI_STATUS *CommandStatus
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *CleanOriginal;
+ CHAR16 *FirstParameter;
+ CHAR16 *TempWalker;
+ SHELL_OPERATION_TYPES Type;
+ CHAR16 *OldCmdLine;
+
+ ASSERT(CmdLine != NULL);
+ if (StrLen(CmdLine) == 0) {
+ return (EFI_SUCCESS);
+ }
+
+ Status = EFI_SUCCESS;
+ FirstParameter = NULL;
+ CleanOriginal = NULL;
+ OldCmdLine = NULL;
+
+ CleanOriginal = StrnCatGrow(&CleanOriginal, NULL, CmdLine, 0);
+ if (CleanOriginal == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ TrimSpaces(&CleanOriginal);
+
+ //
+ // NULL out comments (leveraged from RunScriptFileHandle() ).
+ // The # character on a line is used to denote that all characters on the same line
+ // and to the right of the # are to be ignored by the shell.
+ // Afterwards, again remove spaces, in case any were between the last command-parameter and '#'.
+ //
+ for (TempWalker = CleanOriginal; TempWalker != NULL && *TempWalker != CHAR_NULL; TempWalker++) {
+ if (*TempWalker == L'^') {
+ if (*(TempWalker + 1) == L'#') {
+ TempWalker++;
+ }
+ } else if (*TempWalker == L'#') {
+ *TempWalker = CHAR_NULL;
+ }
+ }
+
+ TrimSpaces(&CleanOriginal);
+
+ //
+ // Handle case that passed in command line is just 1 or more " " characters.
+ //
+ if (StrLen (CleanOriginal) == 0) {
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ Status = ProcessCommandLineToFinal(&CleanOriginal);
+ if (EFI_ERROR(Status)) {
+ goto Done;
+ }
+
+ OldCmdLine = ShellGetRawCmdLine ();
+ ShellSetRawCmdLine (CleanOriginal);
+
+ //
+ // We don't do normal processing with a split command line (output from one command input to another)
+ //
+ if (ContainsSplit(CleanOriginal)) {
+ Status = ProcessNewSplitCommandLine(CleanOriginal);
+ goto Done;
+ }
+
+ //
+ // We need the first parameter information so we can determine the operation type
+ //
+ FirstParameter = AllocateZeroPool(StrSize(CleanOriginal));
+ if (FirstParameter == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+ TempWalker = CleanOriginal;
+ if (!EFI_ERROR (ShellGetNextParameter (&TempWalker, FirstParameter, StrSize(CleanOriginal), TRUE))) {
+ //
+ // Depending on the first parameter we change the behavior
+ //
+ switch (Type = GetOperationType(FirstParameter)) {
+ case File_Sys_Change:
+ Status = ChangeMappedDrive (FirstParameter);
+ break;
+ case Internal_Command:
+ case Script_File_Name:
+ case Efi_Application:
+ Status = SetupAndRunCommandOrFile(Type, CleanOriginal, FirstParameter, ShellInfoObject.NewShellParametersProtocol, CommandStatus);
+ break;
+ default:
+ //
+ // Whatever was typed, it was invalid.
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);
+ SetLastError(SHELL_NOT_FOUND);
+ break;
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);
+ SetLastError(SHELL_NOT_FOUND);
+ }
+
+Done:
+ ShellSetRawCmdLine (OldCmdLine);
+ SHELL_FREE_NON_NULL (OldCmdLine);
+ SHELL_FREE_NON_NULL (CleanOriginal);
+ SHELL_FREE_NON_NULL (FirstParameter);
+
+ return (Status);
+}
+
+/**
+ Function will process and run a command line.
+
+ This will determine if the command line represents an internal shell
+ command or dispatch an external application.
+
+ @param[in] CmdLine The command line to parse.
+
+ @retval EFI_SUCCESS The command was completed.
+ @retval EFI_ABORTED The command's operation was aborted.
+**/
+EFI_STATUS
+EFIAPI
+RunCommand(
+ IN CONST CHAR16 *CmdLine
+ )
+{
+ return (RunShellCommand(CmdLine, NULL));
+}
+
+
+STATIC CONST UINT16 InvalidChars[] = {L'*', L'?', L'<', L'>', L'\\', L'/', L'\"', 0x0001, 0x0002};
+/**
+ Function determines if the CommandName COULD be a valid command. It does not determine whether
+ this is a valid command. It only checks for invalid characters.
+
+ @param[in] CommandName The name to check
+
+ @retval TRUE CommandName could be a command name
+ @retval FALSE CommandName could not be a valid command name
+**/
+BOOLEAN
+EFIAPI
+IsValidCommandName(
+ IN CONST CHAR16 *CommandName
+ )
+{
+ UINTN Count;
+ if (CommandName == NULL) {
+ ASSERT(FALSE);
+ return (FALSE);
+ }
+ for ( Count = 0
+ ; Count < sizeof(InvalidChars) / sizeof(InvalidChars[0])
+ ; Count++
+ ){
+ if (ScanMem16(CommandName, StrSize(CommandName), InvalidChars[Count]) != NULL) {
+ return (FALSE);
+ }
+ }
+ return (TRUE);
+}
+
+/**
+ Function to process a NSH script file via SHELL_FILE_HANDLE.
+
+ @param[in] Handle The handle to the already opened file.
+ @param[in] Name The name of the script file.
+
+ @retval EFI_SUCCESS the script completed successfully
+**/
+EFI_STATUS
+EFIAPI
+RunScriptFileHandle (
+ IN SHELL_FILE_HANDLE Handle,
+ IN CONST CHAR16 *Name
+ )
+{
+ EFI_STATUS Status;
+ SCRIPT_FILE *NewScriptFile;
+ UINTN LoopVar;
+ UINTN PrintBuffSize;
+ CHAR16 *CommandLine;
+ CHAR16 *CommandLine2;
+ CHAR16 *CommandLine3;
+ SCRIPT_COMMAND_LIST *LastCommand;
+ BOOLEAN Ascii;
+ BOOLEAN PreScriptEchoState;
+ BOOLEAN PreCommandEchoState;
+ CONST CHAR16 *CurDir;
+ UINTN LineCount;
+ CHAR16 LeString[50];
+ LIST_ENTRY OldBufferList;
+
+ ASSERT(!ShellCommandGetScriptExit());
+
+ PreScriptEchoState = ShellCommandGetEchoState();
+ PrintBuffSize = PcdGet16(PcdShellPrintBufferSize);
+
+ NewScriptFile = (SCRIPT_FILE*)AllocateZeroPool(sizeof(SCRIPT_FILE));
+ if (NewScriptFile == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ //
+ // Set up the name
+ //
+ ASSERT(NewScriptFile->ScriptName == NULL);
+ NewScriptFile->ScriptName = StrnCatGrow(&NewScriptFile->ScriptName, NULL, Name, 0);
+ if (NewScriptFile->ScriptName == NULL) {
+ DeleteScriptFileStruct(NewScriptFile);
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ //
+ // Save the parameters (used to replace %0 to %9 later on)
+ //
+ NewScriptFile->Argc = ShellInfoObject.NewShellParametersProtocol->Argc;
+ if (NewScriptFile->Argc != 0) {
+ NewScriptFile->Argv = (CHAR16**)AllocateZeroPool(NewScriptFile->Argc * sizeof(CHAR16*));
+ if (NewScriptFile->Argv == NULL) {
+ DeleteScriptFileStruct(NewScriptFile);
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ for (LoopVar = 0 ; LoopVar < 10 && LoopVar < NewScriptFile->Argc; LoopVar++) {
+ ASSERT(NewScriptFile->Argv[LoopVar] == NULL);
+ NewScriptFile->Argv[LoopVar] = StrnCatGrow(&NewScriptFile->Argv[LoopVar], NULL, ShellInfoObject.NewShellParametersProtocol->Argv[LoopVar], 0);
+ if (NewScriptFile->Argv[LoopVar] == NULL) {
+ DeleteScriptFileStruct(NewScriptFile);
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ }
+ } else {
+ NewScriptFile->Argv = NULL;
+ }
+
+ InitializeListHead(&NewScriptFile->CommandList);
+ InitializeListHead(&NewScriptFile->SubstList);
+
+ //
+ // Now build the list of all script commands.
+ //
+ LineCount = 0;
+ while(!ShellFileHandleEof(Handle)) {
+ CommandLine = ShellFileHandleReturnLine(Handle, &Ascii);
+ LineCount++;
+ if (CommandLine == NULL || StrLen(CommandLine) == 0 || CommandLine[0] == '#') {
+ SHELL_FREE_NON_NULL(CommandLine);
+ continue;
+ }
+ NewScriptFile->CurrentCommand = AllocateZeroPool(sizeof(SCRIPT_COMMAND_LIST));
+ if (NewScriptFile->CurrentCommand == NULL) {
+ SHELL_FREE_NON_NULL(CommandLine);
+ DeleteScriptFileStruct(NewScriptFile);
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ NewScriptFile->CurrentCommand->Cl = CommandLine;
+ NewScriptFile->CurrentCommand->Data = NULL;
+ NewScriptFile->CurrentCommand->Line = LineCount;
+
+ InsertTailList(&NewScriptFile->CommandList, &NewScriptFile->CurrentCommand->Link);
+ }
+
+ //
+ // Add this as the topmost script file
+ //
+ ShellCommandSetNewScript (NewScriptFile);
+
+ //
+ // Now enumerate through the commands and run each one.
+ //
+ CommandLine = AllocateZeroPool(PrintBuffSize);
+ if (CommandLine == NULL) {
+ DeleteScriptFileStruct(NewScriptFile);
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ CommandLine2 = AllocateZeroPool(PrintBuffSize);
+ if (CommandLine2 == NULL) {
+ FreePool(CommandLine);
+ DeleteScriptFileStruct(NewScriptFile);
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ for ( NewScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetFirstNode(&NewScriptFile->CommandList)
+ ; !IsNull(&NewScriptFile->CommandList, &NewScriptFile->CurrentCommand->Link)
+ ; // conditional increment in the body of the loop
+ ){
+ ASSERT(CommandLine2 != NULL);
+ StrnCpyS( CommandLine2,
+ PrintBuffSize/sizeof(CHAR16),
+ NewScriptFile->CurrentCommand->Cl,
+ PrintBuffSize/sizeof(CHAR16) - 1
+ );
+
+ SaveBufferList(&OldBufferList);
+
+ //
+ // NULL out comments
+ //
+ for (CommandLine3 = CommandLine2 ; CommandLine3 != NULL && *CommandLine3 != CHAR_NULL ; CommandLine3++) {
+ if (*CommandLine3 == L'^') {
+ if ( *(CommandLine3+1) == L':') {
+ CopyMem(CommandLine3, CommandLine3+1, StrSize(CommandLine3) - sizeof(CommandLine3[0]));
+ } else if (*(CommandLine3+1) == L'#') {
+ CommandLine3++;
+ }
+ } else if (*CommandLine3 == L'#') {
+ *CommandLine3 = CHAR_NULL;
+ }
+ }
+
+ if (CommandLine2 != NULL && StrLen(CommandLine2) >= 1) {
+ //
+ // Due to variability in starting the find and replace action we need to have both buffers the same.
+ //
+ StrnCpyS( CommandLine,
+ PrintBuffSize/sizeof(CHAR16),
+ CommandLine2,
+ PrintBuffSize/sizeof(CHAR16) - 1
+ );
+
+ //
+ // Remove the %0 to %9 from the command line (if we have some arguments)
+ //
+ if (NewScriptFile->Argv != NULL) {
+ switch (NewScriptFile->Argc) {
+ default:
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%9", NewScriptFile->Argv[9], FALSE, FALSE);
+ ASSERT_EFI_ERROR(Status);
+ case 9:
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%8", NewScriptFile->Argv[8], FALSE, FALSE);
+ ASSERT_EFI_ERROR(Status);
+ case 8:
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%7", NewScriptFile->Argv[7], FALSE, FALSE);
+ ASSERT_EFI_ERROR(Status);
+ case 7:
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%6", NewScriptFile->Argv[6], FALSE, FALSE);
+ ASSERT_EFI_ERROR(Status);
+ case 6:
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%5", NewScriptFile->Argv[5], FALSE, FALSE);
+ ASSERT_EFI_ERROR(Status);
+ case 5:
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%4", NewScriptFile->Argv[4], FALSE, FALSE);
+ ASSERT_EFI_ERROR(Status);
+ case 4:
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%3", NewScriptFile->Argv[3], FALSE, FALSE);
+ ASSERT_EFI_ERROR(Status);
+ case 3:
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%2", NewScriptFile->Argv[2], FALSE, FALSE);
+ ASSERT_EFI_ERROR(Status);
+ case 2:
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%1", NewScriptFile->Argv[1], FALSE, FALSE);
+ ASSERT_EFI_ERROR(Status);
+ case 1:
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%0", NewScriptFile->Argv[0], FALSE, FALSE);
+ ASSERT_EFI_ERROR(Status);
+ break;
+ case 0:
+ break;
+ }
+ }
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%1", L"\"\"", FALSE, FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%2", L"\"\"", FALSE, FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%3", L"\"\"", FALSE, FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%4", L"\"\"", FALSE, FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%5", L"\"\"", FALSE, FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%6", L"\"\"", FALSE, FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%7", L"\"\"", FALSE, FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%8", L"\"\"", FALSE, FALSE);
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%9", L"\"\"", FALSE, FALSE);
+
+ StrnCpyS( CommandLine2,
+ PrintBuffSize/sizeof(CHAR16),
+ CommandLine,
+ PrintBuffSize/sizeof(CHAR16) - 1
+ );
+
+ LastCommand = NewScriptFile->CurrentCommand;
+
+ for (CommandLine3 = CommandLine2 ; CommandLine3[0] == L' ' ; CommandLine3++);
+
+ if (CommandLine3 != NULL && CommandLine3[0] == L':' ) {
+ //
+ // This line is a goto target / label
+ //
+ } else {
+ if (CommandLine3 != NULL && StrLen(CommandLine3) > 0) {
+ if (CommandLine3[0] == L'@') {
+ //
+ // We need to save the current echo state
+ // and disable echo for just this command.
+ //
+ PreCommandEchoState = ShellCommandGetEchoState();
+ ShellCommandSetEchoState(FALSE);
+ Status = RunCommand(CommandLine3+1);
+
+ //
+ // If command was "@echo -off" or "@echo -on" then don't restore echo state
+ //
+ if (StrCmp (L"@echo -off", CommandLine3) != 0 &&
+ StrCmp (L"@echo -on", CommandLine3) != 0) {
+ //
+ // Now restore the pre-'@' echo state.
+ //
+ ShellCommandSetEchoState(PreCommandEchoState);
+ }
+ } else {
+ if (ShellCommandGetEchoState()) {
+ CurDir = ShellInfoObject.NewEfiShellProtocol->GetEnv(L"cwd");
+ if (CurDir != NULL && StrLen(CurDir) > 1) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_CURDIR), ShellInfoObject.HiiHandle, CurDir);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_SHELL), ShellInfoObject.HiiHandle);
+ }
+ ShellPrintEx(-1, -1, L"%s\r\n", CommandLine2);
+ }
+ Status = RunCommand(CommandLine3);
+ }
+ }
+
+ if (ShellCommandGetScriptExit()) {
+ //
+ // ShellCommandGetExitCode() always returns a UINT64
+ //
+ UnicodeSPrint(LeString, sizeof(LeString), L"0x%Lx", ShellCommandGetExitCode());
+ DEBUG_CODE(InternalEfiShellSetEnv(L"debuglasterror", LeString, TRUE););
+ InternalEfiShellSetEnv(L"lasterror", LeString, TRUE);
+
+ ShellCommandRegisterExit(FALSE, 0);
+ Status = EFI_SUCCESS;
+ RestoreBufferList(&OldBufferList);
+ break;
+ }
+ if (ShellGetExecutionBreakFlag()) {
+ RestoreBufferList(&OldBufferList);
+ break;
+ }
+ if (EFI_ERROR(Status)) {
+ RestoreBufferList(&OldBufferList);
+ break;
+ }
+ if (ShellCommandGetExit()) {
+ RestoreBufferList(&OldBufferList);
+ break;
+ }
+ }
+ //
+ // If that commend did not update the CurrentCommand then we need to advance it...
+ //
+ if (LastCommand == NewScriptFile->CurrentCommand) {
+ NewScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetNextNode(&NewScriptFile->CommandList, &NewScriptFile->CurrentCommand->Link);
+ if (!IsNull(&NewScriptFile->CommandList, &NewScriptFile->CurrentCommand->Link)) {
+ NewScriptFile->CurrentCommand->Reset = TRUE;
+ }
+ }
+ } else {
+ NewScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetNextNode(&NewScriptFile->CommandList, &NewScriptFile->CurrentCommand->Link);
+ if (!IsNull(&NewScriptFile->CommandList, &NewScriptFile->CurrentCommand->Link)) {
+ NewScriptFile->CurrentCommand->Reset = TRUE;
+ }
+ }
+ RestoreBufferList(&OldBufferList);
+ }
+
+
+ FreePool(CommandLine);
+ FreePool(CommandLine2);
+ ShellCommandSetNewScript (NULL);
+
+ //
+ // Only if this was the last script reset the state.
+ //
+ if (ShellCommandGetCurrentScriptFile()==NULL) {
+ ShellCommandSetEchoState(PreScriptEchoState);
+ }
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to process a NSH script file.
+
+ @param[in] ScriptPath Pointer to the script file name (including file system path).
+ @param[in] Handle the handle of the script file already opened.
+ @param[in] CmdLine the command line to run.
+ @param[in] ParamProtocol the shell parameters protocol pointer
+
+ @retval EFI_SUCCESS the script completed successfully
+**/
+EFI_STATUS
+EFIAPI
+RunScriptFile (
+ IN CONST CHAR16 *ScriptPath,
+ IN SHELL_FILE_HANDLE Handle OPTIONAL,
+ IN CONST CHAR16 *CmdLine,
+ IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol
+ )
+{
+ EFI_STATUS Status;
+ SHELL_FILE_HANDLE FileHandle;
+ UINTN Argc;
+ CHAR16 **Argv;
+
+ if (ShellIsFile(ScriptPath) != EFI_SUCCESS) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ //
+ // get the argc and argv updated for scripts
+ //
+ Status = UpdateArgcArgv(ParamProtocol, CmdLine, Script_File_Name, &Argv, &Argc);
+ if (!EFI_ERROR(Status)) {
+
+ if (Handle == NULL) {
+ //
+ // open the file
+ //
+ Status = ShellOpenFileByName(ScriptPath, &FileHandle, EFI_FILE_MODE_READ, 0);
+ if (!EFI_ERROR(Status)) {
+ //
+ // run it
+ //
+ Status = RunScriptFileHandle(FileHandle, ScriptPath);
+
+ //
+ // now close the file
+ //
+ ShellCloseFile(&FileHandle);
+ }
+ } else {
+ Status = RunScriptFileHandle(Handle, ScriptPath);
+ }
+ }
+
+ //
+ // This is guaranteed to be called after UpdateArgcArgv no matter what else happened.
+ // This is safe even if the update API failed. In this case, it may be a no-op.
+ //
+ RestoreArgcArgv(ParamProtocol, &Argv, &Argc);
+
+ return (Status);
+}
+
diff --git a/Core/ShellPkg/Application/Shell/Shell.h b/Core/ShellPkg/Application/Shell/Shell.h
new file mode 100644
index 0000000000..a34c91ad1e
--- /dev/null
+++ b/Core/ShellPkg/Application/Shell/Shell.h
@@ -0,0 +1,408 @@
+/** @file
+ function definitions for internal to shell functions.
+
+ (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SHELL_INTERNAL_HEADER_
+#define _SHELL_INTERNAL_HEADER_
+
+#include <Uefi.h>
+#include <ShellBase.h>
+
+#include <Guid/ShellVariableGuid.h>
+#include <Guid/ShellAliasGuid.h>
+
+#include <Protocol/LoadedImage.h>
+#include <Protocol/SimpleTextOut.h>
+#include <Protocol/EfiShell.h>
+#include <Protocol/EfiShellInterface.h>
+#include <Protocol/EfiShellEnvironment2.h>
+#include <Protocol/EfiShellParameters.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/HiiPackageList.h>
+
+#include <Library/BaseLib.h>
+#include <Library/UefiApplicationEntryPoint.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/ShellCommandLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/PcdLib.h>
+#include <Library/ShellLib.h>
+#include <Library/SortLib.h>
+#include <Library/HiiLib.h>
+#include <Library/PrintLib.h>
+#include <Library/HandleParsingLib.h>
+#include <Library/FileHandleLib.h>
+#include <Library/UefiHiiServicesLib.h>
+
+#include "ShellParametersProtocol.h"
+#include "ShellProtocol.h"
+#include "ShellEnvVar.h"
+#include "ConsoleLogger.h"
+#include "ShellManParser.h"
+#include "ConsoleWrappers.h"
+#include "FileHandleWrappers.h"
+
+extern CONST CHAR16 mNoNestingEnvVarName[];
+extern CONST CHAR16 mNoNestingTrue[];
+extern CONST CHAR16 mNoNestingFalse[];
+
+typedef struct {
+ LIST_ENTRY Link; ///< Standard linked list handler.
+ SHELL_FILE_HANDLE *SplitStdOut; ///< ConsoleOut for use in the split.
+ SHELL_FILE_HANDLE *SplitStdIn; ///< ConsoleIn for use in the split.
+} SPLIT_LIST;
+
+typedef struct {
+ UINT32 Startup:1; ///< Was "-startup" found on command line.
+ UINT32 NoStartup:1; ///< Was "-nostartup" found on command line.
+ UINT32 NoConsoleOut:1; ///< Was "-noconsoleout" found on command line.
+ UINT32 NoConsoleIn:1; ///< Was "-noconsolein" found on command line.
+ UINT32 NoInterrupt:1; ///< Was "-nointerrupt" found on command line.
+ UINT32 NoMap:1; ///< Was "-nomap" found on command line.
+ UINT32 NoVersion:1; ///< Was "-noversion" found on command line.
+ UINT32 Delay:1; ///< Was "-delay[:n] found on command line
+ UINT32 Exit:1; ///< Was "-_exit" found on command line
+ UINT32 NoNest:1; ///< Was "-nonest" found on command line
+ UINT32 Reserved:7; ///< Extra bits
+} SHELL_BITS;
+
+typedef union {
+ SHELL_BITS Bits;
+ UINT16 AllBits;
+} SHELL_BIT_UNION;
+
+typedef struct {
+ SHELL_BIT_UNION BitUnion;
+ UINTN Delay; ///< Seconds of delay default:5.
+ CHAR16 *FileName; ///< Filename to run upon successful initialization.
+ CHAR16 *FileOptions; ///< Options to pass to FileName.
+} SHELL_INIT_SETTINGS;
+
+typedef struct {
+ BUFFER_LIST CommandHistory;
+ UINTN VisibleRowNumber;
+ UINTN OriginalVisibleRowNumber;
+ BOOLEAN InsertMode; ///< Is the current typing mode insert (FALSE = overwrite).
+} SHELL_VIEWING_SETTINGS;
+
+typedef struct {
+ EFI_SHELL_PARAMETERS_PROTOCOL *NewShellParametersProtocol;
+ EFI_SHELL_PROTOCOL *NewEfiShellProtocol;
+ BOOLEAN PageBreakEnabled;
+ BOOLEAN RootShellInstance;
+ SHELL_INIT_SETTINGS ShellInitSettings;
+ BUFFER_LIST BufferToFreeList; ///< List of buffers that were returned to the user to free.
+ SHELL_VIEWING_SETTINGS ViewingSettings;
+ EFI_HII_HANDLE HiiHandle; ///< Handle from HiiLib.
+ UINTN LogScreenCount; ///< How many screens of log information to save.
+ EFI_EVENT UserBreakTimer; ///< Timer event for polling for CTRL-C.
+ EFI_DEVICE_PATH_PROTOCOL *ImageDevPath; ///< DevicePath for ourselves.
+ EFI_DEVICE_PATH_PROTOCOL *FileDevPath; ///< DevicePath for ourselves.
+ CONSOLE_LOGGER_PRIVATE_DATA *ConsoleInfo; ///< Pointer for ConsoleInformation.
+ EFI_SHELL_PARAMETERS_PROTOCOL *OldShellParameters; ///< old shell parameters to reinstall upon exiting.
+ SHELL_PROTOCOL_HANDLE_LIST OldShellList; ///< List of other instances to reinstall when closing.
+ SPLIT_LIST SplitList; ///< List of Splits in FILO stack.
+ VOID *CtrlCNotifyHandle1; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify.
+ VOID *CtrlCNotifyHandle2; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify.
+ VOID *CtrlCNotifyHandle3; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify.
+ VOID *CtrlCNotifyHandle4; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify.
+ VOID *CtrlSNotifyHandle1; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify.
+ VOID *CtrlSNotifyHandle2; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify.
+ VOID *CtrlSNotifyHandle3; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify.
+ VOID *CtrlSNotifyHandle4; ///< The NotifyHandle returned from SimpleTextInputEx.RegisterKeyNotify.
+ BOOLEAN HaltOutput; ///< TRUE to start a CTRL-S halt.
+} SHELL_INFO;
+
+#pragma pack(1)
+///
+/// HII specific Vendor Device Path definition.
+///
+typedef struct {
+ VENDOR_DEVICE_PATH VendorDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL End;
+} SHELL_MAN_HII_VENDOR_DEVICE_PATH;
+#pragma pack()
+
+extern SHELL_INFO ShellInfoObject;
+
+/**
+ Converts the command line to it's post-processed form. this replaces variables and alias' per UEFI Shell spec.
+
+ @param[in,out] CmdLine pointer to the command line to update
+
+ @retval EFI_SUCCESS The operation was successful
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @return some other error occurred
+**/
+EFI_STATUS
+EFIAPI
+ProcessCommandLineToFinal(
+ IN OUT CHAR16 **CmdLine
+ );
+
+/**
+ Function to update the shell variable "lasterror".
+
+ @param[in] ErrorCode the error code to put into lasterror
+**/
+EFI_STATUS
+EFIAPI
+SetLastError(
+ IN CONST SHELL_STATUS ErrorCode
+ );
+
+/**
+ Sets all the alias' that were registered with the ShellCommandLib library.
+
+ @retval EFI_SUCCESS all init commands were run successfully.
+**/
+EFI_STATUS
+EFIAPI
+SetBuiltInAlias(
+ VOID
+ );
+
+/**
+ This function will populate the 2 device path protocol parameters based on the
+ global gImageHandle. the DevPath will point to the device path for the handle that has
+ loaded image protocol installed on it. the FilePath will point to the device path
+ for the file that was loaded.
+
+ @param[in, out] DevPath on a successful return the device path to the loaded image
+ @param[in, out] FilePath on a successful return the device path to the file
+
+ @retval EFI_SUCCESS the 2 device paths were successfully returned.
+ @return other a error from gBS->HandleProtocol
+
+ @sa HandleProtocol
+**/
+EFI_STATUS
+EFIAPI
+GetDevicePathsForImageAndFile (
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevPath,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath
+ );
+
+/**
+ Process all Uefi Shell 2.0 command line options.
+
+ see Uefi Shell 2.0 section 3.2 for full details.
+
+ the command line should resemble the following:
+
+ shell.efi [ShellOpt-options] [options] [file-name [file-name-options]]
+
+ ShellOpt options Options which control the initialization behavior of the shell.
+ These options are read from the EFI global variable "ShellOpt"
+ and are processed before options or file-name.
+
+ options Options which control the initialization behavior of the shell.
+
+ file-name The name of a UEFI shell application or script to be executed
+ after initialization is complete. By default, if file-name is
+ specified, then -nostartup is implied. Scripts are not supported
+ by level 0.
+
+ file-nameoptions The command-line options that are passed to file-name when it
+ is invoked.
+
+ This will initialize the ShellInitSettings global variable.
+
+ @retval EFI_SUCCESS the variable is initialized.
+**/
+EFI_STATUS
+EFIAPI
+ProcessCommandLine(
+ VOID
+ );
+
+/**
+ Handles all interaction with the default startup script.
+
+ this will check that the correct command line parameters were passed, handle the delay, and then start running the script.
+
+ @param[in] ImagePath The path to the image for shell. The first place to look for the startup script.
+ @param[in] FilePath The path to the file for shell. The second place to look for the startup script.
+
+ @retval EFI_SUCCESS The variable is initialized.
+**/
+EFI_STATUS
+EFIAPI
+DoStartupScript(
+ IN EFI_DEVICE_PATH_PROTOCOL *ImagePath,
+ IN EFI_DEVICE_PATH_PROTOCOL *FilePath
+ );
+
+/**
+ Function to perform the shell prompt looping. It will do a single prompt,
+ dispatch the result, and then return. It is expected that the caller will
+ call this function in a loop many times.
+
+ @retval EFI_SUCCESS
+ @retval RETURN_ABORTED
+**/
+EFI_STATUS
+EFIAPI
+DoShellPrompt (
+ VOID
+ );
+
+/**
+ Add a buffer to the Buffer To Free List for safely returning buffers to other
+ places without risking letting them modify internal shell information.
+
+ @param Buffer Something to pass to FreePool when the shell is exiting.
+**/
+VOID*
+EFIAPI
+AddBufferToFreeList(
+ VOID *Buffer
+ );
+
+/**
+ Add a buffer to the Command History List.
+
+ @param Buffer[in] The line buffer to add.
+**/
+VOID
+EFIAPI
+AddLineToCommandHistory(
+ IN CONST CHAR16 *Buffer
+ );
+
+/**
+ Function will process and run a command line.
+
+ This will determine if the command line represents an internal shell command or dispatch an external application.
+
+ @param[in] CmdLine the command line to parse
+
+ @retval EFI_SUCCESS the command was completed
+ @retval EFI_ABORTED the command's operation was aborted
+**/
+EFI_STATUS
+EFIAPI
+RunCommand(
+ IN CONST CHAR16 *CmdLine
+ );
+
+/**
+ Function will process and run a command line.
+
+ This will determine if the command line represents an internal shell
+ command or dispatch an external application.
+
+ @param[in] CmdLine The command line to parse.
+ @param[out] CommandStatus The status from the command line.
+
+ @retval EFI_SUCCESS The command was completed.
+ @retval EFI_ABORTED The command's operation was aborted.
+**/
+EFI_STATUS
+EFIAPI
+RunShellCommand(
+ IN CONST CHAR16 *CmdLine,
+ OUT EFI_STATUS *CommandStatus
+ );
+
+/**
+ Function determines if the CommandName COULD be a valid command. It does not determine whether
+ this is a valid command. It only checks for invalid characters.
+
+ @param[in] CommandName The name to check
+
+ @retval TRUE CommandName could be a command name
+ @retval FALSE CommandName could not be a valid command name
+**/
+BOOLEAN
+EFIAPI
+IsValidCommandName(
+ IN CONST CHAR16 *CommandName
+ );
+
+/**
+ Function to process a NSH script file via SHELL_FILE_HANDLE.
+
+ @param[in] Handle The handle to the already opened file.
+ @param[in] Name The name of the script file.
+
+ @retval EFI_SUCCESS the script completed successfully
+**/
+EFI_STATUS
+EFIAPI
+RunScriptFileHandle (
+ IN SHELL_FILE_HANDLE Handle,
+ IN CONST CHAR16 *Name
+ );
+
+/**
+ Function to process a NSH script file.
+
+ @param[in] ScriptPath Pointer to the script file name (including file system path).
+ @param[in] Handle the handle of the script file already opened.
+ @param[in] CmdLine the command line to run.
+ @param[in] ParamProtocol the shell parameters protocol pointer
+
+ @retval EFI_SUCCESS the script completed successfully
+**/
+EFI_STATUS
+EFIAPI
+RunScriptFile (
+ IN CONST CHAR16 *ScriptPath,
+ IN SHELL_FILE_HANDLE Handle OPTIONAL,
+ IN CONST CHAR16 *CmdLine,
+ IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol
+ );
+
+/**
+ Cleans off leading and trailing spaces and tabs.
+
+ @param[in] String pointer to the string to trim them off.
+**/
+EFI_STATUS
+EFIAPI
+TrimSpaces(
+ IN CHAR16 **String
+ );
+
+/**
+
+ Create a new buffer list and stores the old one to OldBufferList
+
+ @param OldBufferList The temporary list head used to store the nodes in BufferToFreeList.
+**/
+VOID
+SaveBufferList (
+ OUT LIST_ENTRY *OldBufferList
+ );
+
+/**
+ Restore previous nodes into BufferToFreeList .
+
+ @param OldBufferList The temporary list head used to store the nodes in BufferToFreeList.
+**/
+VOID
+RestoreBufferList (
+ IN OUT LIST_ENTRY *OldBufferList
+ );
+
+
+
+#endif //_SHELL_INTERNAL_HEADER_
+
diff --git a/Core/ShellPkg/Application/Shell/Shell.inf b/Core/ShellPkg/Application/Shell/Shell.inf
new file mode 100644
index 0000000000..a1b6a24e87
--- /dev/null
+++ b/Core/ShellPkg/Application/Shell/Shell.inf
@@ -0,0 +1,112 @@
+## @file
+# This is the shell application
+#
+# (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR>
+# Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = Shell
+ FILE_GUID = 7C04A583-9E3E-4f1c-AD65-E05268D0B4D1
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ ENTRY_POINT = UefiMain
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ Shell.c
+ Shell.h
+ ShellParametersProtocol.c
+ ShellParametersProtocol.h
+ ShellProtocol.c
+ ShellProtocol.h
+ FileHandleWrappers.c
+ FileHandleWrappers.h
+ FileHandleInternal.h
+ ShellEnvVar.c
+ ShellEnvVar.h
+ ShellManParser.c
+ ShellManParser.h
+ Shell.uni
+ ConsoleLogger.c
+ ConsoleLogger.h
+ ConsoleWrappers.c
+ ConsoleWrappers.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ BaseLib
+ UefiApplicationEntryPoint
+ UefiLib
+ DebugLib
+ MemoryAllocationLib
+ ShellCommandLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ DevicePathLib
+ BaseMemoryLib
+ PcdLib
+ FileHandleLib
+ PrintLib
+ HiiLib
+ SortLib
+ HandleParsingLib
+ UefiHiiServicesLib
+
+[Guids]
+ gShellVariableGuid ## SOMETIMES_CONSUMES ## GUID
+ gShellAliasGuid ## SOMETIMES_CONSUMES ## GUID
+ gShellAliasGuid ## SOMETIMES_PRODUCES ## GUID
+
+[Protocols]
+ gEfiShellProtocolGuid ## PRODUCES
+ ## SOMETIMES_CONSUMES
+ gEfiShellParametersProtocolGuid ## PRODUCES
+ ## SOMETIMES_CONSUMES
+
+# gEfiShellEnvironment2Guid ## SOMETIMES_PRODUCES
+# gEfiShellInterfaceGuid ## SOMETIMES_PRODUCES
+
+ gEfiSimpleTextInputExProtocolGuid ## CONSUMES
+ gEfiSimpleTextInProtocolGuid ## CONSUMES
+ gEfiSimpleTextOutProtocolGuid ## CONSUMES
+ gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiLoadedImageProtocolGuid ## CONSUMES
+ gEfiComponentName2ProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiUnicodeCollation2ProtocolGuid ## CONSUMES
+ gEfiDevicePathProtocolGuid ## CONSUMES
+ gEfiHiiPackageListProtocolGuid ## SOMETIMES_PRODUCES
+
+[Pcd]
+ gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel ## CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdShellSupportOldProtocols ## CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdShellRequireHiiPlatform ## CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdShellSupportFrameworkHii ## CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdShellPageBreakDefault ## CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize ## CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdShellInsertModeDefault ## CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdShellScreenLogCount ## CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdShellMapNameLength ## CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdShellPrintBufferSize ## CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdShellForceConsole ## CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdShellSupplier ## CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdShellMaxHistoryCommandCount ## CONSUMES
diff --git a/Core/ShellPkg/Application/Shell/Shell.uni b/Core/ShellPkg/Application/Shell/Shell.uni
new file mode 100644
index 0000000000..ef69f891d2
--- /dev/null
+++ b/Core/ShellPkg/Application/Shell/Shell.uni
@@ -0,0 +1,58 @@
+// *++
+//
+// (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
+// Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved. <BR>
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// Module Name:
+//
+// ShellStrings.uni
+//
+// Abstract:
+//
+// String definitions for the main UEFI Shell 2.0 application
+//
+// Revision History:
+//
+// --*/
+
+/=#
+
+#langdef en-US "English"
+
+#string STR_SHELL_CURDIR #language en-US "%E%s\> %N"
+#string STR_GEN_PROBLEM #language en-US "The argument '%B%s%N' is incorrect.\r\n"
+#string STR_SHELL_SHELL #language en-US "%EShell> %N"
+
+#string STR_SHELL_STARTUP_QUESTION #language en-US "%NPress %HESC%N in %d seconds to skip %Estartup.nsh%N or any other key to continue."
+
+#string STR_SHELL_ENTER_TO_CONT #language en-US "%NPress ENTER to continue:%E"
+#string STR_SHELL_QUIT_CONT #language en-US "%NPress ENTER to continue or 'Q' break:%E"
+
+#string STR_SHELL_NOT_FOUND #language en-US "%N'%E%s%N' is not recognized as an internal or external command, operable program, or script file.\r\n"
+
+#string STR_SHELL_CRLF #language en-US "\r\n"
+
+#string STR_SHELL_ERROR #language en-US "%NCommand Error Status: %r\r\n"
+#string STR_SHELL_ERROR_SCRIPT #language en-US "%NScript Error Status: %r (line number %d)\r\n"
+
+#string STR_SHELL_INVALID_MAPPING #language en-US "%N'%B%s%N' is not a valid mapping.\r\n"
+#string STR_SHELL_INVALID_SPLIT #language en-US "Invalid use of pipe (%B|%N).\r\n"
+
+#string STR_SHELL_INVALID_REDIR #language en-US "Unable to redirect file.\r\n"
+#string STR_SHELL_REDUNDA_REDIR #language en-US "Redundant redirection specified.\r\n"
+
+#string STR_VER_OUTPUT_MAIN_SHELL #language en-US "UEFI %s Shell v%d.%d\r\n"
+#string STR_VER_OUTPUT_MAIN_SUPPLIER #language en-US "%s\r\n"
+#string STR_VER_OUTPUT_MAIN_UEFI #language en-US "UEFI v%d.%02d (%s, 0x%08x)\r\n"
+
+#string STR_SHELL_NO_IN_EX #language en-US "No SimpleTextInputEx was found. CTRL-based features are not usable.\r\n"
+
+#string STR_SHELL_IMAGE_NOT_APP #language en-US "The image is not an application.\r\n"
+
diff --git a/Core/ShellPkg/Application/Shell/ShellEnvVar.c b/Core/ShellPkg/Application/Shell/ShellEnvVar.c
new file mode 100644
index 0000000000..77bf599eab
--- /dev/null
+++ b/Core/ShellPkg/Application/Shell/ShellEnvVar.c
@@ -0,0 +1,576 @@
+/** @file
+ function declarations for shell environment functions.
+
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Shell.h"
+
+#define INIT_NAME_BUFFER_SIZE 128
+#define INIT_DATA_BUFFER_SIZE 1024
+
+//
+// The list is used to cache the environment variables.
+//
+ENV_VAR_LIST gShellEnvVarList;
+
+/**
+ Reports whether an environment variable is Volatile or Non-Volatile.
+
+ @param EnvVarName The name of the environment variable in question
+ @param Volatile Return TRUE if the environment variable is volatile
+
+ @retval EFI_SUCCESS The volatile attribute is returned successfully
+ @retval others Some errors happened.
+**/
+EFI_STATUS
+IsVolatileEnv (
+ IN CONST CHAR16 *EnvVarName,
+ OUT BOOLEAN *Volatile
+ )
+{
+ EFI_STATUS Status;
+ UINTN Size;
+ VOID *Buffer;
+ UINT32 Attribs;
+
+ ASSERT (Volatile != NULL);
+
+ Size = 0;
+ Buffer = NULL;
+
+ //
+ // get the variable
+ //
+ Status = gRT->GetVariable((CHAR16*)EnvVarName,
+ &gShellVariableGuid,
+ &Attribs,
+ &Size,
+ Buffer);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ Buffer = AllocateZeroPool(Size);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = gRT->GetVariable((CHAR16*)EnvVarName,
+ &gShellVariableGuid,
+ &Attribs,
+ &Size,
+ Buffer);
+ FreePool(Buffer);
+ }
+ //
+ // not found means volatile
+ //
+ if (Status == EFI_NOT_FOUND) {
+ *Volatile = TRUE;
+ return EFI_SUCCESS;
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // check for the Non Volatile bit
+ //
+ *Volatile = !(BOOLEAN) ((Attribs & EFI_VARIABLE_NON_VOLATILE) == EFI_VARIABLE_NON_VOLATILE);
+ return EFI_SUCCESS;
+}
+
+/**
+ free function for ENV_VAR_LIST objects.
+
+ @param[in] List The pointer to pointer to list.
+**/
+VOID
+EFIAPI
+FreeEnvironmentVariableList(
+ IN LIST_ENTRY *List
+ )
+{
+ ENV_VAR_LIST *Node;
+
+ ASSERT (List != NULL);
+ if (List == NULL) {
+ return;
+ }
+
+ for ( Node = (ENV_VAR_LIST*)GetFirstNode(List)
+ ; !IsListEmpty(List)
+ ; Node = (ENV_VAR_LIST*)GetFirstNode(List)
+ ){
+ ASSERT(Node != NULL);
+ RemoveEntryList(&Node->Link);
+ if (Node->Key != NULL) {
+ FreePool(Node->Key);
+ }
+ if (Node->Val != NULL) {
+ FreePool(Node->Val);
+ }
+ FreePool(Node);
+ }
+}
+
+/**
+ Creates a list of all Shell-Guid-based environment variables.
+
+ @param[in, out] ListHead The pointer to pointer to LIST ENTRY object for
+ storing this list.
+
+ @retval EFI_SUCCESS the list was created sucessfully.
+**/
+EFI_STATUS
+EFIAPI
+GetEnvironmentVariableList(
+ IN OUT LIST_ENTRY *ListHead
+ )
+{
+ CHAR16 *VariableName;
+ UINTN NameSize;
+ UINTN NameBufferSize;
+ EFI_STATUS Status;
+ EFI_GUID Guid;
+ UINTN ValSize;
+ UINTN ValBufferSize;
+ ENV_VAR_LIST *VarList;
+
+ if (ListHead == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ Status = EFI_SUCCESS;
+
+ ValBufferSize = INIT_DATA_BUFFER_SIZE;
+ NameBufferSize = INIT_NAME_BUFFER_SIZE;
+ VariableName = AllocateZeroPool(NameBufferSize);
+ if (VariableName == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ *VariableName = CHAR_NULL;
+
+ while (!EFI_ERROR(Status)) {
+ NameSize = NameBufferSize;
+ Status = gRT->GetNextVariableName(&NameSize, VariableName, &Guid);
+ if (Status == EFI_NOT_FOUND){
+ Status = EFI_SUCCESS;
+ break;
+ } else if (Status == EFI_BUFFER_TOO_SMALL) {
+ NameBufferSize = NameSize > NameBufferSize * 2 ? NameSize : NameBufferSize * 2;
+ SHELL_FREE_NON_NULL(VariableName);
+ VariableName = AllocateZeroPool(NameBufferSize);
+ if (VariableName == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ }
+ NameSize = NameBufferSize;
+ Status = gRT->GetNextVariableName(&NameSize, VariableName, &Guid);
+ }
+
+ if (!EFI_ERROR(Status) && CompareGuid(&Guid, &gShellVariableGuid)){
+ VarList = AllocateZeroPool(sizeof(ENV_VAR_LIST));
+ if (VarList == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ ValSize = ValBufferSize;
+ VarList->Val = AllocateZeroPool(ValSize);
+ if (VarList->Val == NULL) {
+ SHELL_FREE_NON_NULL(VarList);
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ }
+ Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(VariableName, &VarList->Atts, &ValSize, VarList->Val);
+ if (Status == EFI_BUFFER_TOO_SMALL){
+ ValBufferSize = ValSize > ValBufferSize * 2 ? ValSize : ValBufferSize * 2;
+ SHELL_FREE_NON_NULL (VarList->Val);
+ VarList->Val = AllocateZeroPool(ValBufferSize);
+ if (VarList->Val == NULL) {
+ SHELL_FREE_NON_NULL(VarList);
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ }
+
+ ValSize = ValBufferSize;
+ Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(VariableName, &VarList->Atts, &ValSize, VarList->Val);
+ }
+ if (!EFI_ERROR(Status)) {
+ VarList->Key = AllocateCopyPool(StrSize(VariableName), VariableName);
+ if (VarList->Key == NULL) {
+ SHELL_FREE_NON_NULL(VarList->Val);
+ SHELL_FREE_NON_NULL(VarList);
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ InsertTailList(ListHead, &VarList->Link);
+ }
+ } else {
+ SHELL_FREE_NON_NULL(VarList->Val);
+ SHELL_FREE_NON_NULL(VarList);
+ }
+ } // if (VarList == NULL) ... else ...
+ } // compare guid
+ } // while
+ SHELL_FREE_NON_NULL (VariableName);
+
+ if (EFI_ERROR(Status)) {
+ FreeEnvironmentVariableList(ListHead);
+ }
+
+ return (Status);
+}
+
+/**
+ Sets a list of all Shell-Guid-based environment variables. this will
+ also eliminate all existing shell environment variables (even if they
+ are not on the list).
+
+ This function will also deallocate the memory from List.
+
+ @param[in] ListHead The pointer to LIST_ENTRY from
+ GetShellEnvVarList().
+
+ @retval EFI_SUCCESS the list was Set sucessfully.
+**/
+EFI_STATUS
+EFIAPI
+SetEnvironmentVariableList(
+ IN LIST_ENTRY *ListHead
+ )
+{
+ ENV_VAR_LIST VarList;
+ ENV_VAR_LIST *Node;
+ EFI_STATUS Status;
+ UINTN Size;
+
+ InitializeListHead(&VarList.Link);
+
+ //
+ // Delete all the current environment variables
+ //
+ Status = GetEnvironmentVariableList(&VarList.Link);
+ ASSERT_EFI_ERROR(Status);
+
+ for ( Node = (ENV_VAR_LIST*)GetFirstNode(&VarList.Link)
+ ; !IsNull(&VarList.Link, &Node->Link)
+ ; Node = (ENV_VAR_LIST*)GetNextNode(&VarList.Link, &Node->Link)
+ ){
+ if (Node->Key != NULL) {
+ Status = SHELL_DELETE_ENVIRONMENT_VARIABLE(Node->Key);
+ }
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ FreeEnvironmentVariableList(&VarList.Link);
+
+ //
+ // set all the variables fron the list
+ //
+ for ( Node = (ENV_VAR_LIST*)GetFirstNode(ListHead)
+ ; !IsNull(ListHead, &Node->Link)
+ ; Node = (ENV_VAR_LIST*)GetNextNode(ListHead, &Node->Link)
+ ){
+ Size = StrSize(Node->Val);
+ if (Node->Atts & EFI_VARIABLE_NON_VOLATILE) {
+ Status = SHELL_SET_ENVIRONMENT_VARIABLE_NV(Node->Key, Size, Node->Val);
+ } else {
+ Status = SHELL_SET_ENVIRONMENT_VARIABLE_V (Node->Key, Size, Node->Val);
+ }
+ ASSERT_EFI_ERROR(Status);
+ }
+ FreeEnvironmentVariableList(ListHead);
+
+ return (Status);
+}
+
+/**
+ sets a list of all Shell-Guid-based environment variables.
+
+ @param Environment Points to a NULL-terminated array of environment
+ variables with the format 'x=y', where x is the
+ environment variable name and y is the value.
+
+ @retval EFI_SUCCESS The command executed successfully.
+ @retval EFI_INVALID_PARAMETER The parameter is invalid.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+
+ @sa SetEnvironmentVariableList
+**/
+EFI_STATUS
+EFIAPI
+SetEnvironmentVariables(
+ IN CONST CHAR16 **Environment
+ )
+{
+ CONST CHAR16 *CurrentString;
+ UINTN CurrentCount;
+ ENV_VAR_LIST *VarList;
+ ENV_VAR_LIST *Node;
+
+ VarList = NULL;
+
+ if (Environment == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ //
+ // Build a list identical to the ones used for get/set list functions above
+ //
+ for ( CurrentCount = 0
+ ;
+ ; CurrentCount++
+ ){
+ CurrentString = Environment[CurrentCount];
+ if (CurrentString == NULL) {
+ break;
+ }
+ ASSERT(StrStr(CurrentString, L"=") != NULL);
+ Node = AllocateZeroPool(sizeof(ENV_VAR_LIST));
+ if (Node == NULL) {
+ SetEnvironmentVariableList(&VarList->Link);
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ Node->Key = AllocateZeroPool((StrStr(CurrentString, L"=") - CurrentString + 1) * sizeof(CHAR16));
+ if (Node->Key == NULL) {
+ SHELL_FREE_NON_NULL(Node);
+ SetEnvironmentVariableList(&VarList->Link);
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ //
+ // Copy the string into the Key, leaving the last character allocated as NULL to terminate
+ //
+ StrnCpyS( Node->Key,
+ StrStr(CurrentString, L"=") - CurrentString + 1,
+ CurrentString,
+ StrStr(CurrentString, L"=") - CurrentString
+ );
+
+ //
+ // ValueSize = TotalSize - already removed size - size for '=' + size for terminator (the last 2 items cancel each other)
+ //
+ Node->Val = AllocateCopyPool(StrSize(CurrentString) - StrSize(Node->Key), CurrentString + StrLen(Node->Key) + 1);
+ if (Node->Val == NULL) {
+ SHELL_FREE_NON_NULL(Node->Key);
+ SHELL_FREE_NON_NULL(Node);
+ SetEnvironmentVariableList(&VarList->Link);
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ Node->Atts = EFI_VARIABLE_BOOTSERVICE_ACCESS;
+
+ if (VarList == NULL) {
+ VarList = AllocateZeroPool(sizeof(ENV_VAR_LIST));
+ if (VarList == NULL) {
+ SHELL_FREE_NON_NULL(Node->Key);
+ SHELL_FREE_NON_NULL(Node->Val);
+ SHELL_FREE_NON_NULL(Node);
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ InitializeListHead(&VarList->Link);
+ }
+ InsertTailList(&VarList->Link, &Node->Link);
+
+ } // for loop
+
+ //
+ // set this new list as the set of all environment variables.
+ // this function also frees the memory and deletes all pre-existing
+ // shell-guid based environment variables.
+ //
+ return (SetEnvironmentVariableList(&VarList->Link));
+}
+
+/**
+ Find an environment variable in the gShellEnvVarList.
+
+ @param Key The name of the environment variable.
+ @param Value The value of the environment variable, the buffer
+ shoule be freed by the caller.
+ @param ValueSize The size in bytes of the environment variable
+ including the tailing CHAR_NELL.
+ @param Atts The attributes of the variable.
+
+ @retval EFI_SUCCESS The command executed successfully.
+ @retval EFI_NOT_FOUND The environment variable is not found in
+ gShellEnvVarList.
+
+**/
+EFI_STATUS
+ShellFindEnvVarInList (
+ IN CONST CHAR16 *Key,
+ OUT CHAR16 **Value,
+ OUT UINTN *ValueSize,
+ OUT UINT32 *Atts OPTIONAL
+ )
+{
+ ENV_VAR_LIST *Node;
+
+ if (Key == NULL || Value == NULL || ValueSize == NULL) {
+ return SHELL_INVALID_PARAMETER;
+ }
+
+ for ( Node = (ENV_VAR_LIST*)GetFirstNode(&gShellEnvVarList.Link)
+ ; !IsNull(&gShellEnvVarList.Link, &Node->Link)
+ ; Node = (ENV_VAR_LIST*)GetNextNode(&gShellEnvVarList.Link, &Node->Link)
+ ){
+ if (Node->Key != NULL && StrCmp(Key, Node->Key) == 0) {
+ *Value = AllocateCopyPool(StrSize(Node->Val), Node->Val);
+ *ValueSize = StrSize(Node->Val);
+ if (Atts != NULL) {
+ *Atts = Node->Atts;
+ }
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Add an environment variable into gShellEnvVarList.
+
+ @param Key The name of the environment variable.
+ @param Value The value of environment variable.
+ @param ValueSize The size in bytes of the environment variable
+ including the tailing CHAR_NULL
+ @param Atts The attributes of the variable.
+
+ @retval EFI_SUCCESS The environment variable was added to list successfully.
+ @retval others Some errors happened.
+
+**/
+EFI_STATUS
+ShellAddEnvVarToList (
+ IN CONST CHAR16 *Key,
+ IN CONST CHAR16 *Value,
+ IN UINTN ValueSize,
+ IN UINT32 Atts
+ )
+{
+ ENV_VAR_LIST *Node;
+ CHAR16 *LocalKey;
+ CHAR16 *LocalValue;
+
+ if (Key == NULL || Value == NULL || ValueSize == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ LocalValue = AllocateCopyPool (ValueSize, Value);
+ if (LocalValue == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Update the variable value if it exists in gShellEnvVarList.
+ //
+ for ( Node = (ENV_VAR_LIST*)GetFirstNode(&gShellEnvVarList.Link)
+ ; !IsNull(&gShellEnvVarList.Link, &Node->Link)
+ ; Node = (ENV_VAR_LIST*)GetNextNode(&gShellEnvVarList.Link, &Node->Link)
+ ){
+ if (Node->Key != NULL && StrCmp(Key, Node->Key) == 0) {
+ Node->Atts = Atts;
+ SHELL_FREE_NON_NULL(Node->Val);
+ Node->Val = LocalValue;
+ return EFI_SUCCESS;
+ }
+ }
+
+ //
+ // If the environment varialbe key doesn't exist in list just insert
+ // a new node.
+ //
+ LocalKey = AllocateCopyPool (StrSize(Key), Key);
+ if (LocalKey == NULL) {
+ FreePool (LocalValue);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Node = (ENV_VAR_LIST*)AllocateZeroPool (sizeof(ENV_VAR_LIST));
+ if (Node == NULL) {
+ FreePool (LocalKey);
+ FreePool (LocalValue);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Node->Key = LocalKey;
+ Node->Val = LocalValue;
+ Node->Atts = Atts;
+ InsertTailList(&gShellEnvVarList.Link, &Node->Link);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Remove a specified environment variable in gShellEnvVarList.
+
+ @param Key The name of the environment variable.
+
+ @retval EFI_SUCCESS The command executed successfully.
+ @retval EFI_NOT_FOUND The environment variable is not found in
+ gShellEnvVarList.
+**/
+EFI_STATUS
+ShellRemvoeEnvVarFromList (
+ IN CONST CHAR16 *Key
+ )
+{
+ ENV_VAR_LIST *Node;
+
+ if (Key == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ for ( Node = (ENV_VAR_LIST*)GetFirstNode(&gShellEnvVarList.Link)
+ ; !IsNull(&gShellEnvVarList.Link, &Node->Link)
+ ; Node = (ENV_VAR_LIST*)GetNextNode(&gShellEnvVarList.Link, &Node->Link)
+ ){
+ if (Node->Key != NULL && StrCmp(Key, Node->Key) == 0) {
+ SHELL_FREE_NON_NULL(Node->Key);
+ SHELL_FREE_NON_NULL(Node->Val);
+ RemoveEntryList(&Node->Link);
+ SHELL_FREE_NON_NULL(Node);
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Initialize the gShellEnvVarList and cache all Shell-Guid-based environment
+ variables.
+
+**/
+EFI_STATUS
+ShellInitEnvVarList (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ InitializeListHead(&gShellEnvVarList.Link);
+ Status = GetEnvironmentVariableList (&gShellEnvVarList.Link);
+
+ return Status;
+}
+
+/**
+ Destructe the gShellEnvVarList.
+
+**/
+VOID
+ShellFreeEnvVarList (
+ VOID
+ )
+{
+ FreeEnvironmentVariableList (&gShellEnvVarList.Link);
+ InitializeListHead(&gShellEnvVarList.Link);
+
+ return;
+}
+
diff --git a/Core/ShellPkg/Application/Shell/ShellEnvVar.h b/Core/ShellPkg/Application/Shell/ShellEnvVar.h
new file mode 100644
index 0000000000..f05ef2bd66
--- /dev/null
+++ b/Core/ShellPkg/Application/Shell/ShellEnvVar.h
@@ -0,0 +1,292 @@
+/** @file
+ function definitions for shell environment functions.
+
+ the following includes are required:
+//#include <Guid/ShellVariableGuid.h>
+//#include <Library/UefiRuntimeServicesTableLib.h>
+
+
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SHELL_ENVIRONMENT_VARIABLE_HEADER_
+#define _SHELL_ENVIRONMENT_VARIABLE_HEADER_
+
+typedef struct {
+ LIST_ENTRY Link;
+ CHAR16 *Key;
+ CHAR16 *Val;
+ UINT32 Atts;
+} ENV_VAR_LIST;
+
+//
+// The list is used to cache the environment variables.
+//
+extern ENV_VAR_LIST gShellEnvVarList;
+
+
+/**
+ Reports whether an environment variable is Volatile or Non-Volatile.
+
+ @param EnvVarName The name of the environment variable in question
+ @param Volatile Return TRUE if the environment variable is volatile
+
+ @retval EFI_SUCCESS The volatile attribute is returned successfully
+ @retval others Some errors happened.
+**/
+EFI_STATUS
+IsVolatileEnv (
+ IN CONST CHAR16 *EnvVarName,
+ OUT BOOLEAN *Volatile
+ );
+
+/**
+ Delete a Non-Violatile environment variable.
+
+ This will use the Runtime Services call SetVariable to remove a non-violatile variable.
+
+ @param EnvVarName The name of the environment variable in question
+
+ @retval EFI_SUCCESS The variable was deleted sucessfully
+ @retval other An error ocurred
+ @sa SetVariable
+**/
+#define SHELL_DELETE_ENVIRONMENT_VARIABLE(EnvVarName) \
+ (gRT->SetVariable((CHAR16*)EnvVarName, \
+ &gShellVariableGuid, \
+ 0, \
+ 0, \
+ NULL))
+
+/**
+ Set a Non-Violatile environment variable.
+
+ This will use the Runtime Services call SetVariable to set a non-violatile variable.
+
+ @param EnvVarName The name of the environment variable in question
+ @param BufferSize UINTN size of Buffer
+ @param Buffer Pointer to value to set variable to
+
+ @retval EFI_SUCCESS The variable was changed sucessfully
+ @retval other An error ocurred
+ @sa SetVariable
+**/
+#define SHELL_SET_ENVIRONMENT_VARIABLE_NV(EnvVarName,BufferSize,Buffer) \
+ (gRT->SetVariable((CHAR16*)EnvVarName, \
+ &gShellVariableGuid, \
+ EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS, \
+ BufferSize, \
+ (VOID*)Buffer))
+
+/**
+ Get an environment variable.
+
+ This will use the Runtime Services call GetVariable to get a variable.
+
+ @param EnvVarName The name of the environment variable in question
+ @param BufferSize Pointer to the UINTN size of Buffer
+ @param Buffer Pointer buffer to get variable value into
+
+ @retval EFI_SUCCESS The variable's value was retrieved sucessfully
+ @retval other An error ocurred
+ @sa SetVariable
+**/
+#define SHELL_GET_ENVIRONMENT_VARIABLE(EnvVarName,BufferSize,Buffer) \
+ (gRT->GetVariable((CHAR16*)EnvVarName, \
+ &gShellVariableGuid, \
+ 0, \
+ BufferSize, \
+ Buffer))
+
+/**
+ Get an environment variable.
+
+ This will use the Runtime Services call GetVariable to get a variable.
+
+ @param EnvVarName The name of the environment variable in question
+ @param Atts Pointer to the UINT32 for attributes (or NULL)
+ @param BufferSize Pointer to the UINTN size of Buffer
+ @param Buffer Pointer buffer to get variable value into
+
+ @retval EFI_SUCCESS The variable's value was retrieved sucessfully
+ @retval other An error ocurred
+ @sa SetVariable
+**/
+#define SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(EnvVarName,Atts,BufferSize,Buffer) \
+ (gRT->GetVariable((CHAR16*)EnvVarName, \
+ &gShellVariableGuid, \
+ Atts, \
+ BufferSize, \
+ Buffer))
+
+/**
+ Set a Violatile environment variable.
+
+ This will use the Runtime Services call SetVariable to set a violatile variable.
+
+ @param EnvVarName The name of the environment variable in question
+ @param BufferSize UINTN size of Buffer
+ @param Buffer Pointer to value to set variable to
+
+ @retval EFI_SUCCESS The variable was changed sucessfully
+ @retval other An error ocurred
+ @sa SetVariable
+**/
+#define SHELL_SET_ENVIRONMENT_VARIABLE_V(EnvVarName,BufferSize,Buffer) \
+ (gRT->SetVariable((CHAR16*)EnvVarName, \
+ &gShellVariableGuid, \
+ EFI_VARIABLE_BOOTSERVICE_ACCESS, \
+ BufferSize, \
+ (VOID*)Buffer))
+
+/**
+ Creates a list of all Shell-Guid-based environment variables.
+
+ @param[in, out] List The pointer to pointer to LIST_ENTRY object for
+ storing this list.
+
+ @retval EFI_SUCCESS the list was created sucessfully.
+**/
+EFI_STATUS
+EFIAPI
+GetEnvironmentVariableList(
+ IN OUT LIST_ENTRY *List
+ );
+
+/**
+ Sets a list of all Shell-Guid-based environment variables. this will
+ also eliminate all pre-existing shell environment variables (even if they
+ are not on the list).
+
+ This function will also deallocate the memory from List.
+
+ @param[in] List The pointer to LIST_ENTRY from
+ GetShellEnvVarList().
+
+ @retval EFI_SUCCESS The list was Set sucessfully.
+**/
+EFI_STATUS
+EFIAPI
+SetEnvironmentVariableList(
+ IN LIST_ENTRY *List
+ );
+
+/**
+ sets all Shell-Guid-based environment variables. this will
+ also eliminate all pre-existing shell environment variables (even if they
+ are not on the list).
+
+ @param[in] Environment Points to a NULL-terminated array of environment
+ variables with the format 'x=y', where x is the
+ environment variable name and y is the value.
+
+ @retval EFI_SUCCESS The command executed successfully.
+ @retval EFI_INVALID_PARAMETER The parameter is invalid.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+
+ @sa SetEnvironmentVariableList
+**/
+EFI_STATUS
+EFIAPI
+SetEnvironmentVariables(
+ IN CONST CHAR16 **Environment
+ );
+
+/**
+ free function for ENV_VAR_LIST objects.
+
+ @param[in] List The pointer to pointer to list.
+**/
+VOID
+EFIAPI
+FreeEnvironmentVariableList(
+ IN LIST_ENTRY *List
+ );
+
+/**
+ Find an environment variable in the gShellEnvVarList.
+
+ @param Key The name of the environment variable.
+ @param Value The value of the environment variable, the buffer
+ shoule be freed by the caller.
+ @param ValueSize The size in bytes of the environment variable
+ including the tailing CHAR_NULL.
+ @param Atts The attributes of the variable.
+
+ @retval EFI_SUCCESS The command executed successfully.
+ @retval EFI_NOT_FOUND The environment variable is not found in
+ gShellEnvVarList.
+
+**/
+EFI_STATUS
+ShellFindEnvVarInList (
+ IN CONST CHAR16 *Key,
+ OUT CHAR16 **Value,
+ OUT UINTN *ValueSize,
+ OUT UINT32 *Atts OPTIONAL
+ );
+
+/**
+ Add an environment variable into gShellEnvVarList.
+
+ @param Key The name of the environment variable.
+ @param Value The value of environment variable.
+ @param ValueSize The size in bytes of the environment variable
+ including the tailing CHAR_NULL
+ @param Atts The attributes of the variable.
+
+ @retval EFI_SUCCESS The environment variable was added to list successfully.
+ @retval others Some errors happened.
+
+**/
+EFI_STATUS
+ShellAddEnvVarToList (
+ IN CONST CHAR16 *Key,
+ IN CONST CHAR16 *Value,
+ IN UINTN ValueSize,
+ IN UINT32 Atts
+ );
+
+/**
+ Remove a specified environment variable in gShellEnvVarList.
+
+ @param Key The name of the environment variable.
+
+ @retval EFI_SUCCESS The command executed successfully.
+ @retval EFI_NOT_FOUND The environment variable is not found in
+ gShellEnvVarList.
+**/
+EFI_STATUS
+ShellRemvoeEnvVarFromList (
+ IN CONST CHAR16 *Key
+ );
+
+/**
+ Initialize the gShellEnvVarList and cache all Shell-Guid-based environment
+ variables.
+
+**/
+EFI_STATUS
+ShellInitEnvVarList (
+ VOID
+ );
+
+/**
+ Destructe the gShellEnvVarList.
+
+**/
+VOID
+ShellFreeEnvVarList (
+ VOID
+ );
+
+#endif //_SHELL_ENVIRONMENT_VARIABLE_HEADER_
+
diff --git a/Core/ShellPkg/Application/Shell/ShellManParser.c b/Core/ShellPkg/Application/Shell/ShellManParser.c
new file mode 100644
index 0000000000..948759fe46
--- /dev/null
+++ b/Core/ShellPkg/Application/Shell/ShellManParser.c
@@ -0,0 +1,1013 @@
+/** @file
+ Provides interface to shell MAN file parser.
+
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+ Copyright 2015 Dell Inc.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Shell.h"
+
+#define SHELL_MAN_HII_GUID \
+{ \
+ 0xf62ccd0c, 0x2449, 0x453c, { 0x8a, 0xcb, 0x8c, 0xc5, 0x7c, 0xf0, 0x2a, 0x97 } \
+}
+
+EFI_HII_HANDLE mShellManHiiHandle = NULL;
+EFI_HANDLE mShellManDriverHandle = NULL;
+
+
+SHELL_MAN_HII_VENDOR_DEVICE_PATH mShellManHiiDevicePath = {
+ {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_VENDOR_DP,
+ {
+ (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
+ (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
+ }
+ },
+ SHELL_MAN_HII_GUID
+ },
+ {
+ END_DEVICE_PATH_TYPE,
+ END_ENTIRE_DEVICE_PATH_SUBTYPE,
+ {
+ (UINT8) (END_DEVICE_PATH_LENGTH),
+ (UINT8) ((END_DEVICE_PATH_LENGTH) >> 8)
+ }
+ }
+};
+
+
+/**
+ Convert a Unicode character to upper case only if
+ it maps to a valid small-case ASCII character.
+
+ This internal function only deal with Unicode character
+ which maps to a valid small-case ASCII character, i.e.
+ L'a' to L'z'. For other Unicode character, the input character
+ is returned directly.
+
+ @param Char The character to convert.
+
+ @retval LowerCharacter If the Char is with range L'a' to L'z'.
+ @retval Unchanged Otherwise.
+
+**/
+CHAR16
+EFIAPI
+InternalShellCharToUpper (
+ IN CHAR16 Char
+ );
+
+/**
+ Verifies that the filename has .EFI on the end.
+
+ allocates a new buffer and copies the name (appending .EFI if necessary).
+ Caller to free the buffer.
+
+ @param[in] NameString original name string
+
+ @return the new filename with .efi as the extension.
+**/
+CHAR16 *
+EFIAPI
+GetExecuatableFileName (
+ IN CONST CHAR16 *NameString
+ )
+{
+ CHAR16 *Buffer;
+ CHAR16 *SuffixStr;
+ if (NameString == NULL) {
+ return (NULL);
+ }
+
+ //
+ // Fix the file name
+ //
+ if (StrnCmp(NameString+StrLen(NameString)-StrLen(L".efi"), L".efi", StrLen(L".efi"))==0) {
+ Buffer = AllocateCopyPool(StrSize(NameString), NameString);
+ } else if (StrnCmp(NameString+StrLen(NameString)-StrLen(L".man"), L".man", StrLen(L".man"))==0) {
+ Buffer = AllocateCopyPool(StrSize(NameString), NameString);
+ if (Buffer != NULL) {
+ SuffixStr = Buffer+StrLen(Buffer)-StrLen(L".man");
+ StrnCpyS (SuffixStr, StrSize(L".man")/sizeof(CHAR16), L".efi", StrLen(L".efi"));
+ }
+ } else {
+ Buffer = AllocateZeroPool(StrSize(NameString) + StrLen(L".efi")*sizeof(CHAR16));
+ if (Buffer != NULL) {
+ StrnCpyS( Buffer,
+ (StrSize(NameString) + StrLen(L".efi")*sizeof(CHAR16))/sizeof(CHAR16),
+ NameString,
+ StrLen(NameString)
+ );
+ StrnCatS( Buffer,
+ (StrSize(NameString) + StrLen(L".efi")*sizeof(CHAR16))/sizeof(CHAR16),
+ L".efi",
+ StrLen(L".efi")
+ );
+ }
+ }
+ return (Buffer);
+
+}
+
+/**
+ Verifies that the filename has .MAN on the end.
+
+ allocates a new buffer and copies the name (appending .MAN if necessary)
+
+ ASSERT if ManFileName is NULL
+
+ @param[in] ManFileName original filename
+
+ @return the new filename with .man as the extension.
+**/
+CHAR16 *
+EFIAPI
+GetManFileName(
+ IN CONST CHAR16 *ManFileName
+ )
+{
+ CHAR16 *Buffer;
+ if (ManFileName == NULL) {
+ return (NULL);
+ }
+ //
+ // Fix the file name
+ //
+ if (StrnCmp(ManFileName+StrLen(ManFileName)-4, L".man", 4)==0) {
+ Buffer = AllocateCopyPool(StrSize(ManFileName), ManFileName);
+ } else {
+ Buffer = AllocateZeroPool(StrSize(ManFileName) + 4*sizeof(CHAR16));
+ if (Buffer != NULL) {
+ StrnCpyS( Buffer,
+ (StrSize(ManFileName) + 4*sizeof(CHAR16))/sizeof(CHAR16),
+ ManFileName,
+ StrLen(ManFileName)
+ );
+ StrnCatS( Buffer,
+ (StrSize(ManFileName) + 4*sizeof(CHAR16))/sizeof(CHAR16),
+ L".man",
+ 4
+ );
+ }
+ }
+ return (Buffer);
+}
+
+/**
+ Search the path environment variable for possible locations and test for
+ which one contains a man file with the name specified. If a valid file is found
+ stop searching and return the (opened) SHELL_FILE_HANDLE for that file.
+
+ @param[in] FileName Name of the file to find and open.
+ @param[out] Handle Pointer to the handle of the found file. The
+ value of this is undefined for return values
+ except EFI_SUCCESS.
+
+ @retval EFI_SUCCESS The file was found. Handle is a valid SHELL_FILE_HANDLE
+ @retval EFI_INVALID_PARAMETER A parameter had an invalid value.
+ @retval EFI_NOT_FOUND The file was not found.
+**/
+EFI_STATUS
+EFIAPI
+SearchPathForFile(
+ IN CONST CHAR16 *FileName,
+ OUT SHELL_FILE_HANDLE *Handle
+ )
+{
+ CHAR16 *FullFileName;
+ EFI_STATUS Status;
+
+ if ( FileName == NULL
+ || Handle == NULL
+ || StrLen(FileName) == 0
+ ){
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ FullFileName = ShellFindFilePath(FileName);
+ if (FullFileName == NULL) {
+ return (EFI_NOT_FOUND);
+ }
+
+ //
+ // now open that file
+ //
+ Status = EfiShellOpenFileByName(FullFileName, Handle, EFI_FILE_MODE_READ);
+ FreePool(FullFileName);
+
+ return (Status);
+}
+
+/**
+ parses through Buffer (which is MAN file formatted) and returns the
+ detailed help for any sub section specified in the comma seperated list of
+ sections provided. If the end of the file or a .TH section is found then
+ return.
+
+ Upon a sucessful return the caller is responsible to free the memory in *HelpText
+
+ @param[in] Buffer Buffer to read from
+ @param[in] Sections name of command's sub sections to find
+ @param[in] HelpText pointer to pointer to string where text goes.
+ @param[in] HelpSize pointer to size of allocated HelpText (may be updated)
+
+ @retval EFI_OUT_OF_RESOURCES a memory allocation failed.
+ @retval EFI_SUCCESS the section was found and its description sotred in
+ an alloceted buffer.
+**/
+EFI_STATUS
+EFIAPI
+ManBufferFindSections(
+ IN CONST CHAR16 *Buffer,
+ IN CONST CHAR16 *Sections,
+ IN CHAR16 **HelpText,
+ IN UINTN *HelpSize
+ )
+{
+ EFI_STATUS Status;
+ CONST CHAR16 *CurrentLocation;
+ BOOLEAN CurrentlyReading;
+ CHAR16 *SectionName;
+ UINTN SectionLen;
+ BOOLEAN Found;
+ CHAR16 *TempString;
+ CHAR16 *TempString2;
+
+ if ( Buffer == NULL
+ || HelpText == NULL
+ || HelpSize == NULL
+ ){
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ Status = EFI_SUCCESS;
+ CurrentlyReading = FALSE;
+ Found = FALSE;
+
+ for (CurrentLocation = Buffer,TempString = NULL
+ ; CurrentLocation != NULL && *CurrentLocation != CHAR_NULL
+ ; CurrentLocation=StrStr(CurrentLocation, L"\r\n"),TempString = NULL
+ ){
+ while(CurrentLocation[0] == L'\r' || CurrentLocation[0] == L'\n') {
+ CurrentLocation++;
+ }
+ if (CurrentLocation[0] == L'#') {
+ //
+ // Skip comment lines
+ //
+ continue;
+ }
+ if (StrnCmp(CurrentLocation, L".TH", 3) == 0) {
+ //
+ // we hit the end of this commands section so stop.
+ //
+ break;
+ }
+ if (StrnCmp(CurrentLocation, L".SH ", 4) == 0) {
+ if (Sections == NULL) {
+ CurrentlyReading = TRUE;
+ continue;
+ } else if (CurrentlyReading) {
+ CurrentlyReading = FALSE;
+ }
+ CurrentLocation += 4;
+ //
+ // is this a section we want to read in?
+ //
+ if (StrLen(CurrentLocation)!=0) {
+ TempString2 = StrStr(CurrentLocation, L" ");
+ TempString2 = MIN(TempString2, StrStr(CurrentLocation, L"\r"));
+ TempString2 = MIN(TempString2, StrStr(CurrentLocation, L"\n"));
+ ASSERT(TempString == NULL);
+ TempString = StrnCatGrow(&TempString, NULL, CurrentLocation, TempString2==NULL?0:TempString2 - CurrentLocation);
+ if (TempString == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ }
+ SectionName = TempString;
+ SectionLen = StrLen(SectionName);
+ SectionName = StrStr(Sections, SectionName);
+ if (SectionName == NULL) {
+ SHELL_FREE_NON_NULL(TempString);
+ continue;
+ }
+ if (*(SectionName + SectionLen) == CHAR_NULL || *(SectionName + SectionLen) == L',') {
+ CurrentlyReading = TRUE;
+ }
+ }
+ } else if (CurrentlyReading) {
+ Found = TRUE;
+ if (StrLen(CurrentLocation)!=0) {
+ TempString2 = StrStr(CurrentLocation, L"\r");
+ TempString2 = MIN(TempString2, StrStr(CurrentLocation, L"\n"));
+ ASSERT(TempString == NULL);
+ TempString = StrnCatGrow(&TempString, NULL, CurrentLocation, TempString2==NULL?0:TempString2 - CurrentLocation);
+ if (TempString == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ }
+ //
+ // copy and save the current line.
+ //
+ ASSERT((*HelpText == NULL && *HelpSize == 0) || (*HelpText != NULL));
+ StrnCatGrow (HelpText, HelpSize, TempString, 0);
+ if (HelpText == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ }
+ StrnCatGrow (HelpText, HelpSize, L"\r\n", 0);
+ if (HelpText == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ }
+ }
+ }
+ SHELL_FREE_NON_NULL(TempString);
+ }
+ SHELL_FREE_NON_NULL(TempString);
+ if (!Found && !EFI_ERROR(Status)) {
+ return (EFI_NOT_FOUND);
+ }
+ return (Status);
+}
+
+/**
+ parses through the MAN file specified by SHELL_FILE_HANDLE and returns the
+ detailed help for any sub section specified in the comma seperated list of
+ sections provided. If the end of the file or a .TH section is found then
+ return.
+
+ Upon a sucessful return the caller is responsible to free the memory in *HelpText
+
+ @param[in] Handle FileHandle to read from
+ @param[in] Sections name of command's sub sections to find
+ @param[out] HelpText pointer to pointer to string where text goes.
+ @param[out] HelpSize pointer to size of allocated HelpText (may be updated)
+ @param[in] Ascii TRUE if the file is ASCII, FALSE otherwise.
+
+ @retval EFI_OUT_OF_RESOURCES a memory allocation failed.
+ @retval EFI_SUCCESS the section was found and its description sotred in
+ an alloceted buffer.
+**/
+EFI_STATUS
+EFIAPI
+ManFileFindSections(
+ IN SHELL_FILE_HANDLE Handle,
+ IN CONST CHAR16 *Sections,
+ OUT CHAR16 **HelpText,
+ OUT UINTN *HelpSize,
+ IN BOOLEAN Ascii
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *ReadLine;
+ UINTN Size;
+ BOOLEAN CurrentlyReading;
+ CHAR16 *SectionName;
+ UINTN SectionLen;
+ BOOLEAN Found;
+
+ if ( Handle == NULL
+ || HelpText == NULL
+ || HelpSize == NULL
+ ){
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ Status = EFI_SUCCESS;
+ CurrentlyReading = FALSE;
+ Size = 1024;
+ Found = FALSE;
+
+ ReadLine = AllocateZeroPool(Size);
+ if (ReadLine == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ for (;!ShellFileHandleEof(Handle);Size = 1024) {
+ Status = ShellFileHandleReadLine(Handle, ReadLine, &Size, TRUE, &Ascii);
+ if (ReadLine[0] == L'#') {
+ //
+ // Skip comment lines
+ //
+ continue;
+ }
+ //
+ // ignore too small of buffer...
+ //
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ Status = EFI_SUCCESS;
+ }
+ if (EFI_ERROR(Status)) {
+ break;
+ } else if (StrnCmp(ReadLine, L".TH", 3) == 0) {
+ //
+ // we hit the end of this commands section so stop.
+ //
+ break;
+ } else if (StrnCmp(ReadLine, L".SH", 3) == 0) {
+ if (Sections == NULL) {
+ CurrentlyReading = TRUE;
+ continue;
+ }
+ //
+ // we found a section
+ //
+ if (CurrentlyReading) {
+ CurrentlyReading = FALSE;
+ }
+ //
+ // is this a section we want to read in?
+ //
+ for ( SectionName = ReadLine + 3
+ ; *SectionName == L' '
+ ; SectionName++);
+ SectionLen = StrLen(SectionName);
+ SectionName = StrStr(Sections, SectionName);
+ if (SectionName == NULL) {
+ continue;
+ }
+ if (*(SectionName + SectionLen) == CHAR_NULL || *(SectionName + SectionLen) == L',') {
+ CurrentlyReading = TRUE;
+ }
+ } else if (CurrentlyReading) {
+ Found = TRUE;
+ //
+ // copy and save the current line.
+ //
+ ASSERT((*HelpText == NULL && *HelpSize == 0) || (*HelpText != NULL));
+ StrnCatGrow (HelpText, HelpSize, ReadLine, 0);
+ StrnCatGrow (HelpText, HelpSize, L"\r\n", 0);
+ }
+ }
+ FreePool(ReadLine);
+ if (!Found && !EFI_ERROR(Status)) {
+ return (EFI_NOT_FOUND);
+ }
+ return (Status);
+}
+
+/**
+ parses through the MAN file formatted Buffer and returns the
+ "Brief Description" for the .TH section as specified by Command. If the
+ command section is not found return EFI_NOT_FOUND.
+
+ Upon a sucessful return the caller is responsible to free the memory in *BriefDesc
+
+ @param[in] Buffer Buffer to read from
+ @param[in] Command name of command's section to find
+ @param[in] BriefDesc pointer to pointer to string where description goes.
+ @param[in] BriefSize pointer to size of allocated BriefDesc
+
+ @retval EFI_OUT_OF_RESOURCES a memory allocation failed.
+ @retval EFI_SUCCESS the section was found and its description sotred in
+ an alloceted buffer.
+**/
+EFI_STATUS
+EFIAPI
+ManBufferFindTitleSection(
+ IN CHAR16 **Buffer,
+ IN CONST CHAR16 *Command,
+ IN CHAR16 **BriefDesc,
+ IN UINTN *BriefSize
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *TitleString;
+ CHAR16 *TitleEnd;
+ CHAR16 *CurrentLocation;
+ UINTN TitleLength;
+ UINTN Start;
+ CONST CHAR16 StartString[] = L".TH ";
+ CONST CHAR16 EndString[] = L" 0 ";
+
+ if ( Buffer == NULL
+ || Command == NULL
+ || (BriefDesc != NULL && BriefSize == NULL)
+ ){
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Do not pass any leading path information that may be present to IsTitleHeader().
+ //
+ Start = StrLen(Command);
+ while ((Start != 0)
+ && (*(Command + Start - 1) != L'\\')
+ && (*(Command + Start - 1) != L'/')
+ && (*(Command + Start - 1) != L':')) {
+ --Start;
+ }
+
+ //
+ // more characters for StartString and EndString
+ //
+ TitleLength = StrSize(Command + Start) + (StrLen(StartString) + StrLen(EndString)) * sizeof(CHAR16);
+ TitleString = AllocateZeroPool(TitleLength);
+ if (TitleString == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ StrCpyS(TitleString, TitleLength/sizeof(CHAR16), StartString);
+ StrCatS(TitleString, TitleLength/sizeof(CHAR16), Command + Start);
+ StrCatS(TitleString, TitleLength/sizeof(CHAR16), EndString);
+
+ CurrentLocation = StrStr(*Buffer, TitleString);
+ if (CurrentLocation == NULL){
+ Status = EFI_NOT_FOUND;
+ } else {
+ //
+ // we found it so copy out the rest of the line into BriefDesc
+ // After skipping any spaces or zeroes
+ //
+ for (CurrentLocation += StrLen(TitleString)
+ ; *CurrentLocation == L' ' || *CurrentLocation == L'0' || *CurrentLocation == L'1' || *CurrentLocation == L'\"'
+ ; CurrentLocation++);
+
+ TitleEnd = StrStr(CurrentLocation, L"\"");
+ if (TitleEnd == NULL) {
+ Status = EFI_DEVICE_ERROR;
+ } else {
+ if (BriefDesc != NULL) {
+ *BriefSize = StrSize(TitleEnd);
+ *BriefDesc = AllocateZeroPool(*BriefSize);
+ if (*BriefDesc == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ StrnCpyS(*BriefDesc, (*BriefSize)/sizeof(CHAR16), CurrentLocation, TitleEnd-CurrentLocation);
+ }
+ }
+
+ for (CurrentLocation = TitleEnd
+ ; *CurrentLocation != L'\n'
+ ; CurrentLocation++);
+ for (
+ ; *CurrentLocation == L' ' || *CurrentLocation == L'\n' || *CurrentLocation == L'\r'
+ ; CurrentLocation++);
+ *Buffer = CurrentLocation;
+ }
+ }
+
+ FreePool(TitleString);
+ return (Status);
+}
+
+/**
+ Parses a line from a MAN file to see if it is the Title Header. If it is, then
+ if the "Brief Description" is desired, allocate a buffer for it and return a
+ copy. Upon a sucessful return the caller is responsible to free the memory in
+ *BriefDesc
+
+ Uses a simple state machine that allows "unlimited" whitespace before and after the
+ ".TH", compares Command and the MAN file commnd name without respect to case, and
+ allows "unlimited" whitespace and '0' and '1' characters before the Short Description.
+ The PCRE regex describing this functionality is: ^\s*\.TH\s+(\S)\s[\s01]*(.*)$
+ where group 1 is the Command Name and group 2 is the Short Description.
+
+ @param[in] Command name of command whose MAN file we think Line came from
+ @param[in] Line Pointer to a line from the MAN file
+ @param[out] BriefDesc pointer to pointer to string where description goes.
+ @param[out] BriefSize pointer to size of allocated BriefDesc
+ @param[out] Found TRUE if the Title Header was found and it belongs to Command
+
+ @retval TRUE Line contained the Title Header
+ @retval FALSE Line did not contain the Title Header
+**/
+BOOLEAN
+IsTitleHeader(
+ IN CONST CHAR16 *Command,
+ IN CHAR16 *Line,
+ OUT CHAR16 **BriefDesc OPTIONAL,
+ OUT UINTN *BriefSize OPTIONAL,
+ OUT BOOLEAN *Found
+ )
+{
+ // The states of a simple state machine used to recognize a title header line
+ // and to extract the Short Description, if desired.
+ typedef enum {
+ LookForThMacro, LookForCommandName, CompareCommands, GetBriefDescription, Final
+ } STATEVALUES;
+
+ STATEVALUES State;
+ UINTN CommandIndex; // Indexes Command as we compare its chars to the MAN file.
+ BOOLEAN ReturnValue; // TRUE if this the Title Header line of *some* MAN file.
+ BOOLEAN ReturnFound; // TRUE if this the Title Header line of *the desired* MAN file.
+
+ ReturnValue = FALSE;
+ ReturnFound = FALSE;
+ CommandIndex = 0;
+ State = LookForThMacro;
+
+ do {
+
+ if (*Line == L'\0') {
+ break;
+ }
+
+ switch (State) {
+
+ // Handle "^\s*.TH\s"
+ // Go to state LookForCommandName if the title header macro is present; otherwise,
+ // eat white space. If we see something other than white space, this is not a
+ // title header line.
+ case LookForThMacro:
+ if (StrnCmp (L".TH ", Line, 4) == 0 || StrnCmp (L".TH\t", Line, 4) == 0) {
+ Line += 4;
+ State = LookForCommandName;
+ }
+ else if (*Line == L' ' || *Line == L'\t') {
+ Line++;
+ }
+ else {
+ State = Final;
+ }
+ break;
+
+ // Handle "\s*"
+ // Eat any "extra" whitespace after the title header macro (we have already seen
+ // at least one white space character). Go to state CompareCommands when a
+ // non-white space is seen.
+ case LookForCommandName:
+ if (*Line == L' ' || *Line == L'\t') {
+ Line++;
+ }
+ else {
+ ReturnValue = TRUE; // This is *some* command's title header line.
+ State = CompareCommands;
+ // Do not increment Line; it points to the first character of the command
+ // name on the title header line.
+ }
+ break;
+
+ // Handle "(\S)\s"
+ // Compare Command to the title header command name, ignoring case. When we
+ // reach the end of the command (i.e. we see white space), the next state
+ // depends on whether the caller wants a copy of the Brief Description.
+ case CompareCommands:
+ if (*Line == L' ' || *Line == L'\t') {
+ ReturnFound = TRUE; // This is the desired command's title header line.
+ State = (BriefDesc == NULL) ? Final : GetBriefDescription;
+ }
+ else if (InternalShellCharToUpper (*Line) != InternalShellCharToUpper (*(Command + CommandIndex++))) {
+ State = Final;
+ }
+ Line++;
+ break;
+
+ // Handle "[\s01]*(.*)$"
+ // Skip whitespace, '0', and '1' characters, if any, prior to the brief description.
+ // Return the description to the caller.
+ case GetBriefDescription:
+ if (*Line != L' ' && *Line != L'\t' && *Line != L'0' && *Line != L'1') {
+ *BriefSize = StrSize(Line);
+ *BriefDesc = AllocateZeroPool(*BriefSize);
+ if (*BriefDesc != NULL) {
+ StrCpyS(*BriefDesc, (*BriefSize)/sizeof(CHAR16), Line);
+ }
+ State = Final;
+ }
+ Line++;
+ break;
+
+ default:
+ break;
+ }
+
+ } while (State < Final);
+
+ *Found = ReturnFound;
+ return ReturnValue;
+}
+
+/**
+ parses through the MAN file specified by SHELL_FILE_HANDLE and returns the
+ "Brief Description" for the .TH section as specified by Command. If the
+ command section is not found return EFI_NOT_FOUND.
+
+ Upon a sucessful return the caller is responsible to free the memory in *BriefDesc
+
+ @param[in] Handle FileHandle to read from
+ @param[in] Command name of command's section to find as entered on the
+ command line (may be a relative or absolute path or
+ be in any case: upper, lower, or mixed in numerous ways!).
+ @param[out] BriefDesc pointer to pointer to string where description goes.
+ @param[out] BriefSize pointer to size of allocated BriefDesc
+ @param[in, out] Ascii TRUE if the file is ASCII, FALSE otherwise, will be
+ set if the file handle is at the 0 position.
+
+ @retval EFI_OUT_OF_RESOURCES a memory allocation failed.
+ @retval EFI_SUCCESS the section was found and its description stored in
+ an allocated buffer if requested.
+**/
+EFI_STATUS
+EFIAPI
+ManFileFindTitleSection(
+ IN SHELL_FILE_HANDLE Handle,
+ IN CONST CHAR16 *Command,
+ OUT CHAR16 **BriefDesc OPTIONAL,
+ OUT UINTN *BriefSize OPTIONAL,
+ IN OUT BOOLEAN *Ascii
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *ReadLine;
+ UINTN Size;
+ BOOLEAN Found;
+ UINTN Start;
+
+ if ( Handle == NULL
+ || Command == NULL
+ || (BriefDesc != NULL && BriefSize == NULL)
+ ){
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ Status = EFI_SUCCESS;
+ Size = 1024;
+ Found = FALSE;
+
+ ReadLine = AllocateZeroPool(Size);
+ if (ReadLine == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ //
+ // Do not pass any leading path information that may be present to IsTitleHeader().
+ //
+ Start = StrLen(Command);
+ while ((Start != 0)
+ && (*(Command + Start - 1) != L'\\')
+ && (*(Command + Start - 1) != L'/')
+ && (*(Command + Start - 1) != L':')) {
+ --Start;
+ }
+
+ for (;!ShellFileHandleEof(Handle);Size = 1024) {
+ Status = ShellFileHandleReadLine(Handle, ReadLine, &Size, TRUE, Ascii);
+ //
+ // ignore too small of buffer...
+ //
+ if (EFI_ERROR(Status) && Status != EFI_BUFFER_TOO_SMALL) {
+ break;
+ }
+
+ Status = EFI_NOT_FOUND;
+ if (IsTitleHeader (Command+Start, ReadLine, BriefDesc, BriefSize, &Found)) {
+ Status = Found ? EFI_SUCCESS : EFI_NOT_FOUND;
+ break;
+ }
+ }
+
+ FreePool(ReadLine);
+ return (Status);
+}
+
+/**
+ This function returns the help information for the specified command. The help text
+ will be parsed from a UEFI Shell manual page. (see UEFI Shell 2.0 Appendix B)
+
+ If Sections is specified, then each section name listed will be compared in a casesensitive
+ manner, to the section names described in Appendix B. If the section exists,
+ it will be appended to the returned help text. If the section does not exist, no
+ information will be returned. If Sections is NULL, then all help text information
+ available will be returned.
+
+ if BriefDesc is NULL, then the breif description will not be savedd seperatly,
+ but placed first in the main HelpText.
+
+ @param[in] ManFileName Points to the NULL-terminated UEFI Shell MAN file name.
+ @param[in] Command Points to the NULL-terminated UEFI Shell command name.
+ @param[in] Sections Points to the NULL-terminated comma-delimited
+ section names to return. If NULL, then all
+ sections will be returned.
+ @param[out] BriefDesc On return, points to a callee-allocated buffer
+ containing brief description text.
+ @param[out] HelpText On return, points to a callee-allocated buffer
+ containing all specified help text.
+
+ @retval EFI_SUCCESS The help text was returned.
+ @retval EFI_OUT_OF_RESOURCES The necessary buffer could not be allocated to hold the
+ returned help text.
+ @retval EFI_INVALID_PARAMETER HelpText is NULL.
+ @retval EFI_INVALID_PARAMETER ManFileName is invalid.
+ @retval EFI_NOT_FOUND There is no help text available for Command.
+**/
+EFI_STATUS
+EFIAPI
+ProcessManFile(
+ IN CONST CHAR16 *ManFileName,
+ IN CONST CHAR16 *Command,
+ IN CONST CHAR16 *Sections OPTIONAL,
+ OUT CHAR16 **BriefDesc OPTIONAL,
+ OUT CHAR16 **HelpText
+ )
+{
+ CHAR16 *TempString;
+ SHELL_FILE_HANDLE FileHandle;
+ EFI_HANDLE CmdFileImgHandle;
+ EFI_STATUS Status;
+ UINTN HelpSize;
+ UINTN BriefSize;
+ UINTN StringIdWalker;
+ BOOLEAN Ascii;
+ CHAR16 *TempString2;
+ CHAR16 *CmdFileName;
+ CHAR16 *CmdFilePathName;
+ CHAR16 *StringBuff;
+ EFI_DEVICE_PATH_PROTOCOL *FileDevPath;
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;
+
+ if ( ManFileName == NULL
+ || Command == NULL
+ || HelpText == NULL
+ ){
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ HelpSize = 0;
+ BriefSize = 0;
+ StringIdWalker = 0;
+ TempString = NULL;
+ Ascii = FALSE;
+ CmdFileName = NULL;
+ CmdFilePathName = NULL;
+ CmdFileImgHandle = NULL;
+ StringBuff = NULL;
+ PackageListHeader = NULL;
+ FileDevPath = NULL;
+ DevPath = NULL;
+
+ //
+ // See if it's in HII first
+ //
+ TempString = ShellCommandGetCommandHelp(Command);
+ if (TempString != NULL) {
+ TempString2 = TempString;
+ Status = ManBufferFindTitleSection(&TempString2, Command, BriefDesc, &BriefSize);
+ if (!EFI_ERROR(Status) && HelpText != NULL){
+ Status = ManBufferFindSections(TempString2, Sections, HelpText, &HelpSize);
+ }
+ } else {
+ //
+ // If the image is a external app, check .MAN file first.
+ //
+ FileHandle = NULL;
+ TempString = GetManFileName(ManFileName);
+ if (TempString == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ Status = SearchPathForFile(TempString, &FileHandle);
+ if (EFI_ERROR(Status)) {
+ FileDevPath = FileDevicePath(NULL, TempString);
+ DevPath = AppendDevicePath (ShellInfoObject.ImageDevPath, FileDevPath);
+ Status = InternalOpenFileDevicePath(DevPath, &FileHandle, EFI_FILE_MODE_READ, 0);
+ SHELL_FREE_NON_NULL(FileDevPath);
+ SHELL_FREE_NON_NULL(DevPath);
+ }
+
+ if (!EFI_ERROR(Status)) {
+ HelpSize = 0;
+ BriefSize = 0;
+ Status = ManFileFindTitleSection(FileHandle, Command, BriefDesc, &BriefSize, &Ascii);
+ if (!EFI_ERROR(Status) && HelpText != NULL){
+ Status = ManFileFindSections(FileHandle, Sections, HelpText, &HelpSize, Ascii);
+ }
+ ShellInfoObject.NewEfiShellProtocol->CloseFile(FileHandle);
+ if (!EFI_ERROR(Status)) {
+ //
+ // Get help text from .MAN file success.
+ //
+ goto Done;
+ }
+ }
+
+ //
+ // Load the app image to check EFI_HII_PACKAGE_LIST_PROTOCOL.
+ //
+ CmdFileName = GetExecuatableFileName(TempString);
+ if (CmdFileName == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+ //
+ // If the file in CWD then use the file name, else use the full
+ // path name.
+ //
+ CmdFilePathName = ShellFindFilePath(CmdFileName);
+ if (CmdFilePathName == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+ DevPath = ShellInfoObject.NewEfiShellProtocol->GetDevicePathFromFilePath(CmdFilePathName);
+ Status = gBS->LoadImage(FALSE, gImageHandle, DevPath, NULL, 0, &CmdFileImgHandle);
+ if(EFI_ERROR(Status)) {
+ *HelpText = NULL;
+ goto Done;
+ }
+ Status = gBS->OpenProtocol(
+ CmdFileImgHandle,
+ &gEfiHiiPackageListProtocolGuid,
+ (VOID**)&PackageListHeader,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if(EFI_ERROR(Status)) {
+ *HelpText = NULL;
+ goto Done;
+ }
+
+ //
+ // If get package list on image handle, install it on HiiDatabase.
+ //
+ Status = gBS->InstallProtocolInterface (
+ &mShellManDriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ &mShellManHiiDevicePath
+ );
+ if (EFI_ERROR(Status)) {
+ goto Done;
+ }
+
+ Status = gHiiDatabase->NewPackageList (
+ gHiiDatabase,
+ PackageListHeader,
+ mShellManDriverHandle,
+ &mShellManHiiHandle
+ );
+ if (EFI_ERROR (Status)) {
+ goto Done;
+ }
+
+ StringIdWalker = 1;
+ do {
+ SHELL_FREE_NON_NULL(StringBuff);
+ if (BriefDesc != NULL) {
+ SHELL_FREE_NON_NULL(*BriefDesc);
+ }
+ StringBuff = HiiGetString (mShellManHiiHandle, (EFI_STRING_ID)StringIdWalker, NULL);
+ if (StringBuff == NULL) {
+ Status = EFI_NOT_FOUND;
+ goto Done;
+ }
+ TempString2 = StringBuff;
+ Status = ManBufferFindTitleSection(&TempString2, Command, BriefDesc, &BriefSize);
+ if (!EFI_ERROR(Status) && HelpText != NULL){
+ Status = ManBufferFindSections(TempString2, Sections, HelpText, &HelpSize);
+ }
+ if (!EFI_ERROR(Status)){
+ //
+ // Found what we need and return
+ //
+ goto Done;
+ }
+
+ StringIdWalker += 1;
+ } while (StringIdWalker < 0xFFFF && StringBuff != NULL);
+
+ }
+
+Done:
+ if (mShellManDriverHandle != NULL) {
+ gBS->UninstallProtocolInterface (
+ mShellManDriverHandle,
+ &gEfiDevicePathProtocolGuid,
+ &mShellManHiiDevicePath
+ );
+ mShellManDriverHandle = NULL;
+ }
+
+ if (mShellManHiiHandle != NULL) {
+ HiiRemovePackages (mShellManHiiHandle);
+ mShellManHiiHandle = NULL;
+ }
+
+ if (CmdFileImgHandle != NULL) {
+ Status = gBS->UnloadImage (CmdFileImgHandle);
+ }
+
+ SHELL_FREE_NON_NULL(StringBuff);
+ SHELL_FREE_NON_NULL(TempString);
+ SHELL_FREE_NON_NULL(CmdFileName);
+ SHELL_FREE_NON_NULL(CmdFilePathName);
+ SHELL_FREE_NON_NULL(FileDevPath);
+ SHELL_FREE_NON_NULL(DevPath);
+
+ return (Status);
+}
+
diff --git a/Core/ShellPkg/Application/Shell/ShellManParser.h b/Core/ShellPkg/Application/Shell/ShellManParser.h
new file mode 100644
index 0000000000..3807eec9b2
--- /dev/null
+++ b/Core/ShellPkg/Application/Shell/ShellManParser.h
@@ -0,0 +1,86 @@
+/** @file
+ Provides interface to shell MAN file parser.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SHELL_MAN_FILE_PARSER_HEADER_
+#define _SHELL_MAN_FILE_PARSER_HEADER_
+
+/**
+ This function returns the help information for the specified command. The help text
+ will be parsed from a UEFI Shell manual page. (see UEFI Shell 2.0 Appendix B)
+
+ If Sections is specified, then each section name listed will be compared in a casesensitive
+ manner, to the section names described in Appendix B. If the section exists,
+ it will be appended to the returned help text. If the section does not exist, no
+ information will be returned. If Sections is NULL, then all help text information
+ available will be returned.
+
+ if BriefDesc is NULL, then the breif description will not be savedd seperatly,
+ but placed first in the main HelpText.
+
+ @param[in] ManFileName Points to the NULL-terminated UEFI Shell MAN file name.
+ @param[in] Command Points to the NULL-terminated UEFI Shell command name.
+ @param[in] Sections Points to the NULL-terminated comma-delimited
+ section names to return. If NULL, then all
+ sections will be returned.
+ @param[out] BriefDesc On return, points to a callee-allocated buffer
+ containing brief description text.
+ @param[out] HelpText On return, points to a callee-allocated buffer
+ containing all specified help text.
+
+ @retval EFI_SUCCESS The help text was returned.
+ @retval EFI_OUT_OF_RESOURCES The necessary buffer could not be allocated to hold the
+ returned help text.
+ @retval EFI_INVALID_PARAMETER HelpText is NULL
+ @retval EFI_NOT_FOUND There is no help text available for Command.
+**/
+EFI_STATUS
+EFIAPI
+ProcessManFile(
+ IN CONST CHAR16 *ManFileName,
+ IN CONST CHAR16 *Command,
+ IN CONST CHAR16 *Sections OPTIONAL,
+ OUT CHAR16 **BriefDesc,
+ OUT CHAR16 **HelpText
+ );
+
+/**
+ parses through the MAN file specified by SHELL_FILE_HANDLE and returns the
+ detailed help for any sub section specified in the comma seperated list of
+ sections provided. If the end of the file or a .TH section is found then
+ return.
+
+ Upon a sucessful return the caller is responsible to free the memory in *HelpText
+
+ @param[in] Handle FileHandle to read from
+ @param[in] Sections name of command's sub sections to find
+ @param[out] HelpText pointer to pointer to string where text goes.
+ @param[out] HelpSize pointer to size of allocated HelpText (may be updated)
+ @param[in] Ascii TRUE if the file is ASCII, FALSE otherwise.
+
+ @retval EFI_OUT_OF_RESOURCES a memory allocation failed.
+ @retval EFI_SUCCESS the section was found and its description sotred in
+ an alloceted buffer.
+**/
+EFI_STATUS
+EFIAPI
+ManFileFindSections(
+ IN SHELL_FILE_HANDLE Handle,
+ IN CONST CHAR16 *Sections,
+ OUT CHAR16 **HelpText,
+ OUT UINTN *HelpSize,
+ IN BOOLEAN Ascii
+ );
+
+#endif //_SHELL_MAN_FILE_PARSER_HEADER_
+
diff --git a/Core/ShellPkg/Application/Shell/ShellParametersProtocol.c b/Core/ShellPkg/Application/Shell/ShellParametersProtocol.c
new file mode 100644
index 0000000000..0785902b16
--- /dev/null
+++ b/Core/ShellPkg/Application/Shell/ShellParametersProtocol.c
@@ -0,0 +1,1298 @@
+/** @file
+ Member functions of EFI_SHELL_PARAMETERS_PROTOCOL and functions for creation,
+ manipulation, and initialization of EFI_SHELL_PARAMETERS_PROTOCOL.
+
+ Copyright (C) 2014, Red Hat, Inc.
+ (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Shell.h"
+
+BOOLEAN AsciiRedirection = FALSE;
+
+/**
+ Function to populate Argc and Argv.
+
+ This function parses the CommandLine and divides it into standard C style Argc/Argv
+ parameters for inclusion in EFI_SHELL_PARAMETERS_PROTOCOL. this supports space
+ delimited and quote surrounded parameter definition.
+
+ All special character processing (alias, environment variable, redirection,
+ etc... must be complete before calling this API.
+
+ @param[in] CommandLine String of command line to parse
+ @param[in] StripQuotation if TRUE then strip the quotation marks surrounding
+ the parameters.
+ @param[in, out] Argv pointer to array of strings; one for each parameter
+ @param[in, out] Argc pointer to number of strings in Argv array
+
+ @return EFI_SUCCESS the operation was sucessful
+ @return EFI_OUT_OF_RESOURCES a memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+ParseCommandLineToArgs(
+ IN CONST CHAR16 *CommandLine,
+ IN BOOLEAN StripQuotation,
+ IN OUT CHAR16 ***Argv,
+ IN OUT UINTN *Argc
+ )
+{
+ UINTN Count;
+ CHAR16 *TempParameter;
+ CHAR16 *Walker;
+ CHAR16 *NewParam;
+ CHAR16 *NewCommandLine;
+ UINTN Size;
+ EFI_STATUS Status;
+
+ ASSERT(Argc != NULL);
+ ASSERT(Argv != NULL);
+
+ if (CommandLine == NULL || StrLen(CommandLine)==0) {
+ (*Argc) = 0;
+ (*Argv) = NULL;
+ return (EFI_SUCCESS);
+ }
+
+ NewCommandLine = AllocateCopyPool(StrSize(CommandLine), CommandLine);
+ if (NewCommandLine == NULL){
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ TrimSpaces(&NewCommandLine);
+ Size = StrSize(NewCommandLine);
+ TempParameter = AllocateZeroPool(Size);
+ if (TempParameter == NULL) {
+ SHELL_FREE_NON_NULL(NewCommandLine);
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ for ( Count = 0
+ , Walker = (CHAR16*)NewCommandLine
+ ; Walker != NULL && *Walker != CHAR_NULL
+ ; Count++
+ ) {
+ if (EFI_ERROR (ShellGetNextParameter (&Walker, TempParameter, Size, TRUE))) {
+ break;
+ }
+ }
+
+ //
+ // lets allocate the pointer array
+ //
+ (*Argv) = AllocateZeroPool((Count)*sizeof(CHAR16*));
+ if (*Argv == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ *Argc = 0;
+ Walker = (CHAR16*)NewCommandLine;
+ while(Walker != NULL && *Walker != CHAR_NULL) {
+ SetMem16(TempParameter, Size, CHAR_NULL);
+ if (EFI_ERROR (ShellGetNextParameter (&Walker, TempParameter, Size, StripQuotation))) {
+ Status = EFI_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ NewParam = AllocateCopyPool(StrSize(TempParameter), TempParameter);
+ if (NewParam == NULL){
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Done;
+ }
+ ((CHAR16**)(*Argv))[(*Argc)] = NewParam;
+ (*Argc)++;
+ }
+ ASSERT(Count >= (*Argc));
+ Status = EFI_SUCCESS;
+
+Done:
+ SHELL_FREE_NON_NULL(TempParameter);
+ SHELL_FREE_NON_NULL(NewCommandLine);
+ return (Status);
+}
+
+/**
+ creates a new EFI_SHELL_PARAMETERS_PROTOCOL instance and populates it and then
+ installs it on our handle and if there is an existing version of the protocol
+ that one is cached for removal later.
+
+ @param[in, out] NewShellParameters on a successful return, a pointer to pointer
+ to the newly installed interface.
+ @param[in, out] RootShellInstance on a successful return, pointer to boolean.
+ TRUE if this is the root shell instance.
+
+ @retval EFI_SUCCESS the operation completed successfully.
+ @return other the operation failed.
+ @sa ReinstallProtocolInterface
+ @sa InstallProtocolInterface
+ @sa ParseCommandLineToArgs
+**/
+EFI_STATUS
+EFIAPI
+CreatePopulateInstallShellParametersProtocol (
+ IN OUT EFI_SHELL_PARAMETERS_PROTOCOL **NewShellParameters,
+ IN OUT BOOLEAN *RootShellInstance
+ )
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ CHAR16 *FullCommandLine;
+ UINTN Size;
+
+ Size = 0;
+ FullCommandLine = NULL;
+ LoadedImage = NULL;
+
+ //
+ // Assert for valid parameters
+ //
+ ASSERT(NewShellParameters != NULL);
+ ASSERT(RootShellInstance != NULL);
+
+ //
+ // See if we have a shell parameters placed on us
+ //
+ Status = gBS->OpenProtocol (
+ gImageHandle,
+ &gEfiShellParametersProtocolGuid,
+ (VOID **) &ShellInfoObject.OldShellParameters,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ //
+ // if we don't then we must be the root shell (error is expected)
+ //
+ if (EFI_ERROR (Status)) {
+ *RootShellInstance = TRUE;
+ }
+
+ //
+ // Allocate the new structure
+ //
+ *NewShellParameters = AllocateZeroPool(sizeof(EFI_SHELL_PARAMETERS_PROTOCOL));
+ if ((*NewShellParameters) == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ //
+ // get loaded image protocol
+ //
+ Status = gBS->OpenProtocol (
+ gImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **) &LoadedImage,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ ASSERT_EFI_ERROR(Status);
+ //
+ // Build the full command line
+ //
+ Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, FullCommandLine);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ FullCommandLine = AllocateZeroPool(Size + LoadedImage->LoadOptionsSize);
+ Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, FullCommandLine);
+ }
+ if (Status == EFI_NOT_FOUND) {
+ //
+ // no parameters via environment... ok
+ //
+ } else {
+ if (EFI_ERROR(Status)) {
+ return (Status);
+ }
+ }
+ if (Size == 0 && LoadedImage->LoadOptionsSize != 0) {
+ ASSERT(FullCommandLine == NULL);
+ //
+ // Now we need to include a NULL terminator in the size.
+ //
+ Size = LoadedImage->LoadOptionsSize + sizeof(FullCommandLine[0]);
+ FullCommandLine = AllocateZeroPool(Size);
+ }
+ if (FullCommandLine != NULL) {
+ CopyMem (FullCommandLine, LoadedImage->LoadOptions, LoadedImage->LoadOptionsSize);
+ //
+ // Populate Argc and Argv
+ //
+ Status = ParseCommandLineToArgs(FullCommandLine,
+ TRUE,
+ &(*NewShellParameters)->Argv,
+ &(*NewShellParameters)->Argc);
+
+ FreePool(FullCommandLine);
+
+ ASSERT_EFI_ERROR(Status);
+ } else {
+ (*NewShellParameters)->Argv = NULL;
+ (*NewShellParameters)->Argc = 0;
+ }
+
+ //
+ // Populate the 3 faked file systems...
+ //
+ if (*RootShellInstance) {
+ (*NewShellParameters)->StdIn = &FileInterfaceStdIn;
+ (*NewShellParameters)->StdOut = &FileInterfaceStdOut;
+ (*NewShellParameters)->StdErr = &FileInterfaceStdErr;
+ Status = gBS->InstallProtocolInterface(&gImageHandle,
+ &gEfiShellParametersProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ (VOID*)(*NewShellParameters));
+ } else {
+ //
+ // copy from the existing ones
+ //
+ (*NewShellParameters)->StdIn = ShellInfoObject.OldShellParameters->StdIn;
+ (*NewShellParameters)->StdOut = ShellInfoObject.OldShellParameters->StdOut;
+ (*NewShellParameters)->StdErr = ShellInfoObject.OldShellParameters->StdErr;
+ Status = gBS->ReinstallProtocolInterface(gImageHandle,
+ &gEfiShellParametersProtocolGuid,
+ (VOID*)ShellInfoObject.OldShellParameters,
+ (VOID*)(*NewShellParameters));
+ }
+
+ return (Status);
+}
+
+/**
+ frees all memory used by createion and installation of shell parameters protocol
+ and if there was an old version installed it will restore that one.
+
+ @param NewShellParameters the interface of EFI_SHELL_PARAMETERS_PROTOCOL that is
+ being cleaned up.
+
+ @retval EFI_SUCCESS the cleanup was successful
+ @return other the cleanup failed
+ @sa ReinstallProtocolInterface
+ @sa UninstallProtocolInterface
+**/
+EFI_STATUS
+EFIAPI
+CleanUpShellParametersProtocol (
+ IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *NewShellParameters
+ )
+{
+ EFI_STATUS Status;
+ UINTN LoopCounter;
+
+ //
+ // If the old exists we need to restore it
+ //
+ if (ShellInfoObject.OldShellParameters != NULL) {
+ Status = gBS->ReinstallProtocolInterface(gImageHandle,
+ &gEfiShellParametersProtocolGuid,
+ (VOID*)NewShellParameters,
+ (VOID*)ShellInfoObject.OldShellParameters);
+ DEBUG_CODE(ShellInfoObject.OldShellParameters = NULL;);
+ } else {
+ //
+ // No old one, just uninstall us...
+ //
+ Status = gBS->UninstallProtocolInterface(gImageHandle,
+ &gEfiShellParametersProtocolGuid,
+ (VOID*)NewShellParameters);
+ }
+ if (NewShellParameters->Argv != NULL) {
+ for ( LoopCounter = 0
+ ; LoopCounter < NewShellParameters->Argc
+ ; LoopCounter++
+ ){
+ FreePool(NewShellParameters->Argv[LoopCounter]);
+ }
+ FreePool(NewShellParameters->Argv);
+ }
+ FreePool(NewShellParameters);
+ return (Status);
+}
+
+/**
+ Determin if a file name represents a unicode file.
+
+ @param[in] FileName Pointer to the filename to open.
+
+ @retval EFI_SUCCESS The file is a unicode file.
+ @return An error upon failure.
+**/
+EFI_STATUS
+EFIAPI
+IsUnicodeFile(
+ IN CONST CHAR16 *FileName
+ )
+{
+ SHELL_FILE_HANDLE Handle;
+ EFI_STATUS Status;
+ UINT64 OriginalFilePosition;
+ UINTN CharSize;
+ CHAR16 CharBuffer;
+
+ Status = gEfiShellProtocol->OpenFileByName(FileName, &Handle, EFI_FILE_MODE_READ);
+ if (EFI_ERROR(Status)) {
+ return (Status);
+ }
+ gEfiShellProtocol->GetFilePosition(Handle, &OriginalFilePosition);
+ gEfiShellProtocol->SetFilePosition(Handle, 0);
+ CharSize = sizeof(CHAR16);
+ Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer);
+ if (EFI_ERROR(Status) || CharBuffer != gUnicodeFileTag) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+ gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);
+ gEfiShellProtocol->CloseFile(Handle);
+ return (Status);
+}
+
+/**
+ Strips out quotes sections of a string.
+
+ All of the characters between quotes is replaced with spaces.
+
+ @param[in, out] TheString A pointer to the string to update.
+**/
+VOID
+EFIAPI
+StripQuotes (
+ IN OUT CHAR16 *TheString
+ )
+{
+ BOOLEAN RemoveNow;
+
+ for (RemoveNow = FALSE ; TheString != NULL && *TheString != CHAR_NULL ; TheString++) {
+ if (*TheString == L'^' && *(TheString + 1) == L'\"') {
+ TheString++;
+ } else if (*TheString == L'\"') {
+ RemoveNow = (BOOLEAN)!RemoveNow;
+ } else if (RemoveNow) {
+ *TheString = L' ';
+ }
+ }
+}
+
+/**
+ Calcualte the 32-bit CRC in a EFI table using the service provided by the
+ gRuntime service.
+
+ @param Hdr Pointer to an EFI standard header
+
+**/
+VOID
+CalculateEfiHdrCrc (
+ IN OUT EFI_TABLE_HEADER *Hdr
+ )
+{
+ UINT32 Crc;
+
+ Hdr->CRC32 = 0;
+
+ //
+ // If gBS->CalculateCrce32 () == CoreEfiNotAvailableYet () then
+ // Crc will come back as zero if we set it to zero here
+ //
+ Crc = 0;
+ gBS->CalculateCrc32 ((UINT8 *)Hdr, Hdr->HeaderSize, &Crc);
+ Hdr->CRC32 = Crc;
+}
+
+/**
+ Fix a string to only have the file name, removing starting at the first space of whatever is quoted.
+
+ @param[in] FileName The filename to start with.
+
+ @retval NULL FileName was invalid.
+ @return The modified FileName.
+**/
+CHAR16*
+EFIAPI
+FixFileName (
+ IN CHAR16 *FileName
+ )
+{
+ CHAR16 *Copy;
+ CHAR16 *TempLocation;
+
+ if (FileName == NULL) {
+ return (NULL);
+ }
+
+ if (FileName[0] == L'\"') {
+ Copy = FileName+1;
+ if ((TempLocation = StrStr(Copy , L"\"")) != NULL) {
+ TempLocation[0] = CHAR_NULL;
+ }
+ } else {
+ Copy = FileName;
+ while(Copy[0] == L' ') {
+ Copy++;
+ }
+ if ((TempLocation = StrStr(Copy , L" ")) != NULL) {
+ TempLocation[0] = CHAR_NULL;
+ }
+ }
+
+ if (Copy[0] == CHAR_NULL) {
+ return (NULL);
+ }
+
+ return (Copy);
+}
+
+/**
+ Fix a string to only have the environment variable name, removing starting at the first space of whatever is quoted and removing the leading and trailing %.
+
+ @param[in] FileName The filename to start with.
+
+ @retval NULL FileName was invalid.
+ @return The modified FileName.
+**/
+CHAR16*
+EFIAPI
+FixVarName (
+ IN CHAR16 *FileName
+ )
+{
+ CHAR16 *Copy;
+ CHAR16 *TempLocation;
+
+ Copy = FileName;
+
+ if (FileName[0] == L'%') {
+ Copy = FileName+1;
+ if ((TempLocation = StrStr(Copy , L"%")) != NULL) {
+ TempLocation[0] = CHAR_NULL;
+ }
+ }
+
+ return (FixFileName(Copy));
+}
+
+/**
+ Remove the unicode file tag from the begining of the file buffer since that will not be
+ used by StdIn.
+
+ @param[in] Handle Pointer to the handle of the file to be processed.
+
+ @retval EFI_SUCCESS The unicode file tag has been moved successfully.
+**/
+EFI_STATUS
+EFIAPI
+RemoveFileTag(
+ IN SHELL_FILE_HANDLE *Handle
+ )
+{
+ UINTN CharSize;
+ CHAR16 CharBuffer;
+
+ CharSize = sizeof(CHAR16);
+ CharBuffer = 0;
+ gEfiShellProtocol->ReadFile(*Handle, &CharSize, &CharBuffer);
+ if (CharBuffer != gUnicodeFileTag) {
+ gEfiShellProtocol->SetFilePosition(*Handle, 0);
+ }
+ return (EFI_SUCCESS);
+}
+
+/**
+ Write the unicode file tag to the specified file.
+
+ It is the caller's responsibility to ensure that
+ ShellInfoObject.NewEfiShellProtocol has been initialized before calling this
+ function.
+
+ @param[in] FileHandle The file to write the unicode file tag to.
+
+ @return Status code from ShellInfoObject.NewEfiShellProtocol->WriteFile.
+**/
+EFI_STATUS
+WriteFileTag (
+ IN SHELL_FILE_HANDLE FileHandle
+ )
+{
+ CHAR16 FileTag;
+ UINTN Size;
+ EFI_STATUS Status;
+
+ FileTag = gUnicodeFileTag;
+ Size = sizeof FileTag;
+ Status = ShellInfoObject.NewEfiShellProtocol->WriteFile (FileHandle, &Size,
+ &FileTag);
+ ASSERT (EFI_ERROR (Status) || Size == sizeof FileTag);
+ return Status;
+}
+
+
+/**
+ Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
+ structure by parsing NewCommandLine. The current values are returned to the
+ user.
+
+ This will also update the system table.
+
+ @param[in, out] ShellParameters Pointer to parameter structure to modify.
+ @param[in] NewCommandLine The new command line to parse and use.
+ @param[out] OldStdIn Pointer to old StdIn.
+ @param[out] OldStdOut Pointer to old StdOut.
+ @param[out] OldStdErr Pointer to old StdErr.
+ @param[out] SystemTableInfo Pointer to old system table information.
+
+ @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+UpdateStdInStdOutStdErr(
+ IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
+ IN CHAR16 *NewCommandLine,
+ OUT SHELL_FILE_HANDLE *OldStdIn,
+ OUT SHELL_FILE_HANDLE *OldStdOut,
+ OUT SHELL_FILE_HANDLE *OldStdErr,
+ OUT SYSTEM_TABLE_INFO *SystemTableInfo
+ )
+{
+ CHAR16 *CommandLineCopy;
+ CHAR16 *CommandLineWalker;
+ CHAR16 *StdErrFileName;
+ CHAR16 *StdOutFileName;
+ CHAR16 *StdInFileName;
+ CHAR16 *StdInVarName;
+ CHAR16 *StdOutVarName;
+ CHAR16 *StdErrVarName;
+ EFI_STATUS Status;
+ SHELL_FILE_HANDLE TempHandle;
+ UINT64 FileSize;
+ BOOLEAN OutUnicode;
+ BOOLEAN InUnicode;
+ BOOLEAN ErrUnicode;
+ BOOLEAN OutAppend;
+ BOOLEAN ErrAppend;
+ UINTN Size;
+ SPLIT_LIST *Split;
+ CHAR16 *FirstLocation;
+ BOOLEAN Volatile;
+
+ OutUnicode = TRUE;
+ InUnicode = TRUE;
+ AsciiRedirection = FALSE;
+ ErrUnicode = TRUE;
+ StdInVarName = NULL;
+ StdOutVarName = NULL;
+ StdErrVarName = NULL;
+ StdErrFileName = NULL;
+ StdInFileName = NULL;
+ StdOutFileName = NULL;
+ ErrAppend = FALSE;
+ OutAppend = FALSE;
+ CommandLineCopy = NULL;
+ FirstLocation = NULL;
+
+ if (ShellParameters == NULL || SystemTableInfo == NULL || OldStdIn == NULL || OldStdOut == NULL || OldStdErr == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ SystemTableInfo->ConIn = gST->ConIn;
+ SystemTableInfo->ConInHandle = gST->ConsoleInHandle;
+ SystemTableInfo->ConOut = gST->ConOut;
+ SystemTableInfo->ConOutHandle = gST->ConsoleOutHandle;
+ SystemTableInfo->ErrOut = gST->StdErr;
+ SystemTableInfo->ErrOutHandle = gST->StandardErrorHandle;
+ *OldStdIn = ShellParameters->StdIn;
+ *OldStdOut = ShellParameters->StdOut;
+ *OldStdErr = ShellParameters->StdErr;
+
+ if (NewCommandLine == NULL) {
+ return (EFI_SUCCESS);
+ }
+
+ CommandLineCopy = StrnCatGrow(&CommandLineCopy, NULL, NewCommandLine, 0);
+ if (CommandLineCopy == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ Status = EFI_SUCCESS;
+ Split = NULL;
+ FirstLocation = CommandLineCopy + StrLen(CommandLineCopy);
+
+ StripQuotes(CommandLineCopy);
+
+ if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {
+ Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);
+ if (Split != NULL && Split->SplitStdIn != NULL) {
+ ShellParameters->StdIn = Split->SplitStdIn;
+ }
+ if (Split != NULL && Split->SplitStdOut != NULL) {
+ ShellParameters->StdOut = Split->SplitStdOut;
+ }
+ }
+
+ if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>>v ")) != NULL) {
+ FirstLocation = MIN(CommandLineWalker, FirstLocation);
+ SetMem16(CommandLineWalker, 12, L' ');
+ StdErrVarName = CommandLineWalker += 6;
+ ErrAppend = TRUE;
+ if (StrStr(CommandLineWalker, L" 2>>v ") != NULL) {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+ if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>v ")) != NULL) {
+ FirstLocation = MIN(CommandLineWalker, FirstLocation);
+ SetMem16(CommandLineWalker, 12, L' ');
+ StdOutVarName = CommandLineWalker += 6;
+ OutAppend = TRUE;
+ if (StrStr(CommandLineWalker, L" 1>>v ") != NULL) {
+ Status = EFI_NOT_FOUND;
+ }
+ } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>v ")) != NULL) {
+ FirstLocation = MIN(CommandLineWalker, FirstLocation);
+ SetMem16(CommandLineWalker, 10, L' ');
+ StdOutVarName = CommandLineWalker += 5;
+ OutAppend = TRUE;
+ if (StrStr(CommandLineWalker, L" >>v ") != NULL) {
+ Status = EFI_NOT_FOUND;
+ }
+ } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >v ")) != NULL) {
+ FirstLocation = MIN(CommandLineWalker, FirstLocation);
+ SetMem16(CommandLineWalker, 8, L' ');
+ StdOutVarName = CommandLineWalker += 4;
+ OutAppend = FALSE;
+ if (StrStr(CommandLineWalker, L" >v ") != NULL) {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+ if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>a ")) != NULL) {
+ FirstLocation = MIN(CommandLineWalker, FirstLocation);
+ SetMem16(CommandLineWalker, 12, L' ');
+ StdOutFileName = CommandLineWalker += 6;
+ OutAppend = TRUE;
+ OutUnicode = FALSE;
+ if (StrStr(CommandLineWalker, L" 1>>a ") != NULL) {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+ if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>> ")) != NULL) {
+ FirstLocation = MIN(CommandLineWalker, FirstLocation);
+ SetMem16(CommandLineWalker, 10, L' ');
+ if (StdOutFileName != NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ StdOutFileName = CommandLineWalker += 5;
+ OutAppend = TRUE;
+ }
+ if (StrStr(CommandLineWalker, L" 1>> ") != NULL) {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+ if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >> ")) != NULL) {
+ FirstLocation = MIN(CommandLineWalker, FirstLocation);
+ SetMem16(CommandLineWalker, 8, L' ');
+ if (StdOutFileName != NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ StdOutFileName = CommandLineWalker += 4;
+ OutAppend = TRUE;
+ }
+ if (StrStr(CommandLineWalker, L" >> ") != NULL) {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+ if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>a ")) != NULL) {
+ FirstLocation = MIN(CommandLineWalker, FirstLocation);
+ SetMem16(CommandLineWalker, 10, L' ');
+ if (StdOutFileName != NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ StdOutFileName = CommandLineWalker += 5;
+ OutAppend = TRUE;
+ OutUnicode = FALSE;
+ }
+ if (StrStr(CommandLineWalker, L" >>a ") != NULL) {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+ if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>a ")) != NULL) {
+ FirstLocation = MIN(CommandLineWalker, FirstLocation);
+ SetMem16(CommandLineWalker, 10, L' ');
+ if (StdOutFileName != NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ StdOutFileName = CommandLineWalker += 5;
+ OutAppend = FALSE;
+ OutUnicode = FALSE;
+ }
+ if (StrStr(CommandLineWalker, L" 1>a ") != NULL) {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+ if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >a ")) != NULL) {
+ FirstLocation = MIN(CommandLineWalker, FirstLocation);
+ SetMem16(CommandLineWalker, 8, L' ');
+ if (StdOutFileName != NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ StdOutFileName = CommandLineWalker += 4;
+ OutAppend = FALSE;
+ OutUnicode = FALSE;
+ }
+ if (StrStr(CommandLineWalker, L" >a ") != NULL) {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+ if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>> ")) != NULL) {
+ FirstLocation = MIN(CommandLineWalker, FirstLocation);
+ SetMem16(CommandLineWalker, 10, L' ');
+ if (StdErrFileName != NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ StdErrFileName = CommandLineWalker += 5;
+ ErrAppend = TRUE;
+ }
+ if (StrStr(CommandLineWalker, L" 2>> ") != NULL) {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+
+ if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>v ")) != NULL) {
+ FirstLocation = MIN(CommandLineWalker, FirstLocation);
+ SetMem16(CommandLineWalker, 10, L' ');
+ if (StdErrVarName != NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ StdErrVarName = CommandLineWalker += 5;
+ ErrAppend = FALSE;
+ }
+ if (StrStr(CommandLineWalker, L" 2>v ") != NULL) {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+ if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>v ")) != NULL) {
+ FirstLocation = MIN(CommandLineWalker, FirstLocation);
+ SetMem16(CommandLineWalker, 10, L' ');
+ if (StdOutVarName != NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ StdOutVarName = CommandLineWalker += 5;
+ OutAppend = FALSE;
+ }
+ if (StrStr(CommandLineWalker, L" 1>v ") != NULL) {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+ if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>a ")) != NULL) {
+ FirstLocation = MIN(CommandLineWalker, FirstLocation);
+ SetMem16(CommandLineWalker, 10, L' ');
+ if (StdErrFileName != NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ StdErrFileName = CommandLineWalker += 5;
+ ErrAppend = FALSE;
+ ErrUnicode = FALSE;
+ }
+ if (StrStr(CommandLineWalker, L" 2>a ") != NULL) {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+ if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2> ")) != NULL) {
+ FirstLocation = MIN(CommandLineWalker, FirstLocation);
+ SetMem16(CommandLineWalker, 8, L' ');
+ if (StdErrFileName != NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ StdErrFileName = CommandLineWalker += 4;
+ ErrAppend = FALSE;
+ }
+ if (StrStr(CommandLineWalker, L" 2> ") != NULL) {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+
+ if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1> ")) != NULL) {
+ FirstLocation = MIN(CommandLineWalker, FirstLocation);
+ SetMem16(CommandLineWalker, 8, L' ');
+ if (StdOutFileName != NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ StdOutFileName = CommandLineWalker += 4;
+ OutAppend = FALSE;
+ }
+ if (StrStr(CommandLineWalker, L" 1> ") != NULL) {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+
+ if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" > ")) != NULL) {
+ FirstLocation = MIN(CommandLineWalker, FirstLocation);
+ SetMem16(CommandLineWalker, 6, L' ');
+ if (StdOutFileName != NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ StdOutFileName = CommandLineWalker += 3;
+ OutAppend = FALSE;
+ }
+ if (StrStr(CommandLineWalker, L" > ") != NULL) {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+
+ if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" < ")) != NULL) {
+ FirstLocation = MIN(CommandLineWalker, FirstLocation);
+ SetMem16(CommandLineWalker, 6, L' ');
+ if (StdInFileName != NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ StdInFileName = CommandLineWalker += 3;
+ }
+ if (StrStr(CommandLineWalker, L" < ") != NULL) {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+ if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <a ")) != NULL) {
+ FirstLocation = MIN(CommandLineWalker, FirstLocation);
+ SetMem16(CommandLineWalker, 8, L' ');
+ if (StdInFileName != NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ StdInFileName = CommandLineWalker += 4;
+ InUnicode = FALSE;
+ AsciiRedirection = TRUE;
+ }
+ if (StrStr(CommandLineWalker, L" <a ") != NULL) {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+ if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <v ")) != NULL) {
+ FirstLocation = MIN(CommandLineWalker, FirstLocation);
+ SetMem16(CommandLineWalker, 8, L' ');
+ if (StdInVarName != NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ StdInVarName = CommandLineWalker += 4;
+ }
+ if (StrStr(CommandLineWalker, L" <v ") != NULL) {
+ Status = EFI_NOT_FOUND;
+ }
+ }
+
+ //
+ // re-populate the string to support any filenames that were in quotes.
+ //
+ StrnCpyS(CommandLineCopy, StrSize(CommandLineCopy)/sizeof(CHAR16), NewCommandLine, StrLen(NewCommandLine));
+
+ if (FirstLocation != CommandLineCopy + StrLen(CommandLineCopy)
+ && ((UINTN)(FirstLocation - CommandLineCopy) < StrLen(NewCommandLine))
+ ){
+ *(NewCommandLine + (UINTN)(FirstLocation - CommandLineCopy)) = CHAR_NULL;
+ }
+
+ if (!EFI_ERROR(Status)) {
+
+ if (StdErrFileName != NULL) {
+ if ((StdErrFileName = FixFileName(StdErrFileName)) == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+ if (StdOutFileName != NULL) {
+ if ((StdOutFileName = FixFileName(StdOutFileName)) == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+ if (StdInFileName != NULL) {
+ if ((StdInFileName = FixFileName(StdInFileName)) == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+ if (StdErrVarName != NULL) {
+ if ((StdErrVarName = FixVarName(StdErrVarName)) == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+ if (StdOutVarName != NULL) {
+ if ((StdOutVarName = FixVarName(StdOutVarName)) == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+ if (StdInVarName != NULL) {
+ if ((StdInVarName = FixVarName(StdInVarName)) == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // Verify not the same and not duplicating something from a split
+ //
+ if (
+ //
+ // Check that no 2 filenames are the same
+ //
+ (StdErrFileName != NULL && StdOutFileName!= NULL && StringNoCaseCompare(&StdErrFileName, &StdOutFileName) == 0)
+ ||(StdErrFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdErrFileName, &StdInFileName ) == 0)
+ ||(StdOutFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdOutFileName, &StdInFileName ) == 0)
+ //
+ // Check that no 2 variable names are the same
+ //
+ ||(StdErrVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdInVarName ) == 0)
+ ||(StdOutVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdOutVarName , &StdInVarName ) == 0)
+ ||(StdErrVarName != NULL && StdOutVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdOutVarName ) == 0)
+ //
+ // When a split (using | operator) is in place some are not allowed
+ //
+ ||(Split != NULL && Split->SplitStdIn != NULL && (StdInVarName != NULL || StdInFileName != NULL))
+ ||(Split != NULL && Split->SplitStdOut != NULL && (StdOutVarName != NULL || StdOutFileName != NULL))
+ //
+ // Check that nothing is trying to be output to 2 locations.
+ //
+ ||(StdErrFileName != NULL && StdErrVarName != NULL)
+ ||(StdOutFileName != NULL && StdOutVarName != NULL)
+ ||(StdInFileName != NULL && StdInVarName != NULL)
+ //
+ // Check for no volatile environment variables
+ //
+ ||(StdErrVarName != NULL && !EFI_ERROR (IsVolatileEnv (StdErrVarName, &Volatile)) && !Volatile)
+ ||(StdOutVarName != NULL && !EFI_ERROR (IsVolatileEnv (StdOutVarName, &Volatile)) && !Volatile)
+ //
+ // Cant redirect during a reconnect operation.
+ //
+ ||(StrStr(NewCommandLine, L"connect -r") != NULL
+ && (StdOutVarName != NULL || StdOutFileName != NULL || StdErrFileName != NULL || StdErrVarName != NULL))
+ //
+ // Check that filetypes (Unicode/Ascii) do not change during an append
+ //
+ ||(StdOutFileName != NULL && OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && EFI_ERROR(IsUnicodeFile(StdOutFileName))))
+ ||(StdErrFileName != NULL && ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && EFI_ERROR(IsUnicodeFile(StdErrFileName))))
+ ||(StdOutFileName != NULL && !OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && !EFI_ERROR(IsUnicodeFile(StdOutFileName))))
+ ||(StdErrFileName != NULL && !ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && !EFI_ERROR(IsUnicodeFile(StdErrFileName))))
+ ){
+ Status = EFI_INVALID_PARAMETER;
+ ShellParameters->StdIn = *OldStdIn;
+ ShellParameters->StdOut = *OldStdOut;
+ ShellParameters->StdErr = *OldStdErr;
+ } else if (!EFI_ERROR(Status)){
+ //
+ // Open the Std<Whatever> and we should not have conflicts here...
+ //
+
+ //
+ // StdErr to a file
+ //
+ if (StdErrFileName != NULL) {
+ if (!ErrAppend) {
+ //
+ // delete existing file.
+ //
+ ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdErrFileName);
+ }
+ Status = ShellOpenFileByName(StdErrFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);
+ if (!ErrAppend && ErrUnicode && !EFI_ERROR(Status)) {
+ Status = WriteFileTag (TempHandle);
+ }
+ if (!ErrUnicode && !EFI_ERROR(Status)) {
+ TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);
+ ASSERT(TempHandle != NULL);
+ }
+ if (!EFI_ERROR(Status)) {
+ ShellParameters->StdErr = TempHandle;
+ gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle, gST->StdErr);
+ }
+ }
+
+ //
+ // StdOut to a file
+ //
+ if (!EFI_ERROR(Status) && StdOutFileName != NULL) {
+ if (!OutAppend) {
+ //
+ // delete existing file.
+ //
+ ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdOutFileName);
+ }
+ Status = ShellOpenFileByName(StdOutFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);
+ if (TempHandle == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ if (StrStr(StdOutFileName, L"NUL")==StdOutFileName) {
+ //no-op
+ } else if (!OutAppend && OutUnicode && !EFI_ERROR(Status)) {
+ Status = WriteFileTag (TempHandle);
+ } else if (OutAppend) {
+ Status = ShellInfoObject.NewEfiShellProtocol->GetFileSize(TempHandle, &FileSize);
+ if (!EFI_ERROR(Status)) {
+ //
+ // When appending to a new unicode file, write the file tag.
+ // Otherwise (ie. when appending to a new ASCII file, or an
+ // existent file with any encoding), just seek to the end.
+ //
+ Status = (FileSize == 0 && OutUnicode) ?
+ WriteFileTag (TempHandle) :
+ ShellInfoObject.NewEfiShellProtocol->SetFilePosition (
+ TempHandle,
+ FileSize);
+ }
+ }
+ if (!OutUnicode && !EFI_ERROR(Status)) {
+ TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);
+ ASSERT(TempHandle != NULL);
+ }
+ if (!EFI_ERROR(Status)) {
+ ShellParameters->StdOut = TempHandle;
+ gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle, gST->ConOut);
+ }
+ }
+ }
+
+ //
+ // StdOut to a var
+ //
+ if (!EFI_ERROR(Status) && StdOutVarName != NULL) {
+ if (!OutAppend) {
+ //
+ // delete existing variable.
+ //
+ SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName, 0, L"");
+ }
+ TempHandle = CreateFileInterfaceEnv(StdOutVarName);
+ ASSERT(TempHandle != NULL);
+ ShellParameters->StdOut = TempHandle;
+ gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle, gST->ConOut);
+ }
+
+ //
+ // StdErr to a var
+ //
+ if (!EFI_ERROR(Status) && StdErrVarName != NULL) {
+ if (!ErrAppend) {
+ //
+ // delete existing variable.
+ //
+ SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName, 0, L"");
+ }
+ TempHandle = CreateFileInterfaceEnv(StdErrVarName);
+ ASSERT(TempHandle != NULL);
+ ShellParameters->StdErr = TempHandle;
+ gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle, gST->StdErr);
+ }
+
+ //
+ // StdIn from a var
+ //
+ if (!EFI_ERROR(Status) && StdInVarName != NULL) {
+ TempHandle = CreateFileInterfaceEnv(StdInVarName);
+ if (TempHandle == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ if (!InUnicode) {
+ TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);
+ }
+ Size = 0;
+ if (TempHandle == NULL || ((EFI_FILE_PROTOCOL*)TempHandle)->Read(TempHandle, &Size, NULL) != EFI_BUFFER_TOO_SMALL) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ ShellParameters->StdIn = TempHandle;
+ gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);
+ }
+ }
+ }
+
+ //
+ // StdIn from a file
+ //
+ if (!EFI_ERROR(Status) && StdInFileName != NULL) {
+ Status = ShellOpenFileByName(
+ StdInFileName,
+ &TempHandle,
+ EFI_FILE_MODE_READ,
+ 0);
+ if (!EFI_ERROR(Status)) {
+ if (!InUnicode) {
+ //
+ // Create the ASCII->Unicode conversion layer
+ //
+ TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);
+ }
+ ShellParameters->StdIn = TempHandle;
+ gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);
+ }
+ }
+ }
+ }
+ FreePool(CommandLineCopy);
+
+ CalculateEfiHdrCrc(&gST->Hdr);
+
+ if (gST->ConIn == NULL ||gST->ConOut == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ }
+
+ if (Status == EFI_NOT_FOUND) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_REDUNDA_REDIR), ShellInfoObject.HiiHandle);
+ } else if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_REDIR), ShellInfoObject.HiiHandle);
+ }
+
+ return (Status);
+}
+
+/**
+ Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
+ structure with StdIn and StdOut. The current values are de-allocated.
+
+ @param[in, out] ShellParameters Pointer to parameter structure to modify.
+ @param[in] OldStdIn Pointer to old StdIn.
+ @param[in] OldStdOut Pointer to old StdOut.
+ @param[in] OldStdErr Pointer to old StdErr.
+ @param[in] SystemTableInfo Pointer to old system table information.
+**/
+EFI_STATUS
+EFIAPI
+RestoreStdInStdOutStdErr (
+ IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
+ IN SHELL_FILE_HANDLE *OldStdIn,
+ IN SHELL_FILE_HANDLE *OldStdOut,
+ IN SHELL_FILE_HANDLE *OldStdErr,
+ IN SYSTEM_TABLE_INFO *SystemTableInfo
+ )
+{
+ SPLIT_LIST *Split;
+
+ if (ShellParameters == NULL
+ ||OldStdIn == NULL
+ ||OldStdOut == NULL
+ ||OldStdErr == NULL
+ ||SystemTableInfo == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+ if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {
+ Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);
+ } else {
+ Split = NULL;
+ }
+ if (ShellParameters->StdIn != *OldStdIn) {
+ if ((Split != NULL && Split->SplitStdIn != ShellParameters->StdIn) || Split == NULL) {
+ gEfiShellProtocol->CloseFile(ShellParameters->StdIn);
+ }
+ ShellParameters->StdIn = *OldStdIn;
+ }
+ if (ShellParameters->StdOut != *OldStdOut) {
+ if ((Split != NULL && Split->SplitStdOut != ShellParameters->StdOut) || Split == NULL) {
+ gEfiShellProtocol->CloseFile(ShellParameters->StdOut);
+ }
+ ShellParameters->StdOut = *OldStdOut;
+ }
+ if (ShellParameters->StdErr != *OldStdErr) {
+ gEfiShellProtocol->CloseFile(ShellParameters->StdErr);
+ ShellParameters->StdErr = *OldStdErr;
+ }
+
+ if (gST->ConIn != SystemTableInfo->ConIn) {
+ CloseSimpleTextInOnFile(gST->ConIn);
+ gST->ConIn = SystemTableInfo->ConIn;
+ gST->ConsoleInHandle = SystemTableInfo->ConInHandle;
+ }
+ if (gST->ConOut != SystemTableInfo->ConOut) {
+ CloseSimpleTextOutOnFile(gST->ConOut);
+ gST->ConOut = SystemTableInfo->ConOut;
+ gST->ConsoleOutHandle = SystemTableInfo->ConOutHandle;
+ }
+ if (gST->StdErr != SystemTableInfo->ErrOut) {
+ CloseSimpleTextOutOnFile(gST->StdErr);
+ gST->StdErr = SystemTableInfo->ErrOut;
+ gST->StandardErrorHandle = SystemTableInfo->ErrOutHandle;
+ }
+
+ CalculateEfiHdrCrc(&gST->Hdr);
+
+ return (EFI_SUCCESS);
+}
+/**
+ Funcion will replace the current Argc and Argv in the ShellParameters protocol
+ structure by parsing NewCommandLine. The current values are returned to the
+ user.
+
+ If OldArgv or OldArgc is NULL then that value is not returned.
+
+ @param[in, out] ShellParameters Pointer to parameter structure to modify.
+ @param[in] NewCommandLine The new command line to parse and use.
+ @param[in] Type The type of operation.
+ @param[out] OldArgv Pointer to old list of parameters.
+ @param[out] OldArgc Pointer to old number of items in Argv list.
+
+ @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+UpdateArgcArgv(
+ IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
+ IN CONST CHAR16 *NewCommandLine,
+ IN SHELL_OPERATION_TYPES Type,
+ OUT CHAR16 ***OldArgv OPTIONAL,
+ OUT UINTN *OldArgc OPTIONAL
+ )
+{
+ BOOLEAN StripParamQuotation;
+
+ ASSERT(ShellParameters != NULL);
+ StripParamQuotation = TRUE;
+
+ if (OldArgc != NULL) {
+ *OldArgc = ShellParameters->Argc;
+ }
+ if (OldArgc != NULL) {
+ *OldArgv = ShellParameters->Argv;
+ }
+
+ if (Type == Script_File_Name) {
+ StripParamQuotation = FALSE;
+ }
+
+ return ParseCommandLineToArgs( NewCommandLine,
+ StripParamQuotation,
+ &(ShellParameters->Argv),
+ &(ShellParameters->Argc)
+ );
+}
+
+/**
+ Funcion will replace the current Argc and Argv in the ShellParameters protocol
+ structure with Argv and Argc. The current values are de-allocated and the
+ OldArgv must not be deallocated by the caller.
+
+ @param[in, out] ShellParameters pointer to parameter structure to modify
+ @param[in] OldArgv pointer to old list of parameters
+ @param[in] OldArgc pointer to old number of items in Argv list
+**/
+VOID
+EFIAPI
+RestoreArgcArgv(
+ IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
+ IN CHAR16 ***OldArgv,
+ IN UINTN *OldArgc
+ )
+{
+ UINTN LoopCounter;
+ ASSERT(ShellParameters != NULL);
+ ASSERT(OldArgv != NULL);
+ ASSERT(OldArgc != NULL);
+
+ if (ShellParameters->Argv != NULL) {
+ for ( LoopCounter = 0
+ ; LoopCounter < ShellParameters->Argc
+ ; LoopCounter++
+ ){
+ FreePool(ShellParameters->Argv[LoopCounter]);
+ }
+ FreePool(ShellParameters->Argv);
+ }
+ ShellParameters->Argv = *OldArgv;
+ *OldArgv = NULL;
+ ShellParameters->Argc = *OldArgc;
+ *OldArgc = 0;
+}
diff --git a/Core/ShellPkg/Application/Shell/ShellParametersProtocol.h b/Core/ShellPkg/Application/Shell/ShellParametersProtocol.h
new file mode 100644
index 0000000000..1205d92c19
--- /dev/null
+++ b/Core/ShellPkg/Application/Shell/ShellParametersProtocol.h
@@ -0,0 +1,194 @@
+/** @file
+ Member functions of EFI_SHELL_PARAMETERS_PROTOCOL and functions for creation,
+ manipulation, and initialization of EFI_SHELL_PARAMETERS_PROTOCOL.
+
+ Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SHELL_PARAMETERS_PROTOCOL_PROVIDER_HEADER_
+#define _SHELL_PARAMETERS_PROTOCOL_PROVIDER_HEADER_
+
+#include "Shell.h"
+
+typedef enum {
+ Internal_Command,
+ Script_File_Name,
+ Efi_Application,
+ File_Sys_Change,
+ Unknown_Invalid
+} SHELL_OPERATION_TYPES;
+
+/**
+ creates a new EFI_SHELL_PARAMETERS_PROTOCOL instance and populates it and then
+ installs it on our handle and if there is an existing version of the protocol
+ that one is cached for removal later.
+
+ @param[in, out] NewShellParameters on a successful return, a pointer to pointer
+ to the newly installed interface.
+ @param[in, out] RootShellInstance on a successful return, pointer to boolean.
+ TRUE if this is the root shell instance.
+
+ @retval EFI_SUCCESS the operation completed successfully.
+ @return other the operation failed.
+ @sa ReinstallProtocolInterface
+ @sa InstallProtocolInterface
+ @sa ParseCommandLineToArgs
+**/
+EFI_STATUS
+EFIAPI
+CreatePopulateInstallShellParametersProtocol (
+ IN OUT EFI_SHELL_PARAMETERS_PROTOCOL **NewShellParameters,
+ IN OUT BOOLEAN *RootShellInstance
+ );
+
+/**
+ frees all memory used by createion and installation of shell parameters protocol
+ and if there was an old version installed it will restore that one.
+
+ @param NewShellParameters the interface of EFI_SHELL_PARAMETERS_PROTOCOL that is
+ being cleaned up.
+
+ @retval EFI_SUCCESS the cleanup was successful
+ @return other the cleanup failed
+ @sa ReinstallProtocolInterface
+ @sa UninstallProtocolInterface
+**/
+EFI_STATUS
+EFIAPI
+CleanUpShellParametersProtocol (
+ IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *NewShellParameters
+ );
+
+/**
+ Funcion will replace the current Argc and Argv in the ShellParameters protocol
+ structure by parsing NewCommandLine. The current values are returned to the
+ user.
+
+ @param[in, out] ShellParameters pointer to parameter structure to modify
+ @param[in] NewCommandLine the new command line to parse and use
+ @param[in] Type the type of operation.
+ @param[out] OldArgv pointer to old list of parameters
+ @param[out] OldArgc pointer to old number of items in Argv list
+
+ @retval EFI_SUCCESS operation was sucessful, Argv and Argc are valid
+ @retval EFI_OUT_OF_RESOURCES a memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+UpdateArgcArgv(
+ IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
+ IN CONST CHAR16 *NewCommandLine,
+ IN SHELL_OPERATION_TYPES Type,
+ OUT CHAR16 ***OldArgv,
+ OUT UINTN *OldArgc
+ );
+
+/**
+ Funcion will replace the current Argc and Argv in the ShellParameters protocol
+ structure with Argv and Argc. The current values are de-allocated and the
+ OldArgv must not be deallocated by the caller.
+
+ @param[in, out] ShellParameters pointer to parameter structure to modify
+ @param[in] OldArgv pointer to old list of parameters
+ @param[in] OldArgc pointer to old number of items in Argv list
+**/
+VOID
+EFIAPI
+RestoreArgcArgv(
+ IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
+ IN CHAR16 ***OldArgv,
+ IN UINTN *OldArgc
+ );
+
+typedef struct {
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL *ConIn;
+ EFI_HANDLE ConInHandle;
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ConOut;
+ EFI_HANDLE ConOutHandle;
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *ErrOut;
+ EFI_HANDLE ErrOutHandle;
+} SYSTEM_TABLE_INFO;
+
+/**
+ Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
+ structure by parsing NewCommandLine. The current values are returned to the
+ user.
+
+ This will also update the system table.
+
+ @param[in, out] ShellParameters Pointer to parameter structure to modify.
+ @param[in] NewCommandLine The new command line to parse and use.
+ @param[out] OldStdIn Pointer to old StdIn.
+ @param[out] OldStdOut Pointer to old StdOut.
+ @param[out] OldStdErr Pointer to old StdErr.
+ @param[out] SystemTableInfo Pointer to old system table information.
+
+ @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+UpdateStdInStdOutStdErr(
+ IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
+ IN CHAR16 *NewCommandLine,
+ OUT SHELL_FILE_HANDLE *OldStdIn,
+ OUT SHELL_FILE_HANDLE *OldStdOut,
+ OUT SHELL_FILE_HANDLE *OldStdErr,
+ OUT SYSTEM_TABLE_INFO *SystemTableInfo
+ );
+
+/**
+ Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
+ structure with StdIn and StdOut. The current values are de-allocated.
+
+ @param[in, out] ShellParameters Pointer to parameter structure to modify.
+ @param[in] OldStdIn Pointer to old StdIn.
+ @param[in] OldStdOut Pointer to old StdOut.
+ @param[in] OldStdErr Pointer to old StdErr.
+ @param[in] SystemTableInfo Pointer to old system table information.
+**/
+EFI_STATUS
+EFIAPI
+RestoreStdInStdOutStdErr (
+ IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
+ IN SHELL_FILE_HANDLE *OldStdIn,
+ IN SHELL_FILE_HANDLE *OldStdOut,
+ IN SHELL_FILE_HANDLE *OldStdErr,
+ IN SYSTEM_TABLE_INFO *SystemTableInfo
+ );
+
+/**
+ function to populate Argc and Argv.
+
+ This function parses the CommandLine and divides it into standard C style Argc/Argv
+ parameters for inclusion in EFI_SHELL_PARAMETERS_PROTOCOL. this supports space
+ delimited and quote surrounded parameter definition.
+
+ @param[in] CommandLine String of command line to parse
+ @param[in] StripQuotation if TRUE then strip the quotation marks surrounding
+ the parameters.
+ @param[in, out] Argv pointer to array of strings; one for each parameter
+ @param[in, out] Argc pointer to number of strings in Argv array
+
+ @return EFI_SUCCESS the operation was sucessful
+ @return EFI_OUT_OF_RESOURCES a memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+ParseCommandLineToArgs(
+ IN CONST CHAR16 *CommandLine,
+ IN BOOLEAN StripQuotation,
+ IN OUT CHAR16 ***Argv,
+ IN OUT UINTN *Argc
+ );
+
+#endif //_SHELL_PARAMETERS_PROTOCOL_PROVIDER_HEADER_
+
diff --git a/Core/ShellPkg/Application/Shell/ShellProtocol.c b/Core/ShellPkg/Application/Shell/ShellProtocol.c
new file mode 100644
index 0000000000..55a1e43f06
--- /dev/null
+++ b/Core/ShellPkg/Application/Shell/ShellProtocol.c
@@ -0,0 +1,3939 @@
+/** @file
+ Member functions of EFI_SHELL_PROTOCOL and functions for creation,
+ manipulation, and initialization of EFI_SHELL_PROTOCOL.
+
+ (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Shell.h"
+
+#define INIT_NAME_BUFFER_SIZE 128
+
+/**
+ Close an open file handle.
+
+ This function closes a specified file handle. All "dirty" cached file data is
+ flushed to the device, and the file is closed. In all cases the handle is
+ closed.
+
+ @param[in] FileHandle The file handle to close.
+
+ @retval EFI_SUCCESS The file handle was closed successfully.
+**/
+EFI_STATUS
+EFIAPI
+EfiShellClose (
+ IN SHELL_FILE_HANDLE FileHandle
+ )
+{
+ ShellFileHandleRemove(FileHandle);
+ return (FileHandleClose(ConvertShellHandleToEfiFileProtocol(FileHandle)));
+}
+
+/**
+ Internal worker to determine whether there is a BlockIo somewhere
+ upon the device path specified.
+
+ @param[in] DevicePath The device path to test.
+
+ @retval TRUE gEfiBlockIoProtocolGuid was installed on a handle with this device path
+ @retval FALSE gEfiBlockIoProtocolGuid was not found.
+**/
+BOOLEAN
+EFIAPI
+InternalShellProtocolIsBlockIoPresent(
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathCopy;
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+
+ Handle = NULL;
+
+ DevicePathCopy = (EFI_DEVICE_PATH_PROTOCOL*)DevicePath;
+ Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid, &DevicePathCopy, &Handle);
+
+ if ((Handle != NULL) && (!EFI_ERROR(Status))) {
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/**
+ Internal worker to determine whether there is a file system somewhere
+ upon the device path specified.
+
+ @param[in] DevicePath The device path to test.
+
+ @retval TRUE gEfiSimpleFileSystemProtocolGuid was installed on a handle with this device path
+ @retval FALSE gEfiSimpleFileSystemProtocolGuid was not found.
+**/
+BOOLEAN
+EFIAPI
+InternalShellProtocolIsSimpleFileSystemPresent(
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathCopy;
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+
+ Handle = NULL;
+
+ DevicePathCopy = (EFI_DEVICE_PATH_PROTOCOL*)DevicePath;
+ Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid, &DevicePathCopy, &Handle);
+
+ if ((Handle != NULL) && (!EFI_ERROR(Status))) {
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/**
+ Internal worker debug helper function to print out maps as they are added.
+
+ @param[in] Mapping string mapping that has been added
+ @param[in] DevicePath pointer to device path that has been mapped.
+
+ @retval EFI_SUCCESS the operation was successful.
+ @return other an error ocurred
+
+ @sa LocateHandle
+ @sa OpenProtocol
+**/
+EFI_STATUS
+EFIAPI
+InternalShellProtocolDebugPrintMessage (
+ IN CONST CHAR16 *Mapping,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *Temp;
+
+ Status = EFI_SUCCESS;
+ DEBUG_CODE_BEGIN();
+
+ if (Mapping != NULL) {
+ DEBUG((EFI_D_INFO, "Added new map item:\"%S\"\r\n", Mapping));
+ }
+ Temp = ConvertDevicePathToText(DevicePath, TRUE, TRUE);
+ DEBUG((EFI_D_INFO, "DevicePath: %S\r\n", Temp));
+ FreePool(Temp);
+
+ DEBUG_CODE_END();
+ return (Status);
+}
+
+/**
+ This function creates a mapping for a device path.
+
+ If both DeviecPath and Mapping are NULL, this will reset the mapping to default values.
+
+ @param DevicePath Points to the device path. If this is NULL and Mapping points to a valid mapping,
+ then the mapping will be deleted.
+ @param Mapping Points to the NULL-terminated mapping for the device path. Must end with a ':'
+
+ @retval EFI_SUCCESS Mapping created or deleted successfully.
+ @retval EFI_NO_MAPPING There is no handle that corresponds exactly to DevicePath. See the
+ boot service function LocateDevicePath().
+ @retval EFI_ACCESS_DENIED The mapping is a built-in alias.
+ @retval EFI_INVALID_PARAMETER Mapping was NULL
+ @retval EFI_INVALID_PARAMETER Mapping did not end with a ':'
+ @retval EFI_INVALID_PARAMETER DevicePath was not pointing at a device that had a SIMPLE_FILE_SYSTEM_PROTOCOL installed.
+ @retval EFI_NOT_FOUND There was no mapping found to delete
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed
+**/
+EFI_STATUS
+EFIAPI
+EfiShellSetMap(
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL,
+ IN CONST CHAR16 *Mapping
+ )
+{
+ EFI_STATUS Status;
+ SHELL_MAP_LIST *MapListNode;
+
+ if (Mapping == NULL){
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ if (Mapping[StrLen(Mapping)-1] != ':') {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ //
+ // Delete the mapping
+ //
+ if (DevicePath == NULL) {
+ if (IsListEmpty(&gShellMapList.Link)) {
+ return (EFI_NOT_FOUND);
+ }
+ for ( MapListNode = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link)
+ ; !IsNull(&gShellMapList.Link, &MapListNode->Link)
+ ; MapListNode = (SHELL_MAP_LIST *)GetNextNode(&gShellMapList.Link, &MapListNode->Link)
+ ){
+ if (StringNoCaseCompare(&MapListNode->MapName, &Mapping) == 0) {
+ RemoveEntryList(&MapListNode->Link);
+ SHELL_FREE_NON_NULL(MapListNode->DevicePath);
+ SHELL_FREE_NON_NULL(MapListNode->MapName);
+ SHELL_FREE_NON_NULL(MapListNode->CurrentDirectoryPath);
+ FreePool(MapListNode);
+ return (EFI_SUCCESS);
+ }
+ } // for loop
+
+ //
+ // We didnt find one to delete
+ //
+ return (EFI_NOT_FOUND);
+ }
+
+ //
+ // make sure this is a valid to add device path
+ //
+ ///@todo add BlockIo to this test...
+ if (!InternalShellProtocolIsSimpleFileSystemPresent(DevicePath)
+ && !InternalShellProtocolIsBlockIoPresent(DevicePath)) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ //
+ // First make sure there is no old mapping
+ //
+ Status = EfiShellSetMap(NULL, Mapping);
+ if ((Status != EFI_SUCCESS) && (Status != EFI_NOT_FOUND)) {
+ return (Status);
+ }
+
+ //
+ // now add the new one.
+ //
+ Status = ShellCommandAddMapItemAndUpdatePath(Mapping, DevicePath, 0, FALSE);
+
+ return(Status);
+}
+
+/**
+ Gets the device path from the mapping.
+
+ This function gets the device path associated with a mapping.
+
+ @param Mapping A pointer to the mapping
+
+ @retval !=NULL Pointer to the device path that corresponds to the
+ device mapping. The returned pointer does not need
+ to be freed.
+ @retval NULL There is no device path associated with the
+ specified mapping.
+**/
+CONST EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+EfiShellGetDevicePathFromMap(
+ IN CONST CHAR16 *Mapping
+ )
+{
+ SHELL_MAP_LIST *MapListItem;
+ CHAR16 *NewName;
+ UINTN Size;
+
+ NewName = NULL;
+ Size = 0;
+
+ StrnCatGrow(&NewName, &Size, Mapping, 0);
+ if (Mapping[StrLen(Mapping)-1] != L':') {
+ StrnCatGrow(&NewName, &Size, L":", 0);
+ }
+
+ MapListItem = ShellCommandFindMapItem(NewName);
+
+ FreePool(NewName);
+
+ if (MapListItem != NULL) {
+ return (MapListItem->DevicePath);
+ }
+ return(NULL);
+}
+
+/**
+ Gets the mapping(s) that most closely matches the device path.
+
+ This function gets the mapping which corresponds to the device path *DevicePath. If
+ there is no exact match, then the mapping which most closely matches *DevicePath
+ is returned, and *DevicePath is updated to point to the remaining portion of the
+ device path. If there is an exact match, the mapping is returned and *DevicePath
+ points to the end-of-device-path node.
+
+ If there are multiple map names they will be semi-colon seperated in the
+ NULL-terminated string.
+
+ @param DevicePath On entry, points to a device path pointer. On
+ exit, updates the pointer to point to the
+ portion of the device path after the mapping.
+
+ @retval NULL No mapping was found.
+ @return !=NULL Pointer to NULL-terminated mapping. The buffer
+ is callee allocated and should be freed by the caller.
+**/
+CONST CHAR16 *
+EFIAPI
+EfiShellGetMapFromDevicePath(
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ )
+{
+ SHELL_MAP_LIST *Node;
+ CHAR16 *PathForReturn;
+ UINTN PathSize;
+// EFI_HANDLE PathHandle;
+// EFI_HANDLE MapHandle;
+// EFI_STATUS Status;
+// EFI_DEVICE_PATH_PROTOCOL *DevicePathCopy;
+// EFI_DEVICE_PATH_PROTOCOL *MapPathCopy;
+
+ if (DevicePath == NULL || *DevicePath == NULL) {
+ return (NULL);
+ }
+
+ PathForReturn = NULL;
+ PathSize = 0;
+
+ for ( Node = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link)
+ ; !IsNull(&gShellMapList.Link, &Node->Link)
+ ; Node = (SHELL_MAP_LIST *)GetNextNode(&gShellMapList.Link, &Node->Link)
+ ){
+ //
+ // check for exact match
+ //
+ if (DevicePathCompare(DevicePath, &Node->DevicePath) == 0) {
+ ASSERT((PathForReturn == NULL && PathSize == 0) || (PathForReturn != NULL));
+ if (PathSize != 0) {
+ PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, L";", 0);
+ }
+ PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, Node->MapName, 0);
+ }
+ }
+ if (PathForReturn != NULL) {
+ while (!IsDevicePathEndType (*DevicePath)) {
+ *DevicePath = NextDevicePathNode (*DevicePath);
+ }
+ SetDevicePathEndNode (*DevicePath);
+ }
+/*
+ ///@todo finish code for inexact matches.
+ if (PathForReturn == NULL) {
+ PathSize = 0;
+
+ DevicePathCopy = DuplicateDevicePath(*DevicePath);
+ ASSERT(DevicePathCopy != NULL);
+ Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid, &DevicePathCopy, &PathHandle);
+ ASSERT_EFI_ERROR(Status);
+ //
+ // check each of the device paths we have to get the root of the path for consist mappings
+ //
+ for ( Node = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link)
+ ; !IsNull(&gShellMapList.Link, &Node->Link)
+ ; Node = (SHELL_MAP_LIST *)GetNextNode(&gShellMapList.Link, &Node->Link)
+ ){
+ if ((Node->Flags & SHELL_MAP_FLAGS_CONSIST) == 0) {
+ continue;
+ }
+ MapPathCopy = DuplicateDevicePath(Node->DevicePath);
+ ASSERT(MapPathCopy != NULL);
+ Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid, &MapPathCopy, &MapHandle);
+ if (MapHandle == PathHandle) {
+
+ *DevicePath = DevicePathCopy;
+
+ MapPathCopy = NULL;
+ DevicePathCopy = NULL;
+ PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, Node->MapName, 0);
+ PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, L";", 0);
+ break;
+ }
+ }
+ //
+ // now add on the non-consistent mappings
+ //
+ for ( Node = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link)
+ ; !IsNull(&gShellMapList.Link, &Node->Link)
+ ; Node = (SHELL_MAP_LIST *)GetNextNode(&gShellMapList.Link, &Node->Link)
+ ){
+ if ((Node->Flags & SHELL_MAP_FLAGS_CONSIST) != 0) {
+ continue;
+ }
+ MapPathCopy = Node->DevicePath;
+ ASSERT(MapPathCopy != NULL);
+ Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid, &MapPathCopy, &MapHandle);
+ if (MapHandle == PathHandle) {
+ PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, Node->MapName, 0);
+ PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, L";", 0);
+ break;
+ }
+ }
+ }
+*/
+
+ return (AddBufferToFreeList(PathForReturn));
+}
+
+/**
+ Converts a device path to a file system-style path.
+
+ This function converts a device path to a file system path by replacing part, or all, of
+ the device path with the file-system mapping. If there are more than one application
+ file system mappings, the one that most closely matches Path will be used.
+
+ @param Path The pointer to the device path
+
+ @retval NULL the device path could not be found.
+ @return all The pointer of the NULL-terminated file path. The path
+ is callee-allocated and should be freed by the caller.
+**/
+CHAR16 *
+EFIAPI
+EfiShellGetFilePathFromDevicePath(
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *Path
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathCopy;
+ EFI_DEVICE_PATH_PROTOCOL *MapPathCopy;
+ SHELL_MAP_LIST *MapListItem;
+ CHAR16 *PathForReturn;
+ UINTN PathSize;
+ EFI_HANDLE PathHandle;
+ EFI_HANDLE MapHandle;
+ EFI_STATUS Status;
+ FILEPATH_DEVICE_PATH *FilePath;
+ FILEPATH_DEVICE_PATH *AlignedNode;
+
+ PathForReturn = NULL;
+ PathSize = 0;
+
+ DevicePathCopy = (EFI_DEVICE_PATH_PROTOCOL*)Path;
+ ASSERT(DevicePathCopy != NULL);
+ if (DevicePathCopy == NULL) {
+ return (NULL);
+ }
+ ///@todo BlockIo?
+ Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid, &DevicePathCopy, &PathHandle);
+
+ if (EFI_ERROR(Status)) {
+ return (NULL);
+ }
+ //
+ // check each of the device paths we have to get the root of the path
+ //
+ for ( MapListItem = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link)
+ ; !IsNull(&gShellMapList.Link, &MapListItem->Link)
+ ; MapListItem = (SHELL_MAP_LIST *)GetNextNode(&gShellMapList.Link, &MapListItem->Link)
+ ){
+ MapPathCopy = (EFI_DEVICE_PATH_PROTOCOL*)MapListItem->DevicePath;
+ ASSERT(MapPathCopy != NULL);
+ ///@todo BlockIo?
+ Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid, &MapPathCopy, &MapHandle);
+ if (MapHandle == PathHandle) {
+ ASSERT((PathForReturn == NULL && PathSize == 0) || (PathForReturn != NULL));
+ PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, MapListItem->MapName, 0);
+ //
+ // go through all the remaining nodes in the device path
+ //
+ for ( FilePath = (FILEPATH_DEVICE_PATH*)DevicePathCopy
+ ; !IsDevicePathEnd (&FilePath->Header)
+ ; FilePath = (FILEPATH_DEVICE_PATH*)NextDevicePathNode (&FilePath->Header)
+ ){
+ //
+ // If any node is not a file path node, then the conversion can not be completed
+ //
+ if ((DevicePathType(&FilePath->Header) != MEDIA_DEVICE_PATH) ||
+ (DevicePathSubType(&FilePath->Header) != MEDIA_FILEPATH_DP)) {
+ FreePool(PathForReturn);
+ return NULL;
+ }
+
+ //
+ // append the path part onto the filepath.
+ //
+ ASSERT((PathForReturn == NULL && PathSize == 0) || (PathForReturn != NULL));
+
+ AlignedNode = AllocateCopyPool (DevicePathNodeLength(FilePath), FilePath);
+ if (AlignedNode == NULL) {
+ FreePool (PathForReturn);
+ return NULL;
+ }
+
+ // File Path Device Path Nodes 'can optionally add a "\" separator to
+ // the beginning and/or the end of the Path Name string.'
+ // (UEFI Spec 2.4 section 9.3.6.4).
+ // If necessary, add a "\", but otherwise don't
+ // (This is specified in the above section, and also implied by the
+ // UEFI Shell spec section 3.7)
+ if ((PathSize != 0) &&
+ (PathForReturn != NULL) &&
+ (PathForReturn[PathSize - 1] != L'\\') &&
+ (AlignedNode->PathName[0] != L'\\')) {
+ PathForReturn = StrnCatGrow (&PathForReturn, &PathSize, L"\\", 1);
+ }
+
+ PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, AlignedNode->PathName, 0);
+ FreePool(AlignedNode);
+ } // for loop of remaining nodes
+ }
+ if (PathForReturn != NULL) {
+ break;
+ }
+ } // for loop of paths to check
+ return(PathForReturn);
+}
+
+/**
+ Converts a file system style name to a device path.
+
+ This function converts a file system style name to a device path, by replacing any
+ mapping references to the associated device path.
+
+ @param[in] Path The pointer to the path.
+
+ @return The pointer of the file path. The file path is callee
+ allocated and should be freed by the caller.
+ @retval NULL The path could not be found.
+ @retval NULL There was not enough available memory.
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+EfiShellGetDevicePathFromFilePath(
+ IN CONST CHAR16 *Path
+ )
+{
+ CHAR16 *MapName;
+ CHAR16 *NewPath;
+ CONST CHAR16 *Cwd;
+ UINTN Size;
+ CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathCopy;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathCopyForFree;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePathForReturn;
+ EFI_HANDLE Handle;
+ EFI_STATUS Status;
+
+ if (Path == NULL) {
+ return (NULL);
+ }
+
+ MapName = NULL;
+ NewPath = NULL;
+
+ if (StrStr(Path, L":") == NULL) {
+ Cwd = EfiShellGetCurDir(NULL);
+ if (Cwd == NULL) {
+ return (NULL);
+ }
+ Size = StrSize(Cwd) + StrSize(Path);
+ NewPath = AllocateZeroPool(Size);
+ if (NewPath == NULL) {
+ return (NULL);
+ }
+ StrCpyS(NewPath, Size/sizeof(CHAR16), Cwd);
+ StrCatS(NewPath, Size/sizeof(CHAR16), L"\\");
+ if (*Path == L'\\') {
+ Path++;
+ while (PathRemoveLastItem(NewPath)) ;
+ }
+ StrCatS(NewPath, Size/sizeof(CHAR16), Path);
+ DevicePathForReturn = EfiShellGetDevicePathFromFilePath(NewPath);
+ FreePool(NewPath);
+ return (DevicePathForReturn);
+ }
+
+ Size = 0;
+ //
+ // find the part before (but including) the : for the map name
+ //
+ ASSERT((MapName == NULL && Size == 0) || (MapName != NULL));
+ MapName = StrnCatGrow(&MapName, &Size, Path, (StrStr(Path, L":")-Path+1));
+ if (MapName == NULL || MapName[StrLen(MapName)-1] != L':') {
+ return (NULL);
+ }
+
+ //
+ // look up the device path in the map
+ //
+ DevicePath = EfiShellGetDevicePathFromMap(MapName);
+ if (DevicePath == NULL) {
+ //
+ // Must have been a bad Mapname
+ //
+ return (NULL);
+ }
+
+ //
+ // make a copy for LocateDevicePath to modify (also save a pointer to call FreePool with)
+ //
+ DevicePathCopyForFree = DevicePathCopy = DuplicateDevicePath(DevicePath);
+ if (DevicePathCopy == NULL) {
+ FreePool(MapName);
+ return (NULL);
+ }
+
+ //
+ // get the handle
+ //
+ ///@todo BlockIo?
+ Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid, &DevicePathCopy, &Handle);
+ if (EFI_ERROR(Status)) {
+ if (DevicePathCopyForFree != NULL) {
+ FreePool(DevicePathCopyForFree);
+ }
+ FreePool(MapName);
+ return (NULL);
+ }
+
+ //
+ // build the full device path
+ //
+ if (*(Path+StrLen(MapName)+1) == CHAR_NULL) {
+ DevicePathForReturn = FileDevicePath(Handle, L"\\");
+ } else {
+ DevicePathForReturn = FileDevicePath(Handle, Path+StrLen(MapName));
+ }
+
+ FreePool(MapName);
+ if (DevicePathCopyForFree != NULL) {
+ FreePool(DevicePathCopyForFree);
+ }
+
+ return (DevicePathForReturn);
+}
+
+/**
+ Gets the name of the device specified by the device handle.
+
+ This function gets the user-readable name of the device specified by the device
+ handle. If no user-readable name could be generated, then *BestDeviceName will be
+ NULL and EFI_NOT_FOUND will be returned.
+
+ If EFI_DEVICE_NAME_USE_COMPONENT_NAME is set, then the function will return the
+ device's name using the EFI_COMPONENT_NAME2_PROTOCOL, if present on
+ DeviceHandle.
+
+ If EFI_DEVICE_NAME_USE_DEVICE_PATH is set, then the function will return the
+ device's name using the EFI_DEVICE_PATH_PROTOCOL, if present on DeviceHandle.
+ If both EFI_DEVICE_NAME_USE_COMPONENT_NAME and
+ EFI_DEVICE_NAME_USE_DEVICE_PATH are set, then
+ EFI_DEVICE_NAME_USE_COMPONENT_NAME will have higher priority.
+
+ @param DeviceHandle The handle of the device.
+ @param Flags Determines the possible sources of component names.
+ Valid bits are:
+ EFI_DEVICE_NAME_USE_COMPONENT_NAME
+ EFI_DEVICE_NAME_USE_DEVICE_PATH
+ @param Language A pointer to the language specified for the device
+ name, in the same format as described in the UEFI
+ specification, Appendix M
+ @param BestDeviceName On return, points to the callee-allocated NULL-
+ terminated name of the device. If no device name
+ could be found, points to NULL. The name must be
+ freed by the caller...
+
+ @retval EFI_SUCCESS Get the name successfully.
+ @retval EFI_NOT_FOUND Fail to get the device name.
+ @retval EFI_INVALID_PARAMETER Flags did not have a valid bit set.
+ @retval EFI_INVALID_PARAMETER BestDeviceName was NULL
+ @retval EFI_INVALID_PARAMETER DeviceHandle was NULL
+**/
+EFI_STATUS
+EFIAPI
+EfiShellGetDeviceName(
+ IN EFI_HANDLE DeviceHandle,
+ IN EFI_SHELL_DEVICE_NAME_FLAGS Flags,
+ IN CHAR8 *Language,
+ OUT CHAR16 **BestDeviceName
+ )
+{
+ EFI_STATUS Status;
+ EFI_COMPONENT_NAME2_PROTOCOL *CompName2;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_HANDLE *HandleList;
+ UINTN HandleCount;
+ UINTN LoopVar;
+ CHAR16 *DeviceNameToReturn;
+ CHAR8 *Lang;
+ UINTN ParentControllerCount;
+ EFI_HANDLE *ParentControllerBuffer;
+ UINTN ParentDriverCount;
+ EFI_HANDLE *ParentDriverBuffer;
+
+ if (BestDeviceName == NULL ||
+ DeviceHandle == NULL
+ ){
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ //
+ // make sure one of the 2 supported bits is on
+ //
+ if (((Flags & EFI_DEVICE_NAME_USE_COMPONENT_NAME) == 0) &&
+ ((Flags & EFI_DEVICE_NAME_USE_DEVICE_PATH) == 0)) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ DeviceNameToReturn = NULL;
+ *BestDeviceName = NULL;
+ HandleList = NULL;
+ HandleCount = 0;
+ Lang = NULL;
+
+ if ((Flags & EFI_DEVICE_NAME_USE_COMPONENT_NAME) != 0) {
+ Status = ParseHandleDatabaseByRelationship(
+ NULL,
+ DeviceHandle,
+ HR_DRIVER_BINDING_HANDLE|HR_DEVICE_DRIVER,
+ &HandleCount,
+ &HandleList);
+ for (LoopVar = 0; LoopVar < HandleCount ; LoopVar++){
+ //
+ // Go through those handles until we get one that passes for GetComponentName
+ //
+ Status = gBS->OpenProtocol(
+ HandleList[LoopVar],
+ &gEfiComponentName2ProtocolGuid,
+ (VOID**)&CompName2,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR(Status)) {
+ Status = gBS->OpenProtocol(
+ HandleList[LoopVar],
+ &gEfiComponentNameProtocolGuid,
+ (VOID**)&CompName2,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ }
+
+ if (EFI_ERROR(Status)) {
+ continue;
+ }
+ Lang = GetBestLanguageForDriver(CompName2->SupportedLanguages, Language, FALSE);
+ Status = CompName2->GetControllerName(CompName2, DeviceHandle, NULL, Lang, &DeviceNameToReturn);
+ FreePool(Lang);
+ Lang = NULL;
+ if (!EFI_ERROR(Status) && DeviceNameToReturn != NULL) {
+ break;
+ }
+ }
+ if (HandleList != NULL) {
+ FreePool(HandleList);
+ }
+
+ //
+ // Now check the parent controller using this as the child.
+ //
+ if (DeviceNameToReturn == NULL){
+ PARSE_HANDLE_DATABASE_PARENTS(DeviceHandle, &ParentControllerCount, &ParentControllerBuffer);
+ for (LoopVar = 0 ; LoopVar < ParentControllerCount ; LoopVar++) {
+ PARSE_HANDLE_DATABASE_UEFI_DRIVERS(ParentControllerBuffer[LoopVar], &ParentDriverCount, &ParentDriverBuffer);
+ for (HandleCount = 0 ; HandleCount < ParentDriverCount ; HandleCount++) {
+ //
+ // try using that driver's component name with controller and our driver as the child.
+ //
+ Status = gBS->OpenProtocol(
+ ParentDriverBuffer[HandleCount],
+ &gEfiComponentName2ProtocolGuid,
+ (VOID**)&CompName2,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR(Status)) {
+ Status = gBS->OpenProtocol(
+ ParentDriverBuffer[HandleCount],
+ &gEfiComponentNameProtocolGuid,
+ (VOID**)&CompName2,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ }
+
+ if (EFI_ERROR(Status)) {
+ continue;
+ }
+ Lang = GetBestLanguageForDriver(CompName2->SupportedLanguages, Language, FALSE);
+ Status = CompName2->GetControllerName(CompName2, ParentControllerBuffer[LoopVar], DeviceHandle, Lang, &DeviceNameToReturn);
+ FreePool(Lang);
+ Lang = NULL;
+ if (!EFI_ERROR(Status) && DeviceNameToReturn != NULL) {
+ break;
+ }
+
+
+
+ }
+ SHELL_FREE_NON_NULL(ParentDriverBuffer);
+ if (!EFI_ERROR(Status) && DeviceNameToReturn != NULL) {
+ break;
+ }
+ }
+ SHELL_FREE_NON_NULL(ParentControllerBuffer);
+ }
+ //
+ // dont return on fail since we will try device path if that bit is on
+ //
+ if (DeviceNameToReturn != NULL){
+ ASSERT(BestDeviceName != NULL);
+ StrnCatGrow(BestDeviceName, NULL, DeviceNameToReturn, 0);
+ return (EFI_SUCCESS);
+ }
+ }
+ if ((Flags & EFI_DEVICE_NAME_USE_DEVICE_PATH) != 0) {
+ Status = gBS->OpenProtocol(
+ DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID**)&DevicePath,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (!EFI_ERROR(Status)) {
+ //
+ // use device path to text on the device path
+ //
+ *BestDeviceName = ConvertDevicePathToText(DevicePath, TRUE, TRUE);
+ return (EFI_SUCCESS);
+ }
+ }
+ //
+ // none of the selected bits worked.
+ //
+ return (EFI_NOT_FOUND);
+}
+
+/**
+ Opens the root directory of a device on a handle
+
+ This function opens the root directory of a device and returns a file handle to it.
+
+ @param DeviceHandle The handle of the device that contains the volume.
+ @param FileHandle On exit, points to the file handle corresponding to the root directory on the
+ device.
+
+ @retval EFI_SUCCESS Root opened successfully.
+ @retval EFI_NOT_FOUND EFI_SIMPLE_FILE_SYSTEM could not be found or the root directory
+ could not be opened.
+ @retval EFI_VOLUME_CORRUPTED The data structures in the volume were corrupted.
+ @retval EFI_DEVICE_ERROR The device had an error
+**/
+EFI_STATUS
+EFIAPI
+EfiShellOpenRootByHandle(
+ IN EFI_HANDLE DeviceHandle,
+ OUT SHELL_FILE_HANDLE *FileHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem;
+ EFI_FILE_PROTOCOL *RealFileHandle;
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+
+ //
+ // get the simple file system interface
+ //
+ Status = gBS->OpenProtocol(DeviceHandle,
+ &gEfiSimpleFileSystemProtocolGuid,
+ (VOID**)&SimpleFileSystem,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR(Status)) {
+ return (EFI_NOT_FOUND);
+ }
+
+ Status = gBS->OpenProtocol(DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID**)&DevPath,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR(Status)) {
+ return (EFI_NOT_FOUND);
+ }
+ //
+ // Open the root volume now...
+ //
+ Status = SimpleFileSystem->OpenVolume(SimpleFileSystem, &RealFileHandle);
+ *FileHandle = ConvertEfiFileProtocolToShellHandle(RealFileHandle, EfiShellGetMapFromDevicePath(&DevPath));
+ return (Status);
+}
+
+/**
+ Opens the root directory of a device.
+
+ This function opens the root directory of a device and returns a file handle to it.
+
+ @param DevicePath Points to the device path corresponding to the device where the
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL is installed.
+ @param FileHandle On exit, points to the file handle corresponding to the root directory on the
+ device.
+
+ @retval EFI_SUCCESS Root opened successfully.
+ @retval EFI_NOT_FOUND EFI_SIMPLE_FILE_SYSTEM could not be found or the root directory
+ could not be opened.
+ @retval EFI_VOLUME_CORRUPTED The data structures in the volume were corrupted.
+ @retval EFI_DEVICE_ERROR The device had an error
+ @retval EFI_INVALID_PARAMETER FileHandle is NULL.
+**/
+EFI_STATUS
+EFIAPI
+EfiShellOpenRoot(
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT SHELL_FILE_HANDLE *FileHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+
+ if (FileHandle == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ //
+ // find the handle of the device with that device handle and the file system
+ //
+ ///@todo BlockIo?
+ Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid,
+ &DevicePath,
+ &Handle);
+ if (EFI_ERROR(Status)) {
+ return (EFI_NOT_FOUND);
+ }
+
+ return (EfiShellOpenRootByHandle(Handle, FileHandle));
+}
+
+/**
+ Returns whether any script files are currently being processed.
+
+ @retval TRUE There is at least one script file active.
+ @retval FALSE No script files are active now.
+
+**/
+BOOLEAN
+EFIAPI
+EfiShellBatchIsActive (
+ VOID
+ )
+{
+ if (ShellCommandGetCurrentScriptFile() == NULL) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+/**
+ Worker function to open a file based on a device path. this will open the root
+ of the volume and then traverse down to the file itself.
+
+ @param DevicePath Device Path of the file.
+ @param FileHandle Pointer to the file upon a successful return.
+ @param OpenMode mode to open file in.
+ @param Attributes the File Attributes to use when creating a new file.
+
+ @retval EFI_SUCCESS the file is open and FileHandle is valid
+ @retval EFI_UNSUPPORTED the device path cotained non-path elements
+ @retval other an error ocurred.
+**/
+EFI_STATUS
+EFIAPI
+InternalOpenFileDevicePath(
+ IN OUT EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT SHELL_FILE_HANDLE *FileHandle,
+ IN UINT64 OpenMode,
+ IN UINT64 Attributes OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ FILEPATH_DEVICE_PATH *FilePathNode;
+ EFI_HANDLE Handle;
+ SHELL_FILE_HANDLE ShellHandle;
+ EFI_FILE_PROTOCOL *Handle1;
+ EFI_FILE_PROTOCOL *Handle2;
+ FILEPATH_DEVICE_PATH *AlignedNode;
+
+ if (FileHandle == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+ *FileHandle = NULL;
+ Handle1 = NULL;
+ Handle2 = NULL;
+ Handle = NULL;
+ ShellHandle = NULL;
+ FilePathNode = NULL;
+ AlignedNode = NULL;
+
+ Status = EfiShellOpenRoot(DevicePath, &ShellHandle);
+
+ if (!EFI_ERROR(Status)) {
+ Handle1 = ConvertShellHandleToEfiFileProtocol(ShellHandle);
+ if (Handle1 != NULL) {
+ //
+ // chop off the begining part before the file system part...
+ //
+ ///@todo BlockIo?
+ Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid,
+ &DevicePath,
+ &Handle);
+ if (!EFI_ERROR(Status)) {
+ //
+ // To access as a file system, the file path should only
+ // contain file path components. Follow the file path nodes
+ // and find the target file
+ //
+ for ( FilePathNode = (FILEPATH_DEVICE_PATH *)DevicePath
+ ; !IsDevicePathEnd (&FilePathNode->Header)
+ ; FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header)
+ ){
+ SHELL_FREE_NON_NULL(AlignedNode);
+ AlignedNode = AllocateCopyPool (DevicePathNodeLength(FilePathNode), FilePathNode);
+ //
+ // For file system access each node should be a file path component
+ //
+ if (DevicePathType (&FilePathNode->Header) != MEDIA_DEVICE_PATH ||
+ DevicePathSubType (&FilePathNode->Header) != MEDIA_FILEPATH_DP
+ ) {
+ Status = EFI_UNSUPPORTED;
+ break;
+ }
+
+ //
+ // Open this file path node
+ //
+ Handle2 = Handle1;
+ Handle1 = NULL;
+
+ //
+ // if this is the last node in the DevicePath always create (if that was requested).
+ //
+ if (IsDevicePathEnd ((NextDevicePathNode (&FilePathNode->Header)))) {
+ Status = Handle2->Open (
+ Handle2,
+ &Handle1,
+ AlignedNode->PathName,
+ OpenMode,
+ Attributes
+ );
+ } else {
+
+ //
+ // This is not the last node and we dont want to 'create' existing
+ // directory entries...
+ //
+
+ //
+ // open without letting it create
+ // prevents error on existing files/directories
+ //
+ Status = Handle2->Open (
+ Handle2,
+ &Handle1,
+ AlignedNode->PathName,
+ OpenMode &~EFI_FILE_MODE_CREATE,
+ Attributes
+ );
+ //
+ // if above failed now open and create the 'item'
+ // if OpenMode EFI_FILE_MODE_CREATE bit was on (but disabled above)
+ //
+ if ((EFI_ERROR (Status)) && ((OpenMode & EFI_FILE_MODE_CREATE) != 0)) {
+ Status = Handle2->Open (
+ Handle2,
+ &Handle1,
+ AlignedNode->PathName,
+ OpenMode,
+ Attributes
+ );
+ }
+ }
+ //
+ // Close the last node
+ //
+ ShellInfoObject.NewEfiShellProtocol->CloseFile (Handle2);
+
+ //
+ // If there's been an error, stop
+ //
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ } // for loop
+ }
+ }
+ }
+ SHELL_FREE_NON_NULL(AlignedNode);
+ if (EFI_ERROR(Status)) {
+ if (Handle1 != NULL) {
+ ShellInfoObject.NewEfiShellProtocol->CloseFile(Handle1);
+ }
+ } else {
+ *FileHandle = ConvertEfiFileProtocolToShellHandle(Handle1, ShellFileHandleGetPath(ShellHandle));
+ }
+ return (Status);
+}
+
+/**
+ Creates a file or directory by name.
+
+ This function creates an empty new file or directory with the specified attributes and
+ returns the new file's handle. If the file already exists and is read-only, then
+ EFI_INVALID_PARAMETER will be returned.
+
+ If the file already existed, it is truncated and its attributes updated. If the file is
+ created successfully, the FileHandle is the file's handle, else, the FileHandle is NULL.
+
+ If the file name begins with >v, then the file handle which is returned refers to the
+ shell environment variable with the specified name. If the shell environment variable
+ already exists and is non-volatile then EFI_INVALID_PARAMETER is returned.
+
+ @param FileName Pointer to NULL-terminated file path
+ @param FileAttribs The new file's attrbiutes. the different attributes are
+ described in EFI_FILE_PROTOCOL.Open().
+ @param FileHandle On return, points to the created file handle or directory's handle
+
+ @retval EFI_SUCCESS The file was opened. FileHandle points to the new file's handle.
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
+ @retval EFI_UNSUPPORTED could not open the file path
+ @retval EFI_NOT_FOUND the specified file could not be found on the devide, or could not
+ file the file system on the device.
+ @retval EFI_NO_MEDIA the device has no medium.
+ @retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no
+ longer supported.
+ @retval EFI_DEVICE_ERROR The device reported an error or can't get the file path according
+ the DirName.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a file for write
+ when the media is write-protected.
+ @retval EFI_ACCESS_DENIED The service denied access to the file.
+ @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file.
+ @retval EFI_VOLUME_FULL The volume is full.
+**/
+EFI_STATUS
+EFIAPI
+EfiShellCreateFile(
+ IN CONST CHAR16 *FileName,
+ IN UINT64 FileAttribs,
+ OUT SHELL_FILE_HANDLE *FileHandle
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_STATUS Status;
+ BOOLEAN Volatile;
+
+ //
+ // Is this for an environment variable
+ // do we start with >v
+ //
+ if (StrStr(FileName, L">v") == FileName) {
+ Status = IsVolatileEnv (FileName + 2, &Volatile);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (!Volatile) {
+ return (EFI_INVALID_PARAMETER);
+ }
+ *FileHandle = CreateFileInterfaceEnv(FileName+2);
+ return (EFI_SUCCESS);
+ }
+
+ //
+ // We are opening a regular file.
+ //
+ DevicePath = EfiShellGetDevicePathFromFilePath(FileName);
+ if (DevicePath == NULL) {
+ return (EFI_NOT_FOUND);
+ }
+
+ Status = InternalOpenFileDevicePath(DevicePath, FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, FileAttribs);
+ FreePool(DevicePath);
+
+ return(Status);
+}
+
+/**
+ Register a GUID and a localized human readable name for it.
+
+ If Guid is not assigned a name, then assign GuidName to Guid. This list of GUID
+ names must be used whenever a shell command outputs GUID information.
+
+ This function is only available when the major and minor versions in the
+ EfiShellProtocol are greater than or equal to 2 and 1, respectively.
+
+ @param[in] Guid A pointer to the GUID being registered.
+ @param[in] GuidName A pointer to the localized name for the GUID being registered.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_INVALID_PARAMETER Guid was NULL.
+ @retval EFI_INVALID_PARAMETER GuidName was NULL.
+ @retval EFI_ACCESS_DENIED Guid already is assigned a name.
+**/
+EFI_STATUS
+EFIAPI
+EfiShellRegisterGuidName(
+ IN CONST EFI_GUID *Guid,
+ IN CONST CHAR16 *GuidName
+ )
+{
+ return (AddNewGuidNameMapping(Guid, GuidName, NULL));
+}
+
+/**
+ Opens a file or a directory by file name.
+
+ This function opens the specified file in the specified OpenMode and returns a file
+ handle.
+ If the file name begins with >v, then the file handle which is returned refers to the
+ shell environment variable with the specified name. If the shell environment variable
+ exists, is non-volatile and the OpenMode indicates EFI_FILE_MODE_WRITE, then
+ EFI_INVALID_PARAMETER is returned.
+
+ If the file name is >i, then the file handle which is returned refers to the standard
+ input. If the OpenMode indicates EFI_FILE_MODE_WRITE, then EFI_INVALID_PARAMETER
+ is returned.
+
+ If the file name is >o, then the file handle which is returned refers to the standard
+ output. If the OpenMode indicates EFI_FILE_MODE_READ, then EFI_INVALID_PARAMETER
+ is returned.
+
+ If the file name is >e, then the file handle which is returned refers to the standard
+ error. If the OpenMode indicates EFI_FILE_MODE_READ, then EFI_INVALID_PARAMETER
+ is returned.
+
+ If the file name is NUL, then the file handle that is returned refers to the standard NUL
+ file. If the OpenMode indicates EFI_FILE_MODE_READ, then EFI_INVALID_PARAMETER is
+ returned.
+
+ If return EFI_SUCCESS, the FileHandle is the opened file's handle, else, the
+ FileHandle is NULL.
+
+ @param FileName Points to the NULL-terminated UCS-2 encoded file name.
+ @param FileHandle On return, points to the file handle.
+ @param OpenMode File open mode. Either EFI_FILE_MODE_READ or
+ EFI_FILE_MODE_WRITE from section 12.4 of the UEFI
+ Specification.
+ @retval EFI_SUCCESS The file was opened. FileHandle has the opened file's handle.
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. FileHandle is NULL.
+ @retval EFI_UNSUPPORTED Could not open the file path. FileHandle is NULL.
+ @retval EFI_NOT_FOUND The specified file could not be found on the device or the file
+ system could not be found on the device. FileHandle is NULL.
+ @retval EFI_NO_MEDIA The device has no medium. FileHandle is NULL.
+ @retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no
+ longer supported. FileHandle is NULL.
+ @retval EFI_DEVICE_ERROR The device reported an error or can't get the file path according
+ the FileName. FileHandle is NULL.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. FileHandle is NULL.
+ @retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a file for write
+ when the media is write-protected. FileHandle is NULL.
+ @retval EFI_ACCESS_DENIED The service denied access to the file. FileHandle is NULL.
+ @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file. FileHandle
+ is NULL.
+ @retval EFI_VOLUME_FULL The volume is full. FileHandle is NULL.
+**/
+EFI_STATUS
+EFIAPI
+EfiShellOpenFileByName(
+ IN CONST CHAR16 *FileName,
+ OUT SHELL_FILE_HANDLE *FileHandle,
+ IN UINT64 OpenMode
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_STATUS Status;
+ BOOLEAN Volatile;
+
+ *FileHandle = NULL;
+
+ //
+ // Is this for StdIn
+ //
+ if (StrCmp(FileName, L">i") == 0) {
+ //
+ // make sure not writing to StdIn
+ //
+ if ((OpenMode & EFI_FILE_MODE_WRITE) != 0) {
+ return (EFI_INVALID_PARAMETER);
+ }
+ *FileHandle = ShellInfoObject.NewShellParametersProtocol->StdIn;
+ ASSERT(*FileHandle != NULL);
+ return (EFI_SUCCESS);
+ }
+
+ //
+ // Is this for StdOut
+ //
+ if (StrCmp(FileName, L">o") == 0) {
+ //
+ // make sure not writing to StdIn
+ //
+ if ((OpenMode & EFI_FILE_MODE_READ) != 0) {
+ return (EFI_INVALID_PARAMETER);
+ }
+ *FileHandle = &FileInterfaceStdOut;
+ return (EFI_SUCCESS);
+ }
+
+ //
+ // Is this for NUL file
+ //
+ if (StrCmp(FileName, L"NUL") == 0) {
+ *FileHandle = &FileInterfaceNulFile;
+ return (EFI_SUCCESS);
+ }
+
+ //
+ // Is this for StdErr
+ //
+ if (StrCmp(FileName, L">e") == 0) {
+ //
+ // make sure not writing to StdIn
+ //
+ if ((OpenMode & EFI_FILE_MODE_READ) != 0) {
+ return (EFI_INVALID_PARAMETER);
+ }
+ *FileHandle = &FileInterfaceStdErr;
+ return (EFI_SUCCESS);
+ }
+
+ //
+ // Is this for an environment variable
+ // do we start with >v
+ //
+ if (StrStr(FileName, L">v") == FileName) {
+ Status = IsVolatileEnv (FileName + 2, &Volatile);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ if (!Volatile &&
+ ((OpenMode & EFI_FILE_MODE_WRITE) != 0)) {
+ return (EFI_INVALID_PARAMETER);
+ }
+ *FileHandle = CreateFileInterfaceEnv(FileName+2);
+ return (EFI_SUCCESS);
+ }
+
+ //
+ // We are opening a regular file.
+ //
+ DevicePath = EfiShellGetDevicePathFromFilePath(FileName);
+// DEBUG_CODE(InternalShellProtocolDebugPrintMessage (NULL, DevicePath););
+ if (DevicePath == NULL) {
+ return (EFI_NOT_FOUND);
+ }
+
+ //
+ // Copy the device path, open the file, then free the memory
+ //
+ Status = InternalOpenFileDevicePath(DevicePath, FileHandle, OpenMode, 0); // 0 = no specific file attributes
+ FreePool(DevicePath);
+
+ return(Status);
+}
+
+/**
+ Deletes the file specified by the file name.
+
+ This function deletes a file.
+
+ @param FileName Points to the NULL-terminated file name.
+
+ @retval EFI_SUCCESS The file was closed and deleted, and the handle was closed.
+ @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted.
+ @sa EfiShellCreateFile
+**/
+EFI_STATUS
+EFIAPI
+EfiShellDeleteFileByName(
+ IN CONST CHAR16 *FileName
+ )
+{
+ SHELL_FILE_HANDLE FileHandle;
+ EFI_STATUS Status;
+
+ FileHandle = NULL;
+
+ //
+ // get a handle to the file
+ //
+ Status = EfiShellCreateFile(FileName,
+ 0,
+ &FileHandle);
+ if (EFI_ERROR(Status)) {
+ return (Status);
+ }
+ //
+ // now delete the file
+ //
+ ShellFileHandleRemove(FileHandle);
+ return (ShellInfoObject.NewEfiShellProtocol->DeleteFile(FileHandle));
+}
+
+/**
+ Disables the page break output mode.
+**/
+VOID
+EFIAPI
+EfiShellDisablePageBreak (
+ VOID
+ )
+{
+ ShellInfoObject.PageBreakEnabled = FALSE;
+}
+
+/**
+ Enables the page break output mode.
+**/
+VOID
+EFIAPI
+EfiShellEnablePageBreak (
+ VOID
+ )
+{
+ ShellInfoObject.PageBreakEnabled = TRUE;
+}
+
+/**
+ internal worker function to load and run an image via device path.
+
+ @param ParentImageHandle A handle of the image that is executing the specified
+ command line.
+ @param DevicePath device path of the file to execute
+ @param CommandLine Points to the NULL-terminated UCS-2 encoded string
+ containing the command line. If NULL then the command-
+ line will be empty.
+ @param Environment Points to a NULL-terminated array of environment
+ variables with the format 'x=y', where x is the
+ environment variable name and y is the value. If this
+ is NULL, then the current shell environment is used.
+
+ @param[out] StartImageStatus Returned status from gBS->StartImage.
+
+ @retval EFI_SUCCESS The command executed successfully. The status code
+ returned by the command is pointed to by StatusCode.
+ @retval EFI_INVALID_PARAMETER The parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_UNSUPPORTED Nested shell invocations are not allowed.
+**/
+EFI_STATUS
+EFIAPI
+InternalShellExecuteDevicePath(
+ IN CONST EFI_HANDLE *ParentImageHandle,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN CONST CHAR16 *CommandLine OPTIONAL,
+ IN CONST CHAR16 **Environment OPTIONAL,
+ OUT EFI_STATUS *StartImageStatus OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS StartStatus;
+ EFI_STATUS CleanupStatus;
+ EFI_HANDLE NewHandle;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ LIST_ENTRY OrigEnvs;
+ EFI_SHELL_PARAMETERS_PROTOCOL ShellParamsProtocol;
+ CHAR16 *ImagePath;
+ UINTN Index;
+ CHAR16 *Walker;
+ CHAR16 *NewCmdLine;
+
+ if (ParentImageHandle == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ InitializeListHead(&OrigEnvs);
+ ZeroMem(&ShellParamsProtocol, sizeof(EFI_SHELL_PARAMETERS_PROTOCOL));
+
+ NewHandle = NULL;
+
+ NewCmdLine = AllocateCopyPool (StrSize (CommandLine), CommandLine);
+ if (NewCmdLine == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Walker = NewCmdLine; Walker != NULL && *Walker != CHAR_NULL ; Walker++) {
+ if (*Walker == L'^' && *(Walker+1) == L'#') {
+ CopyMem(Walker, Walker+1, StrSize(Walker) - sizeof(Walker[0]));
+ }
+ }
+
+ //
+ // Load the image with:
+ // FALSE - not from boot manager and NULL, 0 being not already in memory
+ //
+ Status = gBS->LoadImage(
+ FALSE,
+ *ParentImageHandle,
+ (EFI_DEVICE_PATH_PROTOCOL*)DevicePath,
+ NULL,
+ 0,
+ &NewHandle);
+
+ if (EFI_ERROR(Status)) {
+ if (NewHandle != NULL) {
+ gBS->UnloadImage(NewHandle);
+ }
+ FreePool (NewCmdLine);
+ return (Status);
+ }
+ Status = gBS->OpenProtocol(
+ NewHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID**)&LoadedImage,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ if (!EFI_ERROR(Status)) {
+ //
+ // If the image is not an app abort it.
+ //
+ if (LoadedImage->ImageCodeType != EfiLoaderCode){
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_SHELL_IMAGE_NOT_APP),
+ ShellInfoObject.HiiHandle
+ );
+ goto UnloadImage;
+ }
+
+ ASSERT(LoadedImage->LoadOptionsSize == 0);
+ if (NewCmdLine != NULL) {
+ LoadedImage->LoadOptionsSize = (UINT32)StrSize(NewCmdLine);
+ LoadedImage->LoadOptions = (VOID*)NewCmdLine;
+ }
+
+ //
+ // Save our current environment settings for later restoration if necessary
+ //
+ if (Environment != NULL) {
+ Status = GetEnvironmentVariableList(&OrigEnvs);
+ if (!EFI_ERROR(Status)) {
+ Status = SetEnvironmentVariables(Environment);
+ }
+ }
+
+ //
+ // Initialize and install a shell parameters protocol on the image.
+ //
+ ShellParamsProtocol.StdIn = ShellInfoObject.NewShellParametersProtocol->StdIn;
+ ShellParamsProtocol.StdOut = ShellInfoObject.NewShellParametersProtocol->StdOut;
+ ShellParamsProtocol.StdErr = ShellInfoObject.NewShellParametersProtocol->StdErr;
+ Status = UpdateArgcArgv(&ShellParamsProtocol, NewCmdLine, Efi_Application, NULL, NULL);
+ ASSERT_EFI_ERROR(Status);
+ //
+ // Replace Argv[0] with the full path of the binary we're executing:
+ // If the command line was "foo", the binary might be called "foo.efi".
+ // "The first entry in [Argv] is always the full file path of the
+ // executable" - UEFI Shell Spec section 2.3
+ //
+ ImagePath = EfiShellGetFilePathFromDevicePath (DevicePath);
+ // The image we're executing isn't necessarily in a filesystem - it might
+ // be memory mapped. In this case EfiShellGetFilePathFromDevicePath will
+ // return NULL, and we'll leave Argv[0] as UpdateArgcArgv set it.
+ if (ImagePath != NULL) {
+ if (ShellParamsProtocol.Argv == NULL) {
+ // Command line was empty or null.
+ // (UpdateArgcArgv sets Argv to NULL when CommandLine is "" or NULL)
+ ShellParamsProtocol.Argv = AllocatePool (sizeof (CHAR16 *));
+ if (ShellParamsProtocol.Argv == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto UnloadImage;
+ }
+ ShellParamsProtocol.Argc = 1;
+ } else {
+ // Free the string UpdateArgcArgv put in Argv[0];
+ FreePool (ShellParamsProtocol.Argv[0]);
+ }
+ ShellParamsProtocol.Argv[0] = ImagePath;
+ }
+
+ Status = gBS->InstallProtocolInterface(&NewHandle, &gEfiShellParametersProtocolGuid, EFI_NATIVE_INTERFACE, &ShellParamsProtocol);
+ ASSERT_EFI_ERROR(Status);
+
+ ///@todo initialize and install ShellInterface protocol on the new image for compatibility if - PcdGetBool(PcdShellSupportOldProtocols)
+
+ //
+ // now start the image and if the caller wanted the return code pass it to them...
+ //
+ if (!EFI_ERROR(Status)) {
+ StartStatus = gBS->StartImage(
+ NewHandle,
+ 0,
+ NULL
+ );
+ if (StartImageStatus != NULL) {
+ *StartImageStatus = StartStatus;
+ }
+
+ CleanupStatus = gBS->UninstallProtocolInterface(
+ NewHandle,
+ &gEfiShellParametersProtocolGuid,
+ &ShellParamsProtocol
+ );
+ ASSERT_EFI_ERROR(CleanupStatus);
+
+ goto FreeAlloc;
+ }
+
+UnloadImage:
+ // Unload image - We should only get here if we didn't call StartImage
+ gBS->UnloadImage (NewHandle);
+
+FreeAlloc:
+ // Free Argv (Allocated in UpdateArgcArgv)
+ if (ShellParamsProtocol.Argv != NULL) {
+ for (Index = 0; Index < ShellParamsProtocol.Argc; Index++) {
+ if (ShellParamsProtocol.Argv[Index] != NULL) {
+ FreePool (ShellParamsProtocol.Argv[Index]);
+ }
+ }
+ FreePool (ShellParamsProtocol.Argv);
+ }
+ }
+
+ // Restore environment variables
+ if (!IsListEmpty(&OrigEnvs)) {
+ CleanupStatus = SetEnvironmentVariableList(&OrigEnvs);
+ ASSERT_EFI_ERROR (CleanupStatus);
+ }
+
+ FreePool (NewCmdLine);
+
+ return(Status);
+}
+
+/**
+ internal worker function to load and run an image in the current shell.
+
+ @param CommandLine Points to the NULL-terminated UCS-2 encoded string
+ containing the command line. If NULL then the command-
+ line will be empty.
+ @param Environment Points to a NULL-terminated array of environment
+ variables with the format 'x=y', where x is the
+ environment variable name and y is the value. If this
+ is NULL, then the current shell environment is used.
+
+ @param[out] StartImageStatus Returned status from the command line.
+
+ @retval EFI_SUCCESS The command executed successfully. The status code
+ returned by the command is pointed to by StatusCode.
+ @retval EFI_INVALID_PARAMETER The parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_UNSUPPORTED Nested shell invocations are not allowed.
+**/
+EFI_STATUS
+EFIAPI
+InternalShellExecute(
+ IN CONST CHAR16 *CommandLine OPTIONAL,
+ IN CONST CHAR16 **Environment OPTIONAL,
+ OUT EFI_STATUS *StartImageStatus OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS CleanupStatus;
+ LIST_ENTRY OrigEnvs;
+
+ InitializeListHead(&OrigEnvs);
+
+ //
+ // Save our current environment settings for later restoration if necessary
+ //
+ if (Environment != NULL) {
+ Status = GetEnvironmentVariableList(&OrigEnvs);
+ if (!EFI_ERROR(Status)) {
+ Status = SetEnvironmentVariables(Environment);
+ } else {
+ return Status;
+ }
+ }
+
+ Status = RunShellCommand(CommandLine, StartImageStatus);
+
+ // Restore environment variables
+ if (!IsListEmpty(&OrigEnvs)) {
+ CleanupStatus = SetEnvironmentVariableList(&OrigEnvs);
+ ASSERT_EFI_ERROR (CleanupStatus);
+ }
+
+ return(Status);
+}
+
+/**
+ Determine if the UEFI Shell is currently running with nesting enabled or disabled.
+
+ @retval FALSE nesting is required
+ @retval other nesting is enabled
+**/
+STATIC
+BOOLEAN
+EFIAPI
+NestingEnabled(
+)
+{
+ EFI_STATUS Status;
+ CHAR16 *Temp;
+ CHAR16 *Temp2;
+ UINTN TempSize;
+ BOOLEAN RetVal;
+
+ RetVal = TRUE;
+ Temp = NULL;
+ Temp2 = NULL;
+
+ if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest) {
+ TempSize = 0;
+ Temp = NULL;
+ Status = SHELL_GET_ENVIRONMENT_VARIABLE(mNoNestingEnvVarName, &TempSize, Temp);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ Temp = AllocateZeroPool(TempSize + sizeof(CHAR16));
+ if (Temp != NULL) {
+ Status = SHELL_GET_ENVIRONMENT_VARIABLE(mNoNestingEnvVarName, &TempSize, Temp);
+ }
+ }
+ Temp2 = StrnCatGrow(&Temp2, NULL, mNoNestingTrue, 0);
+ if (Temp != NULL && Temp2 != NULL && StringNoCaseCompare(&Temp, &Temp2) == 0) {
+ //
+ // Use the no nesting method.
+ //
+ RetVal = FALSE;
+ }
+ }
+
+ SHELL_FREE_NON_NULL(Temp);
+ SHELL_FREE_NON_NULL(Temp2);
+ return (RetVal);
+}
+
+/**
+ Execute the command line.
+
+ This function creates a nested instance of the shell and executes the specified
+ command (CommandLine) with the specified environment (Environment). Upon return,
+ the status code returned by the specified command is placed in StatusCode.
+
+ If Environment is NULL, then the current environment is used and all changes made
+ by the commands executed will be reflected in the current environment. If the
+ Environment is non-NULL, then the changes made will be discarded.
+
+ The CommandLine is executed from the current working directory on the current
+ device.
+
+ @param ParentImageHandle A handle of the image that is executing the specified
+ command line.
+ @param CommandLine Points to the NULL-terminated UCS-2 encoded string
+ containing the command line. If NULL then the command-
+ line will be empty.
+ @param Environment Points to a NULL-terminated array of environment
+ variables with the format 'x=y', where x is the
+ environment variable name and y is the value. If this
+ is NULL, then the current shell environment is used.
+ @param StatusCode Points to the status code returned by the CommandLine.
+
+ @retval EFI_SUCCESS The command executed successfully. The status code
+ returned by the command is pointed to by StatusCode.
+ @retval EFI_INVALID_PARAMETER The parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_UNSUPPORTED Nested shell invocations are not allowed.
+ @retval EFI_UNSUPPORTED The support level required for this function is not present.
+
+ @sa InternalShellExecuteDevicePath
+**/
+EFI_STATUS
+EFIAPI
+EfiShellExecute(
+ IN EFI_HANDLE *ParentImageHandle,
+ IN CHAR16 *CommandLine OPTIONAL,
+ IN CHAR16 **Environment OPTIONAL,
+ OUT EFI_STATUS *StatusCode OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *Temp;
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+ UINTN Size;
+
+ if ((PcdGet8(PcdShellSupportLevel) < 1)) {
+ return (EFI_UNSUPPORTED);
+ }
+
+ if (NestingEnabled()) {
+ DevPath = AppendDevicePath (ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath);
+
+ DEBUG_CODE_BEGIN();
+ Temp = ConvertDevicePathToText(ShellInfoObject.FileDevPath, TRUE, TRUE);
+ FreePool(Temp);
+ Temp = ConvertDevicePathToText(ShellInfoObject.ImageDevPath, TRUE, TRUE);
+ FreePool(Temp);
+ Temp = ConvertDevicePathToText(DevPath, TRUE, TRUE);
+ FreePool(Temp);
+ DEBUG_CODE_END();
+
+ Temp = NULL;
+ Size = 0;
+ ASSERT((Temp == NULL && Size == 0) || (Temp != NULL));
+ StrnCatGrow(&Temp, &Size, L"Shell.efi -_exit ", 0);
+ StrnCatGrow(&Temp, &Size, CommandLine, 0);
+
+ Status = InternalShellExecuteDevicePath(
+ ParentImageHandle,
+ DevPath,
+ Temp,
+ (CONST CHAR16**)Environment,
+ StatusCode);
+
+ //
+ // de-allocate and return
+ //
+ FreePool(DevPath);
+ FreePool(Temp);
+ } else {
+ Status = InternalShellExecute(
+ (CONST CHAR16*)CommandLine,
+ (CONST CHAR16**)Environment,
+ StatusCode);
+ }
+
+ return(Status);
+}
+
+/**
+ Utility cleanup function for EFI_SHELL_FILE_INFO objects.
+
+ 1) frees all pointers (non-NULL)
+ 2) Closes the SHELL_FILE_HANDLE
+
+ @param FileListNode pointer to the list node to free
+**/
+VOID
+EFIAPI
+InternalFreeShellFileInfoNode(
+ IN EFI_SHELL_FILE_INFO *FileListNode
+ )
+{
+ if (FileListNode->Info != NULL) {
+ FreePool((VOID*)FileListNode->Info);
+ }
+ if (FileListNode->FileName != NULL) {
+ FreePool((VOID*)FileListNode->FileName);
+ }
+ if (FileListNode->FullName != NULL) {
+ FreePool((VOID*)FileListNode->FullName);
+ }
+ if (FileListNode->Handle != NULL) {
+ ShellInfoObject.NewEfiShellProtocol->CloseFile(FileListNode->Handle);
+ }
+ FreePool(FileListNode);
+}
+/**
+ Frees the file list.
+
+ This function cleans up the file list and any related data structures. It has no
+ impact on the files themselves.
+
+ @param FileList The file list to free. Type EFI_SHELL_FILE_INFO is
+ defined in OpenFileList()
+
+ @retval EFI_SUCCESS Free the file list successfully.
+ @retval EFI_INVALID_PARAMETER FileList was NULL or *FileList was NULL;
+**/
+EFI_STATUS
+EFIAPI
+EfiShellFreeFileList(
+ IN EFI_SHELL_FILE_INFO **FileList
+ )
+{
+ EFI_SHELL_FILE_INFO *ShellFileListItem;
+
+ if (FileList == NULL || *FileList == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ for ( ShellFileListItem = (EFI_SHELL_FILE_INFO*)GetFirstNode(&(*FileList)->Link)
+ ; !IsListEmpty(&(*FileList)->Link)
+ ; ShellFileListItem = (EFI_SHELL_FILE_INFO*)GetFirstNode(&(*FileList)->Link)
+ ){
+ RemoveEntryList(&ShellFileListItem->Link);
+ InternalFreeShellFileInfoNode(ShellFileListItem);
+ }
+ InternalFreeShellFileInfoNode(*FileList);
+ *FileList = NULL;
+ return(EFI_SUCCESS);
+}
+
+/**
+ Deletes the duplicate file names files in the given file list.
+
+ This function deletes the reduplicate files in the given file list.
+
+ @param FileList A pointer to the first entry in the file list.
+
+ @retval EFI_SUCCESS Always success.
+ @retval EFI_INVALID_PARAMETER FileList was NULL or *FileList was NULL;
+**/
+EFI_STATUS
+EFIAPI
+EfiShellRemoveDupInFileList(
+ IN EFI_SHELL_FILE_INFO **FileList
+ )
+{
+ EFI_SHELL_FILE_INFO *ShellFileListItem;
+ EFI_SHELL_FILE_INFO *ShellFileListItem2;
+ EFI_SHELL_FILE_INFO *TempNode;
+
+ if (FileList == NULL || *FileList == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+ for ( ShellFileListItem = (EFI_SHELL_FILE_INFO*)GetFirstNode(&(*FileList)->Link)
+ ; !IsNull(&(*FileList)->Link, &ShellFileListItem->Link)
+ ; ShellFileListItem = (EFI_SHELL_FILE_INFO*)GetNextNode(&(*FileList)->Link, &ShellFileListItem->Link)
+ ){
+ for ( ShellFileListItem2 = (EFI_SHELL_FILE_INFO*)GetNextNode(&(*FileList)->Link, &ShellFileListItem->Link)
+ ; !IsNull(&(*FileList)->Link, &ShellFileListItem2->Link)
+ ; ShellFileListItem2 = (EFI_SHELL_FILE_INFO*)GetNextNode(&(*FileList)->Link, &ShellFileListItem2->Link)
+ ){
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)ShellFileListItem->FullName,
+ (CHAR16*)ShellFileListItem2->FullName) == 0
+ ){
+ TempNode = (EFI_SHELL_FILE_INFO *)GetPreviousNode(
+ &(*FileList)->Link,
+ &ShellFileListItem2->Link
+ );
+ RemoveEntryList(&ShellFileListItem2->Link);
+ InternalFreeShellFileInfoNode(ShellFileListItem2);
+ // Set ShellFileListItem2 to PreviousNode so we don't access Freed
+ // memory in GetNextNode in the loop expression above.
+ ShellFileListItem2 = TempNode;
+ }
+ }
+ }
+ return (EFI_SUCCESS);
+}
+
+//
+// This is the same structure as the external version, but it has no CONST qualifiers.
+//
+typedef struct {
+ LIST_ENTRY Link; ///< Linked list members.
+ EFI_STATUS Status; ///< Status of opening the file. Valid only if Handle != NULL.
+ CHAR16 *FullName; ///< Fully qualified filename.
+ CHAR16 *FileName; ///< name of this file.
+ SHELL_FILE_HANDLE Handle; ///< Handle for interacting with the opened file or NULL if closed.
+ EFI_FILE_INFO *Info; ///< Pointer to the FileInfo struct for this file or NULL.
+} EFI_SHELL_FILE_INFO_NO_CONST;
+
+/**
+ Allocates and duplicates a EFI_SHELL_FILE_INFO node.
+
+ @param[in] Node The node to copy from.
+ @param[in] Save TRUE to set Node->Handle to NULL, FALSE otherwise.
+
+ @retval NULL a memory allocation error ocurred
+ @return != NULL a pointer to the new node
+**/
+EFI_SHELL_FILE_INFO*
+EFIAPI
+InternalDuplicateShellFileInfo(
+ IN EFI_SHELL_FILE_INFO *Node,
+ IN BOOLEAN Save
+ )
+{
+ EFI_SHELL_FILE_INFO_NO_CONST *NewNode;
+
+ //
+ // try to confirm that the objects are in sync
+ //
+ ASSERT(sizeof(EFI_SHELL_FILE_INFO_NO_CONST) == sizeof(EFI_SHELL_FILE_INFO));
+
+ NewNode = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));
+ if (NewNode == NULL) {
+ return (NULL);
+ }
+ NewNode->FullName = AllocateCopyPool(StrSize(Node->FullName), Node->FullName);
+ NewNode->FileName = AllocateCopyPool(StrSize(Node->FileName), Node->FileName);
+ NewNode->Info = AllocateCopyPool((UINTN)Node->Info->Size, Node->Info);
+ if ( NewNode->FullName == NULL
+ || NewNode->FileName == NULL
+ || NewNode->Info == NULL
+ ){
+ SHELL_FREE_NON_NULL(NewNode->FullName);
+ SHELL_FREE_NON_NULL(NewNode->FileName);
+ SHELL_FREE_NON_NULL(NewNode->Info);
+ SHELL_FREE_NON_NULL(NewNode);
+ return(NULL);
+ }
+ NewNode->Status = Node->Status;
+ NewNode->Handle = Node->Handle;
+ if (!Save) {
+ Node->Handle = NULL;
+ }
+
+ return((EFI_SHELL_FILE_INFO*)NewNode);
+}
+
+/**
+ Allocates and populates a EFI_SHELL_FILE_INFO structure. if any memory operation
+ failed it will return NULL.
+
+ @param[in] BasePath the Path to prepend onto filename for FullPath
+ @param[in] Status Status member initial value.
+ @param[in] FileName FileName member initial value.
+ @param[in] Handle Handle member initial value.
+ @param[in] Info Info struct to copy.
+
+ @retval NULL An error ocurred.
+ @return a pointer to the newly allocated structure.
+**/
+EFI_SHELL_FILE_INFO *
+EFIAPI
+CreateAndPopulateShellFileInfo(
+ IN CONST CHAR16 *BasePath,
+ IN CONST EFI_STATUS Status,
+ IN CONST CHAR16 *FileName,
+ IN CONST SHELL_FILE_HANDLE Handle,
+ IN CONST EFI_FILE_INFO *Info
+ )
+{
+ EFI_SHELL_FILE_INFO *ShellFileListItem;
+ CHAR16 *TempString;
+ UINTN Size;
+
+ TempString = NULL;
+ Size = 0;
+
+ ShellFileListItem = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));
+ if (ShellFileListItem == NULL) {
+ return (NULL);
+ }
+ if (Info != NULL && Info->Size != 0) {
+ ShellFileListItem->Info = AllocateZeroPool((UINTN)Info->Size);
+ if (ShellFileListItem->Info == NULL) {
+ FreePool(ShellFileListItem);
+ return (NULL);
+ }
+ CopyMem(ShellFileListItem->Info, Info, (UINTN)Info->Size);
+ } else {
+ ShellFileListItem->Info = NULL;
+ }
+ if (FileName != NULL) {
+ ASSERT(TempString == NULL);
+ ShellFileListItem->FileName = StrnCatGrow(&TempString, 0, FileName, 0);
+ if (ShellFileListItem->FileName == NULL) {
+ FreePool(ShellFileListItem->Info);
+ FreePool(ShellFileListItem);
+ return (NULL);
+ }
+ } else {
+ ShellFileListItem->FileName = NULL;
+ }
+ Size = 0;
+ TempString = NULL;
+ if (BasePath != NULL) {
+ ASSERT((TempString == NULL && Size == 0) || (TempString != NULL));
+ TempString = StrnCatGrow(&TempString, &Size, BasePath, 0);
+ if (TempString == NULL) {
+ FreePool((VOID*)ShellFileListItem->FileName);
+ SHELL_FREE_NON_NULL(ShellFileListItem->Info);
+ FreePool(ShellFileListItem);
+ return (NULL);
+ }
+ }
+ if (ShellFileListItem->FileName != NULL) {
+ ASSERT((TempString == NULL && Size == 0) || (TempString != NULL));
+ TempString = StrnCatGrow(&TempString, &Size, ShellFileListItem->FileName, 0);
+ if (TempString == NULL) {
+ FreePool((VOID*)ShellFileListItem->FileName);
+ FreePool(ShellFileListItem->Info);
+ FreePool(ShellFileListItem);
+ return (NULL);
+ }
+ }
+
+ TempString = PathCleanUpDirectories(TempString);
+
+ ShellFileListItem->FullName = TempString;
+ ShellFileListItem->Status = Status;
+ ShellFileListItem->Handle = Handle;
+
+ return (ShellFileListItem);
+}
+
+/**
+ Find all files in a specified directory.
+
+ @param FileDirHandle Handle of the directory to search.
+ @param FileList On return, points to the list of files in the directory
+ or NULL if there are no files in the directory.
+
+ @retval EFI_SUCCESS File information was returned successfully.
+ @retval EFI_VOLUME_CORRUPTED The file system structures have been corrupted.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_NO_MEDIA The device media is not present.
+ @retval EFI_INVALID_PARAMETER The FileDirHandle was not a directory.
+ @return An error from FileHandleGetFileName().
+**/
+EFI_STATUS
+EFIAPI
+EfiShellFindFilesInDir(
+ IN SHELL_FILE_HANDLE FileDirHandle,
+ OUT EFI_SHELL_FILE_INFO **FileList
+ )
+{
+ EFI_SHELL_FILE_INFO *ShellFileList;
+ EFI_SHELL_FILE_INFO *ShellFileListItem;
+ EFI_FILE_INFO *FileInfo;
+ EFI_STATUS Status;
+ BOOLEAN NoFile;
+ CHAR16 *TempString;
+ CHAR16 *BasePath;
+ UINTN Size;
+ CHAR16 *TempSpot;
+
+ BasePath = NULL;
+ Status = FileHandleGetFileName(FileDirHandle, &BasePath);
+ if (EFI_ERROR(Status)) {
+ return (Status);
+ }
+
+ if (ShellFileHandleGetPath(FileDirHandle) != NULL) {
+ TempString = NULL;
+ Size = 0;
+ TempString = StrnCatGrow(&TempString, &Size, ShellFileHandleGetPath(FileDirHandle), 0);
+ if (TempString == NULL) {
+ SHELL_FREE_NON_NULL(BasePath);
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ TempSpot = StrStr(TempString, L";");
+
+ if (TempSpot != NULL) {
+ *TempSpot = CHAR_NULL;
+ }
+
+ TempString = StrnCatGrow(&TempString, &Size, BasePath, 0);
+ if (TempString == NULL) {
+ SHELL_FREE_NON_NULL(BasePath);
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ SHELL_FREE_NON_NULL(BasePath);
+ BasePath = TempString;
+ }
+
+ NoFile = FALSE;
+ ShellFileList = NULL;
+ ShellFileListItem = NULL;
+ FileInfo = NULL;
+ Status = EFI_SUCCESS;
+
+
+ for ( Status = FileHandleFindFirstFile(FileDirHandle, &FileInfo)
+ ; !EFI_ERROR(Status) && !NoFile
+ ; Status = FileHandleFindNextFile(FileDirHandle, FileInfo, &NoFile)
+ ){
+ if (ShellFileList == NULL) {
+ ShellFileList = (EFI_SHELL_FILE_INFO*)AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));
+ if (ShellFileList == NULL) {
+ SHELL_FREE_NON_NULL (BasePath);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ InitializeListHead(&ShellFileList->Link);
+ }
+ //
+ // allocate a new EFI_SHELL_FILE_INFO and populate it...
+ //
+ ShellFileListItem = CreateAndPopulateShellFileInfo(
+ BasePath,
+ EFI_SUCCESS, // success since we didnt fail to open it...
+ FileInfo->FileName,
+ NULL, // no handle since not open
+ FileInfo);
+ if (ShellFileListItem == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ //
+ // Free resources outside the loop.
+ //
+ break;
+ }
+ InsertTailList(&ShellFileList->Link, &ShellFileListItem->Link);
+ }
+ if (EFI_ERROR(Status)) {
+ EfiShellFreeFileList(&ShellFileList);
+ *FileList = NULL;
+ } else {
+ *FileList = ShellFileList;
+ }
+ SHELL_FREE_NON_NULL(BasePath);
+ return(Status);
+}
+
+/**
+ Get the GUID value from a human readable name.
+
+ If GuidName is a known GUID name, then update Guid to have the correct value for
+ that GUID.
+
+ This function is only available when the major and minor versions in the
+ EfiShellProtocol are greater than or equal to 2 and 1, respectively.
+
+ @param[in] GuidName A pointer to the localized name for the GUID being queried.
+ @param[out] Guid A pointer to the GUID structure to be filled in.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_INVALID_PARAMETER Guid was NULL.
+ @retval EFI_INVALID_PARAMETER GuidName was NULL.
+ @retval EFI_NOT_FOUND GuidName is not a known GUID Name.
+**/
+EFI_STATUS
+EFIAPI
+EfiShellGetGuidFromName(
+ IN CONST CHAR16 *GuidName,
+ OUT EFI_GUID *Guid
+ )
+{
+ EFI_GUID *NewGuid;
+ EFI_STATUS Status;
+
+ if (Guid == NULL || GuidName == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ Status = GetGuidFromStringName(GuidName, NULL, &NewGuid);
+
+ if (!EFI_ERROR(Status)) {
+ CopyGuid(NewGuid, Guid);
+ }
+
+ return (Status);
+}
+
+/**
+ Get the human readable name for a GUID from the value.
+
+ If Guid is assigned a name, then update *GuidName to point to the name. The callee
+ should not modify the value.
+
+ This function is only available when the major and minor versions in the
+ EfiShellProtocol are greater than or equal to 2 and 1, respectively.
+
+ @param[in] Guid A pointer to the GUID being queried.
+ @param[out] GuidName A pointer to a pointer the localized to name for the GUID being requested
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_INVALID_PARAMETER Guid was NULL.
+ @retval EFI_INVALID_PARAMETER GuidName was NULL.
+ @retval EFI_NOT_FOUND Guid is not assigned a name.
+**/
+EFI_STATUS
+EFIAPI
+EfiShellGetGuidName(
+ IN CONST EFI_GUID *Guid,
+ OUT CONST CHAR16 **GuidName
+ )
+{
+ CHAR16 *Name;
+
+ if (Guid == NULL || GuidName == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ Name = GetStringNameFromGuid(Guid, NULL);
+ if (Name == NULL || StrLen(Name) == 0) {
+ SHELL_FREE_NON_NULL(Name);
+ return (EFI_NOT_FOUND);
+ }
+
+ *GuidName = AddBufferToFreeList(Name);
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Updates a file name to be preceeded by the mapped drive name
+
+ @param[in] BasePath the Mapped drive name to prepend
+ @param[in, out] Path pointer to pointer to the file name to update.
+
+ @retval EFI_SUCCESS
+ @retval EFI_OUT_OF_RESOURCES
+**/
+EFI_STATUS
+EFIAPI
+UpdateFileName(
+ IN CONST CHAR16 *BasePath,
+ IN OUT CHAR16 **Path
+ )
+{
+ CHAR16 *Path2;
+ UINTN Path2Size;
+
+ Path2Size = 0;
+ Path2 = NULL;
+
+ ASSERT(Path != NULL);
+ ASSERT(*Path != NULL);
+ ASSERT(BasePath != NULL);
+
+ //
+ // convert a local path to an absolute path
+ //
+ if (StrStr(*Path, L":") == NULL) {
+ ASSERT((Path2 == NULL && Path2Size == 0) || (Path2 != NULL));
+ StrnCatGrow(&Path2, &Path2Size, BasePath, 0);
+ if (Path2 == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ ASSERT((Path2 == NULL && Path2Size == 0) || (Path2 != NULL));
+ StrnCatGrow(&Path2, &Path2Size, (*Path)[0] == L'\\'?(*Path) + 1 :*Path, 0);
+ if (Path2 == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ }
+
+ FreePool(*Path);
+ (*Path) = Path2;
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ If FileHandle is a directory then the function reads from FileHandle and reads in
+ each of the FileInfo structures. If one of them matches the Pattern's first
+ "level" then it opens that handle and calls itself on that handle.
+
+ If FileHandle is a file and matches all of the remaining Pattern (which would be
+ on its last node), then add a EFI_SHELL_FILE_INFO object for this file to fileList.
+
+ Upon a EFI_SUCCESS return fromt he function any the caller is responsible to call
+ FreeFileList with FileList.
+
+ @param[in] FilePattern The FilePattern to check against.
+ @param[in] UnicodeCollation The pointer to EFI_UNICODE_COLLATION_PROTOCOL structure
+ @param[in] FileHandle The FileHandle to start with
+ @param[in, out] FileList pointer to pointer to list of found files.
+ @param[in] ParentNode The node for the parent. Same file as identified by HANDLE.
+ @param[in] MapName The file system name this file is on.
+
+ @retval EFI_SUCCESS all files were found and the FileList contains a list.
+ @retval EFI_NOT_FOUND no files were found
+ @retval EFI_OUT_OF_RESOURCES a memory allocation failed
+**/
+EFI_STATUS
+EFIAPI
+ShellSearchHandle(
+ IN CONST CHAR16 *FilePattern,
+ IN EFI_UNICODE_COLLATION_PROTOCOL *UnicodeCollation,
+ IN SHELL_FILE_HANDLE FileHandle,
+ IN OUT EFI_SHELL_FILE_INFO **FileList,
+ IN CONST EFI_SHELL_FILE_INFO *ParentNode OPTIONAL,
+ IN CONST CHAR16 *MapName
+ )
+{
+ EFI_STATUS Status;
+ CONST CHAR16 *NextFilePatternStart;
+ CHAR16 *CurrentFilePattern;
+ EFI_SHELL_FILE_INFO *ShellInfo;
+ EFI_SHELL_FILE_INFO *ShellInfoNode;
+ EFI_SHELL_FILE_INFO *NewShellNode;
+ EFI_FILE_INFO *FileInfo;
+ BOOLEAN Directory;
+ CHAR16 *NewFullName;
+ UINTN Size;
+
+ if ( FilePattern == NULL
+ || UnicodeCollation == NULL
+ || FileList == NULL
+ ){
+ return (EFI_INVALID_PARAMETER);
+ }
+ ShellInfo = NULL;
+ CurrentFilePattern = NULL;
+
+ if (*FilePattern == L'\\') {
+ FilePattern++;
+ }
+
+ for( NextFilePatternStart = FilePattern
+ ; *NextFilePatternStart != CHAR_NULL && *NextFilePatternStart != L'\\'
+ ; NextFilePatternStart++);
+
+ CurrentFilePattern = AllocateZeroPool((NextFilePatternStart-FilePattern+1)*sizeof(CHAR16));
+ if (CurrentFilePattern == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StrnCpyS(CurrentFilePattern, NextFilePatternStart-FilePattern+1, FilePattern, NextFilePatternStart-FilePattern);
+
+ if (CurrentFilePattern[0] == CHAR_NULL
+ &&NextFilePatternStart[0] == CHAR_NULL
+ ){
+ //
+ // we want the parent or root node (if no parent)
+ //
+ if (ParentNode == NULL) {
+ //
+ // We want the root node. create the node.
+ //
+ FileInfo = FileHandleGetInfo(FileHandle);
+ NewShellNode = CreateAndPopulateShellFileInfo(
+ MapName,
+ EFI_SUCCESS,
+ L"\\",
+ FileHandle,
+ FileInfo
+ );
+ SHELL_FREE_NON_NULL(FileInfo);
+ } else {
+ //
+ // Add the current parameter FileHandle to the list, then end...
+ //
+ NewShellNode = InternalDuplicateShellFileInfo((EFI_SHELL_FILE_INFO*)ParentNode, TRUE);
+ }
+ if (NewShellNode == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ NewShellNode->Handle = NULL;
+ if (*FileList == NULL) {
+ *FileList = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));
+ InitializeListHead(&((*FileList)->Link));
+ }
+
+ //
+ // Add to the returning to use list
+ //
+ InsertTailList(&(*FileList)->Link, &NewShellNode->Link);
+
+ Status = EFI_SUCCESS;
+ }
+ } else {
+ Status = EfiShellFindFilesInDir(FileHandle, &ShellInfo);
+
+ if (!EFI_ERROR(Status)){
+ if (StrStr(NextFilePatternStart, L"\\") != NULL){
+ Directory = TRUE;
+ } else {
+ Directory = FALSE;
+ }
+ for ( ShellInfoNode = (EFI_SHELL_FILE_INFO*)GetFirstNode(&ShellInfo->Link)
+ ; !IsNull (&ShellInfo->Link, &ShellInfoNode->Link)
+ ; ShellInfoNode = (EFI_SHELL_FILE_INFO*)GetNextNode(&ShellInfo->Link, &ShellInfoNode->Link)
+ ){
+ if (UnicodeCollation->MetaiMatch(UnicodeCollation, (CHAR16*)ShellInfoNode->FileName, CurrentFilePattern)){
+ if (ShellInfoNode->FullName != NULL && StrStr(ShellInfoNode->FullName, L":") == NULL) {
+ Size = StrSize(ShellInfoNode->FullName);
+ Size += StrSize(MapName) + sizeof(CHAR16);
+ NewFullName = AllocateZeroPool(Size);
+ if (NewFullName == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ StrCpyS(NewFullName, Size/sizeof(CHAR16), MapName);
+ StrCatS(NewFullName, Size/sizeof(CHAR16), ShellInfoNode->FullName+1);
+ FreePool((VOID*)ShellInfoNode->FullName);
+ ShellInfoNode->FullName = NewFullName;
+ }
+ }
+ if (Directory && !EFI_ERROR(Status) && ShellInfoNode->FullName != NULL && ShellInfoNode->FileName != NULL){
+ //
+ // should be a directory
+ //
+
+ //
+ // don't open the . and .. directories
+ //
+ if ( (StrCmp(ShellInfoNode->FileName, L".") != 0)
+ && (StrCmp(ShellInfoNode->FileName, L"..") != 0)
+ ){
+ //
+ //
+ //
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+ //
+ // Open the directory since we need that handle in the next recursion.
+ //
+ ShellInfoNode->Status = EfiShellOpenFileByName (ShellInfoNode->FullName, &ShellInfoNode->Handle, EFI_FILE_MODE_READ);
+
+ //
+ // recurse with the next part of the pattern
+ //
+ Status = ShellSearchHandle(NextFilePatternStart, UnicodeCollation, ShellInfoNode->Handle, FileList, ShellInfoNode, MapName);
+ EfiShellClose(ShellInfoNode->Handle);
+ ShellInfoNode->Handle = NULL;
+ }
+ } else if (!EFI_ERROR(Status)) {
+ //
+ // should be a file
+ //
+
+ //
+ // copy the information we need into a new Node
+ //
+ NewShellNode = InternalDuplicateShellFileInfo(ShellInfoNode, FALSE);
+ if (NewShellNode == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ }
+ if (*FileList == NULL) {
+ *FileList = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));
+ InitializeListHead(&((*FileList)->Link));
+ }
+
+ //
+ // Add to the returning to use list
+ //
+ InsertTailList(&(*FileList)->Link, &NewShellNode->Link);
+ }
+ }
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+ }
+ if (EFI_ERROR(Status)) {
+ EfiShellFreeFileList(&ShellInfo);
+ } else {
+ Status = EfiShellFreeFileList(&ShellInfo);
+ }
+ }
+ }
+
+ FreePool(CurrentFilePattern);
+ return (Status);
+}
+
+/**
+ Find files that match a specified pattern.
+
+ This function searches for all files and directories that match the specified
+ FilePattern. The FilePattern can contain wild-card characters. The resulting file
+ information is placed in the file list FileList.
+
+ Wildcards are processed
+ according to the rules specified in UEFI Shell 2.0 spec section 3.7.1.
+
+ The files in the file list are not opened. The OpenMode field is set to 0 and the FileInfo
+ field is set to NULL.
+
+ if *FileList is not NULL then it must be a pre-existing and properly initialized list.
+
+ @param FilePattern Points to a NULL-terminated shell file path, including wildcards.
+ @param FileList On return, points to the start of a file list containing the names
+ of all matching files or else points to NULL if no matching files
+ were found. only on a EFI_SUCCESS return will; this be non-NULL.
+
+ @retval EFI_SUCCESS Files found. FileList is a valid list.
+ @retval EFI_NOT_FOUND No files found.
+ @retval EFI_NO_MEDIA The device has no media
+ @retval EFI_DEVICE_ERROR The device reported an error
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted
+**/
+EFI_STATUS
+EFIAPI
+EfiShellFindFiles(
+ IN CONST CHAR16 *FilePattern,
+ OUT EFI_SHELL_FILE_INFO **FileList
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *PatternCopy;
+ CHAR16 *PatternCurrentLocation;
+ EFI_DEVICE_PATH_PROTOCOL *RootDevicePath;
+ SHELL_FILE_HANDLE RootFileHandle;
+ CHAR16 *MapName;
+ UINTN Count;
+
+ if ( FilePattern == NULL
+ || FileList == NULL
+ || StrStr(FilePattern, L":") == NULL
+ ){
+ return (EFI_INVALID_PARAMETER);
+ }
+ Status = EFI_SUCCESS;
+ RootDevicePath = NULL;
+ RootFileHandle = NULL;
+ MapName = NULL;
+ PatternCopy = AllocateCopyPool(StrSize(FilePattern), FilePattern);
+ if (PatternCopy == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ PatternCopy = PathCleanUpDirectories(PatternCopy);
+
+ Count = StrStr(PatternCopy, L":") - PatternCopy;
+ Count += 2;
+
+ ASSERT(MapName == NULL);
+ MapName = StrnCatGrow(&MapName, NULL, PatternCopy, Count);
+ if (MapName == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ RootDevicePath = EfiShellGetDevicePathFromFilePath(PatternCopy);
+ if (RootDevicePath == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ Status = EfiShellOpenRoot(RootDevicePath, &RootFileHandle);
+ if (!EFI_ERROR(Status)) {
+ for ( PatternCurrentLocation = PatternCopy
+ ; *PatternCurrentLocation != ':'
+ ; PatternCurrentLocation++);
+ PatternCurrentLocation++;
+ Status = ShellSearchHandle(PatternCurrentLocation, gUnicodeCollation, RootFileHandle, FileList, NULL, MapName);
+ EfiShellClose(RootFileHandle);
+ }
+ FreePool(RootDevicePath);
+ }
+ }
+
+ SHELL_FREE_NON_NULL(PatternCopy);
+ SHELL_FREE_NON_NULL(MapName);
+
+ return(Status);
+}
+
+/**
+ Opens the files that match the path specified.
+
+ This function opens all of the files specified by Path. Wildcards are processed
+ according to the rules specified in UEFI Shell 2.0 spec section 3.7.1. Each
+ matching file has an EFI_SHELL_FILE_INFO structure created in a linked list.
+
+ @param Path A pointer to the path string.
+ @param OpenMode Specifies the mode used to open each file, EFI_FILE_MODE_READ or
+ EFI_FILE_MODE_WRITE.
+ @param FileList Points to the start of a list of files opened.
+
+ @retval EFI_SUCCESS Create the file list successfully.
+ @return Others Can't create the file list.
+**/
+EFI_STATUS
+EFIAPI
+EfiShellOpenFileList(
+ IN CHAR16 *Path,
+ IN UINT64 OpenMode,
+ IN OUT EFI_SHELL_FILE_INFO **FileList
+ )
+{
+ EFI_STATUS Status;
+ EFI_SHELL_FILE_INFO *ShellFileListItem;
+ CHAR16 *Path2;
+ UINTN Path2Size;
+ CONST CHAR16 *CurDir;
+ BOOLEAN Found;
+
+ PathCleanUpDirectories(Path);
+
+ Path2Size = 0;
+ Path2 = NULL;
+
+ if (FileList == NULL || *FileList == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ if (*Path == L'.' && *(Path+1) == L'\\') {
+ Path+=2;
+ }
+
+ //
+ // convert a local path to an absolute path
+ //
+ if (StrStr(Path, L":") == NULL) {
+ CurDir = EfiShellGetCurDir(NULL);
+ ASSERT((Path2 == NULL && Path2Size == 0) || (Path2 != NULL));
+ StrnCatGrow(&Path2, &Path2Size, CurDir, 0);
+ StrnCatGrow(&Path2, &Path2Size, L"\\", 0);
+ if (*Path == L'\\') {
+ Path++;
+ while (PathRemoveLastItem(Path2)) ;
+ }
+ ASSERT((Path2 == NULL && Path2Size == 0) || (Path2 != NULL));
+ StrnCatGrow(&Path2, &Path2Size, Path, 0);
+ } else {
+ ASSERT(Path2 == NULL);
+ StrnCatGrow(&Path2, NULL, Path, 0);
+ }
+
+ PathCleanUpDirectories (Path2);
+
+ //
+ // do the search
+ //
+ Status = EfiShellFindFiles(Path2, FileList);
+
+ FreePool(Path2);
+
+ if (EFI_ERROR(Status)) {
+ return (Status);
+ }
+
+ Found = FALSE;
+ //
+ // We had no errors so open all the files (that are not already opened...)
+ //
+ for ( ShellFileListItem = (EFI_SHELL_FILE_INFO*)GetFirstNode(&(*FileList)->Link)
+ ; !IsNull(&(*FileList)->Link, &ShellFileListItem->Link)
+ ; ShellFileListItem = (EFI_SHELL_FILE_INFO*)GetNextNode(&(*FileList)->Link, &ShellFileListItem->Link)
+ ){
+ if (ShellFileListItem->Status == 0 && ShellFileListItem->Handle == NULL) {
+ ShellFileListItem->Status = EfiShellOpenFileByName (ShellFileListItem->FullName, &ShellFileListItem->Handle, OpenMode);
+ Found = TRUE;
+ }
+ }
+
+ if (!Found) {
+ return (EFI_NOT_FOUND);
+ }
+ return(EFI_SUCCESS);
+}
+
+/**
+ Gets the environment variable and Attributes, or list of environment variables. Can be
+ used instead of GetEnv().
+
+ This function returns the current value of the specified environment variable and
+ the Attributes. If no variable name was specified, then all of the known
+ variables will be returned.
+
+ @param[in] Name A pointer to the environment variable name. If Name is NULL,
+ then the function will return all of the defined shell
+ environment variables. In the case where multiple environment
+ variables are being returned, each variable will be terminated
+ by a NULL, and the list will be terminated by a double NULL.
+ @param[out] Attributes If not NULL, a pointer to the returned attributes bitmask for
+ the environment variable. In the case where Name is NULL, and
+ multiple environment variables are being returned, Attributes
+ is undefined.
+
+ @retval NULL The environment variable doesn't exist.
+ @return A non-NULL value points to the variable's value. The returned
+ pointer does not need to be freed by the caller.
+**/
+CONST CHAR16 *
+EFIAPI
+EfiShellGetEnvEx(
+ IN CONST CHAR16 *Name,
+ OUT UINT32 *Attributes OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ VOID *Buffer;
+ UINTN Size;
+ ENV_VAR_LIST *Node;
+ CHAR16 *CurrentWriteLocation;
+
+ Size = 0;
+ Buffer = NULL;
+
+ if (Name == NULL) {
+
+ //
+ // Build the semi-colon delimited list. (2 passes)
+ //
+ for ( Node = (ENV_VAR_LIST*)GetFirstNode(&gShellEnvVarList.Link)
+ ; !IsNull(&gShellEnvVarList.Link, &Node->Link)
+ ; Node = (ENV_VAR_LIST*)GetNextNode(&gShellEnvVarList.Link, &Node->Link)
+ ){
+ ASSERT(Node->Key != NULL);
+ Size += StrSize(Node->Key);
+ }
+
+ Size += 2*sizeof(CHAR16);
+
+ Buffer = AllocateZeroPool(Size);
+ if (Buffer == NULL) {
+ return (NULL);
+ }
+ CurrentWriteLocation = (CHAR16*)Buffer;
+
+ for ( Node = (ENV_VAR_LIST*)GetFirstNode(&gShellEnvVarList.Link)
+ ; !IsNull(&gShellEnvVarList.Link, &Node->Link)
+ ; Node = (ENV_VAR_LIST*)GetNextNode(&gShellEnvVarList.Link, &Node->Link)
+ ){
+ ASSERT(Node->Key != NULL);
+ StrCpyS( CurrentWriteLocation,
+ (Size)/sizeof(CHAR16) - (CurrentWriteLocation - ((CHAR16*)Buffer)),
+ Node->Key
+ );
+ CurrentWriteLocation += StrLen(CurrentWriteLocation) + 1;
+ }
+
+ } else {
+ //
+ // We are doing a specific environment variable
+ //
+ Status = ShellFindEnvVarInList(Name, (CHAR16**)&Buffer, &Size, Attributes);
+
+ if (EFI_ERROR(Status)){
+ //
+ // get the size we need for this EnvVariable
+ //
+ Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(Name, Attributes, &Size, Buffer);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ //
+ // Allocate the space and recall the get function
+ //
+ Buffer = AllocateZeroPool(Size);
+ Status = SHELL_GET_ENVIRONMENT_VARIABLE_AND_ATTRIBUTES(Name, Attributes, &Size, Buffer);
+ }
+ //
+ // we didnt get it (might not exist)
+ // free the memory if we allocated any and return NULL
+ //
+ if (EFI_ERROR(Status)) {
+ if (Buffer != NULL) {
+ FreePool(Buffer);
+ }
+ return (NULL);
+ } else {
+ //
+ // If we did not find the environment variable in the gShellEnvVarList
+ // but get it from UEFI variable storage successfully then we need update
+ // the gShellEnvVarList.
+ //
+ ShellFreeEnvVarList ();
+ Status = ShellInitEnvVarList ();
+ ASSERT (Status == EFI_SUCCESS);
+ }
+ }
+ }
+
+ //
+ // return the buffer
+ //
+ return (AddBufferToFreeList(Buffer));
+}
+
+/**
+ Gets either a single or list of environment variables.
+
+ If name is not NULL then this function returns the current value of the specified
+ environment variable.
+
+ If Name is NULL, then a list of all environment variable names is returned. Each is a
+ NULL terminated string with a double NULL terminating the list.
+
+ @param Name A pointer to the environment variable name. If
+ Name is NULL, then the function will return all
+ of the defined shell environment variables. In
+ the case where multiple environment variables are
+ being returned, each variable will be terminated by
+ a NULL, and the list will be terminated by a double
+ NULL.
+
+ @retval !=NULL A pointer to the returned string.
+ The returned pointer does not need to be freed by the caller.
+
+ @retval NULL The environment variable doesn't exist or there are
+ no environment variables.
+**/
+CONST CHAR16 *
+EFIAPI
+EfiShellGetEnv(
+ IN CONST CHAR16 *Name
+ )
+{
+ return (EfiShellGetEnvEx(Name, NULL));
+}
+
+/**
+ Internal variable setting function. Allows for setting of the read only variables.
+
+ @param Name Points to the NULL-terminated environment variable name.
+ @param Value Points to the NULL-terminated environment variable value. If the value is an
+ empty string then the environment variable is deleted.
+ @param Volatile Indicates whether the variable is non-volatile (FALSE) or volatile (TRUE).
+
+ @retval EFI_SUCCESS The environment variable was successfully updated.
+**/
+EFI_STATUS
+EFIAPI
+InternalEfiShellSetEnv(
+ IN CONST CHAR16 *Name,
+ IN CONST CHAR16 *Value,
+ IN BOOLEAN Volatile
+ )
+{
+ EFI_STATUS Status;
+
+ if (Value == NULL || StrLen(Value) == 0) {
+ Status = SHELL_DELETE_ENVIRONMENT_VARIABLE(Name);
+ if (!EFI_ERROR(Status)) {
+ ShellRemvoeEnvVarFromList(Name);
+ }
+ } else {
+ SHELL_DELETE_ENVIRONMENT_VARIABLE(Name);
+ Status = ShellAddEnvVarToList(
+ Name, Value, StrSize(Value),
+ EFI_VARIABLE_BOOTSERVICE_ACCESS | (Volatile ? 0 : EFI_VARIABLE_NON_VOLATILE)
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = Volatile
+ ? SHELL_SET_ENVIRONMENT_VARIABLE_V(Name, StrSize(Value), Value)
+ : SHELL_SET_ENVIRONMENT_VARIABLE_NV(Name, StrSize(Value), Value);
+ if (EFI_ERROR (Status)) {
+ ShellRemvoeEnvVarFromList(Name);
+ }
+ }
+ }
+ return Status;
+}
+
+/**
+ Sets the environment variable.
+
+ This function changes the current value of the specified environment variable. If the
+ environment variable exists and the Value is an empty string, then the environment
+ variable is deleted. If the environment variable exists and the Value is not an empty
+ string, then the value of the environment variable is changed. If the environment
+ variable does not exist and the Value is an empty string, there is no action. If the
+ environment variable does not exist and the Value is a non-empty string, then the
+ environment variable is created and assigned the specified value.
+
+ For a description of volatile and non-volatile environment variables, see UEFI Shell
+ 2.0 specification section 3.6.1.
+
+ @param Name Points to the NULL-terminated environment variable name.
+ @param Value Points to the NULL-terminated environment variable value. If the value is an
+ empty string then the environment variable is deleted.
+ @param Volatile Indicates whether the variable is non-volatile (FALSE) or volatile (TRUE).
+
+ @retval EFI_SUCCESS The environment variable was successfully updated.
+**/
+EFI_STATUS
+EFIAPI
+EfiShellSetEnv(
+ IN CONST CHAR16 *Name,
+ IN CONST CHAR16 *Value,
+ IN BOOLEAN Volatile
+ )
+{
+ if (Name == NULL || *Name == CHAR_NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+ //
+ // Make sure we dont 'set' a predefined read only variable
+ //
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)Name,
+ L"cwd") == 0
+ ||gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)Name,
+ L"Lasterror") == 0
+ ||gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)Name,
+ L"profiles") == 0
+ ||gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)Name,
+ L"uefishellsupport") == 0
+ ||gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)Name,
+ L"uefishellversion") == 0
+ ||gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)Name,
+ L"uefiversion") == 0
+ ||(!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest &&
+ gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)Name,
+ (CHAR16*)mNoNestingEnvVarName) == 0)
+ ){
+ return (EFI_INVALID_PARAMETER);
+ }
+ return (InternalEfiShellSetEnv(Name, Value, Volatile));
+}
+
+/**
+ Returns the current directory on the specified device.
+
+ If FileSystemMapping is NULL, it returns the current working directory. If the
+ FileSystemMapping is not NULL, it returns the current directory associated with the
+ FileSystemMapping. In both cases, the returned name includes the file system
+ mapping (i.e. fs0:\current-dir).
+
+ Note that the current directory string should exclude the tailing backslash character.
+
+ @param FileSystemMapping A pointer to the file system mapping. If NULL,
+ then the current working directory is returned.
+
+ @retval !=NULL The current directory.
+ @retval NULL Current directory does not exist.
+**/
+CONST CHAR16 *
+EFIAPI
+EfiShellGetCurDir(
+ IN CONST CHAR16 *FileSystemMapping OPTIONAL
+ )
+{
+ CHAR16 *PathToReturn;
+ UINTN Size;
+ SHELL_MAP_LIST *MapListItem;
+ if (!IsListEmpty(&gShellMapList.Link)) {
+ //
+ // if parameter is NULL, use current
+ //
+ if (FileSystemMapping == NULL) {
+ return (EfiShellGetEnv(L"cwd"));
+ } else {
+ Size = 0;
+ PathToReturn = NULL;
+ MapListItem = ShellCommandFindMapItem(FileSystemMapping);
+ if (MapListItem != NULL) {
+ ASSERT((PathToReturn == NULL && Size == 0) || (PathToReturn != NULL));
+ PathToReturn = StrnCatGrow(&PathToReturn, &Size, MapListItem->MapName, 0);
+ PathToReturn = StrnCatGrow(&PathToReturn, &Size, MapListItem->CurrentDirectoryPath, 0);
+ }
+ }
+ return (AddBufferToFreeList(PathToReturn));
+ } else {
+ return (NULL);
+ }
+}
+
+/**
+ Changes the current directory on the specified device.
+
+ If the FileSystem is NULL, and the directory Dir does not contain a file system's
+ mapped name, this function changes the current working directory.
+
+ If the FileSystem is NULL and the directory Dir contains a mapped name, then the
+ current file system and the current directory on that file system are changed.
+
+ If FileSystem is NULL, and Dir is not NULL, then this changes the current working file
+ system.
+
+ If FileSystem is not NULL and Dir is not NULL, then this function changes the current
+ directory on the specified file system.
+
+ If the current working directory or the current working file system is changed then the
+ %cwd% environment variable will be updated
+
+ Note that the current directory string should exclude the tailing backslash character.
+
+ @param FileSystem A pointer to the file system's mapped name. If NULL, then the current working
+ directory is changed.
+ @param Dir Points to the NULL-terminated directory on the device specified by FileSystem.
+
+ @retval EFI_SUCCESS The operation was sucessful
+ @retval EFI_NOT_FOUND The file system could not be found
+**/
+EFI_STATUS
+EFIAPI
+EfiShellSetCurDir(
+ IN CONST CHAR16 *FileSystem OPTIONAL,
+ IN CONST CHAR16 *Dir
+ )
+{
+ CHAR16 *MapName;
+ SHELL_MAP_LIST *MapListItem;
+ UINTN Size;
+ EFI_STATUS Status;
+ CHAR16 *TempString;
+ CHAR16 *DirectoryName;
+ UINTN TempLen;
+
+ Size = 0;
+ MapName = NULL;
+ MapListItem = NULL;
+ TempString = NULL;
+ DirectoryName = NULL;
+
+ if ((FileSystem == NULL && Dir == NULL) || Dir == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ if (IsListEmpty(&gShellMapList.Link)){
+ return (EFI_NOT_FOUND);
+ }
+
+ DirectoryName = StrnCatGrow(&DirectoryName, NULL, Dir, 0);
+ ASSERT(DirectoryName != NULL);
+
+ PathCleanUpDirectories(DirectoryName);
+
+ if (FileSystem == NULL) {
+ //
+ // determine the file system mapping to use
+ //
+ if (StrStr(DirectoryName, L":") != NULL) {
+ ASSERT(MapName == NULL);
+ MapName = StrnCatGrow(&MapName, NULL, DirectoryName, (StrStr(DirectoryName, L":")-DirectoryName+1));
+ }
+ //
+ // find the file system mapping's entry in the list
+ // or use current
+ //
+ if (MapName != NULL) {
+ MapListItem = ShellCommandFindMapItem(MapName);
+
+ //
+ // make that the current file system mapping
+ //
+ if (MapListItem != NULL) {
+ gShellCurDir = MapListItem;
+ }
+ } else {
+ MapListItem = gShellCurDir;
+ }
+
+ if (MapListItem == NULL) {
+ FreePool (DirectoryName);
+ SHELL_FREE_NON_NULL(MapName);
+ return (EFI_NOT_FOUND);
+ }
+
+ //
+ // now update the MapListItem's current directory
+ //
+ if (MapListItem->CurrentDirectoryPath != NULL && DirectoryName[StrLen(DirectoryName) - 1] != L':') {
+ FreePool(MapListItem->CurrentDirectoryPath);
+ MapListItem->CurrentDirectoryPath = NULL;
+ }
+ if (MapName != NULL) {
+ TempLen = StrLen(MapName);
+ if (TempLen != StrLen(DirectoryName)) {
+ ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));
+ MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, DirectoryName+StrLen(MapName), 0);
+ }
+ FreePool (MapName);
+ } else {
+ ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));
+ MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, DirectoryName, 0);
+ }
+ if ((MapListItem->CurrentDirectoryPath != NULL && MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] == L'\\') || (MapListItem->CurrentDirectoryPath == NULL)) {
+ ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));
+ if (MapListItem->CurrentDirectoryPath != NULL) {
+ MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] = CHAR_NULL;
+ }
+ }
+ } else {
+ //
+ // cant have a mapping in the directory...
+ //
+ if (StrStr(DirectoryName, L":") != NULL) {
+ FreePool (DirectoryName);
+ return (EFI_INVALID_PARAMETER);
+ }
+ //
+ // FileSystem != NULL
+ //
+ MapListItem = ShellCommandFindMapItem(FileSystem);
+ if (MapListItem == NULL) {
+ FreePool (DirectoryName);
+ return (EFI_INVALID_PARAMETER);
+ }
+// gShellCurDir = MapListItem;
+ if (DirectoryName != NULL) {
+ //
+ // change current dir on that file system
+ //
+
+ if (MapListItem->CurrentDirectoryPath != NULL) {
+ FreePool(MapListItem->CurrentDirectoryPath);
+ DEBUG_CODE(MapListItem->CurrentDirectoryPath = NULL;);
+ }
+// ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));
+// MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, FileSystem, 0);
+ ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));
+ MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, L"\\", 0);
+ ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));
+ MapListItem->CurrentDirectoryPath = StrnCatGrow(&MapListItem->CurrentDirectoryPath, &Size, DirectoryName, 0);
+ if (MapListItem->CurrentDirectoryPath != NULL && MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] == L'\\') {
+ ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));
+ MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] = CHAR_NULL;
+ }
+ }
+ }
+ FreePool (DirectoryName);
+ //
+ // if updated the current directory then update the environment variable
+ //
+ if (MapListItem == gShellCurDir) {
+ Size = 0;
+ ASSERT((TempString == NULL && Size == 0) || (TempString != NULL));
+ StrnCatGrow(&TempString, &Size, MapListItem->MapName, 0);
+ ASSERT((TempString == NULL && Size == 0) || (TempString != NULL));
+ StrnCatGrow(&TempString, &Size, MapListItem->CurrentDirectoryPath, 0);
+ Status = InternalEfiShellSetEnv(L"cwd", TempString, TRUE);
+ FreePool(TempString);
+ return (Status);
+ }
+ return(EFI_SUCCESS);
+}
+
+/**
+ Return help information about a specific command.
+
+ This function returns the help information for the specified command. The help text
+ can be internal to the shell or can be from a UEFI Shell manual page.
+
+ If Sections is specified, then each section name listed will be compared in a casesensitive
+ manner, to the section names described in Appendix B. If the section exists,
+ it will be appended to the returned help text. If the section does not exist, no
+ information will be returned. If Sections is NULL, then all help text information
+ available will be returned.
+
+ @param Command Points to the NULL-terminated UEFI Shell command name.
+ @param Sections Points to the NULL-terminated comma-delimited
+ section names to return. If NULL, then all
+ sections will be returned.
+ @param HelpText On return, points to a callee-allocated buffer
+ containing all specified help text.
+
+ @retval EFI_SUCCESS The help text was returned.
+ @retval EFI_OUT_OF_RESOURCES The necessary buffer could not be allocated to hold the
+ returned help text.
+ @retval EFI_INVALID_PARAMETER HelpText is NULL
+ @retval EFI_NOT_FOUND There is no help text available for Command.
+**/
+EFI_STATUS
+EFIAPI
+EfiShellGetHelpText(
+ IN CONST CHAR16 *Command,
+ IN CONST CHAR16 *Sections OPTIONAL,
+ OUT CHAR16 **HelpText
+ )
+{
+ CONST CHAR16 *ManFileName;
+ CHAR16 *FixCommand;
+ EFI_STATUS Status;
+
+ ASSERT(HelpText != NULL);
+ FixCommand = NULL;
+
+ ManFileName = ShellCommandGetManFileNameHandler(Command);
+
+ if (ManFileName != NULL) {
+ return (ProcessManFile(ManFileName, Command, Sections, NULL, HelpText));
+ } else {
+ if ((StrLen(Command)> 4)
+ && (Command[StrLen(Command)-1] == L'i' || Command[StrLen(Command)-1] == L'I')
+ && (Command[StrLen(Command)-2] == L'f' || Command[StrLen(Command)-2] == L'F')
+ && (Command[StrLen(Command)-3] == L'e' || Command[StrLen(Command)-3] == L'E')
+ && (Command[StrLen(Command)-4] == L'.')
+ ) {
+ FixCommand = AllocateZeroPool(StrSize(Command) - 4 * sizeof (CHAR16));
+ if (FixCommand == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StrnCpyS( FixCommand,
+ (StrSize(Command) - 4 * sizeof (CHAR16))/sizeof(CHAR16),
+ Command,
+ StrLen(Command)-4
+ );
+ Status = ProcessManFile(FixCommand, FixCommand, Sections, NULL, HelpText);
+ FreePool(FixCommand);
+ return Status;
+ } else {
+ return (ProcessManFile(Command, Command, Sections, NULL, HelpText));
+ }
+ }
+}
+
+/**
+ Gets the enable status of the page break output mode.
+
+ User can use this function to determine current page break mode.
+
+ @retval TRUE The page break output mode is enabled.
+ @retval FALSE The page break output mode is disabled.
+**/
+BOOLEAN
+EFIAPI
+EfiShellGetPageBreak(
+ VOID
+ )
+{
+ return(ShellInfoObject.PageBreakEnabled);
+}
+
+/**
+ Judges whether the active shell is the root shell.
+
+ This function makes the user to know that whether the active Shell is the root shell.
+
+ @retval TRUE The active Shell is the root Shell.
+ @retval FALSE The active Shell is NOT the root Shell.
+**/
+BOOLEAN
+EFIAPI
+EfiShellIsRootShell(
+ VOID
+ )
+{
+ return(ShellInfoObject.RootShellInstance);
+}
+
+/**
+ function to return a semi-colon delimeted list of all alias' in the current shell
+
+ up to caller to free the memory.
+
+ @retval NULL No alias' were found
+ @retval NULL An error ocurred getting alias'
+ @return !NULL a list of all alias'
+**/
+CHAR16 *
+EFIAPI
+InternalEfiShellGetListAlias(
+ )
+{
+
+ EFI_STATUS Status;
+ EFI_GUID Guid;
+ CHAR16 *VariableName;
+ UINTN NameSize;
+ UINTN NameBufferSize;
+ CHAR16 *RetVal;
+ UINTN RetSize;
+
+ NameBufferSize = INIT_NAME_BUFFER_SIZE;
+ VariableName = AllocateZeroPool(NameBufferSize);
+ RetSize = 0;
+ RetVal = NULL;
+
+ if (VariableName == NULL) {
+ return (NULL);
+ }
+
+ VariableName[0] = CHAR_NULL;
+
+ while (TRUE) {
+ NameSize = NameBufferSize;
+ Status = gRT->GetNextVariableName(&NameSize, VariableName, &Guid);
+ if (Status == EFI_NOT_FOUND){
+ break;
+ } else if (Status == EFI_BUFFER_TOO_SMALL) {
+ NameBufferSize = NameSize > NameBufferSize * 2 ? NameSize : NameBufferSize * 2;
+ SHELL_FREE_NON_NULL(VariableName);
+ VariableName = AllocateZeroPool(NameBufferSize);
+ if (VariableName == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ SHELL_FREE_NON_NULL(RetVal);
+ RetVal = NULL;
+ break;
+ }
+
+ NameSize = NameBufferSize;
+ Status = gRT->GetNextVariableName(&NameSize, VariableName, &Guid);
+ }
+
+ if (EFI_ERROR (Status)) {
+ SHELL_FREE_NON_NULL(RetVal);
+ RetVal = NULL;
+ break;
+ }
+
+ if (CompareGuid(&Guid, &gShellAliasGuid)){
+ ASSERT((RetVal == NULL && RetSize == 0) || (RetVal != NULL));
+ RetVal = StrnCatGrow(&RetVal, &RetSize, VariableName, 0);
+ RetVal = StrnCatGrow(&RetVal, &RetSize, L";", 0);
+ } // compare guid
+ } // while
+ SHELL_FREE_NON_NULL(VariableName);
+
+ return (RetVal);
+}
+
+/**
+ Convert a null-terminated unicode string, in-place, to all lowercase.
+ Then return it.
+
+ @param Str The null-terminated string to be converted to all lowercase.
+
+ @return The null-terminated string converted into all lowercase.
+**/
+CHAR16 *
+ToLower (
+ CHAR16 *Str
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Str[Index] != L'\0'; Index++) {
+ if (Str[Index] >= L'A' && Str[Index] <= L'Z') {
+ Str[Index] -= (CHAR16)(L'A' - L'a');
+ }
+ }
+ return Str;
+}
+
+/**
+ This function returns the command associated with a alias or a list of all
+ alias'.
+
+ @param[in] Alias Points to the NULL-terminated shell alias.
+ If this parameter is NULL, then all
+ aliases will be returned in ReturnedData.
+ @param[out] Volatile upon return of a single command if TRUE indicates
+ this is stored in a volatile fashion. FALSE otherwise.
+
+ @return If Alias is not NULL, it will return a pointer to
+ the NULL-terminated command for that alias.
+ If Alias is NULL, ReturnedData points to a ';'
+ delimited list of alias (e.g.
+ ReturnedData = "dir;del;copy;mfp") that is NULL-terminated.
+ @retval NULL an error ocurred
+ @retval NULL Alias was not a valid Alias
+**/
+CONST CHAR16 *
+EFIAPI
+EfiShellGetAlias(
+ IN CONST CHAR16 *Alias,
+ OUT BOOLEAN *Volatile OPTIONAL
+ )
+{
+ CHAR16 *RetVal;
+ UINTN RetSize;
+ UINT32 Attribs;
+ EFI_STATUS Status;
+ CHAR16 *AliasLower;
+ CHAR16 *AliasVal;
+
+ // Convert to lowercase to make aliases case-insensitive
+ if (Alias != NULL) {
+ AliasLower = AllocateCopyPool (StrSize (Alias), Alias);
+ if (AliasLower == NULL) {
+ return NULL;
+ }
+ ToLower (AliasLower);
+
+ if (Volatile == NULL) {
+ GetVariable2 (AliasLower, &gShellAliasGuid, (VOID **)&AliasVal, NULL);
+ FreePool(AliasLower);
+ return (AddBufferToFreeList(AliasVal));
+ }
+ RetSize = 0;
+ RetVal = NULL;
+ Status = gRT->GetVariable(AliasLower, &gShellAliasGuid, &Attribs, &RetSize, RetVal);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ RetVal = AllocateZeroPool(RetSize);
+ Status = gRT->GetVariable(AliasLower, &gShellAliasGuid, &Attribs, &RetSize, RetVal);
+ }
+ if (EFI_ERROR(Status)) {
+ if (RetVal != NULL) {
+ FreePool(RetVal);
+ }
+ FreePool(AliasLower);
+ return (NULL);
+ }
+ if ((EFI_VARIABLE_NON_VOLATILE & Attribs) == EFI_VARIABLE_NON_VOLATILE) {
+ *Volatile = FALSE;
+ } else {
+ *Volatile = TRUE;
+ }
+
+ FreePool (AliasLower);
+ return (AddBufferToFreeList(RetVal));
+ }
+ return (AddBufferToFreeList(InternalEfiShellGetListAlias()));
+}
+
+/**
+ Changes a shell command alias.
+
+ This function creates an alias for a shell command or if Alias is NULL it will delete an existing alias.
+
+ this function does not check for built in alias'.
+
+ @param[in] Command Points to the NULL-terminated shell command or existing alias.
+ @param[in] Alias Points to the NULL-terminated alias for the shell command. If this is NULL, and
+ Command refers to an alias, that alias will be deleted.
+ @param[in] Volatile if TRUE the Alias being set will be stored in a volatile fashion. if FALSE the
+ Alias being set will be stored in a non-volatile fashion.
+
+ @retval EFI_SUCCESS Alias created or deleted successfully.
+ @retval EFI_NOT_FOUND the Alias intended to be deleted was not found
+**/
+EFI_STATUS
+EFIAPI
+InternalSetAlias(
+ IN CONST CHAR16 *Command,
+ IN CONST CHAR16 *Alias,
+ IN BOOLEAN Volatile
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *AliasLower;
+
+ // Convert to lowercase to make aliases case-insensitive
+ if (Alias != NULL) {
+ AliasLower = AllocateCopyPool (StrSize (Alias), Alias);
+ if (AliasLower == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ToLower (AliasLower);
+ } else {
+ AliasLower = NULL;
+ }
+
+ //
+ // We must be trying to remove one if Alias is NULL
+ //
+ if (Alias == NULL) {
+ //
+ // remove an alias (but passed in COMMAND parameter)
+ //
+ Status = (gRT->SetVariable((CHAR16*)Command, &gShellAliasGuid, 0, 0, NULL));
+ } else {
+ //
+ // Add and replace are the same
+ //
+
+ // We dont check the error return on purpose since the variable may not exist.
+ gRT->SetVariable((CHAR16*)Command, &gShellAliasGuid, 0, 0, NULL);
+
+ Status = (gRT->SetVariable((CHAR16*)Alias, &gShellAliasGuid, EFI_VARIABLE_BOOTSERVICE_ACCESS|(Volatile?0:EFI_VARIABLE_NON_VOLATILE), StrSize(Command), (VOID*)Command));
+ }
+
+ if (Alias != NULL) {
+ FreePool (AliasLower);
+ }
+ return Status;
+}
+
+/**
+ Changes a shell command alias.
+
+ This function creates an alias for a shell command or if Alias is NULL it will delete an existing alias.
+
+
+ @param[in] Command Points to the NULL-terminated shell command or existing alias.
+ @param[in] Alias Points to the NULL-terminated alias for the shell command. If this is NULL, and
+ Command refers to an alias, that alias will be deleted.
+ @param[in] Replace If TRUE and the alias already exists, then the existing alias will be replaced. If
+ FALSE and the alias already exists, then the existing alias is unchanged and
+ EFI_ACCESS_DENIED is returned.
+ @param[in] Volatile if TRUE the Alias being set will be stored in a volatile fashion. if FALSE the
+ Alias being set will be stored in a non-volatile fashion.
+
+ @retval EFI_SUCCESS Alias created or deleted successfully.
+ @retval EFI_NOT_FOUND the Alias intended to be deleted was not found
+ @retval EFI_ACCESS_DENIED The alias is a built-in alias or already existed and Replace was set to
+ FALSE.
+ @retval EFI_INVALID_PARAMETER Command is null or the empty string.
+**/
+EFI_STATUS
+EFIAPI
+EfiShellSetAlias(
+ IN CONST CHAR16 *Command,
+ IN CONST CHAR16 *Alias,
+ IN BOOLEAN Replace,
+ IN BOOLEAN Volatile
+ )
+{
+ if (ShellCommandIsOnAliasList(Alias==NULL?Command:Alias)) {
+ //
+ // cant set over a built in alias
+ //
+ return (EFI_ACCESS_DENIED);
+ } else if (Command == NULL || *Command == CHAR_NULL || StrLen(Command) == 0) {
+ //
+ // Command is null or empty
+ //
+ return (EFI_INVALID_PARAMETER);
+ } else if (EfiShellGetAlias(Command, NULL) != NULL && !Replace) {
+ //
+ // Alias already exists, Replace not set
+ //
+ return (EFI_ACCESS_DENIED);
+ } else {
+ return (InternalSetAlias(Command, Alias, Volatile));
+ }
+}
+
+// Pure FILE_HANDLE operations are passed to FileHandleLib
+// these functions are indicated by the *
+EFI_SHELL_PROTOCOL mShellProtocol = {
+ EfiShellExecute,
+ EfiShellGetEnv,
+ EfiShellSetEnv,
+ EfiShellGetAlias,
+ EfiShellSetAlias,
+ EfiShellGetHelpText,
+ EfiShellGetDevicePathFromMap,
+ EfiShellGetMapFromDevicePath,
+ EfiShellGetDevicePathFromFilePath,
+ EfiShellGetFilePathFromDevicePath,
+ EfiShellSetMap,
+ EfiShellGetCurDir,
+ EfiShellSetCurDir,
+ EfiShellOpenFileList,
+ EfiShellFreeFileList,
+ EfiShellRemoveDupInFileList,
+ EfiShellBatchIsActive,
+ EfiShellIsRootShell,
+ EfiShellEnablePageBreak,
+ EfiShellDisablePageBreak,
+ EfiShellGetPageBreak,
+ EfiShellGetDeviceName,
+ (EFI_SHELL_GET_FILE_INFO)FileHandleGetInfo, //*
+ (EFI_SHELL_SET_FILE_INFO)FileHandleSetInfo, //*
+ EfiShellOpenFileByName,
+ EfiShellClose,
+ EfiShellCreateFile,
+ (EFI_SHELL_READ_FILE)FileHandleRead, //*
+ (EFI_SHELL_WRITE_FILE)FileHandleWrite, //*
+ (EFI_SHELL_DELETE_FILE)FileHandleDelete, //*
+ EfiShellDeleteFileByName,
+ (EFI_SHELL_GET_FILE_POSITION)FileHandleGetPosition, //*
+ (EFI_SHELL_SET_FILE_POSITION)FileHandleSetPosition, //*
+ (EFI_SHELL_FLUSH_FILE)FileHandleFlush, //*
+ EfiShellFindFiles,
+ EfiShellFindFilesInDir,
+ (EFI_SHELL_GET_FILE_SIZE)FileHandleGetSize, //*
+ EfiShellOpenRoot,
+ EfiShellOpenRootByHandle,
+ NULL,
+ SHELL_MAJOR_VERSION,
+ SHELL_MINOR_VERSION,
+
+ // New for UEFI Shell 2.1
+ EfiShellRegisterGuidName,
+ EfiShellGetGuidName,
+ EfiShellGetGuidFromName,
+ EfiShellGetEnvEx
+};
+
+/**
+ Function to create and install on the current handle.
+
+ Will overwrite any existing ShellProtocols in the system to be sure that
+ the current shell is in control.
+
+ This must be removed via calling CleanUpShellProtocol().
+
+ @param[in, out] NewShell The pointer to the pointer to the structure
+ to install.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @return An error from LocateHandle, CreateEvent, or other core function.
+**/
+EFI_STATUS
+EFIAPI
+CreatePopulateInstallShellProtocol (
+ IN OUT EFI_SHELL_PROTOCOL **NewShell
+ )
+{
+ EFI_STATUS Status;
+ UINTN BufferSize;
+ EFI_HANDLE *Buffer;
+ UINTN HandleCounter;
+ SHELL_PROTOCOL_HANDLE_LIST *OldProtocolNode;
+ EFI_SHELL_PROTOCOL *OldShell;
+
+ if (NewShell == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ BufferSize = 0;
+ Buffer = NULL;
+ OldProtocolNode = NULL;
+ InitializeListHead(&ShellInfoObject.OldShellList.Link);
+
+ //
+ // Initialize EfiShellProtocol object...
+ //
+ Status = gBS->CreateEvent(0,
+ 0,
+ NULL,
+ NULL,
+ &mShellProtocol.ExecutionBreak);
+ if (EFI_ERROR(Status)) {
+ return (Status);
+ }
+
+ //
+ // Get the size of the buffer we need.
+ //
+ Status = gBS->LocateHandle(ByProtocol,
+ &gEfiShellProtocolGuid,
+ NULL,
+ &BufferSize,
+ Buffer);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ //
+ // Allocate and recall with buffer of correct size
+ //
+ Buffer = AllocateZeroPool(BufferSize);
+ if (Buffer == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ Status = gBS->LocateHandle(ByProtocol,
+ &gEfiShellProtocolGuid,
+ NULL,
+ &BufferSize,
+ Buffer);
+ if (EFI_ERROR(Status)) {
+ FreePool(Buffer);
+ return (Status);
+ }
+ //
+ // now overwrite each of them, but save the info to restore when we end.
+ //
+ for (HandleCounter = 0 ; HandleCounter < (BufferSize/sizeof(EFI_HANDLE)) ; HandleCounter++) {
+ Status = gBS->OpenProtocol(Buffer[HandleCounter],
+ &gEfiShellProtocolGuid,
+ (VOID **) &OldShell,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR(Status)) {
+ OldProtocolNode = AllocateZeroPool(sizeof(SHELL_PROTOCOL_HANDLE_LIST));
+ if (OldProtocolNode == NULL) {
+ if (!IsListEmpty (&ShellInfoObject.OldShellList.Link)) {
+ CleanUpShellProtocol (&mShellProtocol);
+ }
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ }
+ //
+ // reinstall over the old one...
+ //
+ OldProtocolNode->Handle = Buffer[HandleCounter];
+ OldProtocolNode->Interface = OldShell;
+ Status = gBS->ReinstallProtocolInterface(
+ OldProtocolNode->Handle,
+ &gEfiShellProtocolGuid,
+ OldProtocolNode->Interface,
+ (VOID*)(&mShellProtocol));
+ if (!EFI_ERROR(Status)) {
+ //
+ // we reinstalled sucessfully. log this so we can reverse it later.
+ //
+
+ //
+ // add to the list for subsequent...
+ //
+ InsertTailList(&ShellInfoObject.OldShellList.Link, &OldProtocolNode->Link);
+ }
+ }
+ }
+ FreePool(Buffer);
+ } else if (Status == EFI_NOT_FOUND) {
+ ASSERT(IsListEmpty(&ShellInfoObject.OldShellList.Link));
+ //
+ // no one else published yet. just publish it ourselves.
+ //
+ Status = gBS->InstallProtocolInterface (
+ &gImageHandle,
+ &gEfiShellProtocolGuid,
+ EFI_NATIVE_INTERFACE,
+ (VOID*)(&mShellProtocol));
+ }
+
+ if (PcdGetBool(PcdShellSupportOldProtocols)){
+ ///@todo support ShellEnvironment2
+ ///@todo do we need to support ShellEnvironment (not ShellEnvironment2) also?
+ }
+
+ if (!EFI_ERROR(Status)) {
+ *NewShell = &mShellProtocol;
+ }
+ return (Status);
+}
+
+/**
+ Opposite of CreatePopulateInstallShellProtocol.
+
+ Free all memory and restore the system to the state it was in before calling
+ CreatePopulateInstallShellProtocol.
+
+ @param[in, out] NewShell The pointer to the new shell protocol structure.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+CleanUpShellProtocol (
+ IN OUT EFI_SHELL_PROTOCOL *NewShell
+ )
+{
+ SHELL_PROTOCOL_HANDLE_LIST *Node2;
+
+ //
+ // if we need to restore old protocols...
+ //
+ if (!IsListEmpty(&ShellInfoObject.OldShellList.Link)) {
+ for (Node2 = (SHELL_PROTOCOL_HANDLE_LIST *) GetFirstNode (&ShellInfoObject.OldShellList.Link)
+ ; !IsListEmpty (&ShellInfoObject.OldShellList.Link)
+ ; Node2 = (SHELL_PROTOCOL_HANDLE_LIST *) GetFirstNode (&ShellInfoObject.OldShellList.Link)
+ ) {
+ RemoveEntryList (&Node2->Link);
+ gBS->ReinstallProtocolInterface (Node2->Handle, &gEfiShellProtocolGuid, NewShell, Node2->Interface);
+ FreePool (Node2);
+ }
+ } else {
+ //
+ // no need to restore
+ //
+ gBS->UninstallProtocolInterface (gImageHandle, &gEfiShellProtocolGuid, NewShell);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Cleanup the shell environment.
+
+ @param[in, out] NewShell The pointer to the new shell protocol structure.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+CleanUpShellEnvironment (
+ IN OUT EFI_SHELL_PROTOCOL *NewShell
+ )
+{
+ EFI_STATUS Status;
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;
+
+ CleanUpShellProtocol (NewShell);
+
+ Status = gBS->CloseEvent(NewShell->ExecutionBreak);
+ NewShell->ExecutionBreak = NULL;
+
+ Status = gBS->OpenProtocol(
+ gST->ConsoleInHandle,
+ &gEfiSimpleTextInputExProtocolGuid,
+ (VOID**)&SimpleEx,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+ if (!EFI_ERROR (Status)) {
+ Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlCNotifyHandle1);
+ Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlCNotifyHandle2);
+ Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlCNotifyHandle3);
+ Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlCNotifyHandle4);
+ Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlSNotifyHandle1);
+ Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlSNotifyHandle2);
+ Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlSNotifyHandle3);
+ Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlSNotifyHandle4);
+ }
+ return (Status);
+}
+
+/**
+ Notification function for keystrokes.
+
+ @param[in] KeyData The key that was pressed.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+NotificationFunction(
+ IN EFI_KEY_DATA *KeyData
+ )
+{
+ if ( ((KeyData->Key.UnicodeChar == L'c') &&
+ (KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED) || KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED))) ||
+ (KeyData->Key.UnicodeChar == 3)
+ ){
+ if (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak == NULL) {
+ return (EFI_UNSUPPORTED);
+ }
+ return (gBS->SignalEvent(ShellInfoObject.NewEfiShellProtocol->ExecutionBreak));
+ } else if ((KeyData->Key.UnicodeChar == L's') &&
+ (KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED) || KeyData->KeyState.KeyShiftState == (EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED))
+ ){
+ ShellInfoObject.HaltOutput = TRUE;
+ }
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to start monitoring for CTRL-C using SimpleTextInputEx. This
+ feature's enabled state was not known when the shell initially launched.
+
+ @retval EFI_SUCCESS The feature is enabled.
+ @retval EFI_OUT_OF_RESOURCES There is not enough mnemory available.
+**/
+EFI_STATUS
+EFIAPI
+InernalEfiShellStartMonitor(
+ VOID
+ )
+{
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;
+ EFI_KEY_DATA KeyData;
+ EFI_STATUS Status;
+
+ Status = gBS->OpenProtocol(
+ gST->ConsoleInHandle,
+ &gEfiSimpleTextInputExProtocolGuid,
+ (VOID**)&SimpleEx,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_SHELL_NO_IN_EX),
+ ShellInfoObject.HiiHandle);
+ return (EFI_SUCCESS);
+ }
+
+ if (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak == NULL) {
+ return (EFI_UNSUPPORTED);
+ }
+
+ KeyData.KeyState.KeyToggleState = 0;
+ KeyData.Key.ScanCode = 0;
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED;
+ KeyData.Key.UnicodeChar = L'c';
+
+ Status = SimpleEx->RegisterKeyNotify(
+ SimpleEx,
+ &KeyData,
+ NotificationFunction,
+ &ShellInfoObject.CtrlCNotifyHandle1);
+
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;
+ if (!EFI_ERROR(Status)) {
+ Status = SimpleEx->RegisterKeyNotify(
+ SimpleEx,
+ &KeyData,
+ NotificationFunction,
+ &ShellInfoObject.CtrlCNotifyHandle2);
+ }
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED;
+ KeyData.Key.UnicodeChar = 3;
+ if (!EFI_ERROR(Status)) {
+ Status = SimpleEx->RegisterKeyNotify(
+ SimpleEx,
+ &KeyData,
+ NotificationFunction,
+ &ShellInfoObject.CtrlCNotifyHandle3);
+ }
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;
+ if (!EFI_ERROR(Status)) {
+ Status = SimpleEx->RegisterKeyNotify(
+ SimpleEx,
+ &KeyData,
+ NotificationFunction,
+ &ShellInfoObject.CtrlCNotifyHandle4);
+ }
+ return (Status);
+}
+
diff --git a/Core/ShellPkg/Application/Shell/ShellProtocol.h b/Core/ShellPkg/Application/Shell/ShellProtocol.h
new file mode 100644
index 0000000000..4f701cb749
--- /dev/null
+++ b/Core/ShellPkg/Application/Shell/ShellProtocol.h
@@ -0,0 +1,953 @@
+/** @file
+ Member functions of EFI_SHELL_PROTOCOL and functions for creation,
+ manipulation, and initialization of EFI_SHELL_PROTOCOL.
+
+ (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SHELL_PROTOCOL_HEADER_
+#define _SHELL_PROTOCOL_HEADER_
+
+#include "Shell.h"
+
+typedef struct {
+ LIST_ENTRY Link;
+ EFI_SHELL_PROTOCOL *Interface;
+ EFI_HANDLE Handle;
+} SHELL_PROTOCOL_HANDLE_LIST;
+
+// flags values...
+#define SHELL_MAP_FLAGS_CONSIST BIT1
+
+/**
+ Function to create and install on the current handle.
+
+ Will overwrite any existing ShellProtocols in the system to be sure that
+ the current shell is in control.
+
+ This must be removed via calling CleanUpShellProtocol().
+
+ @param[in, out] NewShell The pointer to the pointer to the structure
+ to install.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @return An error from LocateHandle, CreateEvent, or other core function.
+**/
+EFI_STATUS
+EFIAPI
+CreatePopulateInstallShellProtocol (
+ IN OUT EFI_SHELL_PROTOCOL **NewShell
+ );
+
+/**
+ Opposite of CreatePopulateInstallShellProtocol.
+
+ Free all memory and restore the system to the state it was in before calling
+ CreatePopulateInstallShellProtocol.
+
+ @param[in, out] NewShell The pointer to the new shell protocol structure.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+CleanUpShellProtocol (
+ IN OUT EFI_SHELL_PROTOCOL *NewShell
+ );
+
+/**
+ Cleanup the shell environment.
+
+ @param[in, out] NewShell The pointer to the new shell protocol structure.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+CleanUpShellEnvironment (
+ IN OUT EFI_SHELL_PROTOCOL *NewShell
+ );
+
+/**
+ This function creates a mapping for a device path.
+
+ @param DevicePath Points to the device path. If this is NULL and Mapping points to a valid mapping,
+ then the mapping will be deleted.
+ @param Mapping Points to the NULL-terminated mapping for the device path. Must end with a ':'
+
+ @retval EFI_SUCCESS Mapping created or deleted successfully.
+ @retval EFI_NO_MAPPING There is no handle that corresponds exactly to DevicePath. See the
+ boot service function LocateDevicePath().
+ @retval EFI_ACCESS_DENIED The mapping is a built-in alias.
+ @retval EFI_INVALID_PARAMETER Mapping was NULL
+ @retval EFI_INVALID_PARAMETER Mapping did not end with a ':'
+ @retval EFI_INVALID_PARAMETER DevicePath was not pointing at a device that had a SIMPLE_FILE_SYSTEM_PROTOCOL installed.
+ @retval EFI_NOT_FOUND There was no mapping found to delete
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed
+**/
+EFI_STATUS
+EFIAPI
+EfiShellSetMap(
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath OPTIONAL,
+ IN CONST CHAR16 *Mapping
+ );
+
+/**
+ Gets the device path from the mapping.
+
+ This function gets the device path associated with a mapping.
+
+ @param Mapping A pointer to the mapping
+
+ @retval !=NULL Pointer to the device path that corresponds to the
+ device mapping. The returned pointer does not need
+ to be freed.
+ @retval NULL There is no device path associated with the
+ specified mapping.
+**/
+CONST EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+EfiShellGetDevicePathFromMap(
+ IN CONST CHAR16 *Mapping
+ );
+
+/**
+ Gets the mapping that most closely matches the device path.
+
+ This function gets the mapping which corresponds to the device path *DevicePath. If
+ there is no exact match, then the mapping which most closely matches *DevicePath
+ is returned, and *DevicePath is updated to point to the remaining portion of the
+ device path. If there is an exact match, the mapping is returned and *DevicePath
+ points to the end-of-device-path node.
+
+ @param DevicePath On entry, points to a device path pointer. On
+ exit, updates the pointer to point to the
+ portion of the device path after the mapping.
+
+ @retval NULL No mapping was found.
+ @return !=NULL Pointer to NULL-terminated mapping. The buffer
+ is callee allocated and should be freed by the caller.
+**/
+CONST CHAR16 *
+EFIAPI
+EfiShellGetMapFromDevicePath(
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ );
+
+/**
+ Converts a device path to a file system-style path.
+
+ This function converts a device path to a file system path by replacing part, or all, of
+ the device path with the file-system mapping. If there are more than one application
+ file system mappings, the one that most closely matches Path will be used.
+
+ @param Path The pointer to the device path
+
+ @retval NULL the device path could not be found.
+ @return all The pointer of the NULL-terminated file path. The path
+ is callee-allocated and should be freed by the caller.
+**/
+CHAR16 *
+EFIAPI
+EfiShellGetFilePathFromDevicePath(
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *Path
+ );
+
+/**
+ Converts a file system style name to a device path.
+
+ This function converts a file system style name to a device path, by replacing any
+ mapping references to the associated device path.
+
+ @param Path the pointer to the path
+
+ @return all The pointer of the file path. The file path is callee
+ allocated and should be freed by the caller.
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+EfiShellGetDevicePathFromFilePath(
+ IN CONST CHAR16 *Path
+ );
+
+/**
+ Gets the name of the device specified by the device handle.
+
+ This function gets the user-readable name of the device specified by the device
+ handle. If no user-readable name could be generated, then *BestDeviceName will be
+ NULL and EFI_NOT_FOUND will be returned.
+
+ If EFI_DEVICE_NAME_USE_COMPONENT_NAME is set, then the function will return the
+ device's name using the EFI_COMPONENT_NAME2_PROTOCOL, if present on
+ DeviceHandle.
+
+ If EFI_DEVICE_NAME_USE_DEVICE_PATH is set, then the function will return the
+ device's name using the EFI_DEVICE_PATH_PROTOCOL, if present on DeviceHandle.
+ If both EFI_DEVICE_NAME_USE_COMPONENT_NAME and
+ EFI_DEVICE_NAME_USE_DEVICE_PATH are set, then
+ EFI_DEVICE_NAME_USE_COMPONENT_NAME will have higher priority.
+
+ @param DeviceHandle The handle of the device.
+ @param Flags Determines the possible sources of component names.
+ Valid bits are:
+ EFI_DEVICE_NAME_USE_COMPONENT_NAME
+ EFI_DEVICE_NAME_USE_DEVICE_PATH
+ @param Language A pointer to the language specified for the device
+ name, in the same format as described in the UEFI
+ specification, Appendix M
+ @param BestDeviceName On return, points to the callee-allocated NULL-
+ terminated name of the device. If no device name
+ could be found, points to NULL. The name must be
+ freed by the caller...
+
+ @retval EFI_SUCCESS Get the name successfully.
+ @retval EFI_NOT_FOUND Fail to get the device name.
+ @retval EFI_INVALID_PARAMETER Flags did not have a valid bit set.
+ @retval EFI_INVALID_PARAMETER BestDeviceName was NULL
+ @retval EFI_INVALID_PARAMETER DeviceHandle was NULL
+**/
+EFI_STATUS
+EFIAPI
+EfiShellGetDeviceName(
+ IN EFI_HANDLE DeviceHandle,
+ IN EFI_SHELL_DEVICE_NAME_FLAGS Flags,
+ IN CHAR8 *Language,
+ OUT CHAR16 **BestDeviceName
+ );
+
+/**
+ Opens the root directory of a device on a handle
+
+ This function opens the root directory of a device and returns a file handle to it.
+
+ @param DeviceHandle The handle of the device that contains the volume.
+ @param FileHandle On exit, points to the file handle corresponding to the root directory on the
+ device.
+
+ @retval EFI_SUCCESS Root opened successfully.
+ @retval EFI_NOT_FOUND EFI_SIMPLE_FILE_SYSTEM could not be found or the root directory
+ could not be opened.
+ @retval EFI_VOLUME_CORRUPTED The data structures in the volume were corrupted.
+ @retval EFI_DEVICE_ERROR The device had an error
+**/
+EFI_STATUS
+EFIAPI
+EfiShellOpenRootByHandle(
+ IN EFI_HANDLE DeviceHandle,
+ OUT SHELL_FILE_HANDLE *FileHandle
+ );
+
+/**
+ Opens the root directory of a device.
+
+ This function opens the root directory of a device and returns a file handle to it.
+
+ @param DevicePath Points to the device path corresponding to the device where the
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL is installed.
+ @param FileHandle On exit, points to the file handle corresponding to the root directory on the
+ device.
+
+ @retval EFI_SUCCESS Root opened successfully.
+ @retval EFI_NOT_FOUND EFI_SIMPLE_FILE_SYSTEM could not be found or the root directory
+ could not be opened.
+ @retval EFI_VOLUME_CORRUPTED The data structures in the volume were corrupted.
+ @retval EFI_DEVICE_ERROR The device had an error
+**/
+EFI_STATUS
+EFIAPI
+EfiShellOpenRoot(
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT SHELL_FILE_HANDLE *FileHandle
+ );
+
+/**
+ Returns whether any script files are currently being processed.
+
+ @retval TRUE There is at least one script file active.
+ @retval FALSE No script files are active now.
+
+**/
+BOOLEAN
+EFIAPI
+EfiShellBatchIsActive (
+ VOID
+ );
+
+/**
+ Worker function to open a file based on a device path. this will open the root
+ of the volume and then traverse down to the file itself.
+
+ @param DevicePath2 Device Path of the file
+ @param FileHandle Pointer to the file upon a successful return
+ @param OpenMode mode to open file in.
+ @param Attributes the File Attributes to use when creating a new file
+
+ @retval EFI_SUCCESS the file is open and FileHandle is valid
+ @retval EFI_UNSUPPORTED the device path cotained non-path elements
+ @retval other an error ocurred.
+**/
+EFI_STATUS
+EFIAPI
+InternalOpenFileDevicePath(
+ IN OUT EFI_DEVICE_PATH_PROTOCOL *DevicePath2,
+ OUT SHELL_FILE_HANDLE *FileHandle,
+ IN UINT64 OpenMode,
+ IN UINT64 Attributes OPTIONAL
+ );
+
+/**
+ Creates a file or directory by name.
+
+ This function creates an empty new file or directory with the specified attributes and
+ returns the new file's handle. If the file already exists and is read-only, then
+ EFI_INVALID_PARAMETER will be returned.
+
+ If the file already existed, it is truncated and its attributes updated. If the file is
+ created successfully, the FileHandle is the file's handle, else, the FileHandle is NULL.
+
+ If the file name begins with >v, then the file handle which is returned refers to the
+ shell environment variable with the specified name. If the shell environment variable
+ already exists and is non-volatile then EFI_INVALID_PARAMETER is returned.
+
+ @param FileName Pointer to NULL-terminated file path
+ @param FileAttribs The new file's attrbiutes. the different attributes are
+ described in EFI_FILE_PROTOCOL.Open().
+ @param FileHandle On return, points to the created file handle or directory's handle
+
+ @retval EFI_SUCCESS The file was opened. FileHandle points to the new file's handle.
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
+ @retval EFI_UNSUPPORTED could not open the file path
+ @retval EFI_NOT_FOUND the specified file could not be found on the devide, or could not
+ file the file system on the device.
+ @retval EFI_NO_MEDIA the device has no medium.
+ @retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no
+ longer supported.
+ @retval EFI_DEVICE_ERROR The device reported an error or can't get the file path according
+ the DirName.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a file for write
+ when the media is write-protected.
+ @retval EFI_ACCESS_DENIED The service denied access to the file.
+ @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file.
+ @retval EFI_VOLUME_FULL The volume is full.
+**/
+EFI_STATUS
+EFIAPI
+EfiShellCreateFile(
+ IN CONST CHAR16 *FileName,
+ IN UINT64 FileAttribs,
+ OUT SHELL_FILE_HANDLE *FileHandle
+ );
+
+/**
+ Opens a file or a directory by file name.
+
+ This function opens the specified file in the specified OpenMode and returns a file
+ handle.
+ If the file name begins with >v, then the file handle which is returned refers to the
+ shell environment variable with the specified name. If the shell environment variable
+ exists, is non-volatile and the OpenMode indicates EFI_FILE_MODE_WRITE, then
+ EFI_INVALID_PARAMETER is returned.
+
+ If the file name is >i, then the file handle which is returned refers to the standard
+ input. If the OpenMode indicates EFI_FILE_MODE_WRITE, then EFI_INVALID_PARAMETER
+ is returned.
+
+ If the file name is >o, then the file handle which is returned refers to the standard
+ output. If the OpenMode indicates EFI_FILE_MODE_READ, then EFI_INVALID_PARAMETER
+ is returned.
+
+ If the file name is >e, then the file handle which is returned refers to the standard
+ error. If the OpenMode indicates EFI_FILE_MODE_READ, then EFI_INVALID_PARAMETER
+ is returned.
+
+ If the file name is NUL, then the file handle that is returned refers to the standard NUL
+ file. If the OpenMode indicates EFI_FILE_MODE_READ, then EFI_INVALID_PARAMETER is
+ returned.
+
+ If return EFI_SUCCESS, the FileHandle is the opened file's handle, else, the
+ FileHandle is NULL.
+
+ @param FileName Points to the NULL-terminated UCS-2 encoded file name.
+ @param FileHandle On return, points to the file handle.
+ @param OpenMode File open mode. Either EFI_FILE_MODE_READ or
+ EFI_FILE_MODE_WRITE from section 12.4 of the UEFI
+ Specification.
+ @retval EFI_SUCCESS The file was opened. FileHandle has the opened file's handle.
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. FileHandle is NULL.
+ @retval EFI_UNSUPPORTED Could not open the file path. FileHandle is NULL.
+ @retval EFI_NOT_FOUND The specified file could not be found on the device or the file
+ system could not be found on the device. FileHandle is NULL.
+ @retval EFI_NO_MEDIA The device has no medium. FileHandle is NULL.
+ @retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no
+ longer supported. FileHandle is NULL.
+ @retval EFI_DEVICE_ERROR The device reported an error or can't get the file path according
+ the FileName. FileHandle is NULL.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. FileHandle is NULL.
+ @retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a file for write
+ when the media is write-protected. FileHandle is NULL.
+ @retval EFI_ACCESS_DENIED The service denied access to the file. FileHandle is NULL.
+ @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file. FileHandle
+ is NULL.
+ @retval EFI_VOLUME_FULL The volume is full. FileHandle is NULL.
+**/
+EFI_STATUS
+EFIAPI
+EfiShellOpenFileByName(
+ IN CONST CHAR16 *FileName,
+ OUT SHELL_FILE_HANDLE *FileHandle,
+ IN UINT64 OpenMode
+ );
+
+/**
+ Deletes the file specified by the file name.
+
+ This function deletes a file.
+
+ @param FileName Points to the NULL-terminated file name.
+
+ @retval EFI_SUCCESS The file was closed and deleted, and the handle was closed.
+ @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted.
+ @sa EfiShellCreateFile
+ @sa FileHandleDelete
+**/
+EFI_STATUS
+EFIAPI
+EfiShellDeleteFileByName(
+ IN CONST CHAR16 *FileName
+ );
+
+/**
+ Disables the page break output mode.
+**/
+VOID
+EFIAPI
+EfiShellDisablePageBreak (
+ VOID
+ );
+
+/**
+ Enables the page break output mode.
+**/
+VOID
+EFIAPI
+EfiShellEnablePageBreak (
+ VOID
+ );
+
+/**
+ internal worker function to run a command via Device Path
+
+ @param ParentImageHandle A handle of the image that is executing the specified
+ command line.
+ @param DevicePath device path of the file to execute
+ @param CommandLine Points to the NULL-terminated UCS-2 encoded string
+ containing the command line. If NULL then the command-
+ line will be empty.
+ @param Environment Points to a NULL-terminated array of environment
+ variables with the format 'x=y', where x is the
+ environment variable name and y is the value. If this
+ is NULL, then the current shell environment is used.
+ @param[out] StartImageStatus Returned status from gBS->StartImage.
+
+ @retval EFI_SUCCESS The command executed successfully. The status code
+ returned by the command is pointed to by StatusCode.
+ @retval EFI_INVALID_PARAMETER The parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_UNSUPPORTED Nested shell invocations are not allowed.
+**/
+EFI_STATUS
+EFIAPI
+InternalShellExecuteDevicePath(
+ IN CONST EFI_HANDLE *ParentImageHandle,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN CONST CHAR16 *CommandLine OPTIONAL,
+ IN CONST CHAR16 **Environment OPTIONAL,
+ OUT EFI_STATUS *StartImageStatus OPTIONAL
+ );
+
+/**
+ Execute the command line.
+
+ This function creates a nested instance of the shell and executes the specified
+ command (CommandLine) with the specified environment (Environment). Upon return,
+ the status code returned by the specified command is placed in StatusCode.
+
+ If Environment is NULL, then the current environment is used and all changes made
+ by the commands executed will be reflected in the current environment. If the
+ Environment is non-NULL, then the changes made will be discarded.
+
+ The CommandLine is executed from the current working directory on the current
+ device.
+
+ @param ParentImageHandle A handle of the image that is executing the specified
+ command line.
+ @param CommandLine Points to the NULL-terminated UCS-2 encoded string
+ containing the command line. If NULL then the command-
+ line will be empty.
+ @param Environment Points to a NULL-terminated array of environment
+ variables with the format 'x=y', where x is the
+ environment variable name and y is the value. If this
+ is NULL, then the current shell environment is used.
+ @param StatusCode Points to the status code returned by the command.
+
+ @retval EFI_SUCCESS The command executed successfully. The status code
+ returned by the command is pointed to by StatusCode.
+ @retval EFI_INVALID_PARAMETER The parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_UNSUPPORTED Nested shell invocations are not allowed.
+**/
+EFI_STATUS
+EFIAPI
+EfiShellExecute(
+ IN EFI_HANDLE *ParentImageHandle,
+ IN CHAR16 *CommandLine OPTIONAL,
+ IN CHAR16 **Environment OPTIONAL,
+ OUT EFI_STATUS *StatusCode OPTIONAL
+ );
+
+/**
+ Utility cleanup function for EFI_SHELL_FILE_INFO objects.
+
+ 1) frees all pointers (non-NULL)
+ 2) Closes the SHELL_FILE_HANDLE
+
+ @param FileListNode pointer to the list node to free
+**/
+VOID
+EFIAPI
+FreeShellFileInfoNode(
+ IN EFI_SHELL_FILE_INFO *FileListNode
+ );
+
+/**
+ Frees the file list.
+
+ This function cleans up the file list and any related data structures. It has no
+ impact on the files themselves.
+
+ @param FileList The file list to free. Type EFI_SHELL_FILE_INFO is
+ defined in OpenFileList()
+
+ @retval EFI_SUCCESS Free the file list successfully.
+ @retval EFI_INVALID_PARAMETER FileList was NULL or *FileList was NULL;
+**/
+EFI_STATUS
+EFIAPI
+EfiShellFreeFileList(
+ IN EFI_SHELL_FILE_INFO **FileList
+ );
+
+/**
+ Deletes the duplicate file names files in the given file list.
+
+ This function deletes the reduplicate files in the given file list.
+
+ @param FileList A pointer to the first entry in the file list.
+
+ @retval EFI_SUCCESS Always success.
+ @retval EFI_INVALID_PARAMETER FileList was NULL or *FileList was NULL;
+**/
+EFI_STATUS
+EFIAPI
+EfiShellRemoveDupInFileList(
+ IN EFI_SHELL_FILE_INFO **FileList
+ );
+
+/**
+ Allocates and populates a EFI_SHELL_FILE_INFO structure. if any memory operation
+ failed it will return NULL.
+
+ @param[in] BasePath the Path to prepend onto filename for FullPath
+ @param[in] Status Status member initial value.
+ @param[in] FileName FileName member initial value.
+ @param[in] Handle Handle member initial value.
+ @param[in] Info Info struct to copy.
+
+**/
+EFI_SHELL_FILE_INFO *
+EFIAPI
+CreateAndPopulateShellFileInfo(
+ IN CONST CHAR16 *BasePath,
+ IN CONST EFI_STATUS Status,
+ IN CONST CHAR16 *FileName,
+ IN CONST SHELL_FILE_HANDLE Handle,
+ IN CONST EFI_FILE_INFO *Info
+ );
+
+/**
+ Find all files in a specified directory.
+
+ @param FileDirHandle Handle of the directory to search.
+ @param FileList On return, points to the list of files in the directory
+ or NULL if there are no files in the directory.
+
+ @retval EFI_SUCCESS File information was returned successfully.
+ @retval EFI_VOLUME_CORRUPTED The file system structures have been corrupted.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_NO_MEDIA The device media is not present.
+ @retval EFI_INVALID_PARAMETER The FileDirHandle was not a directory.
+**/
+EFI_STATUS
+EFIAPI
+EfiShellFindFilesInDir(
+ IN SHELL_FILE_HANDLE FileDirHandle,
+ OUT EFI_SHELL_FILE_INFO **FileList
+ );
+
+/**
+ Find files that match a specified pattern.
+
+ This function searches for all files and directories that match the specified
+ FilePattern. The FilePattern can contain wild-card characters. The resulting file
+ information is placed in the file list FileList.
+
+ Wildcards are processed
+ according to the rules specified in UEFI Shell 2.0 spec section 3.7.1.
+
+ The files in the file list are not opened. The OpenMode field is set to 0 and the FileInfo
+ field is set to NULL.
+
+ if *FileList is not NULL then it must be a pre-existing and properly initialized list.
+
+ @param FilePattern Points to a NULL-terminated shell file path, including wildcards.
+ @param FileList On return, points to the start of a file list containing the names
+ of all matching files or else points to NULL if no matching files
+ were found. only on a EFI_SUCCESS return will; this be non-NULL.
+
+ @retval EFI_SUCCESS Files found. FileList is a valid list.
+ @retval EFI_NOT_FOUND No files found.
+ @retval EFI_NO_MEDIA The device has no media
+ @retval EFI_DEVICE_ERROR The device reported an error
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted
+**/
+EFI_STATUS
+EFIAPI
+EfiShellFindFiles(
+ IN CONST CHAR16 *FilePattern,
+ OUT EFI_SHELL_FILE_INFO **FileList
+ );
+
+/**
+ Opens the files that match the path specified.
+
+ This function opens all of the files specified by Path. Wildcards are processed
+ according to the rules specified in UEFI Shell 2.0 spec section 3.7.1. Each
+ matching file has an EFI_SHELL_FILE_INFO structure created in a linked list.
+
+ @param Path A pointer to the path string.
+ @param OpenMode Specifies the mode used to open each file, EFI_FILE_MODE_READ or
+ EFI_FILE_MODE_WRITE.
+ @param FileList Points to the start of a list of files opened.
+
+ @retval EFI_SUCCESS Create the file list successfully.
+ @return Others Can't create the file list.
+**/
+EFI_STATUS
+EFIAPI
+EfiShellOpenFileList(
+ IN CHAR16 *Path,
+ IN UINT64 OpenMode,
+ IN OUT EFI_SHELL_FILE_INFO **FileList
+ );
+
+/**
+ Gets the environment variable.
+
+ This function returns the current value of the specified environment variable.
+
+ @param Name A pointer to the environment variable name
+
+ @retval !=NULL The environment variable's value. The returned
+ pointer does not need to be freed by the caller.
+ @retval NULL The environment variable doesn't exist.
+**/
+CONST CHAR16 *
+EFIAPI
+EfiShellGetEnv(
+ IN CONST CHAR16 *Name
+ );
+
+/**
+ Sets the environment variable.
+
+ This function changes the current value of the specified environment variable. If the
+ environment variable exists and the Value is an empty string, then the environment
+ variable is deleted. If the environment variable exists and the Value is not an empty
+ string, then the value of the environment variable is changed. If the environment
+ variable does not exist and the Value is an empty string, there is no action. If the
+ environment variable does not exist and the Value is a non-empty string, then the
+ environment variable is created and assigned the specified value.
+
+ For a description of volatile and non-volatile environment variables, see UEFI Shell
+ 2.0 specification section 3.6.1.
+
+ @param Name Points to the NULL-terminated environment variable name.
+ @param Value Points to the NULL-terminated environment variable value. If the value is an
+ empty string then the environment variable is deleted.
+ @param Volatile Indicates whether the variable is non-volatile (FALSE) or volatile (TRUE).
+
+ @retval EFI_SUCCESS The environment variable was successfully updated.
+**/
+EFI_STATUS
+EFIAPI
+EfiShellSetEnv(
+ IN CONST CHAR16 *Name,
+ IN CONST CHAR16 *Value,
+ IN BOOLEAN Volatile
+ );
+
+/**
+ Returns the current directory on the specified device.
+
+ If FileSystemMapping is NULL, it returns the current working directory. If the
+ FileSystemMapping is not NULL, it returns the current directory associated with the
+ FileSystemMapping. In both cases, the returned name includes the file system
+ mapping (i.e. fs0:\current-dir).
+
+ @param FileSystemMapping A pointer to the file system mapping. If NULL,
+ then the current working directory is returned.
+
+ @retval !=NULL The current directory.
+ @retval NULL Current directory does not exist.
+**/
+CONST CHAR16 *
+EFIAPI
+EfiShellGetCurDir(
+ IN CONST CHAR16 *FileSystemMapping OPTIONAL
+ );
+
+/**
+ Changes the current directory on the specified device.
+
+ If the FileSystem is NULL, and the directory Dir does not contain a file system's
+ mapped name, this function changes the current working directory. If FileSystem is
+ NULL and the directory Dir contains a mapped name, then the current file system and
+ the current directory on that file system are changed.
+
+ If FileSystem is not NULL, and Dir is NULL, then this changes the current working file
+ system.
+
+ If FileSystem is not NULL and Dir is not NULL, then this function changes the current
+ directory on the specified file system.
+
+ If the current working directory or the current working file system is changed then the
+ %cwd% environment variable will be updated
+
+ @param FileSystem A pointer to the file system's mapped name. If NULL, then the current working
+ directory is changed.
+ @param Dir Points to the NULL-terminated directory on the device specified by FileSystem.
+
+ @retval EFI_SUCCESS The operation was sucessful
+**/
+EFI_STATUS
+EFIAPI
+EfiShellSetCurDir(
+ IN CONST CHAR16 *FileSystem OPTIONAL,
+ IN CONST CHAR16 *Dir
+ );
+
+/**
+ Return help information about a specific command.
+
+ This function returns the help information for the specified command. The help text
+ can be internal to the shell or can be from a UEFI Shell manual page.
+
+ If Sections is specified, then each section name listed will be compared in a casesensitive
+ manner, to the section names described in Appendix B. If the section exists,
+ it will be appended to the returned help text. If the section does not exist, no
+ information will be returned. If Sections is NULL, then all help text information
+ available will be returned.
+
+ @param Command Points to the NULL-terminated UEFI Shell command name.
+ @param Sections Points to the NULL-terminated comma-delimited
+ section names to return. If NULL, then all
+ sections will be returned.
+ @param HelpText On return, points to a callee-allocated buffer
+ containing all specified help text.
+
+ @retval EFI_SUCCESS The help text was returned.
+ @retval EFI_OUT_OF_RESOURCES The necessary buffer could not be allocated to hold the
+ returned help text.
+ @retval EFI_INVALID_PARAMETER HelpText is NULL
+ @retval EFI_NOT_FOUND There is no help text available for Command.
+**/
+EFI_STATUS
+EFIAPI
+EfiShellGetHelpText(
+ IN CONST CHAR16 *Command,
+ IN CONST CHAR16 *Sections OPTIONAL,
+ OUT CHAR16 **HelpText
+ );
+
+/**
+ Gets the enable status of the page break output mode.
+
+ User can use this function to determine current page break mode.
+
+ @retval TRUE The page break output mode is enabled
+ @retval FALSE The page break output mode is disabled
+**/
+BOOLEAN
+EFIAPI
+EfiShellGetPageBreak(
+ VOID
+ );
+
+/**
+ Judges whether the active shell is the root shell.
+
+ This function makes the user to know that whether the active Shell is the root shell.
+
+ @retval TRUE The active Shell is the root Shell.
+ @retval FALSE The active Shell is NOT the root Shell.
+**/
+BOOLEAN
+EFIAPI
+EfiShellIsRootShell(
+ VOID
+ );
+
+/**
+ This function returns the command associated with a alias or a list of all
+ alias'.
+
+ @param[in] Command Points to the NULL-terminated shell alias.
+ If this parameter is NULL, then all
+ aliases will be returned in ReturnedData.
+ @param[out] Volatile upon return of a single command if TRUE indicates
+ this is stored in a volatile fashion. FALSE otherwise.
+ @return If Alias is not NULL, it will return a pointer to
+ the NULL-terminated command for that alias.
+ If Alias is NULL, ReturnedData points to a ';'
+ delimited list of alias (e.g.
+ ReturnedData = "dir;del;copy;mfp") that is NULL-terminated.
+ @retval NULL an error ocurred
+ @retval NULL Alias was not a valid Alias
+**/
+CONST CHAR16 *
+EFIAPI
+EfiShellGetAlias(
+ IN CONST CHAR16 *Command,
+ OUT BOOLEAN *Volatile OPTIONAL
+ );
+
+/**
+ Changes a shell command alias.
+
+ This function creates an alias for a shell command or if Alias is NULL it will delete an existing alias.
+
+ this function does not check for built in alias'.
+
+ @param[in] Command Points to the NULL-terminated shell command or existing alias.
+ @param[in] Alias Points to the NULL-terminated alias for the shell command. If this is NULL, and
+ Command refers to an alias, that alias will be deleted.
+ @param[in] Volatile if TRUE the Alias being set will be stored in a volatile fashion. if FALSE the
+ Alias being set will be stored in a non-volatile fashion.
+
+ @retval EFI_SUCCESS Alias created or deleted successfully.
+ @retval EFI_NOT_FOUND the Alias intended to be deleted was not found
+**/
+EFI_STATUS
+EFIAPI
+InternalSetAlias(
+ IN CONST CHAR16 *Command,
+ IN CONST CHAR16 *Alias OPTIONAL,
+ IN BOOLEAN Volatile
+ );
+
+/**
+ Changes a shell command alias.
+
+ This function creates an alias for a shell command or if Alias is NULL it will delete an existing alias.
+
+
+ @param[in] Command Points to the NULL-terminated shell command or existing alias.
+ @param[in] Alias Points to the NULL-terminated alias for the shell command. If this is NULL, and
+ Command refers to an alias, that alias will be deleted.
+ @param[in] Replace If TRUE and the alias already exists, then the existing alias will be replaced. If
+ FALSE and the alias already exists, then the existing alias is unchanged and
+ EFI_ACCESS_DENIED is returned.
+ @param[in] Volatile if TRUE the Alias being set will be stored in a volatile fashion. if FALSE the
+ Alias being set will be stored in a non-volatile fashion.
+
+ @retval EFI_SUCCESS Alias created or deleted successfully.
+ @retval EFI_NOT_FOUND the Alias intended to be deleted was not found
+ @retval EFI_ACCESS_DENIED The alias is a built-in alias or already existed and Replace was set to
+ FALSE.
+**/
+EFI_STATUS
+EFIAPI
+EfiShellSetAlias(
+ IN CONST CHAR16 *Command,
+ IN CONST CHAR16 *Alias OPTIONAL,
+ IN BOOLEAN Replace,
+ IN BOOLEAN Volatile
+ );
+
+/**
+ Utility cleanup function for EFI_SHELL_FILE_INFO objects.
+
+ 1) frees all pointers (non-NULL)
+ 2) Closes the SHELL_FILE_HANDLE
+
+ @param FileListNode pointer to the list node to free
+**/
+VOID
+EFIAPI
+InternalFreeShellFileInfoNode(
+ IN EFI_SHELL_FILE_INFO *FileListNode
+ );
+
+/**
+ Internal variable setting function. Allows for setting of the read only variables.
+
+ @param Name Points to the NULL-terminated environment variable name.
+ @param Value Points to the NULL-terminated environment variable value. If the value is an
+ empty string then the environment variable is deleted.
+ @param Volatile Indicates whether the variable is non-volatile (FALSE) or volatile (TRUE).
+
+ @retval EFI_SUCCESS The environment variable was successfully updated.
+**/
+EFI_STATUS
+EFIAPI
+InternalEfiShellSetEnv(
+ IN CONST CHAR16 *Name,
+ IN CONST CHAR16 *Value,
+ IN BOOLEAN Volatile
+ );
+
+/**
+ Function to start monitoring for CTRL-C using SimpleTextInputEx. This
+ feature's enabled state was not known when the shell initially launched.
+
+ @retval EFI_SUCCESS The feature is enabled.
+ @retval EFI_OUT_OF_RESOURCES There is not enough mnemory available.
+**/
+EFI_STATUS
+EFIAPI
+InernalEfiShellStartMonitor(
+ VOID
+ );
+
+/**
+ Notification function for keystrokes.
+
+ @param[in] KeyData The key that was pressed.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+NotificationFunction(
+ IN EFI_KEY_DATA *KeyData
+ );
+#endif //_SHELL_PROTOCOL_HEADER_
+
diff --git a/Core/ShellPkg/Application/ShellCTestApp/README.txt b/Core/ShellPkg/Application/ShellCTestApp/README.txt
new file mode 100644
index 0000000000..7814bb8386
--- /dev/null
+++ b/Core/ShellPkg/Application/ShellCTestApp/README.txt
@@ -0,0 +1,5 @@
+TestArgv.nsh is a very simple shell script to test how the interpreter parses
+the parameters. It uses ShellCTestApp.efi to dump the parameters passed from the
+intepreter.
+
+TestArgv.log is the desired output created using "TestArgv.nsh > TestArgv.log". \ No newline at end of file
diff --git a/Core/ShellPkg/Application/ShellCTestApp/ShellCTestApp.c b/Core/ShellPkg/Application/ShellCTestApp/ShellCTestApp.c
new file mode 100644
index 0000000000..08c830cfb7
--- /dev/null
+++ b/Core/ShellPkg/Application/ShellCTestApp/ShellCTestApp.c
@@ -0,0 +1,51 @@
+/** @file
+ This is a test application that demonstrates how to use the C-style entry point
+ for a shell application.
+
+ Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/ShellCEntryLib.h>
+
+/**
+ UEFI application entry point which has an interface similar to a
+ standard C main function.
+
+ The ShellCEntryLib library instance wrappers the actual UEFI application
+ entry point and calls this ShellAppMain function.
+
+ @param[in] Argc The number of items in Argv.
+ @param[in] Argv Array of pointers to strings.
+
+ @retval 0 The application exited normally.
+ @retval Other An error occurred.
+
+**/
+INTN
+EFIAPI
+ShellAppMain (
+ IN UINTN Argc,
+ IN CHAR16 **Argv
+ )
+{
+ UINTN Index;
+ if (Argc == 1) {
+ Print (L"Argv[1] = NULL\n");
+ }
+ for (Index = 1; Index < Argc; Index++) {
+ Print(L"Argv[%d]: \"%s\"\n", Index, Argv[Index]);
+ }
+
+ return 0;
+}
diff --git a/Core/ShellPkg/Application/ShellCTestApp/ShellCTestApp.inf b/Core/ShellPkg/Application/ShellCTestApp/ShellCTestApp.inf
new file mode 100644
index 0000000000..4839b9fd97
--- /dev/null
+++ b/Core/ShellPkg/Application/ShellCTestApp/ShellCTestApp.inf
@@ -0,0 +1,39 @@
+## @file
+# This is the shell application
+#
+# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = ShellCTestApp
+ FILE_GUID = 7a6ca3b8-ee1b-489c-b300-24544a7bd418
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ ENTRY_POINT = ShellCEntryLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ ShellCTestApp.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+
+[LibraryClasses]
+ ShellCEntryLib
+ UefiLib \ No newline at end of file
diff --git a/Core/ShellPkg/Application/ShellCTestApp/TestArgv.log b/Core/ShellPkg/Application/ShellCTestApp/TestArgv.log
new file mode 100644
index 0000000000..e76781ea0e
--- /dev/null
+++ b/Core/ShellPkg/Application/ShellCTestApp/TestArgv.log
Binary files differ
diff --git a/Core/ShellPkg/Application/ShellCTestApp/TestArgv.nsh b/Core/ShellPkg/Application/ShellCTestApp/TestArgv.nsh
new file mode 100644
index 0000000000..013ac123ec
--- /dev/null
+++ b/Core/ShellPkg/Application/ShellCTestApp/TestArgv.nsh
@@ -0,0 +1,64 @@
+#/** @file
+# This is a very simple shell script to test how the interpreter parses the parameters.
+#
+# Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#**/
+echo -on
+set Var_EFCF356F_228C_47C2_AD0C_3B5DAC9A8CFA ValueOfGuid
+set Sharp_E8528E46_A008_4221_8DE0_D5AB42A9C580 ^#
+set Quote_E95DEE8B_E3AA_4155_9ED5_6916394104FC ^"
+set Var_ShellCTestApp_EE6E8BC6_71A6_44A5_BED3_D8F901105CDE ShellCTestApp_EE6E8BC6_71A6_44A5_BED3_D8F901105CDE
+alias ShellCTestApp_EE6E8BC6_71A6_44A5_BED3_D8F901105CDE ShellCTestApp
+
+#
+# '^' should escape all special characters (including space)
+# but has no impact to non-special characters
+#
+ShellCTestApp ^^
+ShellCTestApp ^#
+ShellCTestApp ^%Var_EFCF356F_228C_47C2_AD0C_3B5DAC9A8CFA%
+ShellCTestApp ^"
+ShellCTestApp ^ 1
+ShellCTestApp ^
+ShellCTestApp ^1
+ShellCTestApp ^^^"
+ShellCTestApp ^^^
+
+#
+# '#' should be processed before %% replacement, and inside '"'
+#
+ShellCTestApp #%Var_EFCF356F_228C_47C2_AD0C_3B5DAC9A8CFA%
+#ShellCTestApp "#"
+ShellCTestApp %Sharp_E8528E46_A008_4221_8DE0_D5AB42A9C580%
+
+#
+# '%' should be processed before grouping parameters
+#
+ShellCTestApp "%Var_EFCF356F_228C_47C2_AD0C_3B5DAC9A8CFA% 2%Quote_E95DEE8B_E3AA_4155_9ED5_6916394104FC%
+
+#
+# alias should be processed after %% replacement
+#
+%Var_ShellCTestApp_EE6E8BC6_71A6_44A5_BED3_D8F901105CDE%
+
+#
+# '"' should be stripped, space inside '"' should be kept,
+#
+ShellCTestApp "p 1"
+ShellCTestApp "p"1
+ShellCTestApp "p 1"e"x"""
+
+set -d Var_EFCF356F_228C_47C2_AD0C_3B5DAC9A8CFA
+set -d Sharp_E8528E46_A008_4221_8DE0_D5AB42A9C580
+set -d Quote_E95DEE8B_E3AA_4155_9ED5_6916394104FC
+set -d Var_ShellCTestApp_EE6E8BC6_71A6_44A5_BED3_D8F901105CDE
+alias -d ShellCTestApp_EE6E8BC6_71A6_44A5_BED3_D8F901105CDE
+echo -off \ No newline at end of file
diff --git a/Core/ShellPkg/Application/ShellExecTestApp/SA.c b/Core/ShellPkg/Application/ShellExecTestApp/SA.c
new file mode 100644
index 0000000000..80531d09e9
--- /dev/null
+++ b/Core/ShellPkg/Application/ShellExecTestApp/SA.c
@@ -0,0 +1,38 @@
+/** @file
+ This is a simple shell application
+
+ Copyright (c) 2008 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+#include <Library/UefiApplicationEntryPoint.h>
+#include <Library/UefiLib.h>
+
+/**
+ as the real entry point for the application.
+
+ @param[in] ImageHandle The firmware allocated handle for the EFI image.
+ @param[in] SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The entry point is executed successfully.
+ @retval other Some error occurs when executing this entry point.
+
+**/
+EFI_STATUS
+EFIAPI
+UefiMain (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ Print(L"ShellExecute - Pass");
+ return EFI_SUCCESS;
+}
diff --git a/Core/ShellPkg/Application/ShellExecTestApp/SA.inf b/Core/ShellPkg/Application/ShellExecTestApp/SA.inf
new file mode 100644
index 0000000000..86e3f7b197
--- /dev/null
+++ b/Core/ShellPkg/Application/ShellExecTestApp/SA.inf
@@ -0,0 +1,41 @@
+## @file
+# Sample UEFI Application Reference EDKII Module
+#
+# This is a simple shell application
+#
+# Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010005
+ BASE_NAME = EmptyApplication
+ FILE_GUID = 8F7D7B1D-0E1C-4c98-B12E-4EC99C4081AC
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ ENTRY_POINT = UefiMain
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ SA.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ UefiApplicationEntryPoint
+ UefiLib
+
diff --git a/Core/ShellPkg/Application/ShellSortTestApp/ShellSortTestApp.c b/Core/ShellPkg/Application/ShellSortTestApp/ShellSortTestApp.c
new file mode 100644
index 0000000000..6bdd237e8d
--- /dev/null
+++ b/Core/ShellPkg/Application/ShellSortTestApp/ShellSortTestApp.c
@@ -0,0 +1,83 @@
+/** @file
+ This is a test application that demonstrates how to use the sorting functions.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Uefi.h>
+#include <Library/UefiLib.h>
+#include <Library/DebugLib.h>
+#include <Library/ShellCEntryLib.h>
+#include <Library/SortLib.h>
+
+/**
+ Test comparator.
+
+ @param[in] b1 The first INTN
+ @param[in] b2 The other INTN
+
+ @retval 0 They are the same.
+ @retval -1 b1 is less than b2
+ @retval 1 b1 is greater then b2
+**/
+INTN
+EFIAPI
+Test(CONST VOID *b1, CONST VOID *b2)
+{
+ if (*(INTN*)b1 == *(INTN*)b2) {
+ return (0);
+ }
+ if (*(INTN*)b1 < *(INTN*)b2) {
+ return(-1);
+ }
+ return (1);
+}
+
+/**
+ UEFI application entry point which has an interface similar to a
+ standard C main function.
+
+ The ShellCEntryLib library instance wrappers the actual UEFI application
+ entry point and calls this ShellAppMain function.
+
+ @param Argc Argument count
+ @param Argv The parsed arguments
+
+ @retval 0 The application exited normally.
+ @retval Other An error occurred.
+
+**/
+INTN
+EFIAPI
+ShellAppMain (
+ IN UINTN Argc,
+ IN CHAR16 **Argv
+ )
+{
+ INTN Array[10];
+
+ Array[0] = 2;
+ Array[1] = 3;
+ Array[2] = 4;
+ Array[3] = 1;
+ Array[4] = 5;
+ Array[5] = 6;
+ Array[6] = 7;
+ Array[7] = 8;
+ Array[8] = 1;
+ Array[9] = 5;
+
+ Print(L"Array = %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\r\n", Array[0],Array[1],Array[2],Array[3],Array[4],Array[5],Array[6],Array[7],Array[8],Array[9]);
+ PerformQuickSort(Array, 10, sizeof(INTN), Test);
+ Print(L"POST-SORT\r\n");
+ Print(L"Array = %d, %d, %d, %d, %d, %d, %d, %d, %d, %d\r\n", Array[0],Array[1],Array[2],Array[3],Array[4],Array[5],Array[6],Array[7],Array[8],Array[9]);
+ return 0;
+}
diff --git a/Core/ShellPkg/Application/ShellSortTestApp/ShellSortTestApp.inf b/Core/ShellPkg/Application/ShellSortTestApp/ShellSortTestApp.inf
new file mode 100644
index 0000000000..70130c1c06
--- /dev/null
+++ b/Core/ShellPkg/Application/ShellSortTestApp/ShellSortTestApp.inf
@@ -0,0 +1,42 @@
+## @file
+# This is the shell sorting testing application
+#
+# Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = ShellSortTestApp
+ FILE_GUID = 079E8E98-AE93-4b9a-8A71-1DC869F23E09
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ ENTRY_POINT = ShellCEntryLib
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ ShellSortTestApp.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ ShellCEntryLib
+ UefiLib
+ SortLib
+
diff --git a/Core/ShellPkg/Contributions.txt b/Core/ShellPkg/Contributions.txt
new file mode 100644
index 0000000000..f87cbd73c6
--- /dev/null
+++ b/Core/ShellPkg/Contributions.txt
@@ -0,0 +1,218 @@
+
+======================
+= Code Contributions =
+======================
+
+To make a contribution to a TianoCore project, follow these steps.
+1. Create a change description in the format specified below to
+ use in the source control commit log.
+2. Your commit message must include your "Signed-off-by" signature,
+ and "Contributed-under" message.
+3. Your "Contributed-under" message explicitly states that the
+ contribution is made under the terms of the specified
+ contribution agreement. Your "Contributed-under" message
+ must include the name of contribution agreement and version.
+ For example: Contributed-under: TianoCore Contribution Agreement 1.0
+ The "TianoCore Contribution Agreement" is included below in
+ this document.
+4. Submit your code to the TianoCore project using the process
+ that the project documents on its web page. If the process is
+ not documented, then submit the code on development email list
+ for the project.
+5. It is preferred that contributions are submitted using the same
+ copyright license as the base project. When that is not possible,
+ then contributions using the following licenses can be accepted:
+ * BSD (2-clause): http://opensource.org/licenses/BSD-2-Clause
+ * BSD (3-clause): http://opensource.org/licenses/BSD-3-Clause
+ * MIT: http://opensource.org/licenses/MIT
+ * Python-2.0: http://opensource.org/licenses/Python-2.0
+ * Zlib: http://opensource.org/licenses/Zlib
+
+ Contributions of code put into the public domain can also be
+ accepted.
+
+ Contributions using other licenses might be accepted, but further
+ review will be required.
+
+=====================================================
+= Change Description / Commit Message / Patch Email =
+=====================================================
+
+Your change description should use the standard format for a
+commit message, and must include your "Signed-off-by" signature
+and the "Contributed-under" message.
+
+== Sample Change Description / Commit Message =
+
+=== Start of sample patch email message ===
+
+From: Contributor Name <contributor@example.com>
+Subject: [PATCH] CodeModule: Brief-single-line-summary
+
+Full-commit-message
+
+Contributed-under: TianoCore Contribution Agreement 1.0
+Signed-off-by: Contributor Name <contributor@example.com>
+---
+
+An extra message for the patch email which will not be considered part
+of the commit message can be added here.
+
+Patch content inline or attached
+
+=== End of sample patch email message ===
+
+=== Notes for sample patch email ===
+
+* The first line of commit message is taken from the email's subject
+ line following [PATCH]. The remaining portion of the commit message
+ is the email's content until the '---' line.
+* git format-patch is one way to create this format
+
+=== Definitions for sample patch email ===
+
+* "CodeModule" is a short idenfier for the affected code. For
+ example MdePkg, or MdeModulePkg UsbBusDxe.
+* "Brief-single-line-summary" is a short summary of the change.
+* The entire first line should be less than ~70 characters.
+* "Full-commit-message" a verbose multiple line comment describing
+ the change. Each line should be less than ~70 characters.
+* "Contributed-under" explicitely states that the contribution is
+ made under the terms of the contribtion agreement. This
+ agreement is included below in this document.
+* "Signed-off-by" is the contributor's signature identifying them
+ by their real/legal name and their email address.
+
+========================================
+= TianoCore Contribution Agreement 1.0 =
+========================================
+
+INTEL CORPORATION ("INTEL") MAKES AVAILABLE SOFTWARE, DOCUMENTATION,
+INFORMATION AND/OR OTHER MATERIALS FOR USE IN THE TIANOCORE OPEN SOURCE
+PROJECT (COLLECTIVELY "CONTENT"). USE OF THE CONTENT IS GOVERNED BY THE
+TERMS AND CONDITIONS OF THIS AGREEMENT BETWEEN YOU AND INTEL AND/OR THE
+TERMS AND CONDITIONS OF LICENSE AGREEMENTS OR NOTICES INDICATED OR
+REFERENCED BELOW. BY USING THE CONTENT, YOU AGREE THAT YOUR USE OF THE
+CONTENT IS GOVERNED BY THIS AGREEMENT AND/OR THE TERMS AND CONDITIONS
+OF ANY APPLICABLE LICENSE AGREEMENTS OR NOTICES INDICATED OR REFERENCED
+BELOW. IF YOU DO NOT AGREE TO THE TERMS AND CONDITIONS OF THIS
+AGREEMENT AND THE TERMS AND CONDITIONS OF ANY APPLICABLE LICENSE
+AGREEMENTS OR NOTICES INDICATED OR REFERENCED BELOW, THEN YOU MAY NOT
+USE THE CONTENT.
+
+Unless otherwise indicated, all Content made available on the TianoCore
+site is provided to you under the terms and conditions of the BSD
+License ("BSD"). A copy of the BSD License is available at
+http://opensource.org/licenses/bsd-license.php
+or when applicable, in the associated License.txt file.
+
+Certain other content may be made available under other licenses as
+indicated in or with such Content. (For example, in a License.txt file.)
+
+You accept and agree to the following terms and conditions for Your
+present and future Contributions submitted to TianoCore site. Except
+for the license granted to Intel hereunder, You reserve all right,
+title, and interest in and to Your Contributions.
+
+== SECTION 1: Definitions ==
+* "You" or "Contributor" shall mean the copyright owner or legal
+ entity authorized by the copyright owner that is making a
+ Contribution hereunder. All other entities that control, are
+ controlled by, or are under common control with that entity are
+ considered to be a single Contributor. For the purposes of this
+ definition, "control" means (i) the power, direct or indirect, to
+ cause the direction or management of such entity, whether by
+ contract or otherwise, or (ii) ownership of fifty percent (50%)
+ or more of the outstanding shares, or (iii) beneficial ownership
+ of such entity.
+* "Contribution" shall mean any original work of authorship,
+ including any modifications or additions to an existing work,
+ that is intentionally submitted by You to the TinaoCore site for
+ inclusion in, or documentation of, any of the Content. For the
+ purposes of this definition, "submitted" means any form of
+ electronic, verbal, or written communication sent to the
+ TianoCore site or its representatives, including but not limited
+ to communication on electronic mailing lists, source code
+ control systems, and issue tracking systems that are managed by,
+ or on behalf of, the TianoCore site for the purpose of
+ discussing and improving the Content, but excluding
+ communication that is conspicuously marked or otherwise
+ designated in writing by You as "Not a Contribution."
+
+== SECTION 2: License for Contributions ==
+* Contributor hereby agrees that redistribution and use of the
+ Contribution in source and binary forms, with or without
+ modification, are permitted provided that the following
+ conditions are met:
+** Redistributions of source code must retain the Contributor's
+ copyright notice, this list of conditions and the following
+ disclaimer.
+** Redistributions in binary form must reproduce the Contributor's
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+* Disclaimer. None of the names of Contributor, Intel, or the names
+ of their respective contributors may be used to endorse or
+ promote products derived from this software without specific
+ prior written permission.
+* Contributor grants a license (with the right to sublicense) under
+ claims of Contributor's patents that Contributor can license that
+ are infringed by the Contribution (as delivered by Contributor) to
+ make, use, distribute, sell, offer for sale, and import the
+ Contribution and derivative works thereof solely to the minimum
+ extent necessary for licensee to exercise the granted copyright
+ license; this patent license applies solely to those portions of
+ the Contribution that are unmodified. No hardware per se is
+ licensed.
+* EXCEPT AS EXPRESSLY SET FORTH IN SECTION 3 BELOW, THE
+ CONTRIBUTION IS PROVIDED BY THE CONTRIBUTOR "AS IS" AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ CONTRIBUTOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE
+ CONTRIBUTION, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ DAMAGE.
+
+== SECTION 3: Representations ==
+* You represent that You are legally entitled to grant the above
+ license. If your employer(s) has rights to intellectual property
+ that You create that includes Your Contributions, You represent
+ that You have received permission to make Contributions on behalf
+ of that employer, that Your employer has waived such rights for
+ Your Contributions.
+* You represent that each of Your Contributions is Your original
+ creation (see Section 4 for submissions on behalf of others).
+ You represent that Your Contribution submissions include complete
+ details of any third-party license or other restriction
+ (including, but not limited to, related patents and trademarks)
+ of which You are personally aware and which are associated with
+ any part of Your Contributions.
+
+== SECTION 4: Third Party Contributions ==
+* Should You wish to submit work that is not Your original creation,
+ You may submit it to TianoCore site separately from any
+ Contribution, identifying the complete details of its source
+ and of any license or other restriction (including, but not
+ limited to, related patents, trademarks, and license agreements)
+ of which You are personally aware, and conspicuously marking the
+ work as "Submitted on behalf of a third-party: [named here]".
+
+== SECTION 5: Miscellaneous ==
+* Applicable Laws. Any claims arising under or relating to this
+ Agreement shall be governed by the internal substantive laws of
+ the State of Delaware or federal courts located in Delaware,
+ without regard to principles of conflict of laws.
+* Language. This Agreement is in the English language only, which
+ language shall be controlling in all respects, and all versions
+ of this Agreement in any other language shall be for accommodation
+ only and shall not be binding. All communications and notices made
+ or given pursuant to this Agreement, and all documentation and
+ support to be provided, unless otherwise noted, shall be in the
+ English language.
+
diff --git a/Core/ShellPkg/Include/Guid/ShellAliasGuid.h b/Core/ShellPkg/Include/Guid/ShellAliasGuid.h
new file mode 100644
index 0000000000..346eef4209
--- /dev/null
+++ b/Core/ShellPkg/Include/Guid/ShellAliasGuid.h
@@ -0,0 +1,25 @@
+/** @file
+ GUID for Shell Variable for Get/Set via runtime services.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SHELL_ALIAS_VARIABLE_GUID_H_
+#define _SHELL_ALIAS_VARIABLE_GUID_H_
+
+#define SHELL_ALIAS_VARIABLE_GUID \
+{ \
+ 0x0053d9d6, 0x2659, 0x4599, { 0xa2, 0x6b, 0xef, 0x45, 0x36, 0xe6, 0x31, 0xa9 } \
+}
+
+extern EFI_GUID gShellAliasGuid;
+
+#endif
diff --git a/Core/ShellPkg/Include/Guid/ShellEnvironment2Ext.h b/Core/ShellPkg/Include/Guid/ShellEnvironment2Ext.h
new file mode 100644
index 0000000000..a18d16c0e9
--- /dev/null
+++ b/Core/ShellPkg/Include/Guid/ShellEnvironment2Ext.h
@@ -0,0 +1,25 @@
+/** @file
+ GUID for EFI shell Environment2 Extension.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SHELLPKG_SHELL_ENV2_EXT_GUID_H_
+#define _SHELLPKG_SHELL_ENV2_EXT_GUID_H_
+
+#define SHELLPKG_SHELL_ENV2_EXT_GUID \
+{ \
+ 0xd2c18636, 0x40e5, 0x4eb5, {0xa3, 0x1b, 0x36, 0x69, 0x5f, 0xd4, 0x2c, 0x87} \
+}
+
+extern EFI_GUID gEfiShellEnvironment2ExtGuid;
+
+#endif
diff --git a/Core/ShellPkg/Include/Guid/ShellLibHiiGuid.h b/Core/ShellPkg/Include/Guid/ShellLibHiiGuid.h
new file mode 100644
index 0000000000..15cd85e899
--- /dev/null
+++ b/Core/ShellPkg/Include/Guid/ShellLibHiiGuid.h
@@ -0,0 +1,86 @@
+/** @file
+ GUIDs for HII package list installed by Shell libraries.
+
+ Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SHELLLIB_HII_GUID_H_
+#define _SHELLLIB_HII_GUID_H_
+
+#define HANDLE_PARSING_HII_GUID \
+ { \
+ 0xb8969637, 0x81de, 0x43af, { 0xbc, 0x9a, 0x24, 0xd9, 0x89, 0x13, 0xf2, 0xf6 } \
+ }
+
+#define SHELL_DEBUG1_HII_GUID \
+ { \
+ 0x25f200aa, 0xd3cb, 0x470a, { 0xbf, 0x51, 0xe7, 0xd1, 0x62, 0xd2, 0x2e, 0x6f } \
+ }
+
+#define SHELL_DRIVER1_HII_GUID \
+ { \
+ 0xaf0b742, 0x63ec, 0x45bd, {0x8d, 0xb6, 0x71, 0xad, 0x7f, 0x2f, 0xe8, 0xe8} \
+ }
+
+#define SHELL_INSTALL1_HII_GUID \
+ { \
+ 0x7d574d54, 0xd364, 0x4d4a, { 0x95, 0xe3, 0x49, 0x45, 0xdb, 0x7a, 0xd3, 0xee } \
+ }
+
+#define SHELL_LEVEL1_HII_GUID \
+ { \
+ 0xdec5daa4, 0x6781, 0x4820, { 0x9c, 0x63, 0xa7, 0xb0, 0xe4, 0xf1, 0xdb, 0x31 } \
+ }
+
+#define SHELL_LEVEL2_HII_GUID \
+ { \
+ 0xf95a7ccc, 0x4c55, 0x4426, { 0xa7, 0xb4, 0xdc, 0x89, 0x61, 0x95, 0xb, 0xae } \
+ }
+
+#define SHELL_LEVEL3_HII_GUID \
+ { \
+ 0x4344558d, 0x4ef9, 0x4725, { 0xb1, 0xe4, 0x33, 0x76, 0xe8, 0xd6, 0x97, 0x4f } \
+ }
+
+#define SHELL_NETWORK1_HII_GUID \
+ { \
+ 0xf3d301bb, 0xf4a5, 0x45a8, { 0xb0, 0xb7, 0xfa, 0x99, 0x9c, 0x62, 0x37, 0xae } \
+ }
+
+#define SHELL_NETWORK2_HII_GUID \
+ { \
+ 0x174b2b5, 0xf505, 0x4b12, { 0xaa, 0x60, 0x59, 0xdf, 0xf8, 0xd6, 0xea, 0x37 } \
+ }
+
+#define SHELL_TFTP_HII_GUID \
+ { \
+ 0x738a9314, 0x82c1, 0x4592, { 0x8f, 0xf7, 0xc1, 0xbd, 0xf1, 0xb2, 0x0e, 0xd4 } \
+ }
+
+
+#define SHELL_BCFG_HII_GUID \
+ { \
+ 0x5f5f605d, 0x1583, 0x4a2d, {0xa6, 0xb2, 0xeb, 0x12, 0xda, 0xb4, 0xa2, 0xb6 } \
+ }
+
+extern EFI_GUID gHandleParsingHiiGuid;
+extern EFI_GUID gShellDebug1HiiGuid;
+extern EFI_GUID gShellDriver1HiiGuid;
+extern EFI_GUID gShellInstall1HiiGuid;
+extern EFI_GUID gShellLevel1HiiGuid;
+extern EFI_GUID gShellLevel2HiiGuid;
+extern EFI_GUID gShellLevel3HiiGuid;
+extern EFI_GUID gShellNetwork1HiiGuid;
+extern EFI_GUID gShellNetwork2HiiGuid;
+extern EFI_GUID gShellTftpHiiGuid;
+extern EFI_GUID gShellBcfgHiiGuid;
+
+#endif
diff --git a/Core/ShellPkg/Include/Guid/ShellMapGuid.h b/Core/ShellPkg/Include/Guid/ShellMapGuid.h
new file mode 100644
index 0000000000..180a41bf53
--- /dev/null
+++ b/Core/ShellPkg/Include/Guid/ShellMapGuid.h
@@ -0,0 +1,25 @@
+/** @file
+ GUID for Shell Map for Get/Set via runtime services.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SHELL_MAP_GUID_H_
+#define _SHELL_MAP_GUID_H_
+
+#define SHELL_MAP_GUID \
+{ \
+ 0x51271e13, 0x7de3, 0x43af, { 0x8b, 0xc2, 0x71, 0xad, 0x3b, 0x82, 0x43, 0x25 } \
+}
+
+extern EFI_GUID gShellMapGuid;
+
+#endif \ No newline at end of file
diff --git a/Core/ShellPkg/Include/Guid/ShellPkgTokenSpace.h b/Core/ShellPkg/Include/Guid/ShellPkgTokenSpace.h
new file mode 100644
index 0000000000..d8e1b3acfb
--- /dev/null
+++ b/Core/ShellPkg/Include/Guid/ShellPkgTokenSpace.h
@@ -0,0 +1,25 @@
+/** @file
+ GUID for ShellPkg PCD Token Space.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SHELLPKG_TOKEN_SPACE_GUID_H_
+#define _SHELLPKG_TOKEN_SPACE_GUID_H_
+
+#define EFI_SHELLPKG_TOKEN_SPACE_GUID \
+{ \
+ 0x171e9188, 0x31d3, 0x40f5, { 0xb1, 0xc, 0x53, 0x9b, 0x2d, 0xb9, 0x40, 0xcd } \
+}
+
+extern EFI_GUID gEfiShellPkgTokenSpaceGuid;
+
+#endif
diff --git a/Core/ShellPkg/Include/Guid/ShellVariableGuid.h b/Core/ShellPkg/Include/Guid/ShellVariableGuid.h
new file mode 100644
index 0000000000..46c9211def
--- /dev/null
+++ b/Core/ShellPkg/Include/Guid/ShellVariableGuid.h
@@ -0,0 +1,25 @@
+/** @file
+ GUID for Shell Variable for Get/Set via runtime services.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SHELL_VARIABLE_GUID_H_
+#define _SHELL_VARIABLE_GUID_H_
+
+#define SHELL_VARIABLE_GUID \
+{ \
+ 0x158def5a, 0xf656, 0x419c, { 0xb0, 0x27, 0x7a, 0x31, 0x92, 0xc0, 0x79, 0xd2 } \
+}
+
+extern EFI_GUID gShellVariableGuid;
+
+#endif
diff --git a/Core/ShellPkg/Include/Library/BcfgCommandLib.h b/Core/ShellPkg/Include/Library/BcfgCommandLib.h
new file mode 100644
index 0000000000..9f7454a9d7
--- /dev/null
+++ b/Core/ShellPkg/Include/Library/BcfgCommandLib.h
@@ -0,0 +1,52 @@
+/** @file
+ Header file for BCFG command library.
+
+ Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _BCFG_COMMAND_LIB_H_
+#define _BCFG_COMMAND_LIB_H_
+
+/**
+ "Constructor" for the library.
+
+ This will register the handler for the bcfg command.
+
+ @param[in] ImageHandle the image handle of the process
+ @param[in] SystemTable the EFI System Table pointer
+ @param[in] Name the profile name to use
+
+ @retval EFI_SUCCESS the shell command handlers were installed sucessfully
+ @retval EFI_UNSUPPORTED the shell level required was not found.
+**/
+EFI_STATUS
+EFIAPI
+BcfgLibraryRegisterBcfgCommand (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ IN CONST CHAR16 *Name
+ );
+
+/**
+ "Destructor" for the library. free any resources.
+
+ @param ImageHandle The image handle of the process.
+ @param SystemTable The EFI System Table pointer.
+**/
+EFI_STATUS
+EFIAPI
+BcfgLibraryUnregisterBcfgCommand (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+#endif
+
diff --git a/Core/ShellPkg/Include/Library/HandleParsingLib.h b/Core/ShellPkg/Include/Library/HandleParsingLib.h
new file mode 100644
index 0000000000..441f65fffe
--- /dev/null
+++ b/Core/ShellPkg/Include/Library/HandleParsingLib.h
@@ -0,0 +1,391 @@
+/** @file
+ Provides interface to advanced shell functionality for parsing both handle and protocol database.
+
+ Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __HANDLE_PARSING_LIB__
+#define __HANDLE_PARSING_LIB__
+
+#include <Uefi.h>
+
+/**
+ Function to add a new GUID/Name mapping.
+
+ This cannot overwrite an existing mapping.
+
+ @param[in] Guid The Guid
+ @param[in] TheName The Guid's name
+ @param[in] Lang RFC4646 language code list or NULL
+
+ @retval EFI_SUCCESS The operation was sucessful
+ @retval EFI_ACCESS_DENIED There was a duplicate
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed
+**/
+EFI_STATUS
+EFIAPI
+AddNewGuidNameMapping(
+ IN CONST EFI_GUID *Guid,
+ IN CONST CHAR16 *TheName,
+ IN CONST CHAR8 *Lang OPTIONAL
+ );
+
+/**
+ Function to get the name of a protocol or struct from it's GUID.
+
+ If Guid is NULL, then ASSERT.
+
+ @param[in] Guid The GUID to look for the name of.
+ @param[in] Lang The language to use.
+
+ @return The pointer to a string of the name. The caller
+ is responsible to free this memory.
+**/
+CHAR16*
+EFIAPI
+GetStringNameFromGuid(
+ IN CONST EFI_GUID *Guid,
+ IN CONST CHAR8 *Lang OPTIONAL
+ );
+
+/**
+ Function to get the Guid for a protocol or struct based on it's string name.
+
+ Do not free or modify the returned GUID.
+
+ @param[in] Name The pointer to the string name.
+ @param[in] Lang The pointer to the language code (string).
+ @param[out] Guid The pointer to the pointer to the Guid.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+GetGuidFromStringName(
+ IN CONST CHAR16 *Name,
+ IN CONST CHAR8 *Lang OPTIONAL,
+ OUT EFI_GUID **Guid
+ );
+
+/**
+ Function to dump protocol information from a handle.
+
+ This function will return a allocated string buffer containing the
+ information. The caller is responsible for freeing the memory.
+
+ If Guid is NULL, ASSERT().
+ If TheHandle is NULL, ASSERT().
+
+ @param[in] TheHandle The handle to dump information from.
+ @param[in] Guid The GUID of the protocol to dump.
+ @param[in] Verbose TRUE for extra info. FALSE otherwise.
+
+ @return The pointer to string.
+ @retval NULL An error was encountered.
+**/
+CHAR16*
+EFIAPI
+GetProtocolInformationDump(
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST EFI_GUID *Guid,
+ IN CONST BOOLEAN Verbose
+ );
+
+/**
+ Function to retrieve the driver name (if possible) from the ComponentName or
+ ComponentName2 protocol.
+
+ The string returned must be callee freed.
+
+ @param[in] TheHandle The driver handle to get the name of.
+ @param[in] Language The language to use.
+
+ @retval NULL The name could not be found.
+ @return A pointer to the string name. Do not de-allocate the memory.
+**/
+CONST CHAR16*
+EFIAPI
+GetStringNameFromHandle(
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST CHAR8 *Language
+ );
+
+/**
+ Get best support language for this driver.
+
+ First base on the user input language to search, second base on the current
+ platform used language to search, third get the first language from the
+ support language list. The caller need to free the buffer of the best language.
+
+ @param[in] SupportedLanguages The support languages for this driver.
+ @param[in] InputLanguage The user input language.
+ @param[in] Iso639Language Whether get language for ISO639.
+
+ @return The best support language for this driver.
+**/
+CHAR8 *
+EFIAPI
+GetBestLanguageForDriver (
+ IN CONST CHAR8 *SupportedLanguages,
+ IN CONST CHAR8 *InputLanguage,
+ IN BOOLEAN Iso639Language
+ );
+
+#define HR_UNKNOWN 0
+#define HR_IMAGE_HANDLE BIT1
+#define HR_DRIVER_BINDING_HANDLE BIT2 // has driver binding
+#define HR_DEVICE_DRIVER BIT3 // device driver (hybrid?)
+#define HR_BUS_DRIVER BIT4 // a bus driver (hybrid?)
+#define HR_DRIVER_CONFIGURATION_HANDLE BIT5
+#define HR_DRIVER_DIAGNOSTICS_HANDLE BIT6
+#define HR_COMPONENT_NAME_HANDLE BIT7
+#define HR_DEVICE_HANDLE BIT8
+#define HR_PARENT_HANDLE BIT9
+#define HR_CONTROLLER_HANDLE BIT10
+#define HR_CHILD_HANDLE BIT11
+#define HR_VALID_MASK (BIT1|BIT2|BIT3|BIT4|BIT5|BIT6|BIT7|BIT8|BIT9|BIT10|BIT11)
+
+/**
+ Gets all the related EFI_HANDLEs based on the mask supplied.
+
+ This function will scan all EFI_HANDLES in the UEFI environment's handle database
+ and return all the ones with the specified relationship (Mask) to the specified
+ controller handle.
+
+ If both DriverBindingHandle and ControllerHandle are NULL, then ASSERT.
+ If MatchingHandleCount is NULL, then ASSERT.
+
+ If MatchingHandleBuffer is not NULL upon a successful return, the memory must be
+ caller freed.
+
+ @param[in] DriverBindingHandle The handle with Driver Binding protocol on it.
+ @param[in] ControllerHandle The handle with Device Path protocol on it.
+ @param[in] Mask The mask of what relationship(s) is desired.
+ @param[in] MatchingHandleCount The pointer to UINTN specifying number of HANDLES in
+ MatchingHandleBuffer.
+ @param[out] MatchingHandleBuffer On a successful return, a buffer of MatchingHandleCount
+ EFI_HANDLEs with a terminating NULL EFI_HANDLE.
+
+ @retval EFI_SUCCESS The operation was successful, and any related handles
+ are in MatchingHandleBuffer.
+ @retval EFI_NOT_FOUND No matching handles were found.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid or out of range.
+ @sa ParseHandleDatabaseByRelationshipWithType
+**/
+EFI_STATUS
+EFIAPI
+ParseHandleDatabaseByRelationship (
+ IN CONST EFI_HANDLE DriverBindingHandle OPTIONAL,
+ IN CONST EFI_HANDLE ControllerHandle OPTIONAL,
+ IN CONST UINTN Mask,
+ IN UINTN *MatchingHandleCount,
+ OUT EFI_HANDLE **MatchingHandleBuffer OPTIONAL
+ );
+
+/**
+ Gets all the related EFI_HANDLEs based on the mask supplied.
+
+ This function scans all EFI_HANDLES in the UEFI environment's handle database
+ and returns the ones with the specified relationship (Mask) to the specified
+ controller handle.
+
+ If both DriverBindingHandle and ControllerHandle are NULL, then ASSERT.
+ If MatchingHandleCount is NULL, then ASSERT.
+
+ If MatchingHandleBuffer is not NULL upon a successful return the memory must be
+ caller freed.
+
+ @param[in] DriverBindingHandle The handle with Driver Binding protocol on it.
+ @param[in] ControllerHandle The handle with Device Path protocol on it.
+ @param[in] MatchingHandleCount The pointer to UINTN that specifies the number of HANDLES in
+ MatchingHandleBuffer.
+ @param[out] MatchingHandleBuffer On a successful return, a buffer of MatchingHandleCount
+ EFI_HANDLEs with a terminating NULL EFI_HANDLE.
+ @param[out] HandleType An array of type information.
+
+ @retval EFI_SUCCESS The operation was successful, and any related handles
+ are in MatchingHandleBuffer.
+ @retval EFI_NOT_FOUND No matching handles were found.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid or out of range.
+**/
+EFI_STATUS
+EFIAPI
+ParseHandleDatabaseByRelationshipWithType (
+ IN CONST EFI_HANDLE DriverBindingHandle OPTIONAL,
+ IN CONST EFI_HANDLE ControllerHandle OPTIONAL,
+ IN UINTN *HandleCount,
+ OUT EFI_HANDLE **HandleBuffer,
+ OUT UINTN **HandleType
+ );
+
+/**
+ Gets handles for any parents of the passed in controller.
+
+ @param[in] ControllerHandle The handle of the controller.
+ @param[in] Count The pointer to the number of handles in
+ MatchingHandleBuffer on return.
+ @param[out] Buffer The buffer containing handles on a successful
+ return.
+ @retval EFI_SUCCESS The operation was successful.
+ @sa ParseHandleDatabaseByRelationship
+**/
+#define PARSE_HANDLE_DATABASE_PARENTS(ControllerHandle, Count, Buffer) \
+ ParseHandleDatabaseByRelationship(NULL, ControllerHandle, HR_PARENT_HANDLE, Count, Buffer)
+
+/**
+ Gets handles for any UEFI drivers of the passed in controller.
+
+ @param[in] ControllerHandle The handle of the controller.
+ @param[in] Count The pointer to the number of handles in
+ MatchingHandleBuffer on return.
+ @param[out] Buffer The buffer containing handles on a successful
+ return.
+ @retval EFI_SUCCESS The operation was successful.
+ @sa ParseHandleDatabaseByRelationship
+**/
+#define PARSE_HANDLE_DATABASE_UEFI_DRIVERS(ControllerHandle, Count, Buffer) \
+ ParseHandleDatabaseByRelationship(NULL, ControllerHandle, HR_DRIVER_BINDING_HANDLE|HR_DEVICE_DRIVER, Count, Buffer)
+
+/**
+ Gets handles for any children of the passed in controller by the passed in driver handle.
+
+ @param[in] DriverHandle The handle of the driver.
+ @param[in] ControllerHandle The handle of the controller.
+ @param[in] Count The pointer to the number of handles in
+ MatchingHandleBuffer on return.
+ @param[out] Buffer The buffer containing handles on a successful
+ return.
+ @retval EFI_SUCCESS The operation was successful.
+ @sa ParseHandleDatabaseByRelationship
+**/
+#define PARSE_HANDLE_DATABASE_MANAGED_CHILDREN(DriverHandle, ControllerHandle, Count, Buffer) \
+ ParseHandleDatabaseByRelationship(DriverHandle, ControllerHandle, HR_CHILD_HANDLE|HR_DEVICE_HANDLE, Count, Buffer)
+
+/**
+ Gets handles for any devices managed by the passed in driver.
+
+ @param[in] DriverHandle The handle of the driver.
+ @param[in] Count The pointer to the number of handles in
+ MatchingHandleBuffer on return.
+ @param[out] Buffer The buffer containing handles on a successful
+ return.
+ @retval EFI_SUCCESS The operation was successful.
+ @sa ParseHandleDatabaseByRelationship
+**/
+#define PARSE_HANDLE_DATABASE_DEVICES(DriverHandle, Count, Buffer) \
+ ParseHandleDatabaseByRelationship(DriverHandle, NULL, HR_CONTROLLER_HANDLE|HR_DEVICE_HANDLE, Count, Buffer)
+
+/**
+ Gets handles for any child devices produced by the passed in driver.
+
+ @param[in] DriverHandle The handle of the driver.
+ @param[in] MatchingHandleCount The pointer to the number of handles in
+ MatchingHandleBuffer on return.
+ @param[out] MatchingHandleBuffer The buffer containing handles on a successful
+ return.
+ @retval EFI_SUCCESS The operation was successful.
+ @sa ParseHandleDatabaseByRelationship
+**/
+EFI_STATUS
+EFIAPI
+ParseHandleDatabaseForChildDevices(
+ IN CONST EFI_HANDLE DriverHandle,
+ IN UINTN *MatchingHandleCount,
+ OUT EFI_HANDLE **MatchingHandleBuffer OPTIONAL
+ );
+
+/**
+ Gets handles for any child controllers of the passed in controller.
+
+ @param[in] ControllerHandle The handle of the "parent controller".
+ @param[in] MatchingHandleCount The pointer to the number of handles in
+ MatchingHandleBuffer on return.
+ @param[out] MatchingHandleBuffer The buffer containing handles on a successful
+ return.
+ @retval EFI_SUCCESS The operation was successful.
+ @sa ParseHandleDatabaseByRelationship
+**/
+EFI_STATUS
+EFIAPI
+ParseHandleDatabaseForChildControllers(
+ IN CONST EFI_HANDLE ControllerHandle,
+ IN UINTN *MatchingHandleCount,
+ OUT EFI_HANDLE **MatchingHandleBuffer OPTIONAL
+ );
+
+
+/**
+ Function to retrieve the human-friendly index of a given handle. If the handle
+ does not have a index one will be automatically assigned. The index value is valid
+ until the termination of the shell application.
+
+ @param[in] TheHandle The handle to retrieve an index for.
+
+ @retval 0 A memory allocation failed.
+ @return The index of the handle.
+
+**/
+UINTN
+EFIAPI
+ConvertHandleToHandleIndex(
+ IN CONST EFI_HANDLE TheHandle
+ );
+
+/**
+ Function to retrieve the EFI_HANDLE from the human-friendly index.
+
+ @param[in] TheIndex The index to retrieve the EFI_HANDLE for.
+
+ @retval NULL The index was invalid.
+ @return The EFI_HANDLE that index represents.
+
+**/
+EFI_HANDLE
+EFIAPI
+ConvertHandleIndexToHandle(
+ IN CONST UINTN TheIndex
+ );
+
+/**
+ Function to get all handles that support a given protocol or all handles.
+
+ The caller is responsible to free this memory.
+
+ @param[in] ProtocolGuid The guid of the protocol to get handles for. If NULL
+ then the function will return all handles.
+
+ @retval NULL A memory allocation failed.
+ @return A NULL terminated list of handles.
+**/
+EFI_HANDLE*
+EFIAPI
+GetHandleListByProtocol (
+ IN CONST EFI_GUID *ProtocolGuid OPTIONAL
+ );
+
+/**
+ Function to get all handles that support some protocols.
+
+ The caller is responsible to free this memory.
+
+ @param[in] ProtocolGuids A NULL terminated list of protocol GUIDs.
+
+ @retval NULL A memory allocation failed.
+ @retval NULL ProtocolGuids was NULL.
+ @return A NULL terminated list of EFI_HANDLEs.
+**/
+EFI_HANDLE*
+EFIAPI
+GetHandleListByProtocolList (
+ IN CONST EFI_GUID **ProtocolGuids
+ );
+
+#endif // __HANDLE_PARSING_LIB__
diff --git a/Core/ShellPkg/Include/Library/ShellCEntryLib.h b/Core/ShellPkg/Include/Library/ShellCEntryLib.h
new file mode 100644
index 0000000000..dfbb16f9c3
--- /dev/null
+++ b/Core/ShellPkg/Include/Library/ShellCEntryLib.h
@@ -0,0 +1,40 @@
+/** @file
+ Provides application point extension for "C" style main funciton.
+
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SHELL_C_ENTRY_LIB_
+#define _SHELL_C_ENTRY_LIB_
+
+/**
+ UEFI application entry point which has an interface similar to a
+ standard C main function.
+
+ The ShellCEntryLib library instance wrappers the actual UEFI application
+ entry point and calls this ShellAppMain function.
+
+ @param[in] Argc The number of parameters.
+ @param[in] Argv The array of pointers to parameters.
+
+ @retval 0 The application exited normally.
+ @retval Other An error occurred.
+
+**/
+INTN
+EFIAPI
+ShellAppMain (
+ IN UINTN Argc,
+ IN CHAR16 **Argv
+ );
+
+#endif
+
diff --git a/Core/ShellPkg/Include/Library/ShellCommandLib.h b/Core/ShellPkg/Include/Library/ShellCommandLib.h
new file mode 100644
index 0000000000..44eccc447c
--- /dev/null
+++ b/Core/ShellPkg/Include/Library/ShellCommandLib.h
@@ -0,0 +1,790 @@
+/** @file
+ Provides interface to shell internal functions for shell commands.
+
+ This library is for use ONLY by shell commands linked into the shell application.
+ This library will not funciton if it is used for UEFI Shell 2.0 Applications.
+
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+ (C) Copyright 2013-2014 Hewlett-Packard Development Company, L.P.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SHELL_COMMAND_LIB_
+#define _SHELL_COMMAND_LIB_
+
+#include <Uefi.h>
+#include <ShellBase.h>
+
+#include <Protocol/EfiShell.h>
+#include <Protocol/EfiShellParameters.h>
+#include <Protocol/UnicodeCollation.h>
+#include <Protocol/SimpleFileSystem.h>
+
+#include <Library/UefiBootServicesTableLib.h>
+
+//
+// The extern global protocol poionters.
+//
+extern EFI_UNICODE_COLLATION_PROTOCOL *gUnicodeCollation;
+extern CONST CHAR16* SupportLevel[];
+
+//
+// The map list objects.
+//
+typedef struct {
+ LIST_ENTRY Link;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ CHAR16 *MapName;
+ CHAR16 *CurrentDirectoryPath;
+ UINT64 Flags;
+} SHELL_MAP_LIST;
+/// List of Mappings - DeviceName and Drive Letter(ism).
+extern SHELL_MAP_LIST gShellMapList;
+/// Pointer to node of current directory in the mMapList.
+extern SHELL_MAP_LIST *gShellCurDir;
+
+/**
+ Returns the help MAN fileName for a given shell command.
+
+ @retval !NULL The unicode string of the MAN filename.
+ @retval NULL An error ocurred.
+
+**/
+typedef
+CONST CHAR16 *
+(EFIAPI *SHELL_GET_MAN_FILENAME)(
+ VOID
+ );
+
+/**
+ Runs a shell command on a given command line.
+
+ The specific operation of a given shell command is specified in the UEFI Shell
+ Specification 2.0, or in the source of the given command.
+
+ Upon completion of the command run the shell protocol and environment variables
+ may have been updated due to the operation.
+
+ @param[in] ImageHandle The ImageHandle to the app, or NULL if
+ the command built into shell.
+ @param[in] SystemTable The pointer to the system table.
+
+ @retval RETURN_SUCCESS The shell command was sucessful.
+ @retval RETURN_UNSUPPORTED The command is not supported.
+**/
+typedef
+SHELL_STATUS
+(EFIAPI *SHELL_RUN_COMMAND)(
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Registers the handlers of type SHELL_RUN_COMMAND and
+ SHELL_GET_MAN_FILENAME for each shell command.
+
+ If the ShellSupportLevel is greater than the value of
+ PcdShellSupportLevel, then return RETURN_UNSUPPORTED.
+
+ Registers the the handlers specified by GetHelpInfoHandler and CommandHandler
+ with the command specified by CommandString. If the command named by
+ CommandString has already been registered, then return
+ RETURN_ALREADY_STARTED.
+
+ If there are not enough resources available to register the handlers, then
+ RETURN_OUT_OF_RESOURCES is returned.
+
+ If CommandString is NULL, then ASSERT().
+ If GetHelpInfoHandler is NULL, then ASSERT().
+ If CommandHandler is NULL, then ASSERT().
+ If ProfileName is NULL, then ASSERT().
+
+ @param[in] CommandString The pointer to the command name. This is the
+ name to look for on the command line in
+ the shell.
+ @param[in] CommandHandler The pointer to a function that runs the
+ specified command.
+ @param[in] GetManFileName The pointer to a function that provides man
+ filename.
+ @param[in] ShellMinSupportLevel The minimum Shell Support Level which has this
+ function.
+ @param[in] ProfileName The profile name to require for support of this
+ function.
+ @param[in] CanAffectLE Indicates whether this command's return value
+ can change the LASTERROR environment variable.
+ @param[in] HiiHandle The handle of this command's HII entry.
+ @param[in] ManFormatHelp The HII locator for the help text.
+
+ @retval RETURN_SUCCESS The handlers were registered.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to
+ register the shell command.
+ @retval RETURN_UNSUPPORTED The ShellMinSupportLevel was higher than the
+ currently allowed support level.
+ @retval RETURN_ALREADY_STARTED The CommandString represents a command that
+ is already registered. Only one handler set for
+ a given command is allowed.
+ @sa SHELL_GET_MAN_FILENAME
+ @sa SHELL_RUN_COMMAND
+**/
+RETURN_STATUS
+EFIAPI
+ShellCommandRegisterCommandName (
+ IN CONST CHAR16 *CommandString,
+ IN SHELL_RUN_COMMAND CommandHandler,
+ IN SHELL_GET_MAN_FILENAME GetManFileName,
+ IN UINT32 ShellMinSupportLevel,
+ IN CONST CHAR16 *ProfileName,
+ IN CONST BOOLEAN CanAffectLE,
+ IN CONST EFI_HANDLE HiiHandle,
+ IN CONST EFI_STRING_ID ManFormatHelp
+ );
+
+/**
+ Checks if a command string has been registered for CommandString, and if so, it runs
+ the previously registered handler for that command with the command line.
+
+ If CommandString is NULL, then ASSERT().
+
+ If Sections is specified, then each section name listed will be compared in a case sensitive
+ manner to the section names described in Appendix B UEFI Shell 2.0 Specification. If the section exists,
+ it is appended to the returned help text. If the section does not exist, no
+ information is returned. If Sections is NULL, then all help text information
+ available is returned.
+
+ @param[in] CommandString The pointer to the command name. This is the name
+ found on the command line in the shell.
+ @param[in, out] RetVal The pointer to the return value from the command handler.
+
+ @param[in, out] CanAffectLE Indicates whether this command's return value
+ needs to be placed into LASTERROR environment variable.
+
+ @retval RETURN_SUCCESS The handler was run.
+ @retval RETURN_NOT_FOUND The CommandString did not match a registered
+ command name.
+ @sa SHELL_RUN_COMMAND
+**/
+RETURN_STATUS
+EFIAPI
+ShellCommandRunCommandHandler (
+ IN CONST CHAR16 *CommandString,
+ IN OUT SHELL_STATUS *RetVal,
+ IN OUT BOOLEAN *CanAffectLE OPTIONAL
+ );
+
+/**
+ Checks if a command string has been registered for CommandString, and if so, it
+ returns the MAN filename specified for that command.
+
+ If CommandString is NULL, then ASSERT().
+
+ @param[in] CommandString The pointer to the command name. This is the name
+ found on the command line in the shell.
+
+ @retval NULL The CommandString was not a registered command.
+ @retval other The name of the MAN file.
+ @sa SHELL_GET_MAN_FILENAME
+**/
+CONST CHAR16*
+EFIAPI
+ShellCommandGetManFileNameHandler (
+ IN CONST CHAR16 *CommandString
+ );
+
+
+typedef struct {
+ LIST_ENTRY Link;
+ CHAR16 *CommandString;
+} COMMAND_LIST;
+
+/**
+ Get the list of all available shell internal commands. This is a linked list,
+ via the LIST_ENTRY structure. Enumerate through it using the BaseLib linked
+ list functions. Do not modify the values.
+
+ @param[in] Sort TRUE to alphabetically sort the values first. FALSE otherwise.
+
+ @return A linked list of all available shell commands.
+**/
+CONST COMMAND_LIST*
+EFIAPI
+ShellCommandGetCommandList (
+ IN CONST BOOLEAN Sort
+ );
+
+typedef struct {
+ LIST_ENTRY Link;
+ CHAR16 *CommandString;
+ CHAR16 *Alias;
+} ALIAS_LIST;
+
+/**
+ Registers aliases to be set as part of the initialization of the shell application.
+
+ If Command is NULL, then ASSERT().
+ If Alias is NULL, then ASSERT().
+
+ @param[in] Command The pointer to the Command.
+ @param[in] Alias The pointer to Alias.
+
+ @retval RETURN_SUCCESS The handlers were registered.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to
+ register the shell command.
+**/
+RETURN_STATUS
+EFIAPI
+ShellCommandRegisterAlias (
+ IN CONST CHAR16 *Command,
+ IN CONST CHAR16 *Alias
+ );
+
+/**
+ Get the list of all shell alias commands. This is a linked list,
+ via LIST_ENTRY structure. Enumerate through it using the BaseLib linked
+ list functions. Do not modify the values.
+
+ @return A linked list of all requested shell aliases.
+**/
+CONST ALIAS_LIST*
+EFIAPI
+ShellCommandGetInitAliasList (
+ VOID
+ );
+
+/**
+ Determine if a given alias is on the list of built in aliases.
+
+ @param[in] Alias The alias to test for.
+
+ @retval TRUE The alias is a built in alias.
+ @retval FALSE The alias is not a built in alias.
+**/
+BOOLEAN
+EFIAPI
+ShellCommandIsOnAliasList (
+ IN CONST CHAR16 *Alias
+ );
+
+/**
+ Checks if a command is already on the list.
+
+ @param[in] CommandString The command string to check for on the list.
+
+ @retval TRUE CommandString represents a registered command.
+ @retval FALSE CommandString does not represent a registered command.
+**/
+BOOLEAN
+EFIAPI
+ShellCommandIsCommandOnList (
+ IN CONST CHAR16 *CommandString
+ );
+
+/**
+ Get the help text for a command.
+
+ @param[in] CommandString The command name.
+
+ @retval NULL No help text was found.
+ @return The string of the help text. The caller required to free.
+**/
+CHAR16*
+EFIAPI
+ShellCommandGetCommandHelp (
+ IN CONST CHAR16 *CommandString
+ );
+
+/**
+ Function to make sure that the above pointers are valid.
+**/
+EFI_STATUS
+EFIAPI
+CommandInit (
+ VOID
+ );
+
+/**
+ Function to determine current state of ECHO. Echo determines if lines from scripts
+ and ECHO commands are enabled.
+
+ @retval TRUE Echo is currently enabled.
+ @retval FALSE Echo is currently disabled.
+**/
+BOOLEAN
+EFIAPI
+ShellCommandGetEchoState (
+ VOID
+ );
+
+/**
+ Function to set current state of ECHO. Echo determines if lines from scripts
+ and ECHO commands are enabled.
+
+ @param[in] State TRUE to enable Echo, FALSE otherwise.
+**/
+VOID
+EFIAPI
+ShellCommandSetEchoState (
+ IN BOOLEAN State
+ );
+
+
+
+/**
+ Indicate that the current shell or script should exit.
+
+ @param[in] ScriptOnly TRUE if exiting a script; FALSE otherwise.
+ @param[in] ErrorCode The 64 bit error code to return.
+**/
+VOID
+EFIAPI
+ShellCommandRegisterExit (
+ IN BOOLEAN ScriptOnly,
+ IN CONST UINT64 ErrorCode
+ );
+
+/**
+ Retrieve the Exit code.
+
+ @return the value passed into RegisterExit.
+**/
+UINT64
+EFIAPI
+ShellCommandGetExitCode (
+ VOID
+ );
+
+/**
+ Retrieve the Exit indicator.
+
+ @retval TRUE Exit was indicated.
+ @retval FALSE Exit was not indicated.
+**/
+BOOLEAN
+EFIAPI
+ShellCommandGetExit (
+ VOID
+ );
+
+/**
+ Retrieve the Exit script indicator.
+
+ If ShellCommandGetExit returns FALSE, then the return from this is undefined.
+
+ @retval TRUE ScriptOnly was indicated.
+ @retval FALSE ScriptOnly was not indicated.
+**/
+BOOLEAN
+EFIAPI
+ShellCommandGetScriptExit (
+ VOID
+ );
+
+typedef struct {
+ LIST_ENTRY Link; ///< List enumerator items.
+ UINTN Line; ///< What line of the script file this was on.
+ CHAR16 *Cl; ///< The original command line.
+ VOID *Data; ///< The data structure format dependant upon Command. (not always used)
+ BOOLEAN Reset; ///< Reset the command (it must be treated like a initial run (but it may have data already))
+} SCRIPT_COMMAND_LIST;
+
+typedef struct {
+ CHAR16 *ScriptName; ///< The filename of this script.
+ CHAR16 **Argv; ///< The parmameters to the script file.
+ UINTN Argc; ///< The count of parameters.
+ LIST_ENTRY CommandList; ///< The script converted to a list of commands (SCRIPT_COMMAND_LIST objects).
+ SCRIPT_COMMAND_LIST *CurrentCommand; ///< The command currently being operated. If !=NULL must be a member of CommandList.
+ LIST_ENTRY SubstList; ///< A list of current script loop alias' (ALIAS_LIST objects) (Used for the for %-based replacement).
+} SCRIPT_FILE;
+
+/**
+ Function to return a pointer to the currently running script file object.
+
+ @retval NULL A script file is not currently running.
+ @return A pointer to the current script file object.
+**/
+SCRIPT_FILE*
+EFIAPI
+ShellCommandGetCurrentScriptFile (
+ VOID
+ );
+
+/**
+ Function to set a new script as the currently running one.
+
+ This function will correctly stack and unstack nested scripts.
+
+ @param[in] Script The pointer to new script information structure. If NULL,
+ it removes and de-allocates the topmost Script structure.
+
+ @return A pointer to the current running script file after this
+ change. It is NULL if removing the final script.
+**/
+SCRIPT_FILE*
+EFIAPI
+ShellCommandSetNewScript (
+ IN SCRIPT_FILE *Script OPTIONAL
+ );
+
+/**
+ Function to cleanup all memory from a SCRIPT_FILE structure.
+
+ @param[in] Script The pointer to the structure to cleanup.
+**/
+VOID
+EFIAPI
+DeleteScriptFileStruct (
+ IN SCRIPT_FILE *Script
+ );
+
+/**
+ Function to get the current Profile string.
+
+ This is used to retrieve what profiles were installed.
+
+ @retval NULL There are no installed profiles.
+ @return A semicolon-delimited list of profiles.
+**/
+CONST CHAR16 *
+EFIAPI
+ShellCommandGetProfileList (
+ VOID
+ );
+
+typedef enum {
+ MappingTypeFileSystem,
+ MappingTypeBlockIo,
+ MappingTypeMax
+} SHELL_MAPPING_TYPE;
+
+/**
+ Function to generate the next default mapping name.
+
+ If the return value is not NULL then it must be callee freed.
+
+ @param Type What kind of mapping name to make.
+
+ @retval NULL a memory allocation failed.
+ @return a new map name string
+**/
+CHAR16*
+EFIAPI
+ShellCommandCreateNewMappingName(
+ IN CONST SHELL_MAPPING_TYPE Type
+ );
+
+/**
+ Function to initialize the table for creating consistent map names.
+
+ @param[out] Table The pointer to pointer to pointer to DevicePathProtocol object.
+
+ @retval EFI_SUCCESS The table was created successfully.
+**/
+EFI_STATUS
+EFIAPI
+ShellCommandConsistMappingInitialize (
+ EFI_DEVICE_PATH_PROTOCOL ***Table
+ );
+
+/**
+ Function to uninitialize the table for creating consistent map names.
+
+ The parameter must have been received from ShellCommandConsistMappingInitialize.
+
+ @param[out] Table The pointer to pointer to DevicePathProtocol object.
+
+ @retval EFI_SUCCESS The table was deleted successfully.
+**/
+EFI_STATUS
+EFIAPI
+ShellCommandConsistMappingUnInitialize (
+ EFI_DEVICE_PATH_PROTOCOL **Table
+ );
+
+/**
+ Create a consistent mapped name for the device specified by DevicePath
+ based on the Table.
+
+ This must be called after ShellCommandConsistMappingInitialize() and
+ before ShellCommandConsistMappingUnInitialize() is called.
+
+ @param[in] DevicePath The pointer to the dev path for the device.
+ @param[in] Table The Table of mapping information.
+
+ @retval NULL A consistent mapped name could not be created.
+ @return A pointer to a string allocated from pool with the device name.
+**/
+CHAR16*
+EFIAPI
+ShellCommandConsistMappingGenMappingName (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_DEVICE_PATH_PROTOCOL **Table
+ );
+
+/**
+ Function to search the list of mappings for the first matching node on the
+ list based on the MapKey.
+
+ @param[in] MapKey The pointer to the string key to search for in the map.
+
+ @return the node on the list.
+**/
+SHELL_MAP_LIST*
+EFIAPI
+ShellCommandFindMapItem (
+ IN CONST CHAR16 *MapKey
+ );
+
+/**
+ Function to add a map node to the list of map items and update the "path" environment variable (optionally).
+
+ If Path is TRUE (during initialization only), the path environment variable will also be updated to include
+ default paths on the new map name...
+
+ Path should be FALSE when this function is called from the protocol SetMap function.
+
+ @param[in] Name The human readable mapped name.
+ @param[in] DevicePath The Device Path for this map.
+ @param[in] Flags The Flags attribute for this map item.
+ @param[in] Path TRUE to update path, FALSE to skip this step (should only be TRUE during initialization).
+
+ @retval EFI_SUCCESS The addition was sucessful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.
+**/
+EFI_STATUS
+EFIAPI
+ShellCommandAddMapItemAndUpdatePath(
+ IN CONST CHAR16 *Name,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN CONST UINT64 Flags,
+ IN CONST BOOLEAN Path
+ );
+
+/**
+ Creates the default map names for each device path in the system with
+ a protocol depending on the Type.
+
+ Also sets up the default path environment variable if Type is FileSystem.
+
+ @retval EFI_SUCCESS All map names were created sucessfully.
+ @retval EFI_NOT_FOUND No protocols were found in the system.
+ @return Error returned from gBS->LocateHandle().
+
+ @sa LocateHandle
+**/
+EFI_STATUS
+EFIAPI
+ShellCommandCreateInitialMappingsAndPaths(
+ VOID
+ );
+
+/**
+ Add mappings for any devices without one. Do not change any existing maps.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+ShellCommandUpdateMapping (
+ VOID
+ );
+
+/**
+ Converts a SHELL_FILE_HANDLE to an EFI_FILE_PROTOCOL*.
+
+ @param[in] Handle The SHELL_FILE_HANDLE to convert.
+
+ @return a EFI_FILE_PROTOCOL* representing the same file.
+**/
+EFI_FILE_PROTOCOL*
+EFIAPI
+ConvertShellHandleToEfiFileProtocol(
+ IN CONST SHELL_FILE_HANDLE Handle
+ );
+
+/**
+ Remove a SHELL_FILE_HANDLE frmo the list of SHELL_FILE_HANDLES.
+
+ @param[in] Handle The SHELL_FILE_HANDLE to remove.
+
+ @retval TRUE The item was removed.
+ @retval FALSE The item was not found.
+**/
+BOOLEAN
+EFIAPI
+ShellFileHandleRemove(
+ IN CONST SHELL_FILE_HANDLE Handle
+ );
+
+/**
+ Converts a EFI_FILE_PROTOCOL* to an SHELL_FILE_HANDLE.
+
+ @param[in] Handle The pointer to EFI_FILE_PROTOCOL to convert.
+ @param[in] Path The path to the file for verification.
+
+ @return a SHELL_FILE_HANDLE representing the same file.
+**/
+SHELL_FILE_HANDLE
+EFIAPI
+ConvertEfiFileProtocolToShellHandle(
+ IN CONST EFI_FILE_PROTOCOL *Handle,
+ IN CONST CHAR16 *Path
+ );
+
+/**
+ Find the path that was logged with the specified SHELL_FILE_HANDLE.
+
+ @param[in] Handle The SHELL_FILE_HANDLE to query on.
+
+ @return A pointer to the path for the file.
+**/
+CONST CHAR16*
+EFIAPI
+ShellFileHandleGetPath(
+ IN CONST SHELL_FILE_HANDLE Handle
+ );
+
+
+/**
+ Function to determine if a SHELL_FILE_HANDLE is at the end of the file.
+
+ This will NOT work on directories.
+
+ If Handle is NULL, then ASSERT.
+
+ @param[in] Handle the file handle
+
+ @retval TRUE the position is at the end of the file
+ @retval FALSE the position is not at the end of the file
+**/
+BOOLEAN
+EFIAPI
+ShellFileHandleEof(
+ IN SHELL_FILE_HANDLE Handle
+ );
+
+/**
+ Function to get the original CmdLine string for current command.
+
+ @return A pointer to the buffer of the original command string.
+ It's the caller's responsibility to free the buffer.
+**/
+CHAR16*
+EFIAPI
+ShellGetRawCmdLine (
+ VOID
+ );
+
+/**
+ Function to store the orgignal command string into mOriginalCmdLine.
+
+ @param[in] CmdLine the command line string to store.
+**/
+VOID
+EFIAPI
+ShellSetRawCmdLine (
+ IN CONST CHAR16 *CmdLine
+ );
+
+typedef struct {
+ LIST_ENTRY Link;
+ void *Buffer;
+} BUFFER_LIST;
+
+/**
+ Frees any BUFFER_LIST defined type.
+
+ @param[in] List The pointer to the list head.
+**/
+VOID
+EFIAPI
+FreeBufferList (
+ IN BUFFER_LIST *List
+ );
+
+/**
+ Function printing hex output to the console.
+
+ @param[in] Indent Number of spaces to indent.
+ @param[in] Offset Offset to start with.
+ @param[in] DataSize Length of data.
+ @param[in] UserData Pointer to some data.
+**/
+VOID
+DumpHex (
+ IN UINTN Indent,
+ IN UINTN Offset,
+ IN UINTN DataSize,
+ IN VOID *UserData
+ );
+
+/**
+ Dump HEX data into buffer.
+
+ @param[in] Buffer HEX data to be dumped in Buffer.
+ @param[in] Indent How many spaces to indent the output.
+ @param[in] Offset The offset of the printing.
+ @param[in] DataSize The size in bytes of UserData.
+ @param[in] UserData The data to print out.
+**/
+CHAR16*
+CatSDumpHex (
+ IN CHAR16 *Buffer,
+ IN UINTN Indent,
+ IN UINTN Offset,
+ IN UINTN DataSize,
+ IN VOID *UserData
+ );
+
+/**
+ Return the pointer to the first occurrence of any character from a list of characters.
+
+ @param[in] String The string to parse
+ @param[in] CharacterList The list of character to look for
+ @param[in] IgnoreEscapedCharacter TRUE to ignore escaped characters
+
+ @return The location of the first character in the String.
+ @return Pointer to the ending NULL character of the String.
+**/
+CONST CHAR16*
+EFIAPI
+ShellFindFirstCharacter (
+ IN CONST CHAR16 *String,
+ IN CONST CHAR16 *CharacterList,
+ IN CONST BOOLEAN IgnoreEscapedCharacter
+ );
+
+/**
+ return the next parameter from a command line string;
+
+ This function moves the next parameter from Walker into NextParameter and moves
+ Walker up past that parameter for recursive calling. When the final parameter
+ is moved *Walker will be set to NULL;
+
+ @param[in, out] Walker pointer to string of command line. Adjusted to
+ reminaing command line on return
+ @param[in, out] NextParameter string of command line item extracted.
+ @param[in] Length Length of TempParameter in bytes
+ @param[in] StripQuotation if TRUE then strip the quotation marks surrounding
+ the parameters.
+
+ @return EFI_INALID_PARAMETER A required parameter was NULL or pointed to a NULL or empty string.
+ @return EFI_NOT_FOUND A closing " could not be found on the specified string
+**/
+EFI_STATUS
+EFIAPI
+ShellGetNextParameter(
+ IN OUT CHAR16 **Walker,
+ IN OUT CHAR16 *NextParameter,
+ IN CONST UINTN Length,
+ IN BOOLEAN StripQuotation
+ );
+
+#endif //_SHELL_COMMAND_LIB_
diff --git a/Core/ShellPkg/Include/Library/ShellLib.h b/Core/ShellPkg/Include/Library/ShellLib.h
new file mode 100644
index 0000000000..fe4b9cf785
--- /dev/null
+++ b/Core/ShellPkg/Include/Library/ShellLib.h
@@ -0,0 +1,1400 @@
+/** @file
+ Provides interface to shell functionality for shell commands and applications.
+
+ Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __SHELL_LIB__
+#define __SHELL_LIB__
+
+#include <Uefi.h>
+#include <Guid/FileInfo.h>
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/EfiShellInterface.h>
+#include <Protocol/EfiShellEnvironment2.h>
+#include <Protocol/EfiShell.h>
+#include <Protocol/EfiShellParameters.h>
+
+// (20 * (6+5+2))+1) unicode characters from EFI FAT spec (doubled for bytes)
+#define MAX_FILE_NAME_LEN 512
+
+extern EFI_SHELL_PARAMETERS_PROTOCOL *gEfiShellParametersProtocol;
+extern EFI_SHELL_PROTOCOL *gEfiShellProtocol;
+
+/**
+ This function will retrieve the information about the file for the handle
+ specified and store it in allocated pool memory.
+
+ This function allocates a buffer to store the file's information. It is the
+ caller's responsibility to free the buffer.
+
+ @param[in] FileHandle The file handle of the file for which information is
+ being requested.
+
+ @retval NULL Information could not be retrieved.
+
+ @return The information about the file.
+**/
+EFI_FILE_INFO*
+EFIAPI
+ShellGetFileInfo (
+ IN SHELL_FILE_HANDLE FileHandle
+ );
+
+/**
+ This function sets the information about the file for the opened handle
+ specified.
+
+ @param[in] FileHandle The file handle of the file for which information
+ is being set.
+
+ @param[in] FileInfo The information to set.
+
+ @retval EFI_SUCCESS The information was set.
+ @retval EFI_INVALID_PARAMETER A parameter was out of range or invalid.
+ @retval EFI_UNSUPPORTED The FileHandle does not support FileInfo.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The file or medium is write protected.
+ @retval EFI_ACCESS_DENIED The file was opened read only.
+ @retval EFI_VOLUME_FULL The volume is full.
+**/
+EFI_STATUS
+EFIAPI
+ShellSetFileInfo (
+ IN SHELL_FILE_HANDLE FileHandle,
+ IN EFI_FILE_INFO *FileInfo
+ );
+
+/**
+ This function will open a file or directory referenced by DevicePath.
+
+ This function opens a file with the open mode according to the file path. The
+ Attributes is valid only for EFI_FILE_MODE_CREATE.
+
+ @param[in, out] FilePath On input, the device path to the file. On output,
+ the remaining device path.
+ @param[out] DeviceHandle Pointer to the system device handle.
+ @param[out] FileHandle Pointer to the file handle.
+ @param[in] OpenMode The mode to open the file with.
+ @param[in] Attributes The file's file attributes.
+
+ @retval EFI_SUCCESS The information was set.
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
+ @retval EFI_UNSUPPORTED Could not open the file path.
+ @retval EFI_NOT_FOUND The specified file could not be found on the
+ device or the file system could not be found on
+ the device.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_MEDIA_CHANGED The device has a different medium in it or the
+ medium is no longer supported.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The file or medium is write protected.
+ @retval EFI_ACCESS_DENIED The file was opened read only.
+ @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the
+ file.
+ @retval EFI_VOLUME_FULL The volume is full.
+**/
+EFI_STATUS
+EFIAPI
+ShellOpenFileByDevicePath(
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,
+ OUT EFI_HANDLE *DeviceHandle,
+ OUT SHELL_FILE_HANDLE *FileHandle,
+ IN UINT64 OpenMode,
+ IN UINT64 Attributes
+ );
+
+/**
+ This function will open a file or directory referenced by filename.
+
+ If return is EFI_SUCCESS, the Filehandle is the opened file's handle;
+ otherwise, the Filehandle is NULL. Attributes is valid only for
+ EFI_FILE_MODE_CREATE.
+
+ @param[in] FilePath The pointer to file name.
+ @param[out] FileHandle The pointer to the file handle.
+ @param[in] OpenMode The mode to open the file with.
+ @param[in] Attributes The file's file attributes.
+
+ @retval EFI_SUCCESS The information was set.
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
+ @retval EFI_UNSUPPORTED Could not open the file path.
+ @retval EFI_NOT_FOUND The specified file could not be found on the
+ device or the file system could not be found
+ on the device.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_MEDIA_CHANGED The device has a different medium in it or the
+ medium is no longer supported.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The file or medium is write protected.
+ @retval EFI_ACCESS_DENIED The file was opened read only.
+ @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the
+ file.
+ @retval EFI_VOLUME_FULL The volume is full.
+**/
+EFI_STATUS
+EFIAPI
+ShellOpenFileByName(
+ IN CONST CHAR16 *FilePath,
+ OUT SHELL_FILE_HANDLE *FileHandle,
+ IN UINT64 OpenMode,
+ IN UINT64 Attributes
+ );
+
+/**
+ This function creates a directory.
+
+ If return is EFI_SUCCESS, the Filehandle is the opened directory's handle;
+ otherwise, the Filehandle is NULL. If the directory already existed, this
+ function opens the existing directory.
+
+ @param[in] DirectoryName The pointer to Directory name.
+ @param[out] FileHandle The pointer to the file handle.
+
+ @retval EFI_SUCCESS The information was set.
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
+ @retval EFI_UNSUPPORTED Could not open the file path.
+ @retval EFI_NOT_FOUND The specified file could not be found on the
+ device, or the file system could not be found
+ on the device.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_MEDIA_CHANGED The device has a different medium in it or the
+ medium is no longer supported.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The file or medium is write protected.
+ @retval EFI_ACCESS_DENIED The file was opened read only.
+ @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the
+ file.
+ @retval EFI_VOLUME_FULL The volume is full.
+**/
+EFI_STATUS
+EFIAPI
+ShellCreateDirectory(
+ IN CONST CHAR16 *DirectoryName,
+ OUT SHELL_FILE_HANDLE *FileHandle
+ );
+
+/**
+ This function reads information from an opened file.
+
+ If FileHandle is not a directory, the function reads the requested number of
+ bytes from the file at the file's current position and returns them in Buffer.
+ If the read goes beyond the end of the file, the read length is truncated to the
+ end of the file. The file's current position is increased by the number of bytes
+ returned. If FileHandle is a directory, the function reads the directory entry
+ at the file's current position and returns the entry in Buffer. If the Buffer
+ is not large enough to hold the current directory entry, then
+ EFI_BUFFER_TOO_SMALL is returned and the current file position is not updated.
+ BufferSize is set to be the size of the buffer needed to read the entry. On
+ success, the current position is updated to the next directory entry. If there
+ are no more directory entries, the read returns a zero-length buffer.
+ EFI_FILE_INFO is the structure returned as the directory entry.
+
+ @param[in] FileHandle The opened file handle.
+ @param[in, out] ReadSize On input the size of buffer in bytes. On return
+ the number of bytes written.
+ @param[out] Buffer The buffer to put read data into.
+
+ @retval EFI_SUCCESS Data was read.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_BUFFER_TO_SMALL Buffer is too small. ReadSize contains required
+ size.
+
+**/
+EFI_STATUS
+EFIAPI
+ShellReadFile(
+ IN SHELL_FILE_HANDLE FileHandle,
+ IN OUT UINTN *ReadSize,
+ OUT VOID *Buffer
+ );
+
+/**
+ Write data to a file.
+
+ This function writes the specified number of bytes to the file at the current
+ file position. The current file position is advanced the actual number of bytes
+ written, which is returned in BufferSize. Partial writes only occur when there
+ has been a data error during the write attempt (such as "volume space full").
+ The file is automatically grown to hold the data if required. Direct writes to
+ opened directories are not supported.
+
+ @param[in] FileHandle The opened file for writing.
+
+ @param[in, out] BufferSize On input the number of bytes in Buffer. On output
+ the number of bytes written.
+
+ @param[in] Buffer The buffer containing data to write is stored.
+
+ @retval EFI_SUCCESS Data was written.
+ @retval EFI_UNSUPPORTED Writes to an open directory are not supported.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The device is write-protected.
+ @retval EFI_ACCESS_DENIED The file was open for read only.
+ @retval EFI_VOLUME_FULL The volume is full.
+**/
+EFI_STATUS
+EFIAPI
+ShellWriteFile(
+ IN SHELL_FILE_HANDLE FileHandle,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ );
+
+/**
+ Close an open file handle.
+
+ This function closes a specified file handle. All "dirty" cached file data is
+ flushed to the device, and the file is closed. In all cases the handle is
+ closed.
+
+ @param[in] FileHandle The file handle to close.
+
+ @retval EFI_SUCCESS The file handle was closed sucessfully.
+ @retval INVALID_PARAMETER One of the parameters has an invalid value.
+**/
+EFI_STATUS
+EFIAPI
+ShellCloseFile (
+ IN SHELL_FILE_HANDLE *FileHandle
+ );
+
+/**
+ Delete a file and close the handle
+
+ This function closes and deletes a file. In all cases the file handle is closed.
+ If the file cannot be deleted, the warning code EFI_WARN_DELETE_FAILURE is
+ returned, but the handle is still closed.
+
+ @param[in] FileHandle The file handle to delete.
+
+ @retval EFI_SUCCESS The file was closed sucessfully.
+ @retval EFI_WARN_DELETE_FAILURE The handle was closed, but the file was not
+ deleted.
+ @retval INVALID_PARAMETER One of the parameters has an invalid value.
+**/
+EFI_STATUS
+EFIAPI
+ShellDeleteFile (
+ IN SHELL_FILE_HANDLE *FileHandle
+ );
+
+/**
+ Set the current position in a file.
+
+ This function sets the current file position for the handle to the position
+ supplied. With the exception of seeking to position 0xFFFFFFFFFFFFFFFF, only
+ absolute positioning is supported, and moving past the end of the file is
+ allowed (a subsequent write would grow the file). Moving to position
+ 0xFFFFFFFFFFFFFFFF causes the current position to be set to the end of the file.
+ If FileHandle is a directory, the only position that may be set is zero. This
+ has the effect of starting the read process of the directory entries over.
+
+ @param[in] FileHandle The file handle on which the position is being set.
+
+ @param[in] Position The byte position from the begining of the file.
+
+ @retval EFI_SUCCESS Operation completed sucessfully.
+ @retval EFI_UNSUPPORTED The seek request for non-zero is not valid on
+ directories.
+ @retval INVALID_PARAMETER One of the parameters has an invalid value.
+**/
+EFI_STATUS
+EFIAPI
+ShellSetFilePosition (
+ IN SHELL_FILE_HANDLE FileHandle,
+ IN UINT64 Position
+ );
+
+/**
+ Gets a file's current position
+
+ This function retrieves the current file position for the file handle. For
+ directories, the current file position has no meaning outside of the file
+ system driver and as such the operation is not supported. An error is returned
+ if FileHandle is a directory.
+
+ @param[in] FileHandle The open file handle on which to get the position.
+ @param[out] Position The byte position from the begining of the file.
+
+ @retval EFI_SUCCESS The operation completed sucessfully.
+ @retval INVALID_PARAMETER One of the parameters has an invalid value.
+ @retval EFI_UNSUPPORTED The request is not valid on directories.
+**/
+EFI_STATUS
+EFIAPI
+ShellGetFilePosition (
+ IN SHELL_FILE_HANDLE FileHandle,
+ OUT UINT64 *Position
+ );
+
+/**
+ Flushes data on a file
+
+ This function flushes all modified data associated with a file to a device.
+
+ @param[in] FileHandle The file handle on which to flush data.
+
+ @retval EFI_SUCCESS The data was flushed.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The file or medium is write protected.
+ @retval EFI_ACCESS_DENIED The file was opened for read only.
+**/
+EFI_STATUS
+EFIAPI
+ShellFlushFile (
+ IN SHELL_FILE_HANDLE FileHandle
+ );
+
+/** Retrieve first entry from a directory.
+
+ This function takes an open directory handle and gets information from the
+ first entry in the directory. A buffer is allocated to contain
+ the information and a pointer to the buffer is returned in *Buffer. The
+ caller can use ShellFindNextFile() to get subsequent directory entries.
+
+ The buffer will be freed by ShellFindNextFile() when the last directory
+ entry is read. Otherwise, the caller must free the buffer, using FreePool,
+ when finished with it.
+
+ @param[in] DirHandle The file handle of the directory to search.
+ @param[out] Buffer The pointer to the buffer for the file's information.
+
+ @retval EFI_SUCCESS Found the first file.
+ @retval EFI_NOT_FOUND Cannot find the directory.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @return Others Status of ShellGetFileInfo, ShellSetFilePosition,
+ or ShellReadFile.
+
+ @sa ShellReadFile
+**/
+EFI_STATUS
+EFIAPI
+ShellFindFirstFile (
+ IN SHELL_FILE_HANDLE DirHandle,
+ OUT EFI_FILE_INFO **Buffer
+ );
+
+/** Retrieve next entries from a directory.
+
+ To use this function, the caller must first call the ShellFindFirstFile()
+ function to get the first directory entry. Subsequent directory entries are
+ retrieved by using the ShellFindNextFile() function. This function can
+ be called several times to get each entry from the directory. If the call of
+ ShellFindNextFile() retrieved the last directory entry, the next call of
+ this function will set *NoFile to TRUE and free the buffer.
+
+ @param[in] DirHandle The file handle of the directory.
+ @param[in, out] Buffer The pointer to buffer for file's information.
+ @param[in, out] NoFile The pointer to boolean when last file is found.
+
+ @retval EFI_SUCCESS Found the next file.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+
+ @sa ShellReadFile
+**/
+EFI_STATUS
+EFIAPI
+ShellFindNextFile(
+ IN SHELL_FILE_HANDLE DirHandle,
+ IN OUT EFI_FILE_INFO *Buffer,
+ IN OUT BOOLEAN *NoFile
+ );
+
+/**
+ Retrieve the size of a file.
+
+ This function extracts the file size info from the FileHandle's EFI_FILE_INFO
+ data.
+
+ @param[in] FileHandle The file handle from which size is retrieved.
+ @param[out] Size The pointer to size.
+
+ @retval EFI_SUCCESS The operation was completed sucessfully.
+ @retval EFI_DEVICE_ERROR Cannot access the file.
+**/
+EFI_STATUS
+EFIAPI
+ShellGetFileSize (
+ IN SHELL_FILE_HANDLE FileHandle,
+ OUT UINT64 *Size
+ );
+
+/**
+ Retrieves the status of the break execution flag
+
+ This function is useful to check whether the application is being asked to halt by the shell.
+
+ @retval TRUE The execution break is enabled.
+ @retval FALSE The execution break is not enabled.
+**/
+BOOLEAN
+EFIAPI
+ShellGetExecutionBreakFlag(
+ VOID
+ );
+
+/**
+ Return the value of an environment variable.
+
+ This function gets the value of the environment variable set by the
+ ShellSetEnvironmentVariable function.
+
+ @param[in] EnvKey The key name of the environment variable.
+
+ @retval NULL The named environment variable does not exist.
+ @return != NULL The pointer to the value of the environment variable.
+**/
+CONST CHAR16*
+EFIAPI
+ShellGetEnvironmentVariable (
+ IN CONST CHAR16 *EnvKey
+ );
+
+/**
+ Set the value of an environment variable.
+
+ This function changes the current value of the specified environment variable. If the
+ environment variable exists and the Value is an empty string, then the environment
+ variable is deleted. If the environment variable exists and the Value is not an empty
+ string, then the value of the environment variable is changed. If the environment
+ variable does not exist and the Value is an empty string, there is no action. If the
+ environment variable does not exist and the Value is a non-empty string, then the
+ environment variable is created and assigned the specified value.
+
+ This is not supported pre-UEFI Shell 2.0.
+
+ @param[in] EnvKey The key name of the environment variable.
+ @param[in] EnvVal The Value of the environment variable
+ @param[in] Volatile Indicates whether the variable is non-volatile (FALSE) or volatile (TRUE).
+
+ @retval EFI_SUCCESS The operation completed sucessfully
+ @retval EFI_UNSUPPORTED This operation is not allowed in pre-UEFI 2.0 Shell environments.
+**/
+EFI_STATUS
+EFIAPI
+ShellSetEnvironmentVariable (
+ IN CONST CHAR16 *EnvKey,
+ IN CONST CHAR16 *EnvVal,
+ IN BOOLEAN Volatile
+ );
+
+/**
+ Cause the shell to parse and execute a command line.
+
+ This function creates a nested instance of the shell and executes the specified
+ command (CommandLine) with the specified environment (Environment). Upon return,
+ the status code returned by the specified command is placed in StatusCode.
+ If Environment is NULL, then the current environment is used and all changes made
+ by the commands executed will be reflected in the current environment. If the
+ Environment is non-NULL, then the changes made will be discarded.
+ The CommandLine is executed from the current working directory on the current
+ device.
+
+ The EnvironmentVariables and Status parameters are ignored in a pre-UEFI Shell 2.0
+ environment. The values pointed to by the parameters will be unchanged by the
+ ShellExecute() function. The Output parameter has no effect in a
+ UEFI Shell 2.0 environment.
+
+ @param[in] ParentHandle The parent image starting the operation.
+ @param[in] CommandLine The pointer to a NULL terminated command line.
+ @param[in] Output True to display debug output. False to hide it.
+ @param[in] EnvironmentVariables Optional pointer to array of environment variables
+ in the form "x=y". If NULL, the current set is used.
+ @param[out] Status The status of the run command line.
+
+ @retval EFI_SUCCESS The operation completed sucessfully. Status
+ contains the status code returned.
+ @retval EFI_INVALID_PARAMETER A parameter contains an invalid value.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_UNSUPPORTED The operation is not allowed.
+**/
+EFI_STATUS
+EFIAPI
+ShellExecute (
+ IN EFI_HANDLE *ParentHandle,
+ IN CHAR16 *CommandLine,
+ IN BOOLEAN Output,
+ IN CHAR16 **EnvironmentVariables,
+ OUT EFI_STATUS *Status
+ );
+
+/**
+ Retreives the current directory path.
+
+ If the DeviceName is NULL, it returns the current device's current directory
+ name. If the DeviceName is not NULL, it returns the current directory name
+ on specified drive.
+
+ Note that the current directory string should exclude the tailing backslash character.
+
+ @param[in] DeviceName The name of the file system to get directory on.
+
+ @retval NULL The directory does not exist.
+ @retval != NULL The directory.
+**/
+CONST CHAR16*
+EFIAPI
+ShellGetCurrentDir (
+ IN CHAR16 * CONST DeviceName OPTIONAL
+ );
+
+/**
+ Sets (enabled or disabled) the page break mode.
+
+ When page break mode is enabled the screen will stop scrolling
+ and wait for operator input before scrolling a subsequent screen.
+
+ @param[in] CurrentState TRUE to enable and FALSE to disable.
+**/
+VOID
+EFIAPI
+ShellSetPageBreakMode (
+ IN BOOLEAN CurrentState
+ );
+
+/**
+ Opens a group of files based on a path.
+
+ This function uses the Arg to open all the matching files. Each matched
+ file has a SHELL_FILE_ARG structure to record the file information. These
+ structures are placed on the list ListHead. Users can get the SHELL_FILE_ARG
+ structures from ListHead to access each file. This function supports wildcards
+ and will process '?' and '*' as such. The list must be freed with a call to
+ ShellCloseFileMetaArg().
+
+ If you are NOT appending to an existing list *ListHead must be NULL. If
+ *ListHead is NULL then it must be callee freed.
+
+ @param[in] Arg The pointer to path string.
+ @param[in] OpenMode Mode to open files with.
+ @param[in, out] ListHead Head of linked list of results.
+
+ @retval EFI_SUCCESS The operation was sucessful and the list head
+ contains the list of opened files.
+ @retval != EFI_SUCCESS The operation failed.
+
+ @sa InternalShellConvertFileListType
+**/
+EFI_STATUS
+EFIAPI
+ShellOpenFileMetaArg (
+ IN CHAR16 *Arg,
+ IN UINT64 OpenMode,
+ IN OUT EFI_SHELL_FILE_INFO **ListHead
+ );
+
+/**
+ Free the linked list returned from ShellOpenFileMetaArg.
+
+ @param[in, out] ListHead The pointer to free.
+
+ @retval EFI_SUCCESS The operation was sucessful.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.
+**/
+EFI_STATUS
+EFIAPI
+ShellCloseFileMetaArg (
+ IN OUT EFI_SHELL_FILE_INFO **ListHead
+ );
+
+/**
+ Find a file by searching the CWD and then the path.
+
+ If FileName is NULL, then ASSERT.
+
+ If the return value is not NULL then the memory must be caller freed.
+
+ @param[in] FileName Filename string.
+
+ @retval NULL The file was not found.
+ @retval !NULL The path to the file.
+**/
+CHAR16 *
+EFIAPI
+ShellFindFilePath (
+ IN CONST CHAR16 *FileName
+ );
+
+/**
+ Find a file by searching the CWD and then the path with a variable set of file
+ extensions. If the file is not found it will append each extension in the list
+ in the order provided and return the first one that is successful.
+
+ If FileName is NULL, then ASSERT.
+ If FileExtension is NULL, then the behavior is identical to ShellFindFilePath.
+
+ If the return value is not NULL then the memory must be caller freed.
+
+ @param[in] FileName The filename string.
+ @param[in] FileExtension Semicolon delimited list of possible extensions.
+
+ @retval NULL The file was not found.
+ @retval !NULL The path to the file.
+**/
+CHAR16 *
+EFIAPI
+ShellFindFilePathEx (
+ IN CONST CHAR16 *FileName,
+ IN CONST CHAR16 *FileExtension
+ );
+
+typedef enum {
+ TypeFlag = 0, ///< A flag that is present or not present only (IE "-a").
+ TypeValue, ///< A flag that has some data following it with a space (IE "-a 1").
+ TypePosition, ///< Some data that did not follow a parameter (IE "filename.txt").
+ TypeStart, ///< A flag that has variable value appended to the end (IE "-ad", "-afd", "-adf", etc...).
+ TypeDoubleValue, ///< A flag that has 2 space seperated value data following it (IE "-a 1 2").
+ TypeMaxValue, ///< A flag followed by all the command line data before the next flag.
+ TypeTimeValue, ///< A flag that has a time value following it (IE "-a -5:00").
+ TypeMax,
+} SHELL_PARAM_TYPE;
+
+typedef struct {
+ CHAR16 *Name;
+ SHELL_PARAM_TYPE Type;
+} SHELL_PARAM_ITEM;
+
+
+/// Helper structure for no parameters (besides -? and -b)
+extern SHELL_PARAM_ITEM EmptyParamList[];
+
+/// Helper structure for -sfo only (besides -? and -b)
+extern SHELL_PARAM_ITEM SfoParamList[];
+
+/**
+ Checks the command line arguments passed against the list of valid ones.
+ Optionally removes NULL values first.
+
+ If no initialization is required, then return RETURN_SUCCESS.
+
+ @param[in] CheckList The pointer to list of parameters to check.
+ @param[out] CheckPackage The package of checked values.
+ @param[out] ProblemParam Optional pointer to pointer to unicode string for
+ the paramater that caused failure.
+ @param[in] AutoPageBreak Will automatically set PageBreakEnabled.
+ @param[in] AlwaysAllowNumbers Will never fail for number based flags.
+
+ @retval EFI_SUCCESS The operation completed sucessfully.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.
+ @retval EFI_VOLUME_CORRUPTED The command line was corrupt.
+ @retval EFI_DEVICE_ERROR The commands contained 2 opposing arguments. One
+ of the command line arguments was returned in
+ ProblemParam if provided.
+ @retval EFI_NOT_FOUND A argument required a value that was missing.
+ The invalid command line argument was returned in
+ ProblemParam if provided.
+**/
+EFI_STATUS
+EFIAPI
+ShellCommandLineParseEx (
+ IN CONST SHELL_PARAM_ITEM *CheckList,
+ OUT LIST_ENTRY **CheckPackage,
+ OUT CHAR16 **ProblemParam OPTIONAL,
+ IN BOOLEAN AutoPageBreak,
+ IN BOOLEAN AlwaysAllowNumbers
+ );
+
+/// Make it easy to upgrade from older versions of the shell library.
+#define ShellCommandLineParse(CheckList,CheckPackage,ProblemParam,AutoPageBreak) ShellCommandLineParseEx(CheckList,CheckPackage,ProblemParam,AutoPageBreak,FALSE)
+
+/**
+ Frees shell variable list that was returned from ShellCommandLineParse.
+
+ This function will free all the memory that was used for the CheckPackage
+ list of postprocessed shell arguments.
+
+ If CheckPackage is NULL, then return.
+
+ @param[in] CheckPackage The list to de-allocate.
+ **/
+VOID
+EFIAPI
+ShellCommandLineFreeVarList (
+ IN LIST_ENTRY *CheckPackage
+ );
+
+/**
+ Checks for presence of a flag parameter.
+
+ Flag arguments are in the form of "-<Key>" or "/<Key>", but do not have a value following the key.
+
+ If CheckPackage is NULL then return FALSE.
+ If KeyString is NULL then ASSERT().
+
+ @param[in] CheckPackage The package of parsed command line arguments.
+ @param[in] KeyString The Key of the command line argument to check for.
+
+ @retval TRUE The flag is on the command line.
+ @retval FALSE The flag is not on the command line.
+**/
+BOOLEAN
+EFIAPI
+ShellCommandLineGetFlag (
+ IN CONST LIST_ENTRY * CONST CheckPackage,
+ IN CONST CHAR16 * CONST KeyString
+ );
+
+/**
+ Returns value from command line argument.
+
+ Value parameters are in the form of "-<Key> value" or "/<Key> value".
+
+ If CheckPackage is NULL, then return NULL.
+
+ @param[in] CheckPackage The package of parsed command line arguments.
+ @param[in] KeyString The Key of the command line argument to check for.
+
+ @retval NULL The flag is not on the command line.
+ @retval !=NULL The pointer to unicode string of the value.
+**/
+CONST CHAR16*
+EFIAPI
+ShellCommandLineGetValue (
+ IN CONST LIST_ENTRY *CheckPackage,
+ IN CHAR16 *KeyString
+ );
+
+/**
+ Returns raw value from command line argument.
+
+ Raw value parameters are in the form of "value" in a specific position in the list.
+
+ If CheckPackage is NULL, then return NULL.
+
+ @param[in] CheckPackage The package of parsed command line arguments.
+ @param[in] Position The position of the value.
+
+ @retval NULL The flag is not on the command line.
+ @retval !=NULL The pointer to unicode string of the value.
+**/
+CONST CHAR16*
+EFIAPI
+ShellCommandLineGetRawValue (
+ IN CONST LIST_ENTRY * CONST CheckPackage,
+ IN UINTN Position
+ );
+
+/**
+ Returns the number of command line value parameters that were parsed.
+
+ This will not include flags.
+
+ @param[in] CheckPackage The package of parsed command line arguments.
+
+ @retval (UINTN)-1 No parsing has occurred.
+ @retval other The number of value parameters found.
+**/
+UINTN
+EFIAPI
+ShellCommandLineGetCount(
+ IN CONST LIST_ENTRY *CheckPackage
+ );
+
+/**
+ Determines if a parameter is duplicated.
+
+ If Param is not NULL, then it will point to a callee-allocated string buffer
+ with the parameter value, if a duplicate is found.
+
+ If CheckPackage is NULL, then ASSERT.
+
+ @param[in] CheckPackage The package of parsed command line arguments.
+ @param[out] Param Upon finding one, a pointer to the duplicated parameter.
+
+ @retval EFI_SUCCESS No parameters were duplicated.
+ @retval EFI_DEVICE_ERROR A duplicate was found.
+ **/
+EFI_STATUS
+EFIAPI
+ShellCommandLineCheckDuplicate (
+ IN CONST LIST_ENTRY *CheckPackage,
+ OUT CHAR16 **Param
+ );
+
+/**
+ This function causes the shell library to initialize itself. If the shell library
+ is already initialized it will de-initialize all the current protocol pointers and
+ re-populate them again.
+
+ When the library is used with PcdShellLibAutoInitialize set to true this function
+ will return EFI_SUCCESS and perform no actions.
+
+ This function is intended for internal access for shell commands only.
+
+ @retval EFI_SUCCESS The initialization was complete sucessfully.
+
+**/
+EFI_STATUS
+EFIAPI
+ShellInitialize (
+ VOID
+ );
+
+/**
+ Print at a specific location on the screen.
+
+ This function will move the cursor to a given screen location and print the specified string.
+
+ If -1 is specified for either the Row or Col the current screen location for BOTH
+ will be used.
+
+ If either Row or Col is out of range for the current console, then ASSERT.
+ If Format is NULL, then ASSERT.
+
+ In addition to the standard %-based flags as supported by UefiLib Print() this supports
+ the following additional flags:
+ %N - Set output attribute to normal
+ %H - Set output attribute to highlight
+ %E - Set output attribute to error
+ %B - Set output attribute to blue color
+ %V - Set output attribute to green color
+
+ Note: The background color is controlled by the shell command cls.
+
+ @param[in] Col The column to print at.
+ @param[in] Row The row to print at.
+ @param[in] Format The format string.
+ @param[in] ... The variable argument list.
+
+ @return EFI_SUCCESS The printing was successful.
+ @return EFI_DEVICE_ERROR The console device reported an error.
+**/
+EFI_STATUS
+EFIAPI
+ShellPrintEx(
+ IN INT32 Col OPTIONAL,
+ IN INT32 Row OPTIONAL,
+ IN CONST CHAR16 *Format,
+ ...
+ );
+
+/**
+ Print at a specific location on the screen.
+
+ This function will move the cursor to a given screen location and print the specified string.
+
+ If -1 is specified for either the Row or Col the current screen location for BOTH
+ will be used.
+
+ If either Row or Col is out of range for the current console, then ASSERT.
+ If Format is NULL, then ASSERT.
+
+ In addition to the standard %-based flags as supported by UefiLib Print() this supports
+ the following additional flags:
+ %N - Set output attribute to normal.
+ %H - Set output attribute to highlight.
+ %E - Set output attribute to error.
+ %B - Set output attribute to blue color.
+ %V - Set output attribute to green color.
+
+ Note: The background color is controlled by the shell command cls.
+
+ @param[in] Col The column to print at.
+ @param[in] Row The row to print at.
+ @param[in] Language The language of the string to retrieve. If this parameter
+ is NULL, then the current platform language is used.
+ @param[in] HiiFormatStringId The format string Id for getting from Hii.
+ @param[in] HiiFormatHandle The format string Handle for getting from Hii.
+ @param[in] ... The variable argument list.
+
+ @return EFI_SUCCESS The printing was successful.
+ @return EFI_DEVICE_ERROR The console device reported an error.
+**/
+EFI_STATUS
+EFIAPI
+ShellPrintHiiEx(
+ IN INT32 Col OPTIONAL,
+ IN INT32 Row OPTIONAL,
+ IN CONST CHAR8 *Language OPTIONAL,
+ IN CONST EFI_STRING_ID HiiFormatStringId,
+ IN CONST EFI_HANDLE HiiFormatHandle,
+ ...
+ );
+
+/**
+ Function to determine if a given filename represents a directory.
+
+ If DirName is NULL, then ASSERT.
+
+ @param[in] DirName Path to directory to test.
+
+ @retval EFI_SUCCESS The Path represents a directory.
+ @retval EFI_NOT_FOUND The Path does not represent a directory.
+ @retval other The path failed to open.
+**/
+EFI_STATUS
+EFIAPI
+ShellIsDirectory(
+ IN CONST CHAR16 *DirName
+ );
+
+/**
+ Function to determine if a given filename represents a file.
+
+ This will search the CWD only.
+
+ If Name is NULL, then ASSERT.
+
+ @param[in] Name Path to file to test.
+
+ @retval EFI_SUCCESS The Path represents a file.
+ @retval EFI_NOT_FOUND The Path does not represent a file.
+ @retval other The path failed to open.
+**/
+EFI_STATUS
+EFIAPI
+ShellIsFile(
+ IN CONST CHAR16 *Name
+ );
+
+/**
+ Function to determine if a given filename represents a file.
+
+ This will search the CWD and then the Path.
+
+ If Name is NULL, then ASSERT.
+
+ @param[in] Name Path to file to test.
+
+ @retval EFI_SUCCESS The Path represents a file.
+ @retval EFI_NOT_FOUND The Path does not represent a file.
+ @retval other The path failed to open.
+**/
+EFI_STATUS
+EFIAPI
+ShellIsFileInPath(
+ IN CONST CHAR16 *Name
+ );
+
+/**
+ Function to determine whether a string is decimal or hex representation of a number
+ and return the number converted from the string.
+
+ Note: this function cannot be used when (UINTN)(-1), (0xFFFFFFFF) may be a valid
+ result. Use ShellConvertStringToUint64 instead.
+
+ @param[in] String String representation of a number.
+
+ @return The unsigned integer result of the conversion.
+ @retval (UINTN)(-1) An error occured.
+**/
+UINTN
+EFIAPI
+ShellStrToUintn(
+ IN CONST CHAR16 *String
+ );
+
+/**
+ Function return the number converted from a hex representation of a number.
+
+ Note: this function cannot be used when (UINTN)(-1), (0xFFFFFFFF) may be a valid
+ result. Use ShellConvertStringToUint64 instead.
+
+ @param[in] String String representation of a number.
+
+ @return The unsigned integer result of the conversion.
+ @retval (UINTN)(-1) An error occured.
+**/
+UINTN
+EFIAPI
+ShellHexStrToUintn(
+ IN CONST CHAR16 *String
+ );
+
+/**
+ Safely append with automatic string resizing given length of Destination and
+ desired length of copy from Source.
+
+ Append the first D characters of Source to the end of Destination, where D is
+ the lesser of Count and the StrLen() of Source. If appending those D characters
+ will fit within Destination (whose Size is given as CurrentSize) and
+ still leave room for a NULL terminator, then those characters are appended,
+ starting at the original terminating NULL of Destination, and a new terminating
+ NULL is appended.
+
+ If appending D characters onto Destination will result in a overflow of the size
+ given in CurrentSize the string will be grown such that the copy can be performed
+ and CurrentSize will be updated to the new size.
+
+ If Source is NULL, there is nothing to append, so return the current buffer in
+ Destination.
+
+ If Destination is NULL, then ASSERT().
+ If Destination's current length (including NULL terminator) is already more than
+ CurrentSize, then ASSERT().
+
+ @param[in, out] Destination The String to append onto.
+ @param[in, out] CurrentSize On call, the number of bytes in Destination. On
+ return, possibly the new size (still in bytes). If NULL,
+ then allocate whatever is needed.
+ @param[in] Source The String to append from.
+ @param[in] Count The maximum number of characters to append. If 0, then
+ all are appended.
+
+ @return The Destination after appending the Source.
+**/
+CHAR16*
+EFIAPI
+StrnCatGrow (
+ IN OUT CHAR16 **Destination,
+ IN OUT UINTN *CurrentSize,
+ IN CONST CHAR16 *Source,
+ IN UINTN Count
+ );
+
+/**
+ This is a find and replace function. Upon successful return the NewString is a copy of
+ SourceString with each instance of FindTarget replaced with ReplaceWith.
+
+ If SourceString and NewString overlap the behavior is undefined.
+
+ If the string would grow bigger than NewSize it will halt and return error.
+
+ @param[in] SourceString The string with source buffer.
+ @param[in, out] NewString The string with resultant buffer.
+ @param[in] NewSize The size in bytes of NewString.
+ @param[in] FindTarget The string to look for.
+ @param[in] ReplaceWith The string to replace FindTarget with.
+ @param[in] SkipPreCarrot If TRUE will skip a FindTarget that has a '^'
+ immediately before it.
+ @param[in] ParameterReplacing If TRUE will add "" around items with spaces.
+
+ @retval EFI_INVALID_PARAMETER SourceString was NULL.
+ @retval EFI_INVALID_PARAMETER NewString was NULL.
+ @retval EFI_INVALID_PARAMETER FindTarget was NULL.
+ @retval EFI_INVALID_PARAMETER ReplaceWith was NULL.
+ @retval EFI_INVALID_PARAMETER FindTarget had length < 1.
+ @retval EFI_INVALID_PARAMETER SourceString had length < 1.
+ @retval EFI_BUFFER_TOO_SMALL NewSize was less than the minimum size to hold
+ the new string (truncation occurred).
+ @retval EFI_SUCCESS The string was successfully copied with replacement.
+**/
+EFI_STATUS
+EFIAPI
+ShellCopySearchAndReplace(
+ IN CHAR16 CONST *SourceString,
+ IN OUT CHAR16 *NewString,
+ IN UINTN NewSize,
+ IN CONST CHAR16 *FindTarget,
+ IN CONST CHAR16 *ReplaceWith,
+ IN CONST BOOLEAN SkipPreCarrot,
+ IN CONST BOOLEAN ParameterReplacing
+ );
+
+/**
+ Check if a Unicode character is a hexadecimal character.
+
+ This internal function checks if a Unicode character is a
+ numeric character. The valid hexadecimal characters are
+ L'0' to L'9', L'a' to L'f', or L'A' to L'F'.
+
+
+ @param Char The character to check against.
+
+ @retval TRUE The Char is a hexadecmial character.
+ @retval FALSE The Char is not a hexadecmial character.
+
+**/
+BOOLEAN
+EFIAPI
+ShellIsHexaDecimalDigitCharacter (
+ IN CHAR16 Char
+ );
+
+/**
+ Check if a Unicode character is a decimal character.
+
+ This internal function checks if a Unicode character is a
+ decimal character. The valid characters are
+ L'0' to L'9'.
+
+
+ @param Char The character to check against.
+
+ @retval TRUE The Char is a hexadecmial character.
+ @retval FALSE The Char is not a hexadecmial character.
+
+**/
+BOOLEAN
+EFIAPI
+ShellIsDecimalDigitCharacter (
+ IN CHAR16 Char
+ );
+
+///
+/// What type of answer is requested.
+///
+typedef enum {
+ ShellPromptResponseTypeYesNo,
+ ShellPromptResponseTypeYesNoCancel,
+ ShellPromptResponseTypeFreeform,
+ ShellPromptResponseTypeQuitContinue,
+ ShellPromptResponseTypeYesNoAllCancel,
+ ShellPromptResponseTypeEnterContinue,
+ ShellPromptResponseTypeAnyKeyContinue,
+ ShellPromptResponseTypeMax
+} SHELL_PROMPT_REQUEST_TYPE;
+
+///
+/// What answer was given.
+///
+typedef enum {
+ ShellPromptResponseYes,
+ ShellPromptResponseNo,
+ ShellPromptResponseCancel,
+ ShellPromptResponseQuit,
+ ShellPromptResponseContinue,
+ ShellPromptResponseAll,
+ ShellPromptResponseMax
+} SHELL_PROMPT_RESPONSE;
+
+/**
+ Prompt the user and return the resultant answer to the requestor.
+
+ This function will display the requested question on the shell prompt and then
+ wait for an appropriate answer to be input from the console.
+
+ If the SHELL_PROMPT_REQUEST_TYPE is SHELL_PROMPT_REQUEST_TYPE_YESNO, ShellPromptResponseTypeQuitContinue
+ or SHELL_PROMPT_REQUEST_TYPE_YESNOCANCEL then *Response is of type SHELL_PROMPT_RESPONSE.
+
+ If the SHELL_PROMPT_REQUEST_TYPE is ShellPromptResponseTypeFreeform then *Response is of type
+ CHAR16*.
+
+ In either case *Response must be callee freed if Response was not NULL;
+
+ @param Type What type of question is asked. This is used to filter the input
+ to prevent invalid answers to question.
+ @param Prompt The pointer to a string prompt used to request input.
+ @param Response The pointer to Response, which will be populated upon return.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_UNSUPPORTED The operation is not supported as requested.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.
+ @return other The operation failed.
+**/
+EFI_STATUS
+EFIAPI
+ShellPromptForResponse (
+ IN SHELL_PROMPT_REQUEST_TYPE Type,
+ IN CHAR16 *Prompt OPTIONAL,
+ IN OUT VOID **Response OPTIONAL
+ );
+
+/**
+ Prompt the user and return the resultant answer to the requestor.
+
+ This function is the same as ShellPromptForResponse, except that the prompt is
+ automatically pulled from HII.
+
+ @param[in] Type What type of question is asked. This is used to filter the input
+ to prevent invalid answers to question.
+ @param[in] HiiFormatStringId The format string Id for getting from Hii.
+ @param[in] HiiFormatHandle The format string Handle for getting from Hii.
+ @param[in, out] Response The pointer to Response, which will be populated upon return.
+
+ @retval EFI_SUCCESS The operation was sucessful.
+ @return other The operation failed.
+
+ @sa ShellPromptForResponse
+**/
+EFI_STATUS
+EFIAPI
+ShellPromptForResponseHii (
+ IN SHELL_PROMPT_REQUEST_TYPE Type,
+ IN CONST EFI_STRING_ID HiiFormatStringId,
+ IN CONST EFI_HANDLE HiiFormatHandle,
+ IN OUT VOID **Response
+ );
+
+/**
+ Function to determin if an entire string is a valid number.
+
+ If Hex it must be preceeded with a 0x, 0X, or has ForceHex set TRUE.
+
+ @param[in] String The string to evaluate.
+ @param[in] ForceHex TRUE - always assume hex.
+ @param[in] StopAtSpace TRUE to halt upon finding a space, FALSE to keep going.
+
+ @retval TRUE It is all numeric (dec/hex) characters.
+ @retval FALSE There is a non-numeric character.
+**/
+BOOLEAN
+EFIAPI
+ShellIsHexOrDecimalNumber (
+ IN CONST CHAR16 *String,
+ IN CONST BOOLEAN ForceHex,
+ IN CONST BOOLEAN StopAtSpace
+ );
+
+/**
+ Function to verify and convert a string to its numerical 64 bit representation.
+
+ If Hex it must be preceeded with a 0x, 0X, or has ForceHex set TRUE.
+
+ @param[in] String The string to evaluate.
+ @param[out] Value Upon a successful return the value of the conversion.
+ @param[in] ForceHex TRUE - always assume hex.
+ @param[in] StopAtSpace TRUE to halt upon finding a space, FALSE to
+ process the entire String.
+
+ @retval EFI_SUCCESS The conversion was successful.
+ @retval EFI_INVALID_PARAMETER String contained an invalid character.
+ @retval EFI_NOT_FOUND String was a number, but Value was NULL.
+**/
+EFI_STATUS
+EFIAPI
+ShellConvertStringToUint64(
+ IN CONST CHAR16 *String,
+ OUT UINT64 *Value,
+ IN CONST BOOLEAN ForceHex,
+ IN CONST BOOLEAN StopAtSpace
+ );
+
+/**
+ Function to determine if a given filename exists.
+
+ @param[in] Name Path to test.
+
+ @retval EFI_SUCCESS The Path represents a file.
+ @retval EFI_NOT_FOUND The Path does not represent a file.
+ @retval other The path failed to open.
+**/
+EFI_STATUS
+EFIAPI
+ShellFileExists(
+ IN CONST CHAR16 *Name
+ );
+
+/**
+ Function to read a single line from a SHELL_FILE_HANDLE. The \n is not included in the returned
+ buffer. The returned buffer must be callee freed.
+
+ If the position upon start is 0, then the Ascii Boolean will be set. This should be
+ maintained and not changed for all operations with the same file.
+
+ @param[in] Handle SHELL_FILE_HANDLE to read from.
+ @param[in, out] Ascii Boolean value for indicating whether the file is
+ Ascii (TRUE) or UCS2 (FALSE).
+
+ @return The line of text from the file.
+
+ @sa ShellFileHandleReadLine
+**/
+CHAR16*
+EFIAPI
+ShellFileHandleReturnLine(
+ IN SHELL_FILE_HANDLE Handle,
+ IN OUT BOOLEAN *Ascii
+ );
+
+/**
+ Function to read a single line (up to but not including the \n) from a SHELL_FILE_HANDLE.
+
+ If the position upon start is 0, then the Ascii Boolean will be set. This should be
+ maintained and not changed for all operations with the same file.
+
+ @param[in] Handle SHELL_FILE_HANDLE to read from.
+ @param[in, out] Buffer The pointer to buffer to read into.
+ @param[in, out] Size The pointer to number of bytes in Buffer.
+ @param[in] Truncate If the buffer is large enough, this has no effect.
+ If the buffer is is too small and Truncate is TRUE,
+ the line will be truncated.
+ If the buffer is is too small and Truncate is FALSE,
+ then no read will occur.
+
+ @param[in, out] Ascii Boolean value for indicating whether the file is
+ Ascii (TRUE) or UCS2 (FALSE).
+
+ @retval EFI_SUCCESS The operation was successful. The line is stored in
+ Buffer.
+ @retval EFI_END_OF_FILE There are no more lines in the file.
+ @retval EFI_INVALID_PARAMETER Handle was NULL.
+ @retval EFI_INVALID_PARAMETER Size was NULL.
+ @retval EFI_BUFFER_TOO_SMALL Size was not large enough to store the line.
+ Size was updated to the minimum space required.
+**/
+EFI_STATUS
+EFIAPI
+ShellFileHandleReadLine(
+ IN SHELL_FILE_HANDLE Handle,
+ IN OUT CHAR16 *Buffer,
+ IN OUT UINTN *Size,
+ IN BOOLEAN Truncate,
+ IN OUT BOOLEAN *Ascii
+ );
+
+/**
+ Function to delete a file by name
+
+ @param[in] FileName Pointer to file name to delete.
+
+ @retval EFI_SUCCESS the file was deleted sucessfully
+ @retval EFI_WARN_DELETE_FAILURE the handle was closed, but the file was not
+ deleted
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
+ @retval EFI_NOT_FOUND The specified file could not be found on the
+ device or the file system could not be found
+ on the device.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_MEDIA_CHANGED The device has a different medium in it or the
+ medium is no longer supported.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The file or medium is write protected.
+ @retval EFI_ACCESS_DENIED The file was opened read only.
+ @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the
+ file.
+ @retval other The file failed to open
+**/
+EFI_STATUS
+EFIAPI
+ShellDeleteFileByName(
+ IN CONST CHAR16 *FileName
+ );
+
+/**
+ Function to print help file / man page content in the spec from the UEFI Shell protocol GetHelpText function.
+
+ @param[in] CommandToGetHelpOn Pointer to a string containing the command name of help file to be printed.
+ @param[in] SectionToGetHelpOn Pointer to the section specifier(s).
+ @param[in] PrintCommandText If TRUE, prints the command followed by the help content, otherwise prints
+ the help content only.
+ @retval EFI_DEVICE_ERROR The help data format was incorrect.
+ @retval EFI_NOT_FOUND The help data could not be found.
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+ShellPrintHelp (
+ IN CONST CHAR16 *CommandToGetHelpOn,
+ IN CONST CHAR16 *SectionToGetHelpOn,
+ IN BOOLEAN PrintCommandText
+ );
+
+#endif // __SHELL_LIB__
diff --git a/Core/ShellPkg/Include/Protocol/EfiShell.h b/Core/ShellPkg/Include/Protocol/EfiShell.h
new file mode 100644
index 0000000000..5c7f4f6357
--- /dev/null
+++ b/Core/ShellPkg/Include/Protocol/EfiShell.h
@@ -0,0 +1,1138 @@
+/** @file
+ EFI Shell protocol as defined in the UEFI Shell 2.0 specification including errata.
+
+ (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __EFI_SHELL_PROTOCOL__
+#define __EFI_SHELL_PROTOCOL__
+
+#include <ShellBase.h>
+#include <Guid/FileInfo.h>
+
+#define EFI_SHELL_PROTOCOL_GUID \
+ { \
+ 0x6302d008, 0x7f9b, 0x4f30, { 0x87, 0xac, 0x60, 0xc9, 0xfe, 0xf5, 0xda, 0x4e } \
+ }
+
+// replaced EFI_LIST_ENTRY with LIST_ENTRY for simplicity.
+// they are identical outside of the name.
+typedef struct {
+ LIST_ENTRY Link; ///< Linked list members.
+ EFI_STATUS Status; ///< Status of opening the file. Valid only if Handle != NULL.
+ CONST CHAR16 *FullName; ///< Fully qualified filename.
+ CONST CHAR16 *FileName; ///< name of this file.
+ SHELL_FILE_HANDLE Handle; ///< Handle for interacting with the opened file or NULL if closed.
+ EFI_FILE_INFO *Info; ///< Pointer to the FileInfo struct for this file or NULL.
+} EFI_SHELL_FILE_INFO;
+
+/**
+ Returns whether any script files are currently being processed.
+
+ @retval TRUE There is at least one script file active.
+ @retval FALSE No script files are active now.
+
+**/
+typedef
+BOOLEAN
+(EFIAPI *EFI_SHELL_BATCH_IS_ACTIVE) (
+ VOID
+ );
+
+/**
+ Closes the file handle.
+
+ This function closes a specified file handle. All 'dirty' cached file data is
+ flushed to the device, and the file is closed. In all cases, the handle is
+ closed.
+
+ @param[in] FileHandle The file handle to be closed.
+
+ @retval EFI_SUCCESS The file closed sucessfully.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_CLOSE_FILE)(
+ IN SHELL_FILE_HANDLE FileHandle
+ );
+
+/**
+ Creates a file or directory by name.
+
+ This function creates an empty new file or directory with the specified attributes and
+ returns the new file's handle. If the file already exists and is read-only, then
+ EFI_INVALID_PARAMETER will be returned.
+
+ If the file already existed, it is truncated and its attributes updated. If the file is
+ created successfully, the FileHandle is the file's handle, else, the FileHandle is NULL.
+
+ If the file name begins with >v, then the file handle which is returned refers to the
+ shell environment variable with the specified name. If the shell environment variable
+ already exists and is non-volatile then EFI_INVALID_PARAMETER is returned.
+
+ @param[in] FileName Pointer to NULL-terminated file path.
+ @param[in] FileAttribs The new file's attrbiutes. The different attributes are
+ described in EFI_FILE_PROTOCOL.Open().
+ @param[out] FileHandle On return, points to the created file handle or directory's handle.
+
+ @retval EFI_SUCCESS The file was opened. FileHandle points to the new file's handle.
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
+ @retval EFI_UNSUPPORTED The file path could not be opened.
+ @retval EFI_NOT_FOUND The specified file could not be found on the device, or could not
+ file the file system on the device.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no
+ longer supported.
+ @retval EFI_DEVICE_ERROR The device reported an error or can't get the file path according
+ the DirName.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a file for write
+ when the media is write-protected.
+ @retval EFI_ACCESS_DENIED The service denied access to the file.
+ @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file.
+ @retval EFI_VOLUME_FULL The volume is full.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_CREATE_FILE)(
+ IN CONST CHAR16 *FileName,
+ IN UINT64 FileAttribs,
+ OUT SHELL_FILE_HANDLE *FileHandle
+ );
+
+/**
+ Deletes the file specified by the file handle.
+
+ This function closes and deletes a file. In all cases, the file handle is closed. If the file
+ cannot be deleted, the warning code EFI_WARN_DELETE_FAILURE is returned, but the
+ handle is still closed.
+
+ @param[in] FileHandle The file handle to delete.
+
+ @retval EFI_SUCCESS The file was closed and deleted and the handle was closed.
+ @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_DELETE_FILE)(
+ IN SHELL_FILE_HANDLE FileHandle
+ );
+
+/**
+ Deletes the file specified by the file name.
+
+ This function deletes a file.
+
+ @param[in] FileName Points to the NULL-terminated file name.
+
+ @retval EFI_SUCCESS The file was deleted.
+ @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_DELETE_FILE_BY_NAME)(
+ IN CONST CHAR16 *FileName
+ );
+
+/**
+ Disables the page break output mode.
+**/
+typedef
+VOID
+(EFIAPI *EFI_SHELL_DISABLE_PAGE_BREAK) (
+ VOID
+ );
+
+/**
+ Enables the page break output mode.
+**/
+typedef
+VOID
+(EFIAPI *EFI_SHELL_ENABLE_PAGE_BREAK) (
+ VOID
+ );
+
+/**
+ Execute the command line.
+
+ This function creates a nested instance of the shell and executes the specified
+ command (CommandLine) with the specified environment (Environment). Upon return,
+ the status code returned by the specified command is placed in StatusCode.
+
+ If Environment is NULL, then the current environment is used and all changes made
+ by the commands executed will be reflected in the current environment. If the
+ Environment is non-NULL, then the changes made will be discarded.
+
+ The CommandLine is executed from the current working directory on the current
+ device.
+
+ @param[in] ParentImageHandle A handle of the image that is executing the specified
+ command line.
+ @param[in] CommandLine Points to the NULL-terminated UCS-2 encoded string
+ containing the command line. If NULL then the command-
+ line will be empty.
+ @param[in] Environment Points to a NULL-terminated array of environment
+ variables with the format 'x=y', where x is the
+ environment variable name and y is the value. If this
+ is NULL, then the current shell environment is used.
+ @param[out] ErrorCode Points to the status code returned by the command.
+
+ @retval EFI_SUCCESS The command executed successfully. The status code
+ returned by the command is pointed to by StatusCode.
+ @retval EFI_INVALID_PARAMETER The parameters are invalid.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_UNSUPPORTED Nested shell invocations are not allowed.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_EXECUTE) (
+ IN EFI_HANDLE *ParentImageHandle,
+ IN CHAR16 *CommandLine OPTIONAL,
+ IN CHAR16 **Environment OPTIONAL,
+ OUT EFI_STATUS *StatusCode OPTIONAL
+ );
+
+/**
+ Find files that match a specified pattern.
+
+ This function searches for all files and directories that match the specified
+ FilePattern. The FilePattern can contain wild-card characters. The resulting file
+ information is placed in the file list FileList.
+
+ The files in the file list are not opened. The OpenMode field is set to 0 and the FileInfo
+ field is set to NULL.
+
+ @param[in] FilePattern Points to a NULL-terminated shell file path, including wildcards.
+ @param[out] FileList On return, points to the start of a file list containing the names
+ of all matching files or else points to NULL if no matching files
+ were found.
+
+ @retval EFI_SUCCESS Files found.
+ @retval EFI_NOT_FOUND No files found.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_FIND_FILES)(
+ IN CONST CHAR16 *FilePattern,
+ OUT EFI_SHELL_FILE_INFO **FileList
+ );
+
+/**
+ Find all files in a specified directory.
+
+ @param[in] FileDirHandle Handle of the directory to search.
+ @param[out] FileList On return, points to the list of files in the directory
+ or NULL if there are no files in the directory.
+
+ @retval EFI_SUCCESS File information was returned successfully.
+ @retval EFI_VOLUME_CORRUPTED The file system structures have been corrupted.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_NO_MEDIA The device media is not present.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_FIND_FILES_IN_DIR)(
+IN SHELL_FILE_HANDLE FileDirHandle,
+OUT EFI_SHELL_FILE_INFO **FileList
+);
+
+/**
+ Flushes data back to a device.
+
+ This function flushes all modified data associated with a file to a device.
+
+ @param[in] FileHandle The handle of the file to flush.
+
+ @retval EFI_SUCCESS The data was flushed.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The file or medium is write-protected.
+ @retval EFI_ACCESS_DENIED The file was opened read-only.
+ @retval EFI_VOLUME_FULL The volume is full.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_FLUSH_FILE)(
+ IN SHELL_FILE_HANDLE FileHandle
+ );
+
+/**
+ Frees the file list.
+
+ This function cleans up the file list and any related data structures. It has no
+ impact on the files themselves.
+
+ @param[in] FileList The file list to free. Type EFI_SHELL_FILE_INFO is
+ defined in OpenFileList().
+
+ @retval EFI_SUCCESS Free the file list successfully.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_FREE_FILE_LIST) (
+ IN EFI_SHELL_FILE_INFO **FileList
+ );
+
+/**
+ Returns the current directory on the specified device.
+
+ If FileSystemMapping is NULL, it returns the current working directory. If the
+ FileSystemMapping is not NULL, it returns the current directory associated with the
+ FileSystemMapping. In both cases, the returned name includes the file system
+ mapping (i.e. fs0:\current-dir).
+
+ Note that the current directory string should exclude the tailing backslash character.
+
+ @param[in] FileSystemMapping A pointer to the file system mapping. If NULL,
+ then the current working directory is returned.
+
+ @retval !=NULL The current directory.
+ @retval NULL Current directory does not exist.
+**/
+typedef
+CONST CHAR16 *
+(EFIAPI *EFI_SHELL_GET_CUR_DIR) (
+ IN CONST CHAR16 *FileSystemMapping OPTIONAL
+ );
+
+typedef UINT32 EFI_SHELL_DEVICE_NAME_FLAGS;
+#define EFI_DEVICE_NAME_USE_COMPONENT_NAME 0x00000001
+#define EFI_DEVICE_NAME_USE_DEVICE_PATH 0x00000002
+
+/**
+ Gets the name of the device specified by the device handle.
+
+ This function gets the user-readable name of the device specified by the device
+ handle. If no user-readable name could be generated, then *BestDeviceName will be
+ NULL and EFI_NOT_FOUND will be returned.
+
+ If EFI_DEVICE_NAME_USE_COMPONENT_NAME is set, then the function will return the
+ device's name using the EFI_COMPONENT_NAME2_PROTOCOL, if present on
+ DeviceHandle.
+
+ If EFI_DEVICE_NAME_USE_DEVICE_PATH is set, then the function will return the
+ device's name using the EFI_DEVICE_PATH_PROTOCOL, if present on DeviceHandle.
+ If both EFI_DEVICE_NAME_USE_COMPONENT_NAME and
+ EFI_DEVICE_NAME_USE_DEVICE_PATH are set, then
+ EFI_DEVICE_NAME_USE_COMPONENT_NAME will have higher priority.
+
+ @param[in] DeviceHandle The handle of the device.
+ @param[in] Flags Determines the possible sources of component names.
+ @param[in] Language A pointer to the language specified for the device
+ name, in the same format as described in the UEFI
+ specification, Appendix M.
+ @param[out] BestDeviceName On return, points to the callee-allocated NULL-
+ terminated name of the device. If no device name
+ could be found, points to NULL. The name must be
+ freed by the caller...
+
+ @retval EFI_SUCCESS Get the name successfully.
+ @retval EFI_NOT_FOUND Fail to get the device name.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_GET_DEVICE_NAME) (
+ IN EFI_HANDLE DeviceHandle,
+ IN EFI_SHELL_DEVICE_NAME_FLAGS Flags,
+ IN CHAR8 *Language,
+ OUT CHAR16 **BestDeviceName
+ );
+
+/**
+ Gets the device path from the mapping.
+
+ This function gets the device path associated with a mapping.
+
+ @param[in] Mapping A pointer to the mapping
+
+ @retval !=NULL Pointer to the device path that corresponds to the
+ device mapping. The returned pointer does not need
+ to be freed.
+ @retval NULL There is no device path associated with the
+ specified mapping.
+**/
+typedef
+CONST EFI_DEVICE_PATH_PROTOCOL *
+(EFIAPI *EFI_SHELL_GET_DEVICE_PATH_FROM_MAP) (
+ IN CONST CHAR16 *Mapping
+ );
+
+/**
+ Converts a file system style name to a device path.
+
+ This function converts a file system style name to a device path, by replacing any
+ mapping references to the associated device path.
+
+ @param[in] Path The pointer to the path.
+
+ @return The pointer of the file path. The file path is callee
+ allocated and should be freed by the caller.
+**/
+typedef
+EFI_DEVICE_PATH_PROTOCOL *
+(EFIAPI *EFI_SHELL_GET_DEVICE_PATH_FROM_FILE_PATH) (
+ IN CONST CHAR16 *Path
+ );
+
+/**
+ Gets either a single or list of environment variables.
+
+ If name is not NULL then this function returns the current value of the specified
+ environment variable.
+
+ If Name is NULL than a list of all environment variable names is returned. Each a
+ NULL terminated string with a double NULL terminating the list.
+
+ @param[in] Name A pointer to the environment variable name. If
+ Name is NULL, then the function will return all
+ of the defined shell environment variables. In
+ the case where multiple environment variables are
+ being returned, each variable will be terminated by
+ a NULL, and the list will be terminated by a double
+ NULL.
+
+ @return A pointer to the returned string.
+ The returned pointer does not need to be freed by the caller.
+
+ @retval NULL The environment variable doesn't exist or there are
+ no environment variables.
+**/
+typedef
+CONST CHAR16 *
+(EFIAPI *EFI_SHELL_GET_ENV) (
+ IN CONST CHAR16 *Name OPTIONAL
+ );
+
+/**
+ Gets the environment variable and Attributes, or list of environment variables. Can be
+ used instead of GetEnv().
+
+ This function returns the current value of the specified environment variable and
+ the Attributes. If no variable name was specified, then all of the known
+ variables will be returned.
+
+ @param[in] Name A pointer to the environment variable name. If Name is NULL,
+ then the function will return all of the defined shell
+ environment variables. In the case where multiple environment
+ variables are being returned, each variable will be terminated
+ by a NULL, and the list will be terminated by a double NULL.
+ @param[out] Attributes If not NULL, a pointer to the returned attributes bitmask for
+ the environment variable. In the case where Name is NULL, and
+ multiple environment variables are being returned, Attributes
+ is undefined.
+
+ @retval NULL The environment variable doesn't exist.
+ @return The environment variable's value. The returned pointer does not
+ need to be freed by the caller.
+**/
+typedef
+CONST CHAR16 *
+(EFIAPI *EFI_SHELL_GET_ENV_EX) (
+ IN CONST CHAR16 *Name,
+ OUT UINT32 *Attributes OPTIONAL
+ );
+
+/**
+ Gets the file information from an open file handle.
+
+ This function allocates a buffer to store the file's information. It's the caller's
+ responsibility to free the buffer.
+
+ @param[in] FileHandle A File Handle.
+
+ @retval NULL Cannot get the file info.
+ @return A pointer to a buffer with file information.
+**/
+typedef
+EFI_FILE_INFO *
+(EFIAPI *EFI_SHELL_GET_FILE_INFO)(
+ IN SHELL_FILE_HANDLE FileHandle
+ );
+
+/**
+ Converts a device path to a file system-style path.
+
+ This function converts a device path to a file system path by replacing part, or all, of
+ the device path with the file-system mapping. If there are more than one application
+ file system mappings, the one that most closely matches Path will be used.
+
+ @param[in] Path The pointer to the device path.
+
+ @return The pointer of the NULL-terminated file path. The path
+ is callee-allocated and should be freed by the caller.
+**/
+typedef
+CHAR16 *
+(EFIAPI *EFI_SHELL_GET_FILE_PATH_FROM_DEVICE_PATH) (
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *Path
+ );
+
+/**
+ Gets a file's current position.
+
+ This function returns the current file position for the file handle. For directories, the
+ current file position has no meaning outside of the file system driver and as such, the
+ operation is not supported.
+
+ @param[in] FileHandle The file handle on which to get the current position.
+ @param[out] Position Byte position from the start of the file.
+
+ @retval EFI_SUCCESS Data was accessed.
+ @retval EFI_UNSUPPORTED The request is not valid on open directories.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_GET_FILE_POSITION)(
+ IN SHELL_FILE_HANDLE FileHandle,
+ OUT UINT64 *Position
+ );
+
+/**
+ Gets the size of a file.
+
+ This function returns the size of the file specified by FileHandle.
+
+ @param[in] FileHandle The handle of the file.
+ @param[out] Size The size of this file.
+
+ @retval EFI_SUCCESS Get the file's size.
+ @retval EFI_DEVICE_ERROR Can't access the file.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_GET_FILE_SIZE)(
+ IN SHELL_FILE_HANDLE FileHandle,
+ OUT UINT64 *Size
+ );
+
+/**
+ Get the GUID value from a human readable name.
+
+ If GuidName is a known GUID name, then update Guid to have the correct value for
+ that GUID.
+
+ This function is only available when the major and minor versions in the
+ EfiShellProtocol are greater than or equal to 2 and 1, respectively.
+
+ @param[in] GuidName A pointer to the localized name for the GUID being queried.
+ @param[out] Guid A pointer to the GUID structure to be filled in.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_INVALID_PARAMETER Guid was NULL.
+ @retval EFI_INVALID_PARAMETER GuidName was NULL.
+ @retval EFI_NOT_FOUND GuidName is not a known GUID Name.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_GET_GUID_FROM_NAME)(
+ IN CONST CHAR16 *GuidName,
+ OUT EFI_GUID *Guid
+ );
+
+/**
+ Get the human readable name for a GUID from the value.
+
+ If Guid is assigned a name, then update *GuidName to point to the name. The callee
+ should not modify the value.
+
+ This function is only available when the major and minor versions in the
+ EfiShellProtocol are greater than or equal to 2 and 1, respectively.
+
+ @param[in] Guid A pointer to the GUID being queried.
+ @param[out] GuidName A pointer to a pointer the localized to name for the GUID being requested
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_INVALID_PARAMETER Guid was NULL.
+ @retval EFI_INVALID_PARAMETER GuidName was NULL.
+ @retval EFI_NOT_FOUND Guid is not assigned a name.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_GET_GUID_NAME)(
+ IN CONST EFI_GUID *Guid,
+ OUT CONST CHAR16 **GuidName
+ );
+
+/**
+ Return help information about a specific command.
+
+ This function returns the help information for the specified command. The help text
+ can be internal to the shell or can be from a UEFI Shell manual page.
+
+ If Sections is specified, then each section name listed will be compared in a casesensitive
+ manner, to the section names described in Appendix B. If the section exists,
+ it will be appended to the returned help text. If the section does not exist, no
+ information will be returned. If Sections is NULL, then all help text information
+ available will be returned.
+
+ @param[in] Command Points to the NULL-terminated UEFI Shell command name.
+ @param[in] Sections Points to the NULL-terminated comma-delimited
+ section names to return. If NULL, then all
+ sections will be returned.
+ @param[out] HelpText On return, points to a callee-allocated buffer
+ containing all specified help text.
+
+ @retval EFI_SUCCESS The help text was returned.
+ @retval EFI_OUT_OF_RESOURCES The necessary buffer could not be allocated to hold the
+ returned help text.
+ @retval EFI_INVALID_PARAMETER HelpText is NULL.
+ @retval EFI_NOT_FOUND There is no help text available for Command.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_GET_HELP_TEXT) (
+ IN CONST CHAR16 *Command,
+ IN CONST CHAR16 *Sections OPTIONAL,
+ OUT CHAR16 **HelpText
+ );
+
+/**
+ Gets the mapping(s) that most closely matches the device path.
+
+ This function gets the mapping which corresponds to the device path *DevicePath. If
+ there is no exact match, then the mapping which most closely matches *DevicePath
+ is returned, and *DevicePath is updated to point to the remaining portion of the
+ device path. If there is an exact match, the mapping is returned and *DevicePath
+ points to the end-of-device-path node.
+
+ If there are multiple map names they will be semi-colon seperated in the
+ NULL-terminated string.
+
+ @param[in, out] DevicePath On entry, points to a device path pointer. On
+ exit, updates the pointer to point to the
+ portion of the device path after the mapping.
+
+ @retval NULL No mapping was found.
+ @retval !=NULL Pointer to NULL-terminated mapping. The buffer
+ is callee allocated and should be freed by the caller.
+**/
+typedef
+CONST CHAR16 *
+(EFIAPI *EFI_SHELL_GET_MAP_FROM_DEVICE_PATH) (
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
+ );
+
+/**
+ Gets the enable status of the page break output mode.
+
+ User can use this function to determine current page break mode.
+
+ @retval TRUE The page break output mode is enabled.
+ @retval FALSE The page break output mode is disabled.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EFI_SHELL_GET_PAGE_BREAK) (
+ VOID
+ );
+
+/**
+ Judges whether the active shell is the root shell.
+
+ This function makes the user to know that whether the active Shell is the root shell.
+
+ @retval TRUE The active Shell is the root Shell.
+ @retval FALSE The active Shell is NOT the root Shell.
+**/
+typedef
+BOOLEAN
+(EFIAPI *EFI_SHELL_IS_ROOT_SHELL) (
+VOID
+);
+
+/**
+ Opens a file or a directory by file name.
+
+ This function opens the specified file in the specified OpenMode and returns a file
+ handle.
+ If the file name begins with '>v', then the file handle which is returned refers to the
+ shell environment variable with the specified name. If the shell environment variable
+ exists, is non-volatile and the OpenMode indicates EFI_FILE_MODE_WRITE, then
+ EFI_INVALID_PARAMETER is returned.
+
+ If the file name is '>i', then the file handle which is returned refers to the standard
+ input. If the OpenMode indicates EFI_FILE_MODE_WRITE, then EFI_INVALID_PARAMETER
+ is returned.
+
+ If the file name is '>o', then the file handle which is returned refers to the standard
+ output. If the OpenMode indicates EFI_FILE_MODE_READ, then EFI_INVALID_PARAMETER
+ is returned.
+
+ If the file name is '>e', then the file handle which is returned refers to the standard
+ error. If the OpenMode indicates EFI_FILE_MODE_READ, then EFI_INVALID_PARAMETER
+ is returned.
+
+ If the file name is 'NUL', then the file handle that is returned refers to the standard NUL
+ file. If the OpenMode indicates EFI_FILE_MODE_READ, then EFI_INVALID_PARAMETER is
+ returned.
+
+ If return EFI_SUCCESS, the FileHandle is the opened file's handle, else, the
+ FileHandle is NULL.
+
+ @param[in] FileName Points to the NULL-terminated UCS-2 encoded file name.
+ @param[out] FileHandle On return, points to the file handle.
+ @param[in] OpenMode File open mode. Either EFI_FILE_MODE_READ or
+ EFI_FILE_MODE_WRITE from section 12.4 of the UEFI
+ Specification.
+ @retval EFI_SUCCESS The file was opened. FileHandle has the opened file's handle.
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value. FileHandle is NULL.
+ @retval EFI_UNSUPPORTED Could not open the file path. FileHandle is NULL.
+ @retval EFI_NOT_FOUND The specified file could not be found on the device or the file
+ system could not be found on the device. FileHandle is NULL.
+ @retval EFI_NO_MEDIA The device has no medium. FileHandle is NULL.
+ @retval EFI_MEDIA_CHANGED The device has a different medium in it or the medium is no
+ longer supported. FileHandle is NULL.
+ @retval EFI_DEVICE_ERROR The device reported an error or can't get the file path according
+ the FileName. FileHandle is NULL.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted. FileHandle is NULL.
+ @retval EFI_WRITE_PROTECTED An attempt was made to create a file, or open a file for write
+ when the media is write-protected. FileHandle is NULL.
+ @retval EFI_ACCESS_DENIED The service denied access to the file. FileHandle is NULL.
+ @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the file. FileHandle
+ is NULL.
+ @retval EFI_VOLUME_FULL The volume is full. FileHandle is NULL.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_OPEN_FILE_BY_NAME) (
+ IN CONST CHAR16 *FileName,
+ OUT SHELL_FILE_HANDLE *FileHandle,
+ IN UINT64 OpenMode
+ );
+
+/**
+ Opens the files that match the path specified.
+
+ This function opens all of the files specified by Path. Wildcards are processed
+ according to the rules specified in UEFI Shell 2.0 spec section 3.7.1. Each
+ matching file has an EFI_SHELL_FILE_INFO structure created in a linked list.
+
+ @param[in] Path A pointer to the path string.
+ @param[in] OpenMode Specifies the mode used to open each file, EFI_FILE_MODE_READ or
+ EFI_FILE_MODE_WRITE.
+ @param[in, out] FileList Points to the start of a list of files opened.
+
+ @retval EFI_SUCCESS Create the file list successfully.
+ @return Can't create the file list.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_OPEN_FILE_LIST) (
+ IN CHAR16 *Path,
+ IN UINT64 OpenMode,
+ IN OUT EFI_SHELL_FILE_INFO **FileList
+ );
+
+/**
+ Opens the root directory of a device.
+
+ This function opens the root directory of a device and returns a file handle to it.
+
+ @param[in] DevicePath Points to the device path corresponding to the device where the
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL is installed.
+ @param[out] FileHandle On exit, points to the file handle corresponding to the root directory on the
+ device.
+
+ @retval EFI_SUCCESS Root opened successfully.
+ @retval EFI_NOT_FOUND EFI_SIMPLE_FILE_SYSTEM could not be found or the root directory
+ could not be opened.
+ @retval EFI_VOLUME_CORRUPTED The data structures in the volume were corrupted.
+ @retval EFI_DEVICE_ERROR The device had an error.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_OPEN_ROOT)(
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ OUT SHELL_FILE_HANDLE *FileHandle
+ );
+
+/**
+ Opens the root directory of a device on a handle.
+
+ This function opens the root directory of a device and returns a file handle to it.
+
+ @param[in] DeviceHandle The handle of the device that contains the volume.
+ @param[out] FileHandle On exit, points to the file handle corresponding to the root directory on the
+ device.
+
+ @retval EFI_SUCCESS Root opened successfully.
+ @retval EFI_NOT_FOUND EFI_SIMPLE_FILE_SYSTEM could not be found or the root directory
+ could not be opened.
+ @retval EFI_VOLUME_CORRUPTED The data structures in the volume were corrupted.
+ @retval EFI_DEVICE_ERROR The device had an error.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_OPEN_ROOT_BY_HANDLE)(
+ IN EFI_HANDLE DeviceHandle,
+ OUT SHELL_FILE_HANDLE *FileHandle
+ );
+
+/**
+ Reads data from the file.
+
+ If FileHandle is not a directory, the function reads the requested number of bytes
+ from the file at the file's current position and returns them in Buffer. If the read goes
+ beyond the end of the file, the read length is truncated to the end of the file. The file's
+ current position is increased by the number of bytes returned.
+ If FileHandle is a directory, then an error is returned.
+
+ @param[in] FileHandle The opened file handle for read.
+ @param[in] ReadSize On input, the size of Buffer, in bytes. On output, the amount of data read.
+ @param[in, out] Buffer The buffer in which data is read.
+
+ @retval EFI_SUCCESS Data was read.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_BUFFER_TO_SMALL Buffer is too small. ReadSize contains required size.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_READ_FILE) (
+ IN SHELL_FILE_HANDLE FileHandle,
+ IN OUT UINTN *ReadSize,
+ IN OUT VOID *Buffer
+ );
+
+/**
+ Register a GUID and a localized human readable name for it.
+
+ If Guid is not assigned a name, then assign GuidName to Guid. This list of GUID
+ names must be used whenever a shell command outputs GUID information.
+
+ This function is only available when the major and minor versions in the
+ EfiShellProtocol are greater than or equal to 2 and 1, respectively.
+
+ @param[in] Guid A pointer to the GUID being registered.
+ @param[in] GuidName A pointer to the localized name for the GUID being registered.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_INVALID_PARAMETER Guid was NULL.
+ @retval EFI_INVALID_PARAMETER GuidName was NULL.
+ @retval EFI_ACCESS_DENIED Guid already is assigned a name.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_REGISTER_GUID_NAME)(
+ IN CONST EFI_GUID *Guid,
+ IN CONST CHAR16 *GuidName
+ );
+
+/**
+ Deletes the duplicate file names files in the given file list.
+
+ @param[in] FileList A pointer to the first entry in the file list.
+
+ @retval EFI_SUCCESS Always success.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_REMOVE_DUP_IN_FILE_LIST) (
+ IN EFI_SHELL_FILE_INFO **FileList
+ );
+
+/**
+ Changes a shell command alias.
+
+ This function creates an alias for a shell command.
+
+ @param[in] Command Points to the NULL-terminated shell command or existing alias.
+ @param[in] Alias Points to the NULL-terminated alias for the shell command. If this is NULL, and
+ Command refers to an alias, that alias will be deleted.
+ @param[in] Replace If TRUE and the alias already exists, then the existing alias will be replaced. If
+ FALSE and the alias already exists, then the existing alias is unchanged and
+ EFI_ACCESS_DENIED is returned.
+ @param[in] Volatile if TRUE the Alias being set will be stored in a volatile fashion. if FALSE the
+ Alias being set will be stored in a non-volatile fashion.
+
+ @retval EFI_SUCCESS Alias created or deleted successfully.
+ @retval EFI_ACCESS_DENIED The alias is a built-in alias or already existed and Replace was set to
+ FALSE.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_SET_ALIAS)(
+ IN CONST CHAR16 *Command,
+ IN CONST CHAR16 *Alias,
+ IN BOOLEAN Replace,
+ IN BOOLEAN Volatile
+ );
+
+/**
+ This function returns the command associated with a alias or a list of all
+ alias'.
+
+ @param[in] Alias Points to the NULL-terminated shell alias.
+ If this parameter is NULL, then all
+ aliases will be returned in ReturnedData.
+ @param[out] Volatile Upon return of a single command if TRUE indicates
+ this is stored in a volatile fashion. FALSE otherwise.
+ @return If Alias is not NULL, it will return a pointer to
+ the NULL-terminated command for that alias.
+ If Alias is NULL, ReturnedData points to a ';'
+ delimited list of alias (e.g.
+ ReturnedData = "dir;del;copy;mfp") that is NULL-terminated.
+ @retval NULL An error ocurred.
+ @retval NULL Alias was not a valid Alias.
+**/
+typedef
+CONST CHAR16 *
+(EFIAPI *EFI_SHELL_GET_ALIAS)(
+ IN CONST CHAR16 *Alias,
+ OUT BOOLEAN *Volatile OPTIONAL
+ );
+
+/**
+ Changes the current directory on the specified device.
+
+ If the FileSystem is NULL, and the directory Dir does not contain a file system's
+ mapped name, this function changes the current working directory. If FileSystem is
+ NULL and the directory Dir contains a mapped name, then the current file system and
+ the current directory on that file system are changed.
+
+ If FileSystem is not NULL, and Dir is NULL, then this changes the current working file
+ system.
+
+ If FileSystem is not NULL and Dir is not NULL, then this function changes the current
+ directory on the specified file system.
+
+ If the current working directory or the current working file system is changed then the
+ %cwd% environment variable will be updated.
+
+ @param[in] FileSystem A pointer to the file system's mapped name. If NULL, then the current working
+ directory is changed.
+ @param[in] Dir Points to the NULL-terminated directory on the device specified by FileSystem.
+
+ @retval NULL Current directory does not exist.
+ @return The current directory.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_SET_CUR_DIR) (
+ IN CONST CHAR16 *FileSystem OPTIONAL,
+ IN CONST CHAR16 *Dir
+ );
+
+/**
+ Sets the environment variable.
+
+ This function changes the current value of the specified environment variable. If the
+ environment variable exists and the Value is an empty string, then the environment
+ variable is deleted. If the environment variable exists and the Value is not an empty
+ string, then the value of the environment variable is changed. If the environment
+ variable does not exist and the Value is an empty string, there is no action. If the
+ environment variable does not exist and the Value is a non-empty string, then the
+ environment variable is created and assigned the specified value.
+
+ For a description of volatile and non-volatile environment variables, see UEFI Shell
+ 2.0 specification section 3.6.1.
+
+ @param[in] Name Points to the NULL-terminated environment variable name.
+ @param[in] Value Points to the NULL-terminated environment variable value. If the value is an
+ empty string then the environment variable is deleted.
+ @param[in] Volatile Indicates whether the variable is non-volatile (FALSE) or volatile (TRUE).
+
+ @retval EFI_SUCCESS The environment variable was successfully updated.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_SET_ENV) (
+ IN CONST CHAR16 *Name,
+ IN CONST CHAR16 *Value,
+ IN BOOLEAN Volatile
+ );
+
+/**
+ Sets the file information to an opened file handle.
+
+ This function changes file information. All file information in the EFI_FILE_INFO
+ struct will be updated to the passed in data.
+
+ @param[in] FileHandle A file handle.
+ @param[in] FileInfo Points to new file information.
+
+ @retval EFI_SUCCESS The information was set.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The file or medium is write-protected.
+ @retval EFI_ACCESS_DENIED The file was opened read-only.
+ @retval EFI_VOLUME_FULL The volume is full.
+ @retval EFI_BAD_BUFFER_SIZE BufferSize is smaller than the size of EFI_FILE_INFO.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_SET_FILE_INFO)(
+ IN SHELL_FILE_HANDLE FileHandle,
+ IN CONST EFI_FILE_INFO *FileInfo
+ );
+
+/**
+ Sets a file's current position.
+
+ This function sets the current file position for the handle to the position supplied. With
+ the exception of seeking to position 0xFFFFFFFFFFFFFFFF, only absolute positioning is
+ supported, and seeking past the end of the file is allowed (a subsequent write would
+ grow the file). Seeking to position 0xFFFFFFFFFFFFFFFF causes the current position
+ to be set to the end of the file.
+
+ @param[in] FileHandle The file handle on which requested position will be set.
+ @param[in] Position Byte position from the start of the file.
+
+ @retval EFI_SUCCESS Data was written.
+ @retval EFI_UNSUPPORTED The seek request for nonzero is not valid on open directories.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_SET_FILE_POSITION)(
+ IN SHELL_FILE_HANDLE FileHandle,
+ IN UINT64 Position
+ );
+
+/**
+ This function creates a mapping for a device path.
+
+ @param[in] DevicePath Points to the device path. If this is NULL and Mapping points to a valid mapping,
+ then the mapping will be deleted.
+ @param[in] Mapping Points to the NULL-terminated mapping for the device path.
+
+ @retval EFI_SUCCESS Mapping created or deleted successfully.
+ @retval EFI_NO_MAPPING There is no handle that corresponds exactly to DevicePath. See the
+ boot service function LocateDevicePath().
+ @retval EFI_ACCESS_DENIED The mapping is a built-in alias.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_SET_MAP)(
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN CONST CHAR16 *Mapping
+ );
+
+/**
+ Writes data to the file.
+
+ This function writes the specified number of bytes to the file at the current file position.
+ The current file position is advanced the actual number of bytes written, which is
+ returned in BufferSize. Partial writes only occur when there has been a data error
+ during the write attempt (such as "volume space full"). The file automatically grows to
+ hold the data, if required.
+
+ Direct writes to opened directories are not supported.
+
+ @param[in] FileHandle The opened file handle for writing.
+ @param[in, out] BufferSize On input, size of Buffer.
+ @param[in] Buffer The buffer in which data to write.
+
+ @retval EFI_SUCCESS Data was written.
+ @retval EFI_UNSUPPORTED Writes to open directory are not supported.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The device is write-protected.
+ @retval EFI_ACCESS_DENIED The file was open for read only.
+ @retval EFI_VOLUME_FULL The volume is full.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *EFI_SHELL_WRITE_FILE)(
+ IN SHELL_FILE_HANDLE FileHandle,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ );
+
+//
+// EFI_SHELL_PROTOCOL has been updated since UEFI Shell Spec 2.0
+// Usage of this protocol will require version checking before attempting
+// to use any new members. There is no need to check the version for
+// members that existed in UEFI Shell Spec 2.0.
+//
+// Update below for any future UEFI Shell spec changes to this protocol.
+//
+// Check EFI_SHELL_PROTOCOL MajorVersion and MinorVersion:
+// if ((2 == gEfiShellProtocol->MajorVersion) &&
+// (0 == gEfiShellProtocol->MinorVersion)) {
+// //
+// // Cannot call:
+// // RegisterGuidName - UEFI Shell 2.1
+// // GetGuidName - UEFI Shell 2.1
+// // GetGuidFromName - UEFI Shell 2.1
+// // GetEnvEx - UEFI Shell 2.1
+// //
+// } else {
+// //
+// // Can use all members
+// //
+// }
+//
+typedef struct _EFI_SHELL_PROTOCOL {
+ EFI_SHELL_EXECUTE Execute;
+ EFI_SHELL_GET_ENV GetEnv;
+ EFI_SHELL_SET_ENV SetEnv;
+ EFI_SHELL_GET_ALIAS GetAlias;
+ EFI_SHELL_SET_ALIAS SetAlias;
+ EFI_SHELL_GET_HELP_TEXT GetHelpText;
+ EFI_SHELL_GET_DEVICE_PATH_FROM_MAP GetDevicePathFromMap;
+ EFI_SHELL_GET_MAP_FROM_DEVICE_PATH GetMapFromDevicePath;
+ EFI_SHELL_GET_DEVICE_PATH_FROM_FILE_PATH GetDevicePathFromFilePath;
+ EFI_SHELL_GET_FILE_PATH_FROM_DEVICE_PATH GetFilePathFromDevicePath;
+ EFI_SHELL_SET_MAP SetMap;
+ EFI_SHELL_GET_CUR_DIR GetCurDir;
+ EFI_SHELL_SET_CUR_DIR SetCurDir;
+ EFI_SHELL_OPEN_FILE_LIST OpenFileList;
+ EFI_SHELL_FREE_FILE_LIST FreeFileList;
+ EFI_SHELL_REMOVE_DUP_IN_FILE_LIST RemoveDupInFileList;
+ EFI_SHELL_BATCH_IS_ACTIVE BatchIsActive;
+ EFI_SHELL_IS_ROOT_SHELL IsRootShell;
+ EFI_SHELL_ENABLE_PAGE_BREAK EnablePageBreak;
+ EFI_SHELL_DISABLE_PAGE_BREAK DisablePageBreak;
+ EFI_SHELL_GET_PAGE_BREAK GetPageBreak;
+ EFI_SHELL_GET_DEVICE_NAME GetDeviceName;
+ EFI_SHELL_GET_FILE_INFO GetFileInfo;
+ EFI_SHELL_SET_FILE_INFO SetFileInfo;
+ EFI_SHELL_OPEN_FILE_BY_NAME OpenFileByName;
+ EFI_SHELL_CLOSE_FILE CloseFile;
+ EFI_SHELL_CREATE_FILE CreateFile;
+ EFI_SHELL_READ_FILE ReadFile;
+ EFI_SHELL_WRITE_FILE WriteFile;
+ EFI_SHELL_DELETE_FILE DeleteFile;
+ EFI_SHELL_DELETE_FILE_BY_NAME DeleteFileByName;
+ EFI_SHELL_GET_FILE_POSITION GetFilePosition;
+ EFI_SHELL_SET_FILE_POSITION SetFilePosition;
+ EFI_SHELL_FLUSH_FILE FlushFile;
+ EFI_SHELL_FIND_FILES FindFiles;
+ EFI_SHELL_FIND_FILES_IN_DIR FindFilesInDir;
+ EFI_SHELL_GET_FILE_SIZE GetFileSize;
+ EFI_SHELL_OPEN_ROOT OpenRoot;
+ EFI_SHELL_OPEN_ROOT_BY_HANDLE OpenRootByHandle;
+ EFI_EVENT ExecutionBreak;
+ UINT32 MajorVersion;
+ UINT32 MinorVersion;
+ // Added for Shell 2.1
+ EFI_SHELL_REGISTER_GUID_NAME RegisterGuidName;
+ EFI_SHELL_GET_GUID_NAME GetGuidName;
+ EFI_SHELL_GET_GUID_FROM_NAME GetGuidFromName;
+ EFI_SHELL_GET_ENV_EX GetEnvEx;
+} EFI_SHELL_PROTOCOL;
+
+extern EFI_GUID gEfiShellProtocolGuid;
+
+enum ShellVersion {
+ SHELL_MAJOR_VERSION = 2,
+ SHELL_MINOR_VERSION = 1
+};
+
+#endif
diff --git a/Core/ShellPkg/Include/Protocol/EfiShellDynamicCommand.h b/Core/ShellPkg/Include/Protocol/EfiShellDynamicCommand.h
new file mode 100644
index 0000000000..27e384c0a5
--- /dev/null
+++ b/Core/ShellPkg/Include/Protocol/EfiShellDynamicCommand.h
@@ -0,0 +1,86 @@
+/** @file
+ EFI Shell Dynamic Command registration protocol
+
+ (C) Copyright 2012-2014 Hewlett-Packard Development Company, L.P.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL__
+#define __EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL__
+
+#include <ShellBase.h>
+#include <Protocol/EfiShellParameters.h>
+#include <Protocol/EfiShell.h>
+
+
+// {3C7200E9-005F-4EA4-87DE-A3DFAC8A27C3}
+#define EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL_GUID \
+ { \
+ 0x3c7200e9, 0x005f, 0x4ea4, { 0x87, 0xde, 0xa3, 0xdf, 0xac, 0x8a, 0x27, 0xc3 } \
+ }
+
+
+//
+// Define for forward reference.
+//
+typedef struct _EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL;
+
+
+/**
+ This is the shell command handler function pointer callback type. This
+ function handles the command when it is invoked in the shell.
+
+ @param[in] This The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.
+ @param[in] SystemTable The pointer to the system table.
+ @param[in] ShellParameters The parameters associated with the command.
+ @param[in] Shell The instance of the shell protocol used in the context
+ of processing this command.
+
+ @return EFI_SUCCESS the operation was sucessful
+ @return other the operation failed.
+**/
+typedef
+SHELL_STATUS
+(EFIAPI * SHELL_COMMAND_HANDLER)(
+ IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ IN EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
+ IN EFI_SHELL_PROTOCOL *Shell
+ );
+
+/**
+ This is the command help handler function pointer callback type. This
+ function is responsible for displaying help information for the associated
+ command.
+
+ @param[in] This The instance of the EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL.
+ @param[in] Language The pointer to the language string to use.
+
+ @return string Pool allocated help string, must be freed by caller
+**/
+typedef
+CHAR16*
+(EFIAPI * SHELL_COMMAND_GETHELP)(
+ IN EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *This,
+ IN CONST CHAR8 *Language
+ );
+
+/// EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL protocol structure.
+struct _EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL {
+
+ CONST CHAR16 *CommandName;
+ SHELL_COMMAND_HANDLER Handler;
+ SHELL_COMMAND_GETHELP GetHelp;
+
+};
+
+extern EFI_GUID gEfiShellDynamicCommandProtocolGuid;
+
+#endif
diff --git a/Core/ShellPkg/Include/Protocol/EfiShellEnvironment2.h b/Core/ShellPkg/Include/Protocol/EfiShellEnvironment2.h
new file mode 100644
index 0000000000..1aa1b7e328
--- /dev/null
+++ b/Core/ShellPkg/Include/Protocol/EfiShellEnvironment2.h
@@ -0,0 +1,975 @@
+/** @file
+ Defines for EFI shell environment 2 ported to EDK II build environment. (no spec)
+
+ Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#ifndef _SHELL_ENVIRONMENT_2_PROTOCOL_H_
+#define _SHELL_ENVIRONMENT_2_PROTOCOL_H_
+
+#define DEFAULT_INIT_ROW 1
+#define DEFAULT_AUTO_LF FALSE
+
+/**
+ This function is a prototype for a function that dumps information on a protocol
+ to a given location. The location is dependant on the implementation. This is
+ used when programatically adding shell commands.
+
+ @param[in] Handle The handle the protocol is on.
+ @param[in] Interface The interface to the protocol.
+
+**/
+typedef
+VOID
+(EFIAPI *SHELLENV_DUMP_PROTOCOL_INFO) (
+ IN EFI_HANDLE Handle,
+ IN VOID *Interface
+ );
+
+/**
+ This function is a prototype for each command internal to the EFI shell
+ implementation. The specific command depends on the implementation. This is
+ used when programatically adding shell commands.
+
+ @param[in] ImageHandle The handle to the binary shell.
+ @param[in] SystemTable The pointer to the system table.
+
+ @retval EFI_SUCCESS The command completed.
+ @retval other An error occurred. Any error is possible
+ depending on the implementation of the shell
+ command.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SHELLENV_INTERNAL_COMMAND) (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ This function is a prototype for one that gets a help string for a given command.
+ This is used when programatically adding shell commands. Upon successful return
+ the memory allocated is up to the caller to free.
+
+ @param[in, out] Str Pointer to pointer to string to display for help.
+
+ @retval EFI_SUCCESS The help string is in the parameter Str.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SHELLCMD_GET_LINE_HELP) (
+ IN OUT CHAR16 **Str
+ );
+
+/**
+Structure returned from functions that open multiple files.
+**/
+typedef struct {
+ UINT32 Signature; ///< SHELL_FILE_ARG_SIGNATURE.
+ LIST_ENTRY Link; ///< Linked list helper.
+ EFI_STATUS Status; ///< File's status.
+
+ EFI_FILE_HANDLE Parent; ///< What is the Parent file of this file.
+ UINT64 OpenMode; ///< How was the file opened.
+ CHAR16 *ParentName; ///< String representation of parent.
+ EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath; ///< DevicePath for Parent.
+
+ CHAR16 *FullName; ///< Path and file name for this file.
+ CHAR16 *FileName; ///< File name for this file.
+
+ EFI_FILE_HANDLE Handle; ///< Handle to this file.
+ EFI_FILE_INFO *Info; ///< Pointer to file info for this file.
+} SHELL_FILE_ARG;
+
+/// Signature for SHELL_FILE_ARG.
+#define SHELL_FILE_ARG_SIGNATURE SIGNATURE_32 ('g', 'r', 'a', 'f')
+
+/**
+GUID for the shell environment2 and shell environment.
+**/
+#define SHELL_ENVIRONMENT_PROTOCOL_GUID \
+ { \
+ 0x47c7b221, 0xc42a, 0x11d2, {0x8e, 0x57, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} \
+ }
+
+/**
+GUID for the shell environment2 extension (main GUID above).
+**/
+#define EFI_SE_EXT_SIGNATURE_GUID \
+ { \
+ 0xd2c18636, 0x40e5, 0x4eb5, {0xa3, 0x1b, 0x36, 0x69, 0x5f, 0xd4, 0x2c, 0x87} \
+ }
+
+#define EFI_SHELL_MAJOR_VER 0x00000001 ///< Major version of the EFI_SHELL_ENVIRONMENT2.
+#define EFI_SHELL_MINOR_VER 0x00000000 ///< Minor version of the EFI_SHELL_ENVIRONMENT2.
+
+/**
+ Execute a command line.
+
+ This function will run the CommandLine. This includes loading any required images,
+ parsing any requires scripts, and if DebugOutput is TRUE printing errors
+ encountered directly to the screen.
+
+ @param[in] ParentImageHandle Handle of the image executing this operation.
+ @param[in] CommandLine The string command line to execute.
+ @param[in] DebugOutput TRUE indicates that errors should be printed directly.
+ FALSE supresses error messages.
+
+ @retval EFI_SUCCESS The command line executed and completed.
+ @retval EFI_ABORTED The operation aborted.
+ @retval EFI_INVALID_PARAMETER A parameter did not have a valid value.
+ @retval EFI_OUT_OF_RESOURCES A required memory allocation failed.
+
+@sa HandleProtocol
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SHELLENV_EXECUTE) (
+ IN EFI_HANDLE *ParentImageHandle,
+ IN CHAR16 *CommandLine,
+ IN BOOLEAN DebugOutput
+ );
+
+/**
+ This function returns a shell environment variable value.
+
+ @param[in] Name The pointer to the string with the shell environment
+ variable name.
+
+ @retval NULL The shell environment variable's value could not be found.
+ @retval !=NULL The value of the shell environment variable Name.
+
+**/
+typedef
+CHAR16 *
+(EFIAPI *SHELLENV_GET_ENV) (
+ IN CHAR16 *Name
+ );
+
+/**
+ This function returns a shell environment map value.
+
+ @param[in] Name The pointer to the string with the shell environment
+ map name.
+
+ @retval NULL The shell environment map's value could not be found.
+ @retval !=NULL The value of the shell environment map Name.
+
+**/
+typedef
+CHAR16 *
+(EFIAPI *SHELLENV_GET_MAP) (
+ IN CHAR16 *Name
+ );
+
+/**
+ This function will add an internal command to the shell interface.
+
+ This will allocate all required memory, put the new command on the command
+ list in the correct location.
+
+ @param[in] Handler The handler function to call when the command gets called.
+ @param[in] Cmd The command name.
+ @param[in] GetLineHelp The function to call of type "get help" for this command.
+
+ @retval EFI_SUCCESS The command is now part of the command list.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @sa SHELLENV_INTERNAL_COMMAND
+ @sa SHELLCMD_GET_LINE_HELP
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SHELLENV_ADD_CMD) (
+ IN SHELLENV_INTERNAL_COMMAND Handler,
+ IN CHAR16 *Cmd,
+ IN SHELLCMD_GET_LINE_HELP GetLineHelp
+ );
+
+/**
+ Internal interface to add protocol handlers.
+
+ This function is for internal shell use only. This is how protocol handlers are added.
+ This will get the current protocol info and add the new info or update existing info
+ and then resave the info.
+
+ @param[in] Protocol The pointer to the protocol's GUID.
+ @param[in] DumpToken The function pointer to dump token function or
+ NULL.
+ @param[in] DumpInfo The function pointer to dump infomation function
+ or NULL.
+ @param[in] IdString The English name of the protocol.
+**/
+typedef
+VOID
+(EFIAPI *SHELLENV_ADD_PROT) (
+ IN EFI_GUID *Protocol,
+ IN SHELLENV_DUMP_PROTOCOL_INFO DumpToken OPTIONAL,
+ IN SHELLENV_DUMP_PROTOCOL_INFO DumpInfo OPTIONAL,
+ IN CHAR16 *IdString
+ );
+
+/**
+ This function finds a protocol handle by a GUID.
+
+ This function will check for already known protocols by GUID and if one is
+ found it will return the name of that protocol. If no name is found and
+ GenId is TRUE it will generate ths string.
+
+ @param[in] Protocol The GUID of the protocol to look for.
+ @param[in] GenId Whether to generate a name string if it is not found.
+
+ @return !NULL The Name of the protocol.
+ @retval NULL The Name was not found, and GenId was not TRUE.
+**/
+typedef
+CHAR16*
+(EFIAPI *SHELLENV_GET_PROT) (
+ IN EFI_GUID *Protocol,
+ IN BOOLEAN GenId
+ );
+
+/**
+ This function returns a string array containing the current directory on
+ a given device.
+
+ If DeviceName is specified, then return the current shell directory on that
+ device. If DeviceName is NULL, then return the current directory on the
+ current device. The caller us responsible to free the returned string when
+ no longer required.
+
+ @param[in] DeviceName The name of the device to get the current
+ directory on, or NULL for current device.
+
+ @return String array with the current directory on the current or specified device.
+
+**/
+typedef
+CHAR16*
+(EFIAPI *SHELLENV_CUR_DIR) (
+ IN CHAR16 *DeviceName OPTIONAL
+ );
+
+/**
+ This function will open a group of files that match the Arg path, including
+ support for wildcard characters ('?' and '*') in the Arg path. If there are
+ any wildcard characters in the path this function will find any and all files
+ that match the wildcards. It returns a double linked list based on the
+ LIST_ENTRY linked list structure. Use this in conjunction with the
+ SHELL_FILE_ARG_SIGNATURE to get the SHELL_FILE_ARG structures that are returned.
+ The memory allocated by the callee for this list is freed by making a call to
+ SHELLENV_FREE_FILE_LIST.
+
+ @param[in] Arg The pointer Path to files to open.
+ @param[in, out] ListHead The pointer to the allocated and initialized list head
+ upon which to append all opened file structures.
+
+ @retval EFI_SUCCESS One or more files was opened and a struct of each file's
+ information was appended to ListHead.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_NOT_FOUND No matching files could be found.
+ @sa SHELLENV_FREE_FILE_LIST
+**/typedef
+EFI_STATUS
+(EFIAPI *SHELLENV_FILE_META_ARG) (
+ IN CHAR16 *Arg,
+ IN OUT LIST_ENTRY *ListHead
+ );
+
+/**
+ This frees all of the nodes under the ListHead, but not ListHead itself.
+
+ @param[in, out] ListHead Pointer to list to free all nodes of.
+
+ @retval EFI_SUCCESS This function always returns EFI_SUCCESS.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SHELLENV_FREE_FILE_LIST) (
+ IN OUT LIST_ENTRY *ListHead
+ );
+
+/**
+ This function creates a new instance of the ShellInterface protocol for use on
+ the ImageHandle.
+
+ This function is for internal shell usage. This will allocate and then populate
+ EFI_SHELL_INTERFACE protocol. It is the caller's responsibility to free the
+ memory.
+
+ @param[in] ImageHandle The handle which will use the new ShellInterface
+ protocol.
+
+ @return The newly allocated shell interface protocol.
+
+**/
+typedef
+EFI_SHELL_INTERFACE*
+(EFIAPI *SHELLENV_NEW_SHELL) (
+ IN EFI_HANDLE ImageHandle
+ );
+
+/**
+ This function determines whether a script file is currently being processed.
+
+ A script file (.nsh file) can contain a series of commands and this is useful to
+ know for some shell commands whether they are being run manually or as part of a
+ script.
+
+ @retval TRUE A script file is being processed.
+ @retval FALSE A script file is not being processed.
+**/
+typedef
+BOOLEAN
+(EFIAPI *SHELLENV_BATCH_IS_ACTIVE) (
+ VOID
+ );
+
+/**
+ This is an internal shell function to free any and all allocated resources.
+ This should be called immediately prior to closing the shell.
+**/
+typedef
+VOID
+(EFIAPI *SHELLENV_FREE_RESOURCES) (
+ VOID
+ );
+
+/**
+ This function enables the page break mode.
+
+ This mode causes the output to pause after each complete screen to enable a
+ user to more easily read it. If AutoWrap is TRUE, then rows with too many
+ characters will be chopped and divided into 2 rows. If FALSE, then rows with
+ too many characters may not be fully visible to the user on the screen.
+
+ @param[in] StartRow The row number to start this on.
+ @param[in] AutoWrap Whether to auto wrap rows that are too long.
+**/
+typedef
+VOID
+(EFIAPI *SHELLENV_ENABLE_PAGE_BREAK) (
+ IN INT32 StartRow,
+ IN BOOLEAN AutoWrap
+ );
+
+/**
+ This function disables the page break mode.
+
+ Disabling this causes the output to print out exactly as coded, with no breaks
+ for readability.
+**/
+typedef
+VOID
+(EFIAPI *SHELLENV_DISABLE_PAGE_BREAK) (
+ VOID
+ );
+
+/**
+ Get the status of the page break output mode.
+
+ @retval FALSE Page break output mode is not enabled.
+ @retval TRUE Page break output mode is enabled.
+**/
+typedef
+BOOLEAN
+(EFIAPI *SHELLENV_GET_PAGE_BREAK) (
+ VOID
+ );
+
+/**
+ This function sets the keys to filter for for the console in. The valid
+ values to set are:
+
+ #define EFI_OUTPUT_SCROLL 0x00000001
+ #define EFI_OUTPUT_PAUSE 0x00000002
+ #define EFI_EXECUTION_BREAK 0x00000004
+
+ @param[in] KeyFilter The new key filter to use.
+**/
+typedef
+VOID
+(EFIAPI *SHELLENV_SET_KEY_FILTER) (
+ IN UINT32 KeyFilter
+ );
+
+/**
+ This function gets the keys to filter for for the console in.
+
+ The valid values to get are:
+ #define EFI_OUTPUT_SCROLL 0x00000001
+ #define EFI_OUTPUT_PAUSE 0x00000002
+ #define EFI_EXECUTION_BREAK 0x00000004
+
+ @retval The current filter mask.
+**/
+typedef
+UINT32
+(EFIAPI *SHELLENV_GET_KEY_FILTER) (
+ VOID
+ );
+
+/**
+ This function determines if the shell application should break.
+
+ This is used to inform a shell application that a break condition has been
+ initiated. Long loops should check this to prevent delays to the break.
+
+ @retval TRUE A break has been signaled. The application
+ should exit with EFI_ABORTED as soon as possible.
+ @retval FALSE Continue as normal.
+**/
+typedef
+BOOLEAN
+(EFIAPI *SHELLENV_GET_EXECUTION_BREAK) (
+ VOID
+ );
+
+/**
+ This is an internal shell function used to increment the shell nesting level.
+
+**/
+typedef
+VOID
+(EFIAPI *SHELLENV_INCREMENT_SHELL_NESTING_LEVEL) (
+ VOID
+ );
+
+/**
+ This is an internal shell function used to decrement the shell nesting level.
+**/
+typedef
+VOID
+(EFIAPI *SHELLENV_DECREMENT_SHELL_NESTING_LEVEL) (
+ VOID
+ );
+
+/**
+ This function determines if the caller is running under the root shell.
+
+ @retval TRUE The caller is running under the root shell.
+ @retval FALSE The caller is not running under the root shell.
+
+**/
+typedef
+BOOLEAN
+(EFIAPI *SHELLENV_IS_ROOT_SHELL) (
+ VOID
+ );
+
+/**
+ Close the console proxy to restore the original console.
+
+ This is an internal shell function to handle shell cascading. It restores the
+ original set of console protocols.
+
+ @param[in] ConInHandle The handle of ConIn.
+ @param[in, out] ConIn The pointer to the location to return the pointer to
+ the original console input.
+ @param[in] ConOutHandle The handle of ConOut
+ @param[in, out] ConOut The pointer to the location to return the pointer to
+ the original console output.
+**/
+typedef
+VOID
+(EFIAPI *SHELLENV_CLOSE_CONSOLE_PROXY) (
+ IN EFI_HANDLE ConInHandle,
+ IN OUT EFI_SIMPLE_TEXT_INPUT_PROTOCOL **ConIn,
+ IN EFI_HANDLE ConOutHandle,
+ IN OUT EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL **ConOut
+ );
+
+//
+// declarations of handle enumerator
+//
+/**
+ For ease of use the shell maps handle #'s to short numbers.
+ This is only done on request for various internal commands and the references
+ are immediately freed when the internal command completes.
+**/
+typedef
+VOID
+(EFIAPI *INIT_HANDLE_ENUMERATOR) (
+ VOID
+ );
+
+/**
+ This is an internal shell function to enumerate the handle database.
+
+ This function gets the next handle in the handle database. If no handles are
+ found, EFI_NOT_FOUND is returned. If the previous Handle was the last handle,
+ it is set to NULL before returning.
+
+ This must be called after INIT_HANDLE_ENUMERATOR and before CLOSE_HANDLE_ENUMERATOR.
+
+ @param[in, out] Handle The pointer to pointer to Handle. It is set
+ on a sucessful return.
+
+ @retval EFI_SUCCESS The next handle in the handle database is *Handle.
+ @retval EFI_NOT_FOUND There is not another handle.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *NEXT_HANDLE) (
+ IN OUT EFI_HANDLE **Handle
+ );
+
+/**
+ This is an internal shell function to enumerate the handle database.
+
+ This function skips the next SkipNum handles in the handle database. If there
+ are not enough handles left to skip that many EFI_ACCESS_DENIED is returned and
+ no skip is performed.
+
+ This must be called after INIT_HANDLE_ENUMERATOR and before CLOSE_HANDLE_ENUMERATOR.
+
+ @param[in] SkipNum How many handles to skip
+
+ @retval EFI_SUCCESS The next handle in the handle database is *Handle
+ @retval EFI_ACCESS_DENIED There are not SkipNum handles left in the database
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SKIP_HANDLE) (
+ IN UINTN SkipNum
+ );
+
+/**
+ This is an internal shell function to enumerate the handle database.
+
+ This function resets the the handle database so that NEXT_HANDLE and SKIP_HANDLE
+ will start from EnumIndex on the next call.
+
+ This must be called after INIT_HANDLE_ENUMERATOR and before CLOSE_HANDLE_ENUMERATOR.
+
+ @param[in] EnumIndex Where to start.
+
+ @return The number of handles either read out or skipped before this reset.
+**/
+typedef
+UINTN
+(EFIAPI *RESET_HANDLE_ENUMERATOR) (
+ IN UINTN EnumIndex
+ );
+
+/**
+ This is an internal shell function to enumerate the handle database.
+
+ This must be called after INIT_HANDLE_ENUMERATOR.
+
+ This function releases all memory and resources associated with the handle database.
+ After this no other handle enumerator functions except INIT_HANDLE_ENUMERATOR will
+ function properly.
+**/
+typedef
+VOID
+(EFIAPI *CLOSE_HANDLE_ENUMERATOR) (
+ VOID
+ );
+
+/**
+ This is an internal shell function to enumerate the handle database.
+
+ This function returns the number of handles in the handle database.
+
+ This must be called after INIT_HANDLE_ENUMERATOR and before CLOSE_HANDLE_ENUMERATOR.
+
+ @return The number of handles in the handle database.
+**/
+typedef
+UINTN
+(EFIAPI *GET_NUM) (
+ VOID
+ );
+
+/**
+Handle Enumerator structure.
+**/
+typedef struct {
+ INIT_HANDLE_ENUMERATOR Init; ///< The pointer to INIT_HANDLE_ENUMERATOR function.
+ NEXT_HANDLE Next; ///< The pointer to NEXT_HANDLE function.
+ SKIP_HANDLE Skip; ///< The pointer to SKIP_HANDLE function.
+ RESET_HANDLE_ENUMERATOR Reset; ///< The pointer to RESET_HANDLE_ENUMERATOR function.
+ CLOSE_HANDLE_ENUMERATOR Close; ///< The pointer to CLOSE_HANDLE_ENUMERATOR function.
+ GET_NUM GetNum; ///< The pointer to GET_NUM function.
+} HANDLE_ENUMERATOR;
+
+/**
+ Signature for the PROTOCOL_INFO structure.
+**/
+#define PROTOCOL_INFO_SIGNATURE SIGNATURE_32 ('s', 'p', 'i', 'n')
+
+/**
+ PROTOCOL_INFO structure for protocol enumerator functions.
+**/
+typedef struct {
+ UINTN Signature; ///< PROTOCOL_INFO_SIGNATURE.
+ LIST_ENTRY Link; ///< Standard linked list helper member.
+ //
+ // The parsing info for the protocol.
+ //
+ EFI_GUID ProtocolId; ///< The GUID for the protocol.
+ CHAR16 *IdString; ///< The name of the protocol.
+ SHELLENV_DUMP_PROTOCOL_INFO DumpToken; ///< The pointer to DumpToken function for the protocol.
+ SHELLENV_DUMP_PROTOCOL_INFO DumpInfo; ///< The pointer to DumpInfo function for the protocol.
+ //
+ // Patabase info on which handles are supporting this protocol.
+ //
+ UINTN NoHandles; ///< The number of handles producing this protocol.
+ EFI_HANDLE *Handles; ///< The array of handles.
+
+} PROTOCOL_INFO;
+
+//
+// Declarations of protocol info enumerator.
+//
+/**
+ This is an internal shell function to initialize the protocol enumerator.
+
+ This must be called before NEXT_PROTOCOL_INFO, SKIP_PROTOCOL_INFO,
+ RESET_PROTOCOL_INFO_ENUMERATOR, and CLOSE_PROTOCOL_INFO_ENUMERATOR are
+ called.
+**/
+typedef
+VOID
+(EFIAPI *INIT_PROTOCOL_INFO_ENUMERATOR) (
+ VOID
+ );
+
+/**
+ This function is an internal shell function for enumeration of protocols.
+
+ This function returns the next protocol on the list. If this is called
+ immediately after initialization, it will return the first protocol on the list.
+ If this is called immediately after reset, it will return the first protocol again.
+
+ This cannot be called after CLOSE_PROTOCOL_INFO_ENUMERATOR, but it must be
+ called after INIT_PROTOCOL_INFO_ENUMERATOR.
+
+ @param[in, out] ProtocolInfo The pointer to pointer to protocol information structure.
+
+ @retval EFI_SUCCESS The next protocol's information was sucessfully returned.
+ @retval NULL There are no more protocols.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *NEXT_PROTOCOL_INFO) (
+ IN OUT PROTOCOL_INFO **ProtocolInfo
+ );
+
+/**
+ This function is an internal shell function for enumeration of protocols.
+
+ This cannot be called after CLOSE_PROTOCOL_INFO_ENUMERATOR, but it must be
+ called after INIT_PROTOCOL_INFO_ENUMERATOR.
+
+ This function does nothing and always returns EFI_SUCCESS.
+
+ @retval EFI_SUCCESS Always returned (see above).
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SKIP_PROTOCOL_INFO) (
+ IN UINTN SkipNum
+ );
+
+/**
+ This function is an internal shell function for enumeration of protocols.
+
+ This cannot be called after CLOSE_PROTOCOL_INFO_ENUMERATOR, but it must be
+ called after INIT_PROTOCOL_INFO_ENUMERATOR.
+
+ This function resets the list of protocols such that the next one in the
+ list is the begining of the list.
+**/
+typedef
+VOID
+(EFIAPI *RESET_PROTOCOL_INFO_ENUMERATOR) (
+ VOID
+ );
+
+
+/**
+ This function is an internal shell function for enumeration of protocols.
+
+ This must be called after INIT_PROTOCOL_INFO_ENUMERATOR. After this call
+ no protocol enumerator calls except INIT_PROTOCOL_INFO_ENUMERATOR may be made.
+
+ This function frees any memory or resources associated with the protocol
+ enumerator.
+**/
+typedef
+VOID
+(EFIAPI *CLOSE_PROTOCOL_INFO_ENUMERATOR) (
+ VOID
+ );
+
+/**
+ Protocol enumerator structure of function pointers.
+**/
+typedef struct {
+ INIT_PROTOCOL_INFO_ENUMERATOR Init; ///< The pointer to INIT_PROTOCOL_INFO_ENUMERATOR function.
+ NEXT_PROTOCOL_INFO Next; ///< The pointer to NEXT_PROTOCOL_INFO function.
+ SKIP_PROTOCOL_INFO Skip; ///< The pointer to SKIP_PROTOCOL_INFO function.
+ RESET_PROTOCOL_INFO_ENUMERATOR Reset; ///< The pointer to RESET_PROTOCOL_INFO_ENUMERATOR function.
+ CLOSE_PROTOCOL_INFO_ENUMERATOR Close; ///< The pointer to CLOSE_PROTOCOL_INFO_ENUMERATOR function.
+} PROTOCOL_INFO_ENUMERATOR;
+
+/**
+ This function is used to retrieve a user-friendly display name for a handle.
+
+ If UseComponentName is TRUE then the component name protocol for this device
+ or it's parent device (if required) will be used to obtain the name of the
+ device. If UseDevicePath is TRUE it will get the human readable device path
+ and return that. If both are TRUE it will try to use component name first
+ and device path if that fails.
+
+ It will use either ComponentName or ComponentName2 protocol, depending on
+ what is present.
+
+ This function will furthur verify whether the handle in question produced either
+ EFI_DRIVER_CONFIGRATION_PROTOCOL or EFI_DRIVER_CONFIGURATION2_PROTOCOL and also
+ whether the handle in question produced either EFI_DRIVER_DIAGNOSTICS_PROTOCOL or
+ EFI_DRIVER_DIAGNOSTICS2_PROTOCOL.
+
+ Upon successful return, the memory for *BestDeviceName is up to the caller to free.
+
+ @param[in] DeviceHandle The device handle whose name is desired.
+ @param[in] UseComponentName Whether to use the ComponentName protocol at all.
+ @param[in] UseDevicePath Whether to use the DevicePath protocol at all.
+ @param[in] Language The pointer to the language string to use.
+ @param[in, out] BestDeviceName The pointer to pointer to string allocated with the name.
+ @param[out] ConfigurationStatus The pointer to status for opening a Configuration protocol.
+ @param[out] DiagnosticsStatus The pointer to status for opening a Diagnostics protocol.
+ @param[in] Display Whether to Print this out to default Print location.
+ @param[in] Indent How many characters to indent the printing.
+
+ @retval EFI_SUCCESS This function always returns EFI_SUCCESS.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *GET_DEVICE_NAME) (
+ IN EFI_HANDLE DeviceHandle,
+ IN BOOLEAN UseComponentName,
+ IN BOOLEAN UseDevicePath,
+ IN CHAR8 *Language,
+ IN OUT CHAR16 **BestDeviceName,
+ OUT EFI_STATUS *ConfigurationStatus,
+ OUT EFI_STATUS *DiagnosticsStatus,
+ IN BOOLEAN Display,
+ IN UINTN Indent
+ );
+
+#define EFI_SHELL_COMPATIBLE_MODE_VER L"1.1.1" ///< The string for lowest version this shell supports.
+#define EFI_SHELL_ENHANCED_MODE_VER L"1.1.2" ///< The string for highest version this shell supports.
+
+/**
+ This function gets the shell mode as stored in the shell environment
+ "efishellmode". It will not fail.
+
+ @param[out] Mode Returns a string representing one of the
+ 2 supported modes of the shell.
+
+ @retval EFI_SUCCESS This function always returns success.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *GET_SHELL_MODE) (
+ OUT CHAR16 **Mode
+ );
+
+/**
+ Convert a file system style name to a device path.
+
+ This function will convert a shell path name to a Device Path Protocol path.
+ This function will allocate any required memory for this operation and it
+ is the responsibility of the caller to free that memory when no longer required.
+
+ If anything prevents the complete conversion free any allocated memory and
+ return NULL.
+
+ @param[in] Path The path to convert.
+
+ @retval !NULL A pointer to the callee allocated Device Path.
+ @retval NULL The operation could not be completed.
+**/
+typedef
+EFI_DEVICE_PATH_PROTOCOL*
+(EFIAPI *SHELLENV_NAME_TO_PATH) (
+ IN CHAR16 *Path
+ );
+
+/**
+ Converts a device path into a file system map name.
+
+ If DevPath is NULL, then ASSERT.
+
+ This function looks through the shell environment map for a map whose device
+ path matches the DevPath parameter. If one is found the Name is returned via
+ Name parameter. If sucessful the caller must free the memory allocated for
+ Name.
+
+ This function will use the internal lock to prevent changes to the map during
+ the lookup operation.
+
+ @param[in] DevPath The device path to search for a name for.
+ @param[in] ConsistMapping What state to verify map flag VAR_ID_CONSIST.
+ @param[out] Name On sucessful return the name of that device path.
+
+ @retval EFI_SUCCESS The DevPath was found and the name returned
+ in Name.
+ @retval EFI_OUT_OF_RESOURCES A required memory allocation failed.
+ @retval EFI_UNSUPPORTED The DevPath was not found in the map.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SHELLENV_GET_FS_NAME) (
+ IN EFI_DEVICE_PATH_PROTOCOL * DevPath,
+ IN BOOLEAN ConsistMapping,
+ OUT CHAR16 **Name
+ );
+
+/**
+ This function will open a group of files that match the Arg path, but will not
+ support the wildcard characters ('?' and '*') in the Arg path. If there are
+ any wildcard characters in the path this function will return
+ EFI_INVALID_PARAMETER. The return is a double linked list based on the
+ LIST_ENTRY linked list structure. Use this in conjunction with the
+ SHELL_FILE_ARG_SIGNATURE to get the SHELL_FILE_ARG structures that are returned.
+ The memory allocated by the callee for this list is freed by making a call to
+ SHELLENV_FREE_FILE_LIST.
+
+ @param[in] Arg The pointer to the path of the files to be opened.
+ @param[in, out] ListHead The pointer to allocated and initialized list head
+ upon which to append all the opened file structures.
+
+ @retval EFI_SUCCESS One or more files was opened and a struct of each file's
+ information was appended to ListHead.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_NOT_FOUND No matching files could be found.
+ @sa SHELLENV_FREE_FILE_LIST
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SHELLENV_FILE_META_ARG_NO_WILDCARD) (
+ IN CHAR16 *Arg,
+ IN OUT LIST_ENTRY *ListHead
+ );
+
+/**
+ This function removes duplicate file listings from lists.
+
+ This is a function for use with SHELLENV_FILE_META_ARG_NO_WILDCARD and
+ SHELLENV_FILE_META_ARG. This function will verify that there are no duplicate
+ files in the list of returned files. Any file listed twice will have one of its
+ instances removed.
+
+ @param[in] ListHead The pointer to linked list head that was returned from
+ SHELLENV_FILE_META_ARG_NO_WILDCARD or
+ SHELLENV_FILE_META_ARG.
+
+ @retval EFI_SUCCESS This function always returns success.
+
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SHELLENV_DEL_DUP_FILE) (
+ IN LIST_ENTRY * ListHead
+ );
+
+/**
+ Converts a File System map name to a device path.
+
+ If DevPath is NULL, then ASSERT().
+
+ This function looks through the shell environment map for a map whose Name
+ matches the Name parameter. If one is found, the device path pointer is
+ updated to point to that file systems device path. The caller should not
+ free the memory from that device path.
+
+ This function will use the internal lock to prevent changes to the map during
+ the lookup operation.
+
+ @param[in] Name The pointer to the NULL terminated UNICODE string of the
+ file system name.
+ @param[out] DevPath The pointer to pointer to DevicePath. Only valid on
+ successful return.
+
+ @retval EFI_SUCCESS The conversion was successful, and the device
+ path was returned.
+ @retval EFI_NOT_FOUND The file system could not be found in the map.
+**/
+typedef
+EFI_STATUS
+(EFIAPI *SHELLENV_GET_FS_DEVICE_PATH) (
+ IN CHAR16 *Name,
+ OUT EFI_DEVICE_PATH_PROTOCOL **DevPath
+ );
+
+/// EFI_SHELL_ENVIRONMENT2 protocol structure.
+typedef struct {
+ SHELLENV_EXECUTE Execute;
+ SHELLENV_GET_ENV GetEnv;
+ SHELLENV_GET_MAP GetMap;
+ SHELLENV_ADD_CMD AddCmd;
+ SHELLENV_ADD_PROT AddProt;
+ SHELLENV_GET_PROT GetProt;
+ SHELLENV_CUR_DIR CurDir;
+ SHELLENV_FILE_META_ARG FileMetaArg;
+ SHELLENV_FREE_FILE_LIST FreeFileList;
+
+ //
+ // The following services are only used by the shell itself.
+ //
+ SHELLENV_NEW_SHELL NewShell;
+ SHELLENV_BATCH_IS_ACTIVE BatchIsActive;
+
+ SHELLENV_FREE_RESOURCES FreeResources;
+
+ //
+ // GUID to differentiate ShellEnvironment2 from ShellEnvironment.
+ //
+ EFI_GUID SESGuid;
+ //
+ // Major Version grows if shell environment interface has been changes.
+ //
+ UINT32 MajorVersion;
+ UINT32 MinorVersion;
+ SHELLENV_ENABLE_PAGE_BREAK EnablePageBreak;
+ SHELLENV_DISABLE_PAGE_BREAK DisablePageBreak;
+ SHELLENV_GET_PAGE_BREAK GetPageBreak;
+
+ SHELLENV_SET_KEY_FILTER SetKeyFilter;
+ SHELLENV_GET_KEY_FILTER GetKeyFilter;
+
+ SHELLENV_GET_EXECUTION_BREAK GetExecutionBreak;
+ SHELLENV_INCREMENT_SHELL_NESTING_LEVEL IncrementShellNestingLevel;
+ SHELLENV_DECREMENT_SHELL_NESTING_LEVEL DecrementShellNestingLevel;
+ SHELLENV_IS_ROOT_SHELL IsRootShell;
+
+ SHELLENV_CLOSE_CONSOLE_PROXY CloseConsoleProxy;
+ HANDLE_ENUMERATOR HandleEnumerator;
+ PROTOCOL_INFO_ENUMERATOR ProtocolInfoEnumerator;
+ GET_DEVICE_NAME GetDeviceName;
+ GET_SHELL_MODE GetShellMode;
+ SHELLENV_NAME_TO_PATH NameToPath;
+ SHELLENV_GET_FS_NAME GetFsName;
+ SHELLENV_FILE_META_ARG_NO_WILDCARD FileMetaArgNoWildCard;
+ SHELLENV_DEL_DUP_FILE DelDupFileArg;
+ SHELLENV_GET_FS_DEVICE_PATH GetFsDevicePath;
+} EFI_SHELL_ENVIRONMENT2;
+
+extern EFI_GUID gEfiShellEnvironment2Guid;
+extern EFI_GUID gEfiShellEnvironment2ExtGuid;
+
+#endif // _SHELL_ENVIRONMENT_2_PROTOCOL_H_
diff --git a/Core/ShellPkg/Include/Protocol/EfiShellInterface.h b/Core/ShellPkg/Include/Protocol/EfiShellInterface.h
new file mode 100644
index 0000000000..6a34c60b07
--- /dev/null
+++ b/Core/ShellPkg/Include/Protocol/EfiShellInterface.h
@@ -0,0 +1,94 @@
+/** @file
+ EFI Shell Interface protocol from EDK shell (no spec).
+
+ Shell Interface - additional information (over image_info) provided
+ to an application started by the shell.
+
+ ConIo provides a file-style interface to the console.
+
+ The shell interface's and data (including ConIo) are only valid during
+ the applications Entry Point. Once the application returns from it's
+ entry point the data is freed by the invoking shell.
+
+ Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SHELLINTERFACE_H_
+#define _SHELLINTERFACE_H_
+
+#include <Protocol/SimpleFileSystem.h>
+
+#define SHELL_INTERFACE_PROTOCOL_GUID \
+ { \
+ 0x47c7b223, 0xc42a, 0x11d2, {0x8e, 0x57, 0x0, 0xa0, 0xc9, 0x69, 0x72, 0x3b} \
+ }
+
+///
+/// Bit definitions for EFI_SHELL_ARG_INFO
+///
+typedef enum {
+ ARG_NO_ATTRIB = 0x0,
+ ARG_IS_QUOTED = BIT0,
+ ARG_PARTIALLY_QUOTED = BIT1,
+ ARG_FIRST_HALF_QUOTED = BIT2,
+ ARG_FIRST_CHAR_IS_ESC = BIT3
+} EFI_SHELL_ARG_INFO_TYPES;
+
+///
+/// Attributes for an argument.
+///
+typedef struct _EFI_SHELL_ARG_INFO {
+ UINT32 Attributes;
+} EFI_SHELL_ARG_INFO;
+
+///
+/// This protocol provides access to additional information about a shell application.
+///
+typedef struct {
+ ///
+ /// Handle back to original image handle & image information.
+ ///
+ EFI_HANDLE ImageHandle;
+ EFI_LOADED_IMAGE_PROTOCOL *Info;
+
+ ///
+ /// Parsed arg list converted more C-like format.
+ ///
+ CHAR16 **Argv;
+ UINTN Argc;
+
+ ///
+ /// Storage for file redirection args after parsing.
+ ///
+ CHAR16 **RedirArgv;
+ UINTN RedirArgc;
+
+ ///
+ /// A file style handle for console io.
+ ///
+ EFI_FILE_PROTOCOL *StdIn;
+ EFI_FILE_PROTOCOL *StdOut;
+ EFI_FILE_PROTOCOL *StdErr;
+
+ ///
+ /// List of attributes for each argument.
+ ///
+ EFI_SHELL_ARG_INFO *ArgInfo;
+
+ ///
+ /// Whether we are echoing.
+ ///
+ BOOLEAN EchoOn;
+} EFI_SHELL_INTERFACE;
+
+extern EFI_GUID gEfiShellInterfaceGuid;
+
+#endif
diff --git a/Core/ShellPkg/Include/Protocol/EfiShellParameters.h b/Core/ShellPkg/Include/Protocol/EfiShellParameters.h
new file mode 100644
index 0000000000..e52328b3a4
--- /dev/null
+++ b/Core/ShellPkg/Include/Protocol/EfiShellParameters.h
@@ -0,0 +1,60 @@
+/** @file
+ EFI Shell protocol as defined in the UEFI Shell 2.0 specification.
+
+ Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __EFI_SHELL_PARAMETERS_PROTOCOL__
+#define __EFI_SHELL_PARAMETERS_PROTOCOL__
+
+#include <ShellBase.h>
+
+#define EFI_SHELL_PARAMETERS_PROTOCOL_GUID \
+ { \
+ 0x752f3136, 0x4e16, 0x4fdc, { 0xa2, 0x2a, 0xe5, 0xf4, 0x68, 0x12, 0xf4, 0xca } \
+ }
+
+typedef struct _EFI_SHELL_PARAMETERS_PROTOCOL {
+ ///
+ /// Points to an Argc-element array of points to NULL-terminated strings containing
+ /// the command-line parameters. The first entry in the array is always the full file
+ /// path of the executable. Any quotation marks that were used to preserve
+ /// whitespace have been removed.
+ ///
+ CHAR16 **Argv;
+
+ ///
+ /// The number of elements in the Argv array.
+ ///
+ UINTN Argc;
+
+ ///
+ /// The file handle for the standard input for this executable. This may be different
+ /// from the ConInHandle in EFI_SYSTEM_TABLE.
+ ///
+ SHELL_FILE_HANDLE StdIn;
+
+ ///
+ /// The file handle for the standard output for this executable. This may be different
+ /// from the ConOutHandle in EFI_SYSTEM_TABLE.
+ ///
+ SHELL_FILE_HANDLE StdOut;
+
+ ///
+ /// The file handle for the standard error output for this executable. This may be
+ /// different from the StdErrHandle in EFI_SYSTEM_TABLE.
+ ///
+ SHELL_FILE_HANDLE StdErr;
+} EFI_SHELL_PARAMETERS_PROTOCOL;
+
+extern EFI_GUID gEfiShellParametersProtocolGuid;
+
+#endif
diff --git a/Core/ShellPkg/Include/ShellBase.h b/Core/ShellPkg/Include/ShellBase.h
new file mode 100644
index 0000000000..09f87b4cc0
--- /dev/null
+++ b/Core/ShellPkg/Include/ShellBase.h
@@ -0,0 +1,157 @@
+/** @file
+ Root include file for Shell Package modules that utilize the SHELL_RETURN type
+
+ Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SHELL_BASE_
+#define _SHELL_BASE_
+
+typedef VOID *SHELL_FILE_HANDLE;
+
+#define SHELL_FREE_NON_NULL(Pointer) \
+ do { \
+ if ((Pointer) != NULL) { \
+ FreePool((Pointer)); \
+ (Pointer) = NULL; \
+ } \
+ } while(FALSE)
+
+typedef enum {
+///
+/// The operation completed successfully.
+///
+SHELL_SUCCESS = 0,
+
+///
+/// The image failed to load.
+///
+SHELL_LOAD_ERROR = 1,
+
+///
+/// The parameter was incorrect.
+///
+SHELL_INVALID_PARAMETER = 2,
+
+///
+/// The operation is not supported.
+///
+SHELL_UNSUPPORTED = 3,
+
+///
+/// The buffer was not the proper size for the request.
+///
+SHELL_BAD_BUFFER_SIZE = 4,
+
+///
+/// The buffer was not large enough to hold the requested data.
+/// The required buffer size is returned in the appropriate
+/// parameter when this error occurs.
+///
+SHELL_BUFFER_TOO_SMALL = 5,
+
+///
+/// There is no data pending upon return.
+///
+SHELL_NOT_READY = 6,
+
+///
+/// The physical device reported an error while attempting the
+/// operation.
+///
+SHELL_DEVICE_ERROR = 7,
+
+///
+/// The device cannot be written to.
+///
+SHELL_WRITE_PROTECTED = 8,
+
+///
+/// The resource has run out.
+///
+SHELL_OUT_OF_RESOURCES = 9,
+
+///
+/// An inconsistency was detected on the file system causing the
+/// operation to fail.
+///
+SHELL_VOLUME_CORRUPTED = 10,
+
+///
+/// There is no more space on the file system.
+///
+SHELL_VOLUME_FULL = 11,
+
+///
+/// The device does not contain any medium to perform the
+/// operation.
+///
+SHELL_NO_MEDIA = 12,
+
+///
+/// The medium in the device has changed since the last
+/// access.
+///
+SHELL_MEDIA_CHANGED = 13,
+
+///
+/// The item was not found.
+///
+SHELL_NOT_FOUND = 14,
+
+///
+/// Access was denied.
+///
+SHELL_ACCESS_DENIED = 15,
+
+// note the skipping of 16 and 17
+
+///
+/// A timeout time expired.
+///
+SHELL_TIMEOUT = 18,
+
+///
+/// The protocol has not been started.
+///
+SHELL_NOT_STARTED = 19,
+
+///
+/// The protocol has already been started.
+///
+SHELL_ALREADY_STARTED = 20,
+
+///
+/// The operation was aborted.
+///
+SHELL_ABORTED = 21,
+
+// note the skipping of 22, 23, and 24
+
+///
+/// A function encountered an internal version that was
+/// incompatible with a version requested by the caller.
+///
+SHELL_INCOMPATIBLE_VERSION = 25,
+
+///
+/// The function was not performed due to a security violation.
+///
+SHELL_SECURITY_VIOLATION = 26,
+
+///
+/// The function was performed and resulted in an unequal
+/// comparison..
+///
+SHELL_NOT_EQUAL = 27
+}SHELL_STATUS;
+
+#endif //__SHELL_BASE_
diff --git a/Core/ShellPkg/Library/UefiDpLib/Dp.c b/Core/ShellPkg/Library/UefiDpLib/Dp.c
new file mode 100644
index 0000000000..75c7d11dc3
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiDpLib/Dp.c
@@ -0,0 +1,407 @@
+/** @file
+ Shell command for Displaying Performance Metrics.
+
+ The Dp command reads performance data and presents it in several
+ different formats depending upon the needs of the user. Both
+ Trace and Measured Profiling information is processed and presented.
+
+ Dp uses the "PerformanceLib" to read the measurement records.
+ The "TimerLib" provides information about the timer, such as frequency,
+ beginning, and ending counter values.
+ Measurement records contain identifying information (Handle, Token, Module)
+ and start and end time values.
+ Dp uses this information to group records in different ways. It also uses
+ timer information to calculate elapsed time for each measurement.
+
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.
+ (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include "UefiDpLib.h"
+#include <Guid/GlobalVariable.h>
+#include <Library/PrintLib.h>
+#include <Library/HandleParsingLib.h>
+#include <Library/DevicePathLib.h>
+
+#include <Library/ShellLib.h>
+#include <Library/BaseLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/TimerLib.h>
+#include <Library/UefiLib.h>
+
+#include <Guid/Performance.h>
+
+#include "PerformanceTokens.h"
+#include "Dp.h"
+#include "Literals.h"
+#include "DpInternal.h"
+
+//
+/// Module-Global Variables
+///@{
+CHAR16 mGaugeString[DP_GAUGE_STRING_LENGTH + 1];
+CHAR16 mUnicodeToken[DXE_PERFORMANCE_STRING_SIZE];
+UINT64 mInterestThreshold;
+BOOLEAN mShowId = FALSE;
+
+PERF_SUMMARY_DATA SummaryData = { 0 }; ///< Create the SummaryData structure and init. to ZERO.
+
+/// Timer Specific Information.
+TIMER_INFO TimerInfo;
+
+/// Items for which to gather cumulative statistics.
+PERF_CUM_DATA CumData[] = {
+ PERF_INIT_CUM_DATA (LOAD_IMAGE_TOK),
+ PERF_INIT_CUM_DATA (START_IMAGE_TOK),
+ PERF_INIT_CUM_DATA (DRIVERBINDING_START_TOK),
+ PERF_INIT_CUM_DATA (DRIVERBINDING_SUPPORT_TOK)
+};
+
+/// Number of items for which we are gathering cumulative statistics.
+UINT32 const NumCum = sizeof(CumData) / sizeof(PERF_CUM_DATA);
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-v", TypeFlag}, // -v Verbose Mode
+ {L"-A", TypeFlag}, // -A All, Cooked
+ {L"-R", TypeFlag}, // -R RAW All
+ {L"-s", TypeFlag}, // -s Summary
+#if PROFILING_IMPLEMENTED
+ {L"-P", TypeFlag}, // -P Dump Profile Data
+ {L"-T", TypeFlag}, // -T Dump Trace Data
+#endif // PROFILING_IMPLEMENTED
+ {L"-x", TypeFlag}, // -x eXclude Cumulative Items
+ {L"-i", TypeFlag}, // -i Display Identifier
+ {L"-c", TypeValue}, // -c Display cumulative data.
+ {L"-n", TypeValue}, // -n # Number of records to display for A and R
+ {L"-t", TypeValue}, // -t # Threshold of interest
+ {NULL, TypeMax}
+ };
+
+///@}
+
+/**
+ Display the trailing Verbose information.
+**/
+VOID
+DumpStatistics( void )
+{
+ EFI_STRING StringPtr;
+ EFI_STRING StringPtrUnknown;
+ StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_STATISTICS), NULL);
+ StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
+ (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMTRACE), gDpHiiHandle, SummaryData.NumTrace);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMINCOMPLETE), gDpHiiHandle, SummaryData.NumIncomplete);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPHASES), gDpHiiHandle, SummaryData.NumSummary);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMHANDLES), gDpHiiHandle, SummaryData.NumHandles, SummaryData.NumTrace - SummaryData.NumHandles);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPEIMS), gDpHiiHandle, SummaryData.NumPEIMs);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMGLOBALS), gDpHiiHandle, SummaryData.NumGlobal);
+#if PROFILING_IMPLEMENTED
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_STATS_NUMPROFILE), gDpHiiHandle, SummaryData.NumProfile);
+#endif // PROFILING_IMPLEMENTED
+ SHELL_FREE_NON_NULL (StringPtr);
+ SHELL_FREE_NON_NULL (StringPtrUnknown);
+}
+
+/**
+ Initialize the cumulative data.
+
+**/
+VOID
+InitCumulativeData (
+ VOID
+ )
+{
+ UINTN Index;
+
+ for (Index = 0; Index < NumCum; ++Index) {
+ CumData[Index].Count = 0;
+ CumData[Index].MinDur = PERF_MAXDUR;
+ CumData[Index].MaxDur = 0;
+ CumData[Index].Duration = 0;
+ }
+}
+
+/**
+ Dump performance data.
+
+ @param[in] ImageHandle The image handle.
+ @param[in] SystemTable The system table.
+
+ @retval SHELL_SUCCESS Command completed successfully.
+ @retval SHELL_INVALID_PARAMETER Command usage error.
+ @retval SHELL_ABORTED The user aborts the operation.
+ @retval value Unknown error.
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDp (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ LIST_ENTRY *ParamPackage;
+ CONST CHAR16 *CmdLineArg;
+ EFI_STATUS Status;
+
+ UINT64 Freq;
+ UINT64 Ticker;
+ UINTN Number2Display;
+
+ EFI_STRING StringPtr;
+ BOOLEAN SummaryMode;
+ BOOLEAN VerboseMode;
+ BOOLEAN AllMode;
+ BOOLEAN RawMode;
+ BOOLEAN TraceMode;
+ BOOLEAN ProfileMode;
+ BOOLEAN ExcludeMode;
+ BOOLEAN CumulativeMode;
+ CONST CHAR16 *CustomCumulativeToken;
+ PERF_CUM_DATA *CustomCumulativeData;
+ UINTN NameSize;
+ SHELL_STATUS ShellStatus;
+
+ StringPtr = NULL;
+ SummaryMode = FALSE;
+ VerboseMode = FALSE;
+ AllMode = FALSE;
+ RawMode = FALSE;
+ TraceMode = FALSE;
+ ProfileMode = FALSE;
+ ExcludeMode = FALSE;
+ CumulativeMode = FALSE;
+ CustomCumulativeData = NULL;
+ ShellStatus = SHELL_SUCCESS;
+
+ // Get DP's entry time as soon as possible.
+ // This is used as the Shell-Phase end time.
+ //
+ Ticker = GetPerformanceCounter ();
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Process Command Line arguments
+ //
+ Status = ShellCommandLineParse (ParamList, &ParamPackage, NULL, TRUE);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_INVALID_ARG), gDpHiiHandle);
+ return SHELL_INVALID_PARAMETER;
+ }
+
+ //
+ // Boolean options
+ //
+ VerboseMode = ShellCommandLineGetFlag (ParamPackage, L"-v");
+ SummaryMode = (BOOLEAN) (ShellCommandLineGetFlag (ParamPackage, L"-S") || ShellCommandLineGetFlag (ParamPackage, L"-s"));
+ AllMode = ShellCommandLineGetFlag (ParamPackage, L"-A");
+ RawMode = ShellCommandLineGetFlag (ParamPackage, L"-R");
+#if PROFILING_IMPLEMENTED
+ TraceMode = ShellCommandLineGetFlag (ParamPackage, L"-T");
+ ProfileMode = ShellCommandLineGetFlag (ParamPackage, L"-P");
+#endif // PROFILING_IMPLEMENTED
+ ExcludeMode = ShellCommandLineGetFlag (ParamPackage, L"-x");
+ mShowId = ShellCommandLineGetFlag (ParamPackage, L"-i");
+ CumulativeMode = ShellCommandLineGetFlag (ParamPackage, L"-c");
+
+ // Options with Values
+ CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-n");
+ if (CmdLineArg == NULL) {
+ Number2Display = DEFAULT_DISPLAYCOUNT;
+ } else {
+ Number2Display = StrDecimalToUintn(CmdLineArg);
+ if (Number2Display == 0) {
+ Number2Display = MAXIMUM_DISPLAYCOUNT;
+ }
+ }
+
+ CmdLineArg = ShellCommandLineGetValue (ParamPackage, L"-t");
+ if (CmdLineArg == NULL) {
+ mInterestThreshold = DEFAULT_THRESHOLD; // 1ms := 1,000 us
+ } else {
+ mInterestThreshold = StrDecimalToUint64(CmdLineArg);
+ }
+
+ // Handle Flag combinations and default behaviors
+ // If both TraceMode and ProfileMode are FALSE, set them both to TRUE
+ if ((! TraceMode) && (! ProfileMode)) {
+ TraceMode = TRUE;
+#if PROFILING_IMPLEMENTED
+ ProfileMode = TRUE;
+#endif // PROFILING_IMPLEMENTED
+ }
+
+ //
+ // Initialize the pre-defined cumulative data.
+ //
+ InitCumulativeData ();
+
+ //
+ // Init the custom cumulative data.
+ //
+ CustomCumulativeToken = ShellCommandLineGetValue (ParamPackage, L"-c");
+ if (CustomCumulativeToken != NULL) {
+ CustomCumulativeData = AllocateZeroPool (sizeof (PERF_CUM_DATA));
+ if (CustomCumulativeData == NULL) {
+ return SHELL_OUT_OF_RESOURCES;
+ }
+ CustomCumulativeData->MinDur = 0;
+ CustomCumulativeData->MaxDur = 0;
+ CustomCumulativeData->Count = 0;
+ CustomCumulativeData->Duration = 0;
+ NameSize = StrLen (CustomCumulativeToken) + 1;
+ CustomCumulativeData->Name = AllocateZeroPool (NameSize);
+ if (CustomCumulativeData->Name == NULL) {
+ FreePool (CustomCumulativeData);
+ return SHELL_OUT_OF_RESOURCES;
+ }
+ UnicodeStrToAsciiStrS (CustomCumulativeToken, CustomCumulativeData->Name, NameSize);
+ }
+
+ //
+ // Timer specific processing
+ //
+ // Get the Performance counter characteristics:
+ // Freq = Frequency in Hz
+ // StartCount = Value loaded into the counter when it starts counting
+ // EndCount = Value counter counts to before it needs to be reset
+ //
+ Freq = GetPerformanceCounterProperties (&TimerInfo.StartCount, &TimerInfo.EndCount);
+
+ // Convert the Frequency from Hz to KHz
+ TimerInfo.Frequency = (UINT32)DivU64x32 (Freq, 1000);
+
+ // Determine in which direction the performance counter counts.
+ TimerInfo.CountUp = (BOOLEAN) (TimerInfo.EndCount >= TimerInfo.StartCount);
+
+ //
+ // Print header
+ //
+ // print DP's build version
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_BUILD_REVISION), gDpHiiHandle, DP_MAJOR_VERSION, DP_MINOR_VERSION);
+
+ // print performance timer characteristics
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_KHZ), gDpHiiHandle, TimerInfo.Frequency);
+
+ if (VerboseMode && !RawMode) {
+ StringPtr = HiiGetString (gDpHiiHandle,
+ (EFI_STRING_ID) (TimerInfo.CountUp ? STRING_TOKEN (STR_DP_UP) : STRING_TOKEN (STR_DP_DOWN)), NULL);
+ ASSERT (StringPtr != NULL);
+ // Print Timer count range and direction
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TIMER_PROPERTIES), gDpHiiHandle,
+ StringPtr,
+ TimerInfo.StartCount,
+ TimerInfo.EndCount
+ );
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_VERBOSE_THRESHOLD), gDpHiiHandle, mInterestThreshold);
+ }
+
+/****************************************************************************
+**** Print Sections based on command line options
+****
+**** Option modes have the following priority:
+**** v Verbose -- Valid in combination with any other options
+**** t Threshold -- Modifies All, Raw, and Cooked output
+**** Default is 0 for All and Raw mode
+**** Default is DEFAULT_THRESHOLD for "Cooked" mode
+**** n Number2Display Used by All and Raw mode. Otherwise ignored.
+**** A All -- R and S options are ignored
+**** R Raw -- S option is ignored
+**** s Summary -- Modifies "Cooked" output only
+**** Cooked (Default)
+****
+**** The All, Raw, and Cooked modes are modified by the Trace and Profile
+**** options.
+**** !T && !P := (0) Default, Both are displayed
+**** T && !P := (1) Only Trace records are displayed
+**** !T && P := (2) Only Profile records are displayed
+**** T && P := (3) Same as Default, both are displayed
+****************************************************************************/
+ GatherStatistics (CustomCumulativeData);
+ if (CumulativeMode) {
+ ProcessCumulative (CustomCumulativeData);
+ } else if (AllMode) {
+ if (TraceMode) {
+ Status = DumpAllTrace( Number2Display, ExcludeMode);
+ if (Status == EFI_ABORTED) {
+ ShellStatus = SHELL_ABORTED;
+ goto Done;
+ }
+ }
+ if (ProfileMode) {
+ DumpAllProfile( Number2Display, ExcludeMode);
+ }
+ } else if (RawMode) {
+ if (TraceMode) {
+ Status = DumpRawTrace( Number2Display, ExcludeMode);
+ if (Status == EFI_ABORTED) {
+ ShellStatus = SHELL_ABORTED;
+ goto Done;
+ }
+ }
+ if (ProfileMode) {
+ DumpRawProfile( Number2Display, ExcludeMode);
+ }
+ } else {
+ //------------- Begin Cooked Mode Processing
+ if (TraceMode) {
+ ProcessPhases ( Ticker );
+ if ( ! SummaryMode) {
+ Status = ProcessHandles ( ExcludeMode);
+ if (Status == EFI_ABORTED) {
+ ShellStatus = SHELL_ABORTED;
+ goto Done;
+ }
+
+ Status = ProcessPeims ();
+ if (Status == EFI_ABORTED) {
+ ShellStatus = SHELL_ABORTED;
+ goto Done;
+ }
+
+ Status = ProcessGlobal ();
+ if (Status == EFI_ABORTED) {
+ ShellStatus = SHELL_ABORTED;
+ goto Done;
+ }
+
+ ProcessCumulative (NULL);
+ }
+ }
+ if (ProfileMode) {
+ DumpAllProfile( Number2Display, ExcludeMode);
+ }
+ } //------------- End of Cooked Mode Processing
+ if ( VerboseMode || SummaryMode) {
+ DumpStatistics();
+ }
+
+Done:
+ if (ParamPackage != NULL) {
+ ShellCommandLineFreeVarList (ParamPackage);
+ }
+ SHELL_FREE_NON_NULL (StringPtr);
+ if (CustomCumulativeData != NULL) {
+ SHELL_FREE_NON_NULL (CustomCumulativeData->Name);
+ }
+ SHELL_FREE_NON_NULL (CustomCumulativeData);
+
+ return ShellStatus;
+}
diff --git a/Core/ShellPkg/Library/UefiDpLib/Dp.h b/Core/ShellPkg/Library/UefiDpLib/Dp.h
new file mode 100644
index 0000000000..72e2c3ba18
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiDpLib/Dp.h
@@ -0,0 +1,98 @@
+/** @file
+ Common declarations for the Dp Performance Reporting Utility.
+
+ Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#ifndef _EFI_APP_DP_H_
+#define _EFI_APP_DP_H_
+
+#include <Library/ShellLib.h>
+#include <ShellBase.h>
+
+#define DP_MAJOR_VERSION 2
+#define DP_MINOR_VERSION 4
+
+/**
+ * The value assigned to DP_DEBUG controls which debug output
+ * is generated. Set it to ZERO to disable.
+**/
+#define DP_DEBUG 0
+
+/**
+ * Set to 1 once Profiling has been implemented in order to enable
+ * profiling related options and report output.
+**/
+#define PROFILING_IMPLEMENTED 0
+
+#define DEFAULT_THRESHOLD 1000 ///< One millisecond.
+#define DEFAULT_DISPLAYCOUNT 50
+#define MAXIMUM_DISPLAYCOUNT 999999 ///< Arbitrary maximum reasonable number.
+
+#define PERF_MAXDUR 0xFFFFFFFFFFFFFFFFULL
+
+/// Determine whether 0 <= C < L. If L == 0, return true regardless of C.
+#define WITHIN_LIMIT( C, L) ( ((L) == 0) || ((C) < (L)) )
+
+/// Structure for storing Timer specific information.
+typedef struct {
+ UINT64 StartCount; ///< Value timer is initialized with.
+ UINT64 EndCount; ///< Value timer has just before it wraps.
+ UINT32 Frequency; ///< Timer count frequency in KHz.
+ BOOLEAN CountUp; ///< TRUE if the counter counts up.
+} TIMER_INFO;
+
+/** Initialize one PERF_CUM_DATA structure instance for token t.
+ *
+ * This parameterized macro takes a single argument, t, which is expected
+ * to resolve to a pointer to an ASCII string literal. This parameter may
+ * take any one of the following forms:
+ * - PERF_INIT_CUM_DATA("Token") A string literal
+ * - PERF_INIT_CUM_DATA(pointer) A pointer -- CHAR8 *pointer;
+ * - PERF_INIT_CUM_DATA(array) Address of an array -- CHAR8 array[N];
+**/
+#define PERF_INIT_CUM_DATA(t) { 0ULL, PERF_MAXDUR, 0ULL, (t), 0U }
+
+typedef struct {
+ UINT64 Duration; ///< Cumulative duration for this item.
+ UINT64 MinDur; ///< Smallest duration encountered.
+ UINT64 MaxDur; ///< Largest duration encountered.
+ CHAR8 *Name; ///< ASCII name of this item.
+ UINT32 Count; ///< Total number of measurements accumulated.
+} PERF_CUM_DATA;
+
+typedef struct {
+ UINT32 NumTrace; ///< Number of recorded TRACE performance measurements.
+ UINT32 NumProfile; ///< Number of recorded PROFILE performance measurements.
+ UINT32 NumIncomplete; ///< Number of measurements with no END value.
+ UINT32 NumSummary; ///< Number of summary section measurements.
+ UINT32 NumHandles; ///< Number of measurements with handles.
+ UINT32 NumPEIMs; ///< Number of measurements of PEIMs.
+ UINT32 NumGlobal; ///< Number of measurements with END value and NULL handle.
+} PERF_SUMMARY_DATA;
+
+typedef struct {
+ CONST VOID *Handle;
+ CONST CHAR8 *Token; ///< Measured token string name.
+ CONST CHAR8 *Module; ///< Module string name.
+ UINT64 StartTimeStamp; ///< Start time point.
+ UINT64 EndTimeStamp; ///< End time point.
+ UINT32 Identifier; ///< Identifier.
+} MEASUREMENT_RECORD;
+
+typedef struct {
+ CHAR8 *Name; ///< Measured token string name.
+ UINT64 CumulativeTime; ///< Accumulated Elapsed Time.
+ UINT64 MinTime; ///< Minimum Elapsed Time.
+ UINT64 MaxTime; ///< Maximum Elapsed Time.
+ UINT32 Count; ///< Number of measurements accumulated.
+} PROFILE_RECORD;
+
+#endif // _EFI_APP_DP_H_
diff --git a/Core/ShellPkg/Library/UefiDpLib/DpInternal.h b/Core/ShellPkg/Library/UefiDpLib/DpInternal.h
new file mode 100644
index 0000000000..b5ec5f0401
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiDpLib/DpInternal.h
@@ -0,0 +1,356 @@
+/** @file
+ Declarations of objects defined internally to the Dp Application.
+
+ Declarations of data and functions which are private to the Dp application.
+ This file should never be referenced by anything other than components of the
+ Dp application. In addition to global data, function declarations for
+ DpUtilities.c, DpTrace.c, and DpProfile.c are included here.
+
+ Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.
+ (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#ifndef _DP_INTELNAL_H_
+#define _DP_INTELNAL_H_
+
+#define DP_GAUGE_STRING_LENGTH 36
+
+//
+/// Module-Global Variables
+///@{
+extern EFI_HII_HANDLE gDpHiiHandle;
+extern CHAR16 mGaugeString[DP_GAUGE_STRING_LENGTH + 1];
+extern CHAR16 mUnicodeToken[DXE_PERFORMANCE_STRING_SIZE];
+extern UINT64 mInterestThreshold;
+extern BOOLEAN mShowId;
+
+extern PERF_SUMMARY_DATA SummaryData; ///< Create the SummaryData structure and init. to ZERO.
+
+/// Timer Specific Information.
+extern TIMER_INFO TimerInfo;
+
+/// Items for which to gather cumulative statistics.
+extern PERF_CUM_DATA CumData[];
+
+/// Number of items for which we are gathering cumulative statistics.
+extern UINT32 const NumCum;
+
+///@}
+
+/**
+ Calculate an event's duration in timer ticks.
+
+ Given the count direction and the event's start and end timer values,
+ calculate the duration of the event in timer ticks. Information for
+ the current measurement is pointed to by the parameter.
+
+ If the measurement's start time is 1, it indicates that the developer
+ is indicating that the measurement began at the release of reset.
+ The start time is adjusted to the timer's starting count before performing
+ the elapsed time calculation.
+
+ The calculated duration, in ticks, is the absolute difference between
+ the measurement's ending and starting counts.
+
+ @param Measurement Pointer to a MEASUREMENT_RECORD structure containing
+ data for the current measurement.
+
+ @return The 64-bit duration of the event.
+**/
+UINT64
+GetDuration (
+ IN OUT MEASUREMENT_RECORD *Measurement
+ );
+
+/**
+ Determine whether the Measurement record is for an EFI Phase.
+
+ The Token and Module members of the measurement record are checked.
+ Module must be empty and Token must be one of SEC, PEI, DXE, BDS, or SHELL.
+
+ @param[in] Measurement A pointer to the Measurement record to test.
+
+ @retval TRUE The measurement record is for an EFI Phase.
+ @retval FALSE The measurement record is NOT for an EFI Phase.
+**/
+BOOLEAN
+IsPhase(
+ IN MEASUREMENT_RECORD *Measurement
+ );
+
+/**
+ Get the file name portion of the Pdb File Name.
+
+ The portion of the Pdb File Name between the last backslash and
+ either a following period or the end of the string is converted
+ to Unicode and copied into UnicodeBuffer. The name is truncated,
+ if necessary, to ensure that UnicodeBuffer is not overrun.
+
+ @param[in] PdbFileName Pdb file name.
+ @param[out] UnicodeBuffer The resultant Unicode File Name.
+
+**/
+VOID
+DpGetShortPdbFileName (
+ IN CHAR8 *PdbFileName,
+ OUT CHAR16 *UnicodeBuffer
+ );
+
+/**
+ Get a human readable name for an image handle.
+ The following methods will be tried orderly:
+ 1. Image PDB
+ 2. ComponentName2 protocol
+ 3. FFS UI section
+ 4. Image GUID
+ 5. Image DevicePath
+ 6. Unknown Driver Name
+
+ @param[in] Handle
+
+ @post The resulting Unicode name string is stored in the
+ mGaugeString global array.
+
+**/
+VOID
+DpGetNameFromHandle (
+ IN EFI_HANDLE Handle
+ );
+
+/**
+ Calculate the Duration in microseconds.
+
+ Duration is multiplied by 1000, instead of Frequency being divided by 1000 or
+ multiplying the result by 1000, in order to maintain precision. Since Duration is
+ a 64-bit value, multiplying it by 1000 is unlikely to produce an overflow.
+
+ The time is calculated as (Duration * 1000) / Timer_Frequency.
+
+ @param[in] Duration The event duration in timer ticks.
+
+ @return A 64-bit value which is the Elapsed time in microseconds.
+**/
+UINT64
+DurationInMicroSeconds (
+ IN UINT64 Duration
+ );
+
+/**
+ Get index of Measurement Record's match in the CumData array.
+
+ If the Measurement's Token value matches a Token in one of the CumData
+ records, the index of the matching record is returned. The returned
+ index is a signed value so that negative values can indicate that
+ the Measurement didn't match any entry in the CumData array.
+
+ @param[in] Measurement A pointer to a Measurement Record to match against the CumData array.
+
+ @retval <0 Token is not in the CumData array.
+ @retval >=0 Return value is the index into CumData where Token is found.
+**/
+INTN
+GetCumulativeItem(
+ IN MEASUREMENT_RECORD *Measurement
+ );
+
+/**
+ Collect verbose statistics about the logged performance measurements.
+
+ General Summary information for all Trace measurements is gathered and
+ stored within the SummaryData structure. This information is both
+ used internally by subsequent reporting functions, and displayed
+ at the end of verbose reports.
+
+ @pre The SummaryData and CumData structures must be initialized
+ prior to calling this function.
+
+ @post The SummaryData and CumData structures contain statistics for the
+ current performance logs.
+
+ @param[in, out] CustomCumulativeData The pointer to the custom cumulative data.
+
+**/
+VOID
+GatherStatistics(
+ IN OUT PERF_CUM_DATA *CustomCumulativeData OPTIONAL
+ );
+
+/**
+ Gather and print ALL Trace Records.
+
+ Displays all "interesting" Trace measurements in order.<BR>
+ The number of records displayed is controlled by:
+ - records with a duration less than mInterestThreshold microseconds are not displayed.
+ - No more than Limit records are displayed. A Limit of zero will not limit the output.
+ - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not
+ displayed.
+
+ @pre The mInterestThreshold global variable is set to the shortest duration to be printed.
+ The mGaugeString and mUnicodeToken global arrays are used for temporary string storage.
+ They must not be in use by a calling function.
+
+ @param[in] Limit The number of records to print. Zero is ALL.
+ @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_ABORTED The user aborts the operation.
+ @return Others from a call to gBS->LocateHandleBuffer().
+**/
+EFI_STATUS
+DumpAllTrace(
+ IN UINTN Limit,
+ IN BOOLEAN ExcludeFlag
+ );
+
+/**
+ Gather and print Raw Trace Records.
+
+ All Trace measurements with a duration greater than or equal to
+ mInterestThreshold are printed without interpretation.
+
+ The number of records displayed is controlled by:
+ - records with a duration less than mInterestThreshold microseconds are not displayed.
+ - No more than Limit records are displayed. A Limit of zero will not limit the output.
+ - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not
+ displayed.
+
+ @pre The mInterestThreshold global variable is set to the shortest duration to be printed.
+
+ @param[in] Limit The number of records to print. Zero is ALL.
+ @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_ABORTED The user aborts the operation.
+**/
+EFI_STATUS
+DumpRawTrace(
+ IN UINTN Limit,
+ IN BOOLEAN ExcludeFlag
+ );
+
+/**
+ Gather and print Major Phase metrics.
+
+ @param[in] Ticker The timer value for the END of Shell phase
+
+**/
+VOID
+ProcessPhases(
+ IN UINT64 Ticker
+ );
+
+
+/**
+ Gather and print Handle data.
+
+ @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_ABORTED The user aborts the operation.
+ @return Others from a call to gBS->LocateHandleBuffer().
+**/
+EFI_STATUS
+ProcessHandles(
+ IN BOOLEAN ExcludeFlag
+ );
+
+
+/**
+ Gather and print PEIM data.
+
+ Only prints complete PEIM records
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_ABORTED The user aborts the operation.
+**/
+EFI_STATUS
+ProcessPeims(
+ VOID
+ );
+
+/**
+ Gather and print global data.
+
+ Strips out incomplete or "Execution Phase" records
+ Only prints records where Handle is NULL
+ Increment TIndex for every record, even skipped ones, so that we have an
+ indication of every measurement record taken.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_ABORTED The user aborts the operation.
+**/
+EFI_STATUS
+ProcessGlobal(
+ VOID
+ );
+
+/**
+ Gather and print cumulative data.
+
+ Traverse the measurement records and:<BR>
+ For each record with a Token listed in the CumData array:<BR>
+ - Update the instance count and the total, minimum, and maximum durations.
+ Finally, print the gathered cumulative statistics.
+
+ @param[in] CustomCumulativeData The pointer to the custom cumulative data.
+
+**/
+VOID
+ProcessCumulative(
+ IN PERF_CUM_DATA *CustomCumulativeData OPTIONAL
+ );
+
+/**
+ Gather and print ALL Profiling Records.
+
+ Displays all "interesting" Profile measurements in order.
+ The number of records displayed is controlled by:
+ - records with a duration less than mInterestThreshold microseconds are not displayed.
+ - No more than Limit records are displayed. A Limit of zero will not limit the output.
+ - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not
+ displayed.
+
+ @pre The mInterestThreshold global variable is set to the shortest duration to be printed.
+ The mGaugeString and mUnicodeToken global arrays are used for temporary string storage.
+ They must not be in use by a calling function.
+
+ @param[in] Limit The number of records to print. Zero is ALL.
+ @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.
+
+**/
+VOID
+DumpAllProfile(
+ IN UINTN Limit,
+ IN BOOLEAN ExcludeFlag
+ );
+
+/**
+ Gather and print Raw Profile Records.
+
+ All Profile measurements with a duration greater than or equal to
+ mInterestThreshold are printed without interpretation.
+
+ The number of records displayed is controlled by:
+ - records with a duration less than mInterestThreshold microseconds are not displayed.
+ - No more than Limit records are displayed. A Limit of zero will not limit the output.
+ - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not
+ displayed.
+
+ @pre The mInterestThreshold global variable is set to the shortest duration to be printed.
+
+ @param[in] Limit The number of records to print. Zero is ALL.
+ @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.
+
+**/
+VOID
+DumpRawProfile(
+ IN UINTN Limit,
+ IN BOOLEAN ExcludeFlag
+ );
+
+#endif
diff --git a/Core/ShellPkg/Library/UefiDpLib/DpProfile.c b/Core/ShellPkg/Library/UefiDpLib/DpProfile.c
new file mode 100644
index 0000000000..64583988c1
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiDpLib/DpProfile.c
@@ -0,0 +1,101 @@
+/** @file
+ Measured Profiling reporting for the Dp utility.
+
+ Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/TimerLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/PerformanceLib.h>
+#include <Library/PrintLib.h>
+#include <Library/HiiLib.h>
+#include <Library/PcdLib.h>
+
+#include <Guid/Performance.h>
+
+#include "Dp.h"
+#include "Literals.h"
+#include "DpInternal.h"
+
+/**
+ Gather and print ALL Profiling Records.
+
+ Displays all "interesting" Profile measurements in order.
+ The number of records displayed is controlled by:
+ - records with a duration less than mInterestThreshold microseconds are not displayed.
+ - No more than Limit records are displayed. A Limit of zero will not limit the output.
+ - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not
+ displayed.
+
+ @pre The mInterestThreshold global variable is set to the shortest duration to be printed.
+ The mGaugeString and mUnicodeToken global arrays are used for temporary string storage.
+ They must not be in use by a calling function.
+
+ @param[in] Limit The number of records to print. Zero is ALL.
+ @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.
+
+**/
+VOID
+DumpAllProfile(
+ IN UINTN Limit,
+ IN BOOLEAN ExcludeFlag
+ )
+{
+ EFI_STRING StringPtr;
+ EFI_STRING StringPtrUnknown;
+
+ StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
+ StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_PROFILE), NULL);
+
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
+ (StringPtr == NULL) ? StringPtrUnknown: StringPtr);
+ FreePool (StringPtr);
+ FreePool (StringPtrUnknown);
+}
+
+/**
+ Gather and print Raw Profile Records.
+
+ All Profile measurements with a duration greater than or equal to
+ mInterestThreshold are printed without interpretation.
+
+ The number of records displayed is controlled by:
+ - records with a duration less than mInterestThreshold microseconds are not displayed.
+ - No more than Limit records are displayed. A Limit of zero will not limit the output.
+ - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not
+ displayed.
+
+ @pre The mInterestThreshold global variable is set to the shortest duration to be printed.
+
+ @param[in] Limit The number of records to print. Zero is ALL.
+ @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.
+
+**/
+VOID
+DumpRawProfile(
+ IN UINTN Limit,
+ IN BOOLEAN ExcludeFlag
+ )
+{
+ EFI_STRING StringPtr;
+ EFI_STRING StringPtrUnknown;
+
+ StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
+ StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_RAWPROFILE), NULL);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
+ (StringPtr == NULL) ? StringPtrUnknown: StringPtr);
+ FreePool (StringPtr);
+ FreePool (StringPtrUnknown);
+}
diff --git a/Core/ShellPkg/Library/UefiDpLib/DpTrace.c b/Core/ShellPkg/Library/UefiDpLib/DpTrace.c
new file mode 100644
index 0000000000..f3f781fdb9
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiDpLib/DpTrace.c
@@ -0,0 +1,897 @@
+/** @file
+ Trace reporting for the Dp utility.
+
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.
+ (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/TimerLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/PerformanceLib.h>
+#include <Library/PrintLib.h>
+#include <Library/HiiLib.h>
+#include <Library/PcdLib.h>
+
+#include <Guid/Performance.h>
+
+#include "Dp.h"
+#include "Literals.h"
+#include "DpInternal.h"
+
+/**
+ Collect verbose statistics about the logged performance measurements.
+
+ General Summary information for all Trace measurements is gathered and
+ stored within the SummaryData structure. This information is both
+ used internally by subsequent reporting functions, and displayed
+ at the end of verbose reports.
+
+ @pre The SummaryData and CumData structures must be initialized
+ prior to calling this function.
+
+ @post The SummaryData and CumData structures contain statistics for the
+ current performance logs.
+
+ @param[in, out] CustomCumulativeData A pointer to the cumtom cumulative data.
+
+**/
+VOID
+GatherStatistics(
+ IN OUT PERF_CUM_DATA *CustomCumulativeData OPTIONAL
+ )
+{
+ MEASUREMENT_RECORD Measurement;
+ UINT64 Duration;
+ UINTN LogEntryKey;
+ INTN TIndex;
+
+ LogEntryKey = 0;
+ while ((LogEntryKey = GetPerformanceMeasurementEx (
+ LogEntryKey,
+ &Measurement.Handle,
+ &Measurement.Token,
+ &Measurement.Module,
+ &Measurement.StartTimeStamp,
+ &Measurement.EndTimeStamp,
+ &Measurement.Identifier)) != 0)
+ {
+ ++SummaryData.NumTrace; // Count the number of TRACE Measurement records
+ if (Measurement.EndTimeStamp == 0) {
+ ++SummaryData.NumIncomplete; // Count the incomplete records
+ continue;
+ }
+
+ if (Measurement.Handle != NULL) {
+ ++SummaryData.NumHandles; // Count the number of measurements with non-NULL handles
+ }
+
+ if (IsPhase( &Measurement)) {
+ ++SummaryData.NumSummary; // Count the number of major phases
+ }
+ else { // !IsPhase(...
+ if(Measurement.Handle == NULL) {
+ ++SummaryData.NumGlobal;
+ }
+ }
+
+ if (AsciiStrnCmp (Measurement.Token, ALit_PEIM, PERF_TOKEN_LENGTH) == 0) {
+ ++SummaryData.NumPEIMs; // Count PEIM measurements
+ }
+
+ Duration = GetDuration (&Measurement);
+ TIndex = GetCumulativeItem (&Measurement);
+ if (TIndex >= 0) {
+ CumData[TIndex].Duration += Duration;
+ CumData[TIndex].Count++;
+ if ( Duration < CumData[TIndex].MinDur ) {
+ CumData[TIndex].MinDur = Duration;
+ }
+ if ( Duration > CumData[TIndex].MaxDur ) {
+ CumData[TIndex].MaxDur = Duration;
+ }
+ }
+
+ //
+ // Collect the data for custom cumulative data.
+ //
+ if ((CustomCumulativeData != NULL) && (AsciiStrCmp (Measurement.Token, CustomCumulativeData->Name) == 0)) {
+ CustomCumulativeData->Duration += Duration;
+ CustomCumulativeData->Count++;
+ if (Duration < CustomCumulativeData->MinDur) {
+ CustomCumulativeData->MinDur = Duration;
+ }
+ if (Duration > CustomCumulativeData->MaxDur) {
+ CustomCumulativeData->MaxDur = Duration;
+ }
+ }
+ }
+}
+
+/**
+ Gather and print ALL Trace Records.
+
+ Displays all "interesting" Trace measurements in order.<BR>
+ The number of records displayed is controlled by:
+ - records with a duration less than mInterestThreshold microseconds are not displayed.
+ - No more than Limit records are displayed. A Limit of zero will not limit the output.
+ - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not
+ displayed.
+
+ @pre The mInterestThreshold global variable is set to the shortest duration to be printed.
+ The mGaugeString and mUnicodeToken global arrays are used for temporary string storage.
+ They must not be in use by a calling function.
+
+ @param[in] Limit The number of records to print. Zero is ALL.
+ @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_ABORTED The user aborts the operation.
+ @return Others from a call to gBS->LocateHandleBuffer().
+**/
+EFI_STATUS
+DumpAllTrace(
+ IN UINTN Limit,
+ IN BOOLEAN ExcludeFlag
+ )
+{
+ MEASUREMENT_RECORD Measurement;
+ UINT64 ElapsedTime;
+ UINT64 Duration;
+ CHAR16 *IncFlag;
+ UINTN LogEntryKey;
+ UINTN Count;
+ UINTN Index;
+ UINTN TIndex;
+
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+ EFI_STATUS Status;
+ EFI_STRING StringPtrUnknown;
+
+ StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
+ IncFlag = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_ALL), NULL);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
+ (IncFlag == NULL) ? StringPtrUnknown : IncFlag);
+ FreePool (StringPtrUnknown);
+
+ // Get Handle information
+ //
+ Status = gBS->LocateHandleBuffer (AllHandles, NULL, NULL, &HandleCount, &HandleBuffer);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLES_ERROR), gDpHiiHandle, Status);
+ }
+ else {
+ // We have successfully populated the HandleBuffer
+ // Display ALL Measurement Records
+ // Up to Limit lines displayed
+ // Display only records with Elapsed times >= mInterestThreshold
+ // Display driver names in Module field for records with Handles.
+ //
+ if (mShowId) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_HEADR2), gDpHiiHandle);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_DASHES2), gDpHiiHandle);
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_HEADR), gDpHiiHandle);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), gDpHiiHandle);
+ }
+
+ LogEntryKey = 0;
+ Count = 0;
+ Index = 0;
+ while ( WITHIN_LIMIT(Count, Limit) &&
+ ((LogEntryKey = GetPerformanceMeasurementEx (
+ LogEntryKey,
+ &Measurement.Handle,
+ &Measurement.Token,
+ &Measurement.Module,
+ &Measurement.StartTimeStamp,
+ &Measurement.EndTimeStamp,
+ &Measurement.Identifier)) != 0)
+ )
+ {
+ ++Index; // Count every record. First record is 1.
+ ElapsedTime = 0;
+ SHELL_FREE_NON_NULL (IncFlag);
+ if (Measurement.EndTimeStamp != 0) {
+ Duration = GetDuration (&Measurement);
+ ElapsedTime = DurationInMicroSeconds ( Duration );
+ IncFlag = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_COMPLETE), NULL);
+ }
+ else {
+ IncFlag = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_INCOMPLETE), NULL); // Mark incomplete records
+ }
+ if (((Measurement.EndTimeStamp != 0) && (ElapsedTime < mInterestThreshold)) ||
+ ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))
+ ) { // Ignore "uninteresting" or excluded records
+ continue;
+ }
+ ++Count; // Count the number of records printed
+
+ // If Handle is non-zero, see if we can determine a name for the driver
+ AsciiStrToUnicodeStrS (Measurement.Module, mGaugeString, sizeof (mGaugeString) / sizeof (mGaugeString[0])); // Use Module by default
+ AsciiStrToUnicodeStrS (Measurement.Token, mUnicodeToken, sizeof (mUnicodeToken) / sizeof (mUnicodeToken[0]));
+ if (Measurement.Handle != NULL) {
+ // See if the Handle is in the HandleBuffer
+ for (TIndex = 0; TIndex < HandleCount; TIndex++) {
+ if (Measurement.Handle == HandleBuffer[TIndex]) {
+ DpGetNameFromHandle (HandleBuffer[TIndex]);
+ break;
+ }
+ }
+ }
+
+ if (AsciiStrnCmp (Measurement.Token, ALit_PEIM, PERF_TOKEN_LENGTH) == 0) {
+ UnicodeSPrint (mGaugeString, sizeof (mGaugeString), L"%g", Measurement.Handle);
+ }
+
+ // Ensure that the argument strings are not too long.
+ mGaugeString[DP_GAUGE_STRING_LENGTH] = 0;
+ mUnicodeToken[13] = 0;
+
+ if (mShowId) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_VARS2), gDpHiiHandle,
+ Index, // 1 based, Which measurement record is being printed
+ IncFlag,
+ Measurement.Handle,
+ mGaugeString,
+ mUnicodeToken,
+ ElapsedTime,
+ Measurement.Identifier
+ );
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_ALL_VARS), gDpHiiHandle,
+ Index, // 1 based, Which measurement record is being printed
+ IncFlag,
+ Measurement.Handle,
+ mGaugeString,
+ mUnicodeToken,
+ ElapsedTime
+ );
+ }
+ if (ShellGetExecutionBreakFlag ()) {
+ Status = EFI_ABORTED;
+ break;
+ }
+ }
+ }
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+ SHELL_FREE_NON_NULL (IncFlag);
+
+ return Status;
+}
+
+/**
+ Gather and print Raw Trace Records.
+
+ All Trace measurements with a duration greater than or equal to
+ mInterestThreshold are printed without interpretation.
+
+ The number of records displayed is controlled by:
+ - records with a duration less than mInterestThreshold microseconds are not displayed.
+ - No more than Limit records are displayed. A Limit of zero will not limit the output.
+ - If the ExcludeFlag is TRUE, records matching entries in the CumData array are not
+ displayed.
+
+ @pre The mInterestThreshold global variable is set to the shortest duration to be printed.
+
+ @param[in] Limit The number of records to print. Zero is ALL.
+ @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_ABORTED The user aborts the operation.
+**/
+EFI_STATUS
+DumpRawTrace(
+ IN UINTN Limit,
+ IN BOOLEAN ExcludeFlag
+ )
+{
+ MEASUREMENT_RECORD Measurement;
+ UINT64 ElapsedTime;
+ UINT64 Duration;
+ UINTN LogEntryKey;
+ UINTN Count;
+ UINTN Index;
+
+ EFI_STRING StringPtr;
+ EFI_STRING StringPtrUnknown;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
+ StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_RAWTRACE), NULL);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
+ (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
+ FreePool (StringPtr);
+ FreePool (StringPtrUnknown);
+
+ if (mShowId) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_HEADR2), gDpHiiHandle);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_DASHES2), gDpHiiHandle);
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_HEADR), gDpHiiHandle);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_DASHES), gDpHiiHandle);
+ }
+
+ LogEntryKey = 0;
+ Count = 0;
+ Index = 0;
+ while ( WITHIN_LIMIT(Count, Limit) &&
+ ((LogEntryKey = GetPerformanceMeasurementEx (
+ LogEntryKey,
+ &Measurement.Handle,
+ &Measurement.Token,
+ &Measurement.Module,
+ &Measurement.StartTimeStamp,
+ &Measurement.EndTimeStamp,
+ &Measurement.Identifier)) != 0)
+ )
+ {
+ ++Index; // Count every record. First record is 1.
+ ElapsedTime = 0;
+ if (Measurement.EndTimeStamp != 0) {
+ Duration = GetDuration (&Measurement);
+ ElapsedTime = DurationInMicroSeconds ( Duration );
+ }
+ if ((ElapsedTime < mInterestThreshold) ||
+ ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))
+ ) { // Ignore "uninteresting" or Excluded records
+ continue;
+ }
+ ++Count; // Count the number of records printed
+
+ if (mShowId) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_VARS2), gDpHiiHandle,
+ Index, // 1 based, Which measurement record is being printed
+ Measurement.Handle,
+ Measurement.StartTimeStamp,
+ Measurement.EndTimeStamp,
+ Measurement.Token,
+ Measurement.Module,
+ Measurement.Identifier
+ );
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_RAW_VARS), gDpHiiHandle,
+ Index, // 1 based, Which measurement record is being printed
+ Measurement.Handle,
+ Measurement.StartTimeStamp,
+ Measurement.EndTimeStamp,
+ Measurement.Token,
+ Measurement.Module
+ );
+ }
+ if (ShellGetExecutionBreakFlag ()) {
+ Status = EFI_ABORTED;
+ break;
+ }
+ }
+ return Status;
+}
+
+/**
+ Gather and print Major Phase metrics.
+
+ @param[in] Ticker The timer value for the END of Shell phase
+
+**/
+VOID
+ProcessPhases(
+ IN UINT64 Ticker
+ )
+{
+ MEASUREMENT_RECORD Measurement;
+ UINT64 BdsTimeoutValue;
+ UINT64 SecTime;
+ UINT64 PeiTime;
+ UINT64 DxeTime;
+ UINT64 BdsTime;
+ UINT64 ShellTime;
+ UINT64 ElapsedTime;
+ UINT64 Duration;
+ UINT64 Total;
+ EFI_STRING StringPtr;
+ UINTN LogEntryKey;
+ EFI_STRING StringPtrUnknown;
+
+ BdsTimeoutValue = 0;
+ SecTime = 0;
+ PeiTime = 0;
+ DxeTime = 0;
+ BdsTime = 0;
+ ShellTime = 0;
+ //
+ // Get Execution Phase Statistics
+ //
+ StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
+ StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_PHASES), NULL);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
+ (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
+ FreePool (StringPtr);
+ FreePool (StringPtrUnknown);
+
+ LogEntryKey = 0;
+ while ((LogEntryKey = GetPerformanceMeasurementEx (
+ LogEntryKey,
+ &Measurement.Handle,
+ &Measurement.Token,
+ &Measurement.Module,
+ &Measurement.StartTimeStamp,
+ &Measurement.EndTimeStamp,
+ &Measurement.Identifier)) != 0)
+ {
+ if (AsciiStrnCmp (Measurement.Token, ALit_SHELL, PERF_TOKEN_LENGTH) == 0) {
+ Measurement.EndTimeStamp = Ticker;
+ }
+ if (Measurement.EndTimeStamp == 0) { // Skip "incomplete" records
+ continue;
+ }
+ Duration = GetDuration (&Measurement);
+ if ( Measurement.Handle != NULL
+ && (AsciiStrnCmp (Measurement.Token, ALit_BdsTO, PERF_TOKEN_LENGTH) == 0)
+ )
+ {
+ BdsTimeoutValue = Duration;
+ } else if (AsciiStrnCmp (Measurement.Token, ALit_SEC, PERF_TOKEN_LENGTH) == 0) {
+ SecTime = Duration;
+ } else if (AsciiStrnCmp (Measurement.Token, ALit_PEI, PERF_TOKEN_LENGTH) == 0) {
+ PeiTime = Duration;
+ } else if (AsciiStrnCmp (Measurement.Token, ALit_DXE, PERF_TOKEN_LENGTH) == 0) {
+ DxeTime = Duration;
+ } else if (AsciiStrnCmp (Measurement.Token, ALit_BDS, PERF_TOKEN_LENGTH) == 0) {
+ BdsTime = Duration;
+ } else if (AsciiStrnCmp (Measurement.Token, ALit_SHELL, PERF_TOKEN_LENGTH) == 0) {
+ ShellTime = Duration;
+ }
+ }
+
+ Total = 0;
+
+ // print SEC phase duration time
+ //
+ if (SecTime > 0) {
+ ElapsedTime = DurationInMicroSeconds ( SecTime ); // Calculate elapsed time in microseconds
+ Total += DivU64x32 (ElapsedTime, 1000); // Accumulate time in milliseconds
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SEC_PHASE), gDpHiiHandle, ElapsedTime);
+ }
+
+ // print PEI phase duration time
+ //
+ if (PeiTime > 0) {
+ ElapsedTime = DivU64x32 (
+ PeiTime,
+ (UINT32)TimerInfo.Frequency
+ );
+ Total += ElapsedTime;
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), gDpHiiHandle, ALit_PEI, ElapsedTime);
+ }
+
+ // print DXE phase duration time
+ //
+ if (DxeTime > 0) {
+ ElapsedTime = DivU64x32 (
+ DxeTime,
+ (UINT32)TimerInfo.Frequency
+ );
+ Total += ElapsedTime;
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), gDpHiiHandle, ALit_DXE, ElapsedTime);
+ }
+
+ // print BDS phase duration time
+ //
+ if (BdsTime > 0) {
+ ElapsedTime = DivU64x32 (
+ BdsTime,
+ (UINT32)TimerInfo.Frequency
+ );
+ Total += ElapsedTime;
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), gDpHiiHandle, ALit_BDS, ElapsedTime);
+ }
+
+ if (BdsTimeoutValue > 0) {
+ ElapsedTime = DivU64x32 (
+ BdsTimeoutValue,
+ (UINT32)TimerInfo.Frequency
+ );
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_BDSTO), gDpHiiHandle, ALit_BdsTO, ElapsedTime);
+ }
+
+ // print SHELL phase duration time
+ //
+ if (ShellTime > 0) {
+ ElapsedTime = DivU64x32 (
+ ShellTime,
+ (UINT32)TimerInfo.Frequency
+ );
+ Total += ElapsedTime;
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PHASE_DURATION), gDpHiiHandle, ALit_SHELL, ElapsedTime);
+ }
+
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_TOTAL_DURATION), gDpHiiHandle, Total);
+}
+
+/**
+ Gather and print Handle data.
+
+ @param[in] ExcludeFlag TRUE to exclude individual Cumulative items from display.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_ABORTED The user aborts the operation.
+ @return Others from a call to gBS->LocateHandleBuffer().
+**/
+EFI_STATUS
+ProcessHandles(
+ IN BOOLEAN ExcludeFlag
+ )
+{
+ MEASUREMENT_RECORD Measurement;
+ UINT64 ElapsedTime;
+ UINT64 Duration;
+ EFI_HANDLE *HandleBuffer;
+ EFI_STRING StringPtr;
+ UINTN Index;
+ UINTN LogEntryKey;
+ UINTN Count;
+ UINTN HandleCount;
+ EFI_STATUS Status;
+ EFI_STRING StringPtrUnknown;
+
+ StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
+ StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_DRIVERS), NULL);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
+ (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
+ FreePool (StringPtr);
+ FreePool (StringPtrUnknown);
+
+ Status = gBS->LocateHandleBuffer (AllHandles, NULL, NULL, &HandleCount, &HandleBuffer);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLES_ERROR), gDpHiiHandle, Status);
+ }
+ else {
+#if DP_DEBUG == 2
+ Print (L"There are %,d Handles defined.\n", (Size / sizeof(HandleBuffer[0])));
+#endif
+
+ if (mShowId) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_SECTION2), gDpHiiHandle);
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_SECTION), gDpHiiHandle);
+ }
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), gDpHiiHandle);
+
+ LogEntryKey = 0;
+ Count = 0;
+ while ((LogEntryKey = GetPerformanceMeasurementEx (
+ LogEntryKey,
+ &Measurement.Handle,
+ &Measurement.Token,
+ &Measurement.Module,
+ &Measurement.StartTimeStamp,
+ &Measurement.EndTimeStamp,
+ &Measurement.Identifier)) != 0)
+ {
+ Count++;
+ Duration = GetDuration (&Measurement);
+ ElapsedTime = DurationInMicroSeconds ( Duration );
+ if ((ElapsedTime < mInterestThreshold) ||
+ (Measurement.EndTimeStamp == 0) ||
+ (Measurement.Handle == NULL) ||
+ ((ExcludeFlag) && (GetCumulativeItem(&Measurement) >= 0))
+ ) { // Ignore "uninteresting" or excluded records
+ continue;
+ }
+ mGaugeString[0] = 0; // Empty driver name by default
+ AsciiStrToUnicodeStrS (Measurement.Token, mUnicodeToken, sizeof (mUnicodeToken) / sizeof (mUnicodeToken[0]));
+ // See if the Handle is in the HandleBuffer
+ for (Index = 0; Index < HandleCount; Index++) {
+ if (Measurement.Handle == HandleBuffer[Index]) {
+ DpGetNameFromHandle (HandleBuffer[Index]); // Name is put into mGaugeString
+ break;
+ }
+ }
+ // Ensure that the argument strings are not too long.
+ mGaugeString[DP_GAUGE_STRING_LENGTH] = 0;
+ mUnicodeToken[11] = 0;
+ if (mGaugeString[0] != 0) {
+ // Display the record if it has a valid handle.
+ if (mShowId) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_VARS2), gDpHiiHandle,
+ Count, // 1 based, Which measurement record is being printed
+ Index + 1, // 1 based, Which handle is being printed
+ mGaugeString,
+ mUnicodeToken,
+ ElapsedTime,
+ Measurement.Identifier
+ );
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_HANDLE_VARS), gDpHiiHandle,
+ Count, // 1 based, Which measurement record is being printed
+ Index + 1, // 1 based, Which handle is being printed
+ mGaugeString,
+ mUnicodeToken,
+ ElapsedTime
+ );
+ }
+ }
+ if (ShellGetExecutionBreakFlag ()) {
+ Status = EFI_ABORTED;
+ break;
+ }
+ }
+ }
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+ return Status;
+}
+
+/**
+ Gather and print PEIM data.
+
+ Only prints complete PEIM records
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_ABORTED The user aborts the operation.
+**/
+EFI_STATUS
+ProcessPeims(
+ VOID
+)
+{
+ MEASUREMENT_RECORD Measurement;
+ UINT64 Duration;
+ UINT64 ElapsedTime;
+ EFI_STRING StringPtr;
+ UINTN LogEntryKey;
+ UINTN TIndex;
+ EFI_STRING StringPtrUnknown;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
+ StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_PEIMS), NULL);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
+ (StringPtr == NULL) ? StringPtrUnknown : StringPtr);
+ FreePool (StringPtr);
+ FreePool (StringPtrUnknown);
+
+ if (mShowId) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_SECTION2), gDpHiiHandle);
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_SECTION), gDpHiiHandle);
+ }
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), gDpHiiHandle);
+ TIndex = 0;
+ LogEntryKey = 0;
+ while ((LogEntryKey = GetPerformanceMeasurementEx (
+ LogEntryKey,
+ &Measurement.Handle,
+ &Measurement.Token,
+ &Measurement.Module,
+ &Measurement.StartTimeStamp,
+ &Measurement.EndTimeStamp,
+ &Measurement.Identifier)) != 0)
+ {
+ TIndex++;
+ if ((Measurement.EndTimeStamp == 0) ||
+ (AsciiStrnCmp (Measurement.Token, ALit_PEIM, PERF_TOKEN_LENGTH) != 0)
+ ) {
+ continue;
+ }
+
+ Duration = GetDuration (&Measurement);
+ ElapsedTime = DurationInMicroSeconds ( Duration ); // Calculate elapsed time in microseconds
+ if (ElapsedTime >= mInterestThreshold) {
+ // PEIM FILE Handle is the start address of its FFS file that contains its file guid.
+ if (mShowId) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_VARS2), gDpHiiHandle,
+ TIndex, // 1 based, Which measurement record is being printed
+ Measurement.Handle, // base address
+ Measurement.Handle, // file guid
+ ElapsedTime,
+ Measurement.Identifier
+ );
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_PEIM_VARS), gDpHiiHandle,
+ TIndex, // 1 based, Which measurement record is being printed
+ Measurement.Handle, // base address
+ Measurement.Handle, // file guid
+ ElapsedTime
+ );
+ }
+ }
+ if (ShellGetExecutionBreakFlag ()) {
+ Status = EFI_ABORTED;
+ break;
+ }
+ }
+ return Status;
+}
+
+/**
+ Gather and print global data.
+
+ Strips out incomplete or "Execution Phase" records
+ Only prints records where Handle is NULL
+ Increment TIndex for every record, even skipped ones, so that we have an
+ indication of every measurement record taken.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_ABORTED The user aborts the operation.
+**/
+EFI_STATUS
+ProcessGlobal(
+ VOID
+)
+{
+ MEASUREMENT_RECORD Measurement;
+ UINT64 Duration;
+ UINT64 ElapsedTime;
+ EFI_STRING StringPtr;
+ UINTN LogEntryKey;
+ UINTN Index; // Index, or number, of the measurement record being processed
+ EFI_STRING StringPtrUnknown;
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
+ StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_GENERAL), NULL);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
+ (StringPtr == NULL) ? StringPtrUnknown: StringPtr);
+ FreePool (StringPtr);
+ FreePool (StringPtrUnknown);
+
+ if (mShowId) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_SECTION2), gDpHiiHandle);
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_SECTION), gDpHiiHandle);
+ }
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), gDpHiiHandle);
+
+ Index = 1;
+ LogEntryKey = 0;
+
+ while ((LogEntryKey = GetPerformanceMeasurementEx (
+ LogEntryKey,
+ &Measurement.Handle,
+ &Measurement.Token,
+ &Measurement.Module,
+ &Measurement.StartTimeStamp,
+ &Measurement.EndTimeStamp,
+ &Measurement.Identifier)) != 0)
+ {
+ AsciiStrToUnicodeStrS (Measurement.Module, mGaugeString, sizeof (mGaugeString) / sizeof (mGaugeString[0]));
+ AsciiStrToUnicodeStrS (Measurement.Token, mUnicodeToken, sizeof (mUnicodeToken) / sizeof (mUnicodeToken[0]));
+ mGaugeString[25] = 0;
+ mUnicodeToken[31] = 0;
+ if ( ! ( IsPhase( &Measurement) ||
+ (Measurement.Handle != NULL) ||
+ (Measurement.EndTimeStamp == 0)
+ ))
+ {
+ Duration = GetDuration (&Measurement);
+ ElapsedTime = DurationInMicroSeconds ( Duration );
+ if (ElapsedTime >= mInterestThreshold) {
+ if (mShowId) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_VARS2), gDpHiiHandle,
+ Index,
+ mGaugeString,
+ mUnicodeToken,
+ ElapsedTime,
+ Measurement.Identifier
+ );
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_GLOBAL_VARS), gDpHiiHandle,
+ Index,
+ mGaugeString,
+ mUnicodeToken,
+ ElapsedTime
+ );
+ }
+ }
+ }
+ if (ShellGetExecutionBreakFlag ()) {
+ Status = EFI_ABORTED;
+ break;
+ }
+ Index++;
+ }
+ return Status;
+}
+
+/**
+ Gather and print cumulative data.
+
+ Traverse the measurement records and:<BR>
+ For each record with a Token listed in the CumData array:<BR>
+ - Update the instance count and the total, minimum, and maximum durations.
+ Finally, print the gathered cumulative statistics.
+
+ @param[in] CustomCumulativeData A pointer to the cumtom cumulative data.
+
+**/
+VOID
+ProcessCumulative(
+ IN PERF_CUM_DATA *CustomCumulativeData OPTIONAL
+ )
+{
+ UINT64 AvgDur; // the computed average duration
+ UINT64 Dur;
+ UINT64 MinDur;
+ UINT64 MaxDur;
+ EFI_STRING StringPtr;
+ UINTN TIndex;
+ EFI_STRING StringPtrUnknown;
+
+ StringPtrUnknown = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_ALIT_UNKNOWN), NULL);
+ StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_SECTION_CUMULATIVE), NULL);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_SECTION_HEADER), gDpHiiHandle,
+ (StringPtr == NULL) ? StringPtrUnknown: StringPtr);
+ FreePool (StringPtr);
+ FreePool (StringPtrUnknown);
+
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_SECT_1), gDpHiiHandle);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_SECT_2), gDpHiiHandle);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_DASHES), gDpHiiHandle);
+
+ for ( TIndex = 0; TIndex < NumCum; ++TIndex) {
+ if (CumData[TIndex].Count != 0) {
+ AvgDur = DivU64x32 (CumData[TIndex].Duration, CumData[TIndex].Count);
+ AvgDur = DurationInMicroSeconds(AvgDur);
+ Dur = DurationInMicroSeconds(CumData[TIndex].Duration);
+ MaxDur = DurationInMicroSeconds(CumData[TIndex].MaxDur);
+ MinDur = DurationInMicroSeconds(CumData[TIndex].MinDur);
+
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_STATS), gDpHiiHandle,
+ CumData[TIndex].Name,
+ CumData[TIndex].Count,
+ Dur,
+ AvgDur,
+ MinDur,
+ MaxDur
+ );
+ }
+ }
+
+ //
+ // Print the custom cumulative data.
+ //
+ if (CustomCumulativeData != NULL) {
+ if (CustomCumulativeData->Count != 0) {
+ AvgDur = DivU64x32 (CustomCumulativeData->Duration, CustomCumulativeData->Count);
+ AvgDur = DurationInMicroSeconds (AvgDur);
+ Dur = DurationInMicroSeconds (CustomCumulativeData->Duration);
+ MaxDur = DurationInMicroSeconds (CustomCumulativeData->MaxDur);
+ MinDur = DurationInMicroSeconds (CustomCumulativeData->MinDur);
+ } else {
+ AvgDur = 0;
+ Dur = 0;
+ MaxDur = 0;
+ MinDur = 0;
+ }
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DP_CUMULATIVE_STATS), gDpHiiHandle,
+ CustomCumulativeData->Name,
+ CustomCumulativeData->Count,
+ Dur,
+ AvgDur,
+ MinDur,
+ MaxDur
+ );
+ }
+}
diff --git a/Core/ShellPkg/Library/UefiDpLib/DpUtilities.c b/Core/ShellPkg/Library/UefiDpLib/DpUtilities.c
new file mode 100644
index 0000000000..fbdd938bc3
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiDpLib/DpUtilities.c
@@ -0,0 +1,405 @@
+/** @file
+ Utility functions used by the Dp application.
+
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.
+ (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/TimerLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/PrintLib.h>
+#include <Library/HiiLib.h>
+#include <Library/PcdLib.h>
+#include <Library/UefiLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HandleParsingLib.h>
+
+#include <Pi/PiFirmwareFile.h>
+#include <Library/DxeServicesLib.h>
+
+#include <Protocol/LoadedImage.h>
+#include <Protocol/DriverBinding.h>
+#include <Protocol/ComponentName2.h>
+#include <Protocol/DevicePath.h>
+
+#include <Guid/Performance.h>
+
+#include "Dp.h"
+#include "Literals.h"
+#include "DpInternal.h"
+
+/**
+ Calculate an event's duration in timer ticks.
+
+ Given the count direction and the event's start and end timer values,
+ calculate the duration of the event in timer ticks. Information for
+ the current measurement is pointed to by the parameter.
+
+ If the measurement's start time is 1, it indicates that the developer
+ is indicating that the measurement began at the release of reset.
+ The start time is adjusted to the timer's starting count before performing
+ the elapsed time calculation.
+
+ The calculated duration, in ticks, is the absolute difference between
+ the measurement's ending and starting counts.
+
+ @param Measurement Pointer to a MEASUREMENT_RECORD structure containing
+ data for the current measurement.
+
+ @return The 64-bit duration of the event.
+**/
+UINT64
+GetDuration (
+ IN OUT MEASUREMENT_RECORD *Measurement
+ )
+{
+ UINT64 Duration;
+ BOOLEAN Error;
+
+ if (Measurement->EndTimeStamp == 0) {
+ return 0;
+ }
+
+ // PERF_START macros are called with a value of 1 to indicate
+ // the beginning of time. So, adjust the start ticker value
+ // to the real beginning of time.
+ // Assumes no wraparound. Even then, there is a very low probability
+ // of having a valid StartTicker value of 1.
+ if (Measurement->StartTimeStamp == 1) {
+ Measurement->StartTimeStamp = TimerInfo.StartCount;
+ }
+ if (TimerInfo.CountUp) {
+ Duration = Measurement->EndTimeStamp - Measurement->StartTimeStamp;
+ Error = (BOOLEAN)(Duration > Measurement->EndTimeStamp);
+ }
+ else {
+ Duration = Measurement->StartTimeStamp - Measurement->EndTimeStamp;
+ Error = (BOOLEAN)(Duration > Measurement->StartTimeStamp);
+ }
+
+ if (Error) {
+ DEBUG ((EFI_D_ERROR, ALit_TimerLibError));
+ Duration = 0;
+ }
+ return Duration;
+}
+
+/**
+ Determine whether the Measurement record is for an EFI Phase.
+
+ The Token and Module members of the measurement record are checked.
+ Module must be empty and Token must be one of SEC, PEI, DXE, BDS, or SHELL.
+
+ @param[in] Measurement A pointer to the Measurement record to test.
+
+ @retval TRUE The measurement record is for an EFI Phase.
+ @retval FALSE The measurement record is NOT for an EFI Phase.
+**/
+BOOLEAN
+IsPhase(
+ IN MEASUREMENT_RECORD *Measurement
+ )
+{
+ BOOLEAN RetVal;
+
+ RetVal = (BOOLEAN)( ( *Measurement->Module == '\0') &&
+ ((AsciiStrnCmp (Measurement->Token, ALit_SEC, PERF_TOKEN_LENGTH) == 0) ||
+ (AsciiStrnCmp (Measurement->Token, ALit_PEI, PERF_TOKEN_LENGTH) == 0) ||
+ (AsciiStrnCmp (Measurement->Token, ALit_DXE, PERF_TOKEN_LENGTH) == 0) ||
+ (AsciiStrnCmp (Measurement->Token, ALit_BDS, PERF_TOKEN_LENGTH) == 0))
+ );
+ return RetVal;
+}
+
+/**
+ Get the file name portion of the Pdb File Name.
+
+ The portion of the Pdb File Name between the last backslash and
+ either a following period or the end of the string is converted
+ to Unicode and copied into UnicodeBuffer. The name is truncated,
+ if necessary, to ensure that UnicodeBuffer is not overrun.
+
+ @param[in] PdbFileName Pdb file name.
+ @param[out] UnicodeBuffer The resultant Unicode File Name.
+
+**/
+VOID
+DpGetShortPdbFileName (
+ IN CHAR8 *PdbFileName,
+ OUT CHAR16 *UnicodeBuffer
+ )
+{
+ UINTN IndexA; // Current work location within an ASCII string.
+ UINTN IndexU; // Current work location within a Unicode string.
+ UINTN StartIndex;
+ UINTN EndIndex;
+
+ ZeroMem (UnicodeBuffer, (DP_GAUGE_STRING_LENGTH + 1) * sizeof (CHAR16));
+
+ if (PdbFileName == NULL) {
+ StrnCpyS (UnicodeBuffer, DP_GAUGE_STRING_LENGTH + 1, L" ", 1);
+ } else {
+ StartIndex = 0;
+ for (EndIndex = 0; PdbFileName[EndIndex] != 0; EndIndex++)
+ ;
+ for (IndexA = 0; PdbFileName[IndexA] != 0; IndexA++) {
+ if (PdbFileName[IndexA] == '\\') {
+ StartIndex = IndexA + 1;
+ }
+
+ if (PdbFileName[IndexA] == '.') {
+ EndIndex = IndexA;
+ }
+ }
+
+ IndexU = 0;
+ for (IndexA = StartIndex; IndexA < EndIndex; IndexA++) {
+ UnicodeBuffer[IndexU] = (CHAR16) PdbFileName[IndexA];
+ IndexU++;
+ if (IndexU >= DP_GAUGE_STRING_LENGTH) {
+ UnicodeBuffer[DP_GAUGE_STRING_LENGTH] = 0;
+ break;
+ }
+ }
+ }
+}
+
+/**
+ Get a human readable name for an image handle.
+ The following methods will be tried orderly:
+ 1. Image PDB
+ 2. ComponentName2 protocol
+ 3. FFS UI section
+ 4. Image GUID
+ 5. Image DevicePath
+ 6. Unknown Driver Name
+
+ @param[in] Handle
+
+ @post The resulting Unicode name string is stored in the
+ mGaugeString global array.
+
+**/
+VOID
+DpGetNameFromHandle (
+ IN EFI_HANDLE Handle
+ )
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *Image;
+ CHAR8 *PdbFileName;
+ EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
+ EFI_STRING StringPtr;
+ EFI_DEVICE_PATH_PROTOCOL *LoadedImageDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_GUID *NameGuid;
+ CHAR16 *NameString;
+ UINTN StringSize;
+ CHAR8 *PlatformLanguage;
+ EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;
+
+ Image = NULL;
+ LoadedImageDevicePath = NULL;
+ DevicePath = NULL;
+
+ //
+ // Method 1: Get the name string from image PDB
+ //
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **) &Image
+ );
+
+ if (EFI_ERROR (Status)) {
+ Status = gBS->OpenProtocol (
+ Handle,
+ &gEfiDriverBindingProtocolGuid,
+ (VOID **) &DriverBinding,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->HandleProtocol (
+ DriverBinding->ImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **) &Image
+ );
+ }
+ }
+
+ if (!EFI_ERROR (Status)) {
+ PdbFileName = PeCoffLoaderGetPdbPointer (Image->ImageBase);
+
+ if (PdbFileName != NULL) {
+ DpGetShortPdbFileName (PdbFileName, mGaugeString);
+ return;
+ }
+ }
+
+ //
+ // Method 2: Get the name string from ComponentName2 protocol
+ //
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiComponentName2ProtocolGuid,
+ (VOID **) &ComponentName2
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Get the current platform language setting
+ //
+ PlatformLanguage = GetBestLanguageForDriver(ComponentName2->SupportedLanguages, NULL, FALSE);
+ Status = ComponentName2->GetDriverName (
+ ComponentName2,
+ PlatformLanguage != NULL ? PlatformLanguage : "en-US",
+ &StringPtr
+ );
+ if (!EFI_ERROR (Status)) {
+ SHELL_FREE_NON_NULL (PlatformLanguage);
+ StrnCpyS (mGaugeString, DP_GAUGE_STRING_LENGTH + 1, StringPtr, DP_GAUGE_STRING_LENGTH);
+ mGaugeString[DP_GAUGE_STRING_LENGTH] = 0;
+ return;
+ }
+ }
+
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiLoadedImageDevicePathProtocolGuid,
+ (VOID **) &LoadedImageDevicePath
+ );
+ if (!EFI_ERROR (Status) && (LoadedImageDevicePath != NULL)) {
+ DevicePath = LoadedImageDevicePath;
+ } else if (Image != NULL) {
+ DevicePath = Image->FilePath;
+ }
+
+ if (DevicePath != NULL) {
+ //
+ // Try to get image GUID from image DevicePath
+ //
+ NameGuid = NULL;
+ while (!IsDevicePathEndType (DevicePath)) {
+ NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) DevicePath);
+ if (NameGuid != NULL) {
+ break;
+ }
+ DevicePath = NextDevicePathNode (DevicePath);
+ }
+
+ if (NameGuid != NULL) {
+ //
+ // Try to get the image's FFS UI section by image GUID
+ //
+ NameString = NULL;
+ StringSize = 0;
+ Status = GetSectionFromAnyFv (
+ NameGuid,
+ EFI_SECTION_USER_INTERFACE,
+ 0,
+ (VOID **) &NameString,
+ &StringSize
+ );
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // Method 3. Get the name string from FFS UI section
+ //
+ StrnCpyS (mGaugeString, DP_GAUGE_STRING_LENGTH + 1, NameString, DP_GAUGE_STRING_LENGTH);
+ mGaugeString[DP_GAUGE_STRING_LENGTH] = 0;
+ FreePool (NameString);
+ } else {
+ //
+ // Method 4: Get the name string from image GUID
+ //
+ UnicodeSPrint (mGaugeString, sizeof (mGaugeString), L"%g", NameGuid);
+ }
+ return;
+ } else {
+ //
+ // Method 5: Get the name string from image DevicePath
+ //
+ NameString = ConvertDevicePathToText (DevicePath, TRUE, FALSE);
+ if (NameString != NULL) {
+ StrnCpyS (mGaugeString, DP_GAUGE_STRING_LENGTH + 1, NameString, DP_GAUGE_STRING_LENGTH);
+ mGaugeString[DP_GAUGE_STRING_LENGTH] = 0;
+ FreePool (NameString);
+ return;
+ }
+ }
+ }
+
+ //
+ // Method 6: Unknown Driver Name
+ //
+ StringPtr = HiiGetString (gDpHiiHandle, STRING_TOKEN (STR_DP_ERROR_NAME), NULL);
+ ASSERT (StringPtr != NULL);
+ StrnCpyS (mGaugeString, DP_GAUGE_STRING_LENGTH + 1, StringPtr, DP_GAUGE_STRING_LENGTH);
+ FreePool (StringPtr);
+}
+
+/**
+ Calculate the Duration in microseconds.
+
+ Duration is multiplied by 1000, instead of Frequency being divided by 1000 or
+ multiplying the result by 1000, in order to maintain precision. Since Duration is
+ a 64-bit value, multiplying it by 1000 is unlikely to produce an overflow.
+
+ The time is calculated as (Duration * 1000) / Timer_Frequency.
+
+ @param[in] Duration The event duration in timer ticks.
+
+ @return A 64-bit value which is the Elapsed time in microseconds.
+**/
+UINT64
+DurationInMicroSeconds (
+ IN UINT64 Duration
+ )
+{
+ UINT64 Temp;
+
+ Temp = MultU64x32 (Duration, 1000);
+ return DivU64x32 (Temp, TimerInfo.Frequency);
+}
+
+/**
+ Get index of Measurement Record's match in the CumData array.
+
+ If the Measurement's Token value matches a Token in one of the CumData
+ records, the index of the matching record is returned. The returned
+ index is a signed value so that negative values can indicate that
+ the Measurement didn't match any entry in the CumData array.
+
+ @param[in] Measurement A pointer to a Measurement Record to match against the CumData array.
+
+ @retval <0 Token is not in the CumData array.
+ @retval >=0 Return value is the index into CumData where Token is found.
+**/
+INTN
+GetCumulativeItem(
+ IN MEASUREMENT_RECORD *Measurement
+ )
+{
+ INTN Index;
+
+ for( Index = 0; Index < (INTN)NumCum; ++Index) {
+ if (AsciiStrnCmp (Measurement->Token, CumData[Index].Name, PERF_TOKEN_LENGTH) == 0) {
+ return Index; // Exit, we found a match
+ }
+ }
+ // If the for loop exits, Token was not found.
+ return -1; // Indicate failure
+}
diff --git a/Core/ShellPkg/Library/UefiDpLib/Literals.c b/Core/ShellPkg/Library/UefiDpLib/Literals.c
new file mode 100644
index 0000000000..68de0fbc9e
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiDpLib/Literals.c
@@ -0,0 +1,23 @@
+/** @file
+ Definitions of ASCII string literals used by DP.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#include <PerformanceTokens.h>
+
+// ASCII String literals which probably don't need translation
+CHAR8 const ALit_TimerLibError[] = "Timer library instance error!\n";
+CHAR8 const ALit_SEC[] = SEC_TOK;
+CHAR8 const ALit_DXE[] = DXE_TOK;
+CHAR8 const ALit_SHELL[] = SHELL_TOK;
+CHAR8 const ALit_PEI[] = PEI_TOK;
+CHAR8 const ALit_BDS[] = BDS_TOK;
+CHAR8 const ALit_BdsTO[] = "BdsTimeOut";
+CHAR8 const ALit_PEIM[] = "PEIM";
diff --git a/Core/ShellPkg/Library/UefiDpLib/Literals.h b/Core/ShellPkg/Library/UefiDpLib/Literals.h
new file mode 100644
index 0000000000..8aec09c024
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiDpLib/Literals.h
@@ -0,0 +1,26 @@
+/** @file
+ Declarations of ASCII string literals used by DP.
+
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+#ifndef _LITERALS_H_
+#define _LITERALS_H_
+
+// ASCII String literals which probably don't need translation
+extern CHAR8 const ALit_TimerLibError[];
+extern CHAR8 const ALit_SEC[];
+extern CHAR8 const ALit_DXE[];
+extern CHAR8 const ALit_SHELL[];
+extern CHAR8 const ALit_PEI[];
+extern CHAR8 const ALit_BDS[];
+extern CHAR8 const ALit_BdsTO[];
+extern CHAR8 const ALit_PEIM[];
+
+#endif // _LITERALS_H_
diff --git a/Core/ShellPkg/Library/UefiDpLib/PerformanceTokens.h b/Core/ShellPkg/Library/UefiDpLib/PerformanceTokens.h
new file mode 100644
index 0000000000..bbbc48d776
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiDpLib/PerformanceTokens.h
@@ -0,0 +1,28 @@
+/** @file
+ ASCII String Literals with special meaning to Performance measurement and the Dp utility.
+
+Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef __PERFORMANCE_TOKENS_H__
+#define __PERFORMANCE_TOKENS_H__
+
+#define SEC_TOK "SEC" ///< SEC Phase
+#define DXE_TOK "DXE" ///< DEC Phase
+#define SHELL_TOK "SHELL" ///< Shell Phase
+#define PEI_TOK "PEI" ///< PEI Phase
+#define BDS_TOK "BDS" ///< BDS Phase
+#define DRIVERBINDING_START_TOK "DB:Start:" ///< Driver Binding Start() function call
+#define DRIVERBINDING_SUPPORT_TOK "DB:Support:" ///< Driver Binding Support() function call
+#define LOAD_IMAGE_TOK "LoadImage:" ///< Load a dispatched module
+#define START_IMAGE_TOK "StartImage:" ///< Dispatched Modules Entry Point execution
+
+#endif // __PERFORMANCE_TOKENS_H__
diff --git a/Core/ShellPkg/Library/UefiDpLib/Readme.txt b/Core/ShellPkg/Library/UefiDpLib/Readme.txt
new file mode 100644
index 0000000000..849efa4360
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiDpLib/Readme.txt
@@ -0,0 +1,2 @@
+from PerformancePkg\Dp_App
+SVN 13406
diff --git a/Core/ShellPkg/Library/UefiDpLib/UefiDpLib.c b/Core/ShellPkg/Library/UefiDpLib/UefiDpLib.c
new file mode 100644
index 0000000000..f3ecfeac7f
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiDpLib/UefiDpLib.c
@@ -0,0 +1,101 @@
+/** @file
+ Main file for NULL named library for install1 shell command functions.
+
+ Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiDpLib.h"
+
+STATIC CONST CHAR16 mFileName[] = L"ShellCommands";
+EFI_HANDLE gDpHiiHandle = NULL;
+
+#define DP_HII_GUID \
+ { \
+ 0xeb832fd9, 0x9089, 0x4898, { 0x83, 0xc9, 0x41, 0x61, 0x8f, 0x5c, 0x48, 0xb9 } \
+ }
+
+EFI_GUID gDpHiiGuid = DP_HII_GUID;
+
+/**
+ Function to get the filename with help context if HII will not be used.
+
+ @return The filename with help text in it.
+**/
+CONST CHAR16*
+EFIAPI
+UefiDpLibGetManFileName (
+ VOID
+ )
+{
+ return (mFileName);
+}
+
+/**
+ Constructor for the Shell Level 1 Commands library.
+
+ Install the handlers for level 1 UEFI Shell 2.0 commands.
+
+ @param ImageHandle the image handle of the process
+ @param SystemTable the EFI System Table pointer
+
+ @retval EFI_SUCCESS the shell command handlers were installed sucessfully
+ @retval EFI_UNSUPPORTED the shell level required was not found.
+**/
+EFI_STATUS
+EFIAPI
+UefiDpLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ //
+ // check our bit of the profiles mask
+ //
+ if ((PcdGet8(PcdShellProfileMask) & BIT2) == 0) {
+ return (EFI_SUCCESS);
+ }
+
+ //
+ // 3rd parameter 'HII strings array' must be name of .uni strings file followed by 'Strings', e.g. mycommands.uni must be
+ // specified as 'mycommandsStrings' because the build Autogen process defines this as a string array for the strings in your
+ // .uni file. Examine your Build folder under your package's DEBUG folder and you will find it defined in a xxxStrDefs.h file.
+ //
+ gDpHiiHandle = HiiAddPackages (&gDpHiiGuid, gImageHandle, UefiDpLibStrings, NULL);
+ if (gDpHiiHandle == NULL) {
+ return (EFI_DEVICE_ERROR);
+ }
+
+ //
+ // install our shell command handlers that are always installed
+ //
+ ShellCommandRegisterCommandName(L"dp", ShellCommandRunDp , UefiDpLibGetManFileName, 0, L"", FALSE, gDpHiiHandle, STRING_TOKEN(STR_GET_HELP_DP));
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Destructor for the library. free any resources.
+
+ @param ImageHandle The image handle of the process.
+ @param SystemTable The EFI System Table pointer.
+**/
+EFI_STATUS
+EFIAPI
+UefiDpLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ if (gDpHiiHandle != NULL) {
+ HiiRemovePackages(gDpHiiHandle);
+ }
+ return (EFI_SUCCESS);
+}
diff --git a/Core/ShellPkg/Library/UefiDpLib/UefiDpLib.h b/Core/ShellPkg/Library/UefiDpLib/UefiDpLib.h
new file mode 100644
index 0000000000..3dd9ddf9ff
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiDpLib/UefiDpLib.h
@@ -0,0 +1,65 @@
+/** @file
+ Main file for NULL named library for dp command functions.
+
+ Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _UEFI_DP_LIB_H_
+#define _UEFI_DP_LIB_H_
+
+#include <Uefi.h>
+#include <ShellBase.h>
+
+extern EFI_GUID gDpHiiGuid;
+
+#include <Protocol/EfiShell.h>
+#include <Protocol/EfiShellParameters.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/UnicodeCollation.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/ShellCommandLib.h>
+#include <Library/ShellLib.h>
+#include <Library/SortLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HiiLib.h>
+#include <Library/FileHandleLib.h>
+
+extern EFI_HANDLE gDpHiiHandle;
+
+/**
+ Function for 'dp' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+
+ @retval SHELL_SUCCESS Command completed successfully.
+ @retval SHELL_INVALID_PARAMETER Command usage error.
+ @retval SHELL_ABORTED The user aborts the operation.
+ @retval value Unknown error.
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDp (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+#endif
+
diff --git a/Core/ShellPkg/Library/UefiDpLib/UefiDpLib.inf b/Core/ShellPkg/Library/UefiDpLib/UefiDpLib.inf
new file mode 100644
index 0000000000..70d2163d2b
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiDpLib/UefiDpLib.inf
@@ -0,0 +1,75 @@
+## @file
+# Display Performance Application, Module information file.
+#
+# Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = UefiDpLib
+ FILE_GUID = 9DF262F7-CF81-4294-B5A5-B2E3CAFE5618
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER
+ CONSTRUCTOR = UefiDpLibConstructor
+ DESTRUCTOR = UefiDpLibDestructor
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ PerformanceTokens.h
+ UefiDpLib.c
+ UefiDpLib.h
+ UefiDpLib.uni
+ Dp.c
+ Dp.h
+ Literals.h
+ Literals.c
+ DpInternal.h
+ DpUtilities.c
+ DpTrace.c
+ DpProfile.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ TimerLib
+ PerformanceLib
+ DxeServicesLib
+ MemoryAllocationLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ ShellCommandLib
+ ShellLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ SortLib
+ PrintLib
+ DevicePathLib
+
+[Protocols]
+ gEfiLoadedImageProtocolGuid ## CONSUMES
+ gEfiDriverBindingProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiComponentName2ProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiLoadedImageDevicePathProtocolGuid ## SOMETIMES_CONSUMES
+
+[Pcd]
+ gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize ## UNDEFINED
+ gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask ## CONSUMES
diff --git a/Core/ShellPkg/Library/UefiDpLib/UefiDpLib.uni b/Core/ShellPkg/Library/UefiDpLib/UefiDpLib.uni
new file mode 100644
index 0000000000..b092274510
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiDpLib/UefiDpLib.uni
@@ -0,0 +1,130 @@
+// *++
+//
+// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.<BR>
+// Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>
+// (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+//
+// Module Name:
+//
+// DpStrings.uni
+//
+// Abstract:
+//
+// String definitions for the Shell dp command
+//
+// Revision History:
+//
+// --*/
+
+/=#
+
+#langdef en-US "English"
+
+#string STR_DP_UP #language en-US "UP"
+#string STR_DP_DOWN #language en-US "DOWN"
+#string STR_DP_DASHES #language en-US "-------------------------------------------------------------------------------\n"
+#string STR_DP_SECTION_HEADER #language en-US "\n==[ %s ]========\n"
+#string STR_DP_INVALID_ARG #language en-US "Invalid argument(s)\n"
+#string STR_DP_HANDLES_ERROR #language en-US "Locate all handles error - %r\n"
+#string STR_DP_ERROR_NAME #language en-US "Unknown driver name"
+#string STR_DP_BUILD_REVISION #language en-US "\nDP Build Version: %d.%d\n"
+#string STR_DP_KHZ #language en-US "System Performance Timer Frequency: %,8d (KHz)\n"
+#string STR_DP_TIMER_PROPERTIES #language en-US "System Performance Timer counts %s from 0x%Lx to 0x%Lx\n"
+#string STR_DP_VERBOSE_THRESHOLD #language en-US "Measurements less than %,Ld microseconds are not displayed.\n"
+#string STR_DP_SECTION_PHASES #language en-US "Major Phases"
+#string STR_DP_SEC_PHASE #language en-US " SEC Phase Duration: %L8d (us)\n"
+#string STR_DP_PHASE_BDSTO #language en-US " BDS Timeout: %L8d (ms) included in BDS Duration\n"
+#string STR_DP_PHASE_DURATION #language en-US "%5a Phase Duration: %L8d (ms)\n"
+#string STR_DP_TOTAL_DURATION #language en-US "Total Duration: %L8d (ms)\n"
+#string STR_DP_SECTION_DRIVERS #language en-US "Drivers by Handle"
+#string STR_DP_HANDLE_SECTION #language en-US "Index: Handle Driver Name Description Time(us)\n"
+#string STR_DP_HANDLE_VARS #language en-US "%5d: [%3x] %36s %11s %L8d\n"
+#string STR_DP_HANDLE_SECTION2 #language en-US "Index: Handle Driver Name Description Time(us) ID\n"
+#string STR_DP_HANDLE_VARS2 #language en-US "%5d: [%3x] %36s %11s %L8d %5d\n"
+#string STR_DP_SECTION_PEIMS #language en-US "PEIMs"
+#string STR_DP_PEIM_SECTION #language en-US "Index: Pointer Value Instance GUID Token Time(us)\n"
+#string STR_DP_PEIM_VARS #language en-US "%5d: 0x%11p %g PEIM %L8d\n"
+#string STR_DP_PEIM_SECTION2 #language en-US "Index: Pointer Value Instance GUID Token Time(us) ID\n"
+#string STR_DP_PEIM_VARS2 #language en-US "%5d: 0x%11p %g PEIM %L8d %5d\n"
+#string STR_DP_SECTION_GENERAL #language en-US "General"
+#string STR_DP_GLOBAL_SECTION #language en-US "Index Name Description Time(us)\n"
+#string STR_DP_GLOBAL_VARS #language en-US "%5d:%25s %31s %L8d\n"
+#string STR_DP_GLOBAL_SECTION2 #language en-US "Index Name Description Time(us) ID\n"
+#string STR_DP_GLOBAL_VARS2 #language en-US "%5d:%25s %31s %L8d %5d\n"
+#string STR_DP_SECTION_CUMULATIVE #language en-US "Cumulative"
+#string STR_DP_CUMULATIVE_SECT_1 #language en-US "(Times in microsec.) Cumulative Average Shortest Longest\n"
+#string STR_DP_CUMULATIVE_SECT_2 #language en-US " Name Count Duration Duration Duration Duration\n"
+#string STR_DP_CUMULATIVE_STATS #language en-US "%11a %8d %L10d %L10d %L10d %L10d\n"
+#string STR_DP_SECTION_STATISTICS #language en-US "Statistics"
+#string STR_DP_STATS_NUMTRACE #language en-US "There were %d measurements taken, of which:\n"
+#string STR_DP_STATS_NUMINCOMPLETE #language en-US "%,8d are incomplete.\n"
+#string STR_DP_STATS_NUMPHASES #language en-US "%,8d are major execution phases.\n"
+#string STR_DP_STATS_NUMHANDLES #language en-US "%,8d have non-NULL handles, %d are NULL.\n"
+#string STR_DP_STATS_NUMPEIMS #language en-US "%,8d are PEIMs.\n"
+#string STR_DP_STATS_NUMGLOBALS #language en-US "%,8d are general measurements.\n"
+#string STR_DP_STATS_NUMPROFILE #language en-US "%,8d are profiling records.\n"
+#string STR_DP_SECTION_PROFILE #language en-US "Sequential Profile Records"
+#string STR_DP_SECTION_ALL #language en-US "Sequential Trace Records"
+#string STR_DP_ALL_HEADR #language en-US "\nIndex Handle Module Token Time(us)\n"
+#string STR_DP_ALL_VARS #language en-US "%5d:%3s0x%08p %36s %13s %L8d\n"
+#string STR_DP_ALL_DASHES2 #language en-US "-------------------------------------------------------------------------------------\n"
+#string STR_DP_ALL_HEADR2 #language en-US "\nIndex Handle Module Token Time(us) ID\n"
+#string STR_DP_ALL_VARS2 #language en-US "%5d:%3s0x%08p %36s %13s %L8d %5d\n"
+#string STR_DP_SECTION_RAWTRACE #language en-US "RAW Trace"
+#string STR_DP_SECTION_RAWPROFILE #language en-US "RAW Profile"
+#string STR_DP_RAW_DASHES #language en-US "---------------------------------------------------------------------------------------------------------------------------\n"
+#string STR_DP_RAW_VARS #language en-US "%5d: %16LX %16LX %16LX %31a %31a\n"
+#string STR_DP_RAW_HEADR #language en-US "\nIndex Handle Start Count End Count Token Module\n"
+#string STR_DP_RAW_DASHES2 #language en-US "---------------------------------------------------------------------------------------------------------------------------------\n"
+#string STR_DP_RAW_VARS2 #language en-US "%5d: %16LX %16LX %16LX %31a %31a %5d\n"
+#string STR_DP_RAW_HEADR2 #language en-US "\nIndex Handle Start Count End Count Token Module ID\n"
+#string STR_DP_INCOMPLETE #language en-US " I "
+#string STR_DP_COMPLETE #language en-US " "
+#string STR_ALIT_UNKNOWN #language en-US "Unknown"
+
+#string STR_GET_HELP_DP #language en-US ""
+".TH dp 0 "Display performance metrics"\r\n"
+".SH NAME\r\n"
+"Displays performance metrics that are stored in memory.\r\n"
+".SH SYNOPSIS\r\n"
+"DP [-b] [-v] [-x] [-s | -A | -R] [-T] [-P] [-t value] [-n count] [-c [token]][-i] [-h | -?]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -b - Displays on multiple pages\r\n"
+" -v - Displays additional information\r\n"
+" -x - Prevents display of individual measurements for cumulative items\r\n"
+" -s - Displays summary information only\r\n"
+" -A - Displays all measurements in a list\r\n"
+" -R - Displays all measurements in raw format\r\n"
+" -T - Displays trace measurements only\r\n"
+" -P - Displays profile measurements only\r\n"
+" -t VALUE - Sets display threshold to VALUE microseconds\r\n"
+" -n COUNT - Limits display to COUNT lines in All and Raw modes\r\n"
+" -i - Displays identifier\r\n"
+" -c TOKEN - Display pre-defined and custom cumulative data\r\n"
+" Pre-defined cumulative token are:\r\n"
+" 1. LoadImage:\r\n"
+" 2. StartImage:\r\n"
+" 3. DB:Start:\r\n"
+" 4. DB:Support:\r\n"
+" -? - Displays DP help information\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. Displays Performance metrics that are stored in memory.\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_NOT_FOUND The requested option was not found.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly formatted or its value was out of bounds.\r\n"
+" SHELL_UNSUPPORTED The action as requested was unsupported.\r\n"
+" SHELL_OUT_OF_RESOURCES There was insufficient free space for the request to be completed.\r\n"
diff --git a/Core/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c b/Core/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c
new file mode 100644
index 0000000000..3fb55df8cc
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.c
@@ -0,0 +1,3080 @@
+/** @file
+ Provides interface to advanced shell functionality for parsing both handle and protocol database.
+
+ Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
+ (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiHandleParsingLib.h"
+#include "IndustryStandard/Acpi10.h"
+
+EFI_HANDLE mHandleParsingHiiHandle = NULL;
+HANDLE_INDEX_LIST mHandleList = {{{NULL,NULL},0,0},0};
+GUID_INFO_BLOCK *GuidList;
+UINTN GuidListCount;
+/**
+ Function to translate the EFI_MEMORY_TYPE into a string.
+
+ @param[in] Memory The memory type.
+
+ @retval A string representation of the type allocated from BS Pool.
+**/
+CHAR16*
+EFIAPI
+ConvertMemoryType (
+ IN CONST EFI_MEMORY_TYPE Memory
+ )
+{
+ CHAR16 *RetVal;
+ RetVal = NULL;
+
+ switch (Memory) {
+ case EfiReservedMemoryType: StrnCatGrow(&RetVal, NULL, L"EfiReservedMemoryType", 0); break;
+ case EfiLoaderCode: StrnCatGrow(&RetVal, NULL, L"EfiLoaderCode", 0); break;
+ case EfiLoaderData: StrnCatGrow(&RetVal, NULL, L"EfiLoaderData", 0); break;
+ case EfiBootServicesCode: StrnCatGrow(&RetVal, NULL, L"EfiBootServicesCode", 0); break;
+ case EfiBootServicesData: StrnCatGrow(&RetVal, NULL, L"EfiBootServicesData", 0); break;
+ case EfiRuntimeServicesCode: StrnCatGrow(&RetVal, NULL, L"EfiRuntimeServicesCode", 0); break;
+ case EfiRuntimeServicesData: StrnCatGrow(&RetVal, NULL, L"EfiRuntimeServicesData", 0); break;
+ case EfiConventionalMemory: StrnCatGrow(&RetVal, NULL, L"EfiConventionalMemory", 0); break;
+ case EfiUnusableMemory: StrnCatGrow(&RetVal, NULL, L"EfiUnusableMemory", 0); break;
+ case EfiACPIReclaimMemory: StrnCatGrow(&RetVal, NULL, L"EfiACPIReclaimMemory", 0); break;
+ case EfiACPIMemoryNVS: StrnCatGrow(&RetVal, NULL, L"EfiACPIMemoryNVS", 0); break;
+ case EfiMemoryMappedIO: StrnCatGrow(&RetVal, NULL, L"EfiMemoryMappedIO", 0); break;
+ case EfiMemoryMappedIOPortSpace: StrnCatGrow(&RetVal, NULL, L"EfiMemoryMappedIOPortSpace", 0); break;
+ case EfiPalCode: StrnCatGrow(&RetVal, NULL, L"EfiPalCode", 0); break;
+ case EfiMaxMemoryType: StrnCatGrow(&RetVal, NULL, L"EfiMaxMemoryType", 0); break;
+ default: ASSERT(FALSE);
+ }
+ return (RetVal);
+}
+
+/**
+ Function to translate the EFI_GRAPHICS_PIXEL_FORMAT into a string.
+
+ @param[in] Fmt The format type.
+
+ @retval A string representation of the type allocated from BS Pool.
+**/
+CHAR16*
+EFIAPI
+ConvertPixelFormat (
+ IN CONST EFI_GRAPHICS_PIXEL_FORMAT Fmt
+ )
+{
+ CHAR16 *RetVal;
+ RetVal = NULL;
+
+ switch (Fmt) {
+ case PixelRedGreenBlueReserved8BitPerColor: StrnCatGrow(&RetVal, NULL, L"PixelRedGreenBlueReserved8BitPerColor", 0); break;
+ case PixelBlueGreenRedReserved8BitPerColor: StrnCatGrow(&RetVal, NULL, L"PixelBlueGreenRedReserved8BitPerColor", 0); break;
+ case PixelBitMask: StrnCatGrow(&RetVal, NULL, L"PixelBitMask", 0); break;
+ case PixelBltOnly: StrnCatGrow(&RetVal, NULL, L"PixelBltOnly", 0); break;
+ case PixelFormatMax: StrnCatGrow(&RetVal, NULL, L"PixelFormatMax", 0); break;
+ default: ASSERT(FALSE);
+ }
+ return (RetVal);
+}
+
+/**
+ Constructor for the library.
+
+ @param[in] ImageHandle Ignored.
+ @param[in] SystemTable Ignored.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+HandleParsingLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ GuidListCount = 0;
+ GuidList = NULL;
+
+ //
+ // Do nothing with mHandleParsingHiiHandle. Initialize HII as needed.
+ //
+ return (EFI_SUCCESS);
+}
+
+/**
+ Initialization function for HII packages.
+
+**/
+VOID
+HandleParsingHiiInit (VOID)
+{
+ if (mHandleParsingHiiHandle == NULL) {
+ mHandleParsingHiiHandle = HiiAddPackages (&gHandleParsingHiiGuid, gImageHandle, UefiHandleParsingLibStrings, NULL);
+ ASSERT (mHandleParsingHiiHandle != NULL);
+ }
+}
+
+/**
+ Destructor for the library. free any resources.
+
+ @param[in] ImageHandle Ignored.
+ @param[in] SystemTable Ignored.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+HandleParsingLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ UINTN LoopCount;
+
+ for (LoopCount = 0; GuidList != NULL && LoopCount < GuidListCount; LoopCount++) {
+ SHELL_FREE_NON_NULL(GuidList[LoopCount].GuidId);
+ }
+
+ SHELL_FREE_NON_NULL(GuidList);
+ if (mHandleParsingHiiHandle != NULL) {
+ HiiRemovePackages(mHandleParsingHiiHandle);
+ }
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to dump information about LoadedImage.
+
+ This will allocate the return buffer from boot services pool.
+
+ @param[in] TheHandle The handle that has LoadedImage installed.
+ @param[in] Verbose TRUE for additional information, FALSE otherwise.
+
+ @retval A poitner to a string containing the information.
+**/
+CHAR16*
+EFIAPI
+LoadedImageProtocolDumpInformation(
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST BOOLEAN Verbose
+ )
+{
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ EFI_STATUS Status;
+ CHAR16 *RetVal;
+ CHAR16 *Temp;
+ CHAR16 *CodeType;
+ CHAR16 *DataType;
+
+ if (!Verbose) {
+ return (CatSPrint(NULL, L"LoadedImage"));
+ }
+
+ HandleParsingHiiInit();
+
+ Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_LI_DUMP_MAIN), NULL);
+ if (Temp == NULL) {
+ return NULL;
+ }
+
+ Status = gBS->OpenProtocol (
+ TheHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID**)&LoadedImage,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ SHELL_FREE_NON_NULL (Temp);
+ return NULL;
+ }
+
+ DataType = ConvertMemoryType(LoadedImage->ImageDataType);
+ CodeType = ConvertMemoryType(LoadedImage->ImageCodeType);
+
+ RetVal = CatSPrint(
+ NULL,
+ Temp,
+ LoadedImage->Revision,
+ LoadedImage->ParentHandle,
+ LoadedImage->SystemTable,
+ LoadedImage->DeviceHandle,
+ LoadedImage->FilePath,
+ LoadedImage->LoadOptionsSize,
+ LoadedImage->LoadOptions,
+ LoadedImage->ImageBase,
+ LoadedImage->ImageSize,
+ CodeType,
+ DataType,
+ LoadedImage->Unload
+ );
+
+
+ SHELL_FREE_NON_NULL(Temp);
+ SHELL_FREE_NON_NULL(CodeType);
+ SHELL_FREE_NON_NULL(DataType);
+
+ return RetVal;
+}
+
+/**
+ Function to dump information about GOP.
+
+ This will allocate the return buffer from boot services pool.
+
+ @param[in] TheHandle The handle that has LoadedImage installed.
+ @param[in] Verbose TRUE for additional information, FALSE otherwise.
+
+ @retval A poitner to a string containing the information.
+**/
+CHAR16*
+EFIAPI
+GraphicsOutputProtocolDumpInformation(
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST BOOLEAN Verbose
+ )
+{
+ EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;
+ EFI_STATUS Status;
+ CHAR16 *RetVal;
+ CHAR16 *Temp;
+ CHAR16 *Fmt;
+ CHAR16 *TempRetVal;
+ UINTN GopInfoSize;
+ UINT32 Mode;
+ EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *GopInfo;
+
+ if (!Verbose) {
+ return (CatSPrint(NULL, L"GraphicsOutput"));
+ }
+
+ HandleParsingHiiInit();
+
+ Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_GOP_DUMP_MAIN), NULL);
+ if (Temp == NULL) {
+ return NULL;
+ }
+
+ Status = gBS->OpenProtocol (
+ TheHandle,
+ &gEfiGraphicsOutputProtocolGuid,
+ (VOID**)&GraphicsOutput,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ SHELL_FREE_NON_NULL (Temp);
+ return NULL;
+ }
+
+ Fmt = ConvertPixelFormat(GraphicsOutput->Mode->Info->PixelFormat);
+
+ RetVal = CatSPrint(
+ NULL,
+ Temp,
+ GraphicsOutput->Mode->MaxMode,
+ GraphicsOutput->Mode->Mode,
+ GraphicsOutput->Mode->FrameBufferBase,
+ (UINT64)GraphicsOutput->Mode->FrameBufferSize,
+ (UINT64)GraphicsOutput->Mode->SizeOfInfo,
+ GraphicsOutput->Mode->Info->Version,
+ GraphicsOutput->Mode->Info->HorizontalResolution,
+ GraphicsOutput->Mode->Info->VerticalResolution,
+ Fmt,
+ GraphicsOutput->Mode->Info->PixelsPerScanLine,
+ GraphicsOutput->Mode->Info->PixelFormat!=PixelBitMask?0:GraphicsOutput->Mode->Info->PixelInformation.RedMask,
+ GraphicsOutput->Mode->Info->PixelFormat!=PixelBitMask?0:GraphicsOutput->Mode->Info->PixelInformation.GreenMask,
+ GraphicsOutput->Mode->Info->PixelFormat!=PixelBitMask?0:GraphicsOutput->Mode->Info->PixelInformation.BlueMask
+ );
+
+ SHELL_FREE_NON_NULL (Temp);
+
+ Temp = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN (STR_GOP_RES_LIST_MAIN), NULL);
+ if (Temp == NULL) {
+ SHELL_FREE_NON_NULL (RetVal);
+ goto EXIT;
+ }
+
+ TempRetVal = CatSPrint (RetVal, Temp);
+ SHELL_FREE_NON_NULL (RetVal);
+ if (TempRetVal == NULL) {
+ goto EXIT;
+ }
+ RetVal = TempRetVal;
+ SHELL_FREE_NON_NULL (Temp);
+
+ Temp = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN (STR_GOP_RES_LIST_ENTRY), NULL);
+ if (Temp == NULL) {
+ SHELL_FREE_NON_NULL (RetVal);
+ goto EXIT;
+ }
+
+
+ for (Mode = 0; Mode < GraphicsOutput->Mode->MaxMode; Mode++) {
+ Status = GraphicsOutput->QueryMode (
+ GraphicsOutput,
+ Mode,
+ &GopInfoSize,
+ &GopInfo
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ TempRetVal = CatSPrint (
+ RetVal,
+ Temp,
+ Mode,
+ GopInfo->HorizontalResolution,
+ GopInfo->VerticalResolution
+ );
+
+ SHELL_FREE_NON_NULL (GopInfo);
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+ }
+
+
+EXIT:
+ SHELL_FREE_NON_NULL(Temp);
+ SHELL_FREE_NON_NULL(Fmt);
+
+ return RetVal;
+}
+
+/**
+ Function to dump information about EDID Discovered Protocol.
+
+ This will allocate the return buffer from boot services pool.
+
+ @param[in] TheHandle The handle that has LoadedImage installed.
+ @param[in] Verbose TRUE for additional information, FALSE otherwise.
+
+ @retval A pointer to a string containing the information.
+**/
+CHAR16*
+EFIAPI
+EdidDiscoveredProtocolDumpInformation (
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST BOOLEAN Verbose
+ )
+{
+ EFI_EDID_DISCOVERED_PROTOCOL *EdidDiscovered;
+ EFI_STATUS Status;
+ CHAR16 *RetVal;
+ CHAR16 *Temp;
+ CHAR16 *TempRetVal;
+
+ if (!Verbose) {
+ return (CatSPrint (NULL, L"EDIDDiscovered"));
+ }
+
+ Status = gBS->OpenProtocol (
+ TheHandle,
+ &gEfiEdidDiscoveredProtocolGuid,
+ (VOID**)&EdidDiscovered,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ Temp = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN (STR_EDID_DISCOVERED_MAIN), NULL);
+ if (Temp == NULL) {
+ return NULL;
+ }
+
+ RetVal = CatSPrint (NULL, Temp, EdidDiscovered->SizeOfEdid);
+ SHELL_FREE_NON_NULL (Temp);
+
+ if (EdidDiscovered->SizeOfEdid != 0) {
+ Temp = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN (STR_EDID_DISCOVERED_DATA), NULL);
+ if (Temp == NULL) {
+ SHELL_FREE_NON_NULL (RetVal);
+ return NULL;
+ }
+ TempRetVal = CatSPrint (RetVal, Temp);
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+
+ TempRetVal = CatSDumpHex (RetVal, 7, 0, EdidDiscovered->SizeOfEdid, EdidDiscovered->Edid);
+ RetVal = TempRetVal;
+ }
+ return RetVal;
+}
+
+/**
+ Function to dump information about EDID Active Protocol.
+
+ This will allocate the return buffer from boot services pool.
+
+ @param[in] TheHandle The handle that has LoadedImage installed.
+ @param[in] Verbose TRUE for additional information, FALSE otherwise.
+
+ @retval A pointer to a string containing the information.
+**/
+CHAR16*
+EFIAPI
+EdidActiveProtocolDumpInformation (
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST BOOLEAN Verbose
+ )
+{
+ EFI_EDID_ACTIVE_PROTOCOL *EdidActive;
+ EFI_STATUS Status;
+ CHAR16 *RetVal;
+ CHAR16 *Temp;
+ CHAR16 *TempRetVal;
+
+ if (!Verbose) {
+ return (CatSPrint (NULL, L"EDIDActive"));
+ }
+
+ Status = gBS->OpenProtocol (
+ TheHandle,
+ &gEfiEdidActiveProtocolGuid,
+ (VOID**)&EdidActive,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ Temp = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN (STR_EDID_ACTIVE_MAIN), NULL);
+ if (Temp == NULL) {
+ return NULL;
+ }
+
+ RetVal = CatSPrint (NULL, Temp, EdidActive->SizeOfEdid);
+ SHELL_FREE_NON_NULL (Temp);
+
+ if (EdidActive->SizeOfEdid != 0) {
+ Temp = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN (STR_EDID_ACTIVE_DATA), NULL);
+ if (Temp == NULL) {
+ SHELL_FREE_NON_NULL (RetVal);
+ return NULL;
+ }
+ TempRetVal = CatSPrint (RetVal, Temp);
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+
+ TempRetVal = CatSDumpHex (RetVal, 7, 0, EdidActive->SizeOfEdid, EdidActive->Edid);
+ RetVal = TempRetVal;
+ }
+ return RetVal;
+}
+
+/**
+ Function to dump information about PciRootBridgeIo.
+
+ This will allocate the return buffer from boot services pool.
+
+ @param[in] TheHandle The handle that has PciRootBridgeIo installed.
+ @param[in] Verbose TRUE for additional information, FALSE otherwise.
+
+ @retval A poitner to a string containing the information.
+**/
+CHAR16*
+EFIAPI
+PciRootBridgeIoDumpInformation(
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST BOOLEAN Verbose
+ )
+{
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Configuration;
+ UINT64 Supports;
+ UINT64 Attributes;
+ CHAR16 *Temp;
+ CHAR16 *Temp2;
+ CHAR16 *RetVal;
+ EFI_STATUS Status;
+
+ RetVal = NULL;
+
+ if (!Verbose) {
+ return (CatSPrint(NULL, L"PciRootBridgeIo"));
+ }
+
+ HandleParsingHiiInit();
+
+ Status = gBS->HandleProtocol(
+ TheHandle,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ (VOID**)&PciRootBridgeIo);
+
+ if (EFI_ERROR(Status)) {
+ return NULL;
+ }
+
+ Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_PCIRB_DUMP_PH), NULL);
+ if (Temp == NULL) {
+ return NULL;
+ }
+ Temp2 = CatSPrint(L"\r\n", Temp, PciRootBridgeIo->ParentHandle);
+ FreePool(Temp);
+ RetVal = Temp2;
+ Temp2 = NULL;
+
+ Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_PCIRB_DUMP_SEG), NULL);
+ if (Temp == NULL) {
+ SHELL_FREE_NON_NULL(RetVal);
+ return NULL;
+ }
+ Temp2 = CatSPrint(RetVal, Temp, PciRootBridgeIo->SegmentNumber);
+ FreePool(Temp);
+ FreePool(RetVal);
+ RetVal = Temp2;
+ Temp2 = NULL;
+
+ Supports = 0;
+ Attributes = 0;
+ Status = PciRootBridgeIo->GetAttributes (PciRootBridgeIo, &Supports, &Attributes);
+ if (!EFI_ERROR(Status)) {
+ Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_PCIRB_DUMP_ATT), NULL);
+ if (Temp == NULL) {
+ SHELL_FREE_NON_NULL(RetVal);
+ return NULL;
+ }
+ Temp2 = CatSPrint(RetVal, Temp, Attributes);
+ FreePool(Temp);
+ FreePool(RetVal);
+ RetVal = Temp2;
+ Temp2 = NULL;
+
+ Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_PCIRB_DUMP_SUPPORTS), NULL);
+ if (Temp == NULL) {
+ SHELL_FREE_NON_NULL(RetVal);
+ return NULL;
+ }
+ Temp2 = CatSPrint(RetVal, Temp, Supports);
+ FreePool(Temp);
+ FreePool(RetVal);
+ RetVal = Temp2;
+ Temp2 = NULL;
+ }
+
+ Configuration = NULL;
+ Status = PciRootBridgeIo->Configuration (PciRootBridgeIo, (VOID **) &Configuration);
+ if (!EFI_ERROR(Status) && Configuration != NULL) {
+ Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_PCIRB_DUMP_TITLE), NULL);
+ if (Temp == NULL) {
+ SHELL_FREE_NON_NULL(RetVal);
+ return NULL;
+ }
+ Temp2 = CatSPrint(RetVal, Temp, Supports);
+ FreePool(Temp);
+ FreePool(RetVal);
+ RetVal = Temp2;
+ Temp2 = NULL;
+ while (Configuration->Desc == ACPI_ADDRESS_SPACE_DESCRIPTOR) {
+ Temp = NULL;
+ switch (Configuration->ResType) {
+ case ACPI_ADDRESS_SPACE_TYPE_MEM:
+ Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_PCIRB_DUMP_MEM), NULL);
+ break;
+ case ACPI_ADDRESS_SPACE_TYPE_IO:
+ Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_PCIRB_DUMP_IO), NULL);
+ break;
+ case ACPI_ADDRESS_SPACE_TYPE_BUS:
+ Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_PCIRB_DUMP_BUS), NULL);
+ break;
+ }
+ if (Temp != NULL) {
+ Temp2 = CatSPrint(RetVal, L"%s", Temp);
+ FreePool(Temp);
+ FreePool(RetVal);
+ RetVal = Temp2;
+ Temp2 = NULL;
+ }
+
+ Temp2 = CatSPrint(RetVal,
+ L"%H%02x %016lx %016lx %02x%N\r\n",
+ Configuration->SpecificFlag,
+ Configuration->AddrRangeMin,
+ Configuration->AddrRangeMax,
+ Configuration->AddrSpaceGranularity
+ );
+ FreePool(RetVal);
+ RetVal = Temp2;
+ Temp2 = NULL;
+ Configuration++;
+ }
+ }
+ return (RetVal);
+}
+
+/**
+ Function to dump information about SimpleTextOut.
+
+ This will allocate the return buffer from boot services pool.
+
+ @param[in] TheHandle The handle that has SimpleTextOut installed.
+ @param[in] Verbose TRUE for additional information, FALSE otherwise.
+
+ @retval A poitner to a string containing the information.
+**/
+CHAR16*
+EFIAPI
+TxtOutProtocolDumpInformation(
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST BOOLEAN Verbose
+ )
+{
+ EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *Dev;
+ INTN Index;
+ UINTN Col;
+ UINTN Row;
+ EFI_STATUS Status;
+ CHAR16 *RetVal;
+ UINTN Size;
+ CHAR16 *Temp;
+ UINTN NewSize;
+
+ if (!Verbose) {
+ return (NULL);
+ }
+
+ HandleParsingHiiInit();
+
+ RetVal = NULL;
+ Size = 0;
+
+ Status = gBS->HandleProtocol(
+ TheHandle,
+ &gEfiSimpleTextOutProtocolGuid,
+ (VOID**)&Dev);
+
+ ASSERT_EFI_ERROR(Status);
+ ASSERT (Dev != NULL && Dev->Mode != NULL);
+
+ Size = (Dev->Mode->MaxMode + 1) * 80;
+ RetVal = AllocateZeroPool(Size);
+
+ Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_TXT_OUT_DUMP_HEADER), NULL);
+ if (Temp != NULL) {
+ UnicodeSPrint(RetVal, Size, Temp, Dev, Dev->Mode->Attribute);
+ FreePool(Temp);
+ }
+
+ //
+ // Dump TextOut Info
+ //
+ Temp = HiiGetString(mHandleParsingHiiHandle, STRING_TOKEN(STR_TXT_OUT_DUMP_LINE), NULL);
+ for (Index = 0; Index < Dev->Mode->MaxMode; Index++) {
+ Status = Dev->QueryMode (Dev, Index, &Col, &Row);
+ NewSize = Size - StrSize(RetVal);
+ UnicodeSPrint(
+ RetVal + StrLen(RetVal),
+ NewSize,
+ Temp == NULL?L"":Temp,
+ Index == Dev->Mode->Mode ? L'*' : L' ',
+ Index,
+ !EFI_ERROR(Status)?(INTN)Col:-1,
+ !EFI_ERROR(Status)?(INTN)Row:-1
+ );
+ }
+ FreePool(Temp);
+ return (RetVal);
+}
+
+STATIC CONST UINTN VersionStringSize = 60;
+
+/**
+ Function to dump information about EfiDriverSupportedEfiVersion protocol.
+
+ This will allocate the return buffer from boot services pool.
+
+ @param[in] TheHandle The handle that has the protocol installed.
+ @param[in] Verbose TRUE for additional information, FALSE otherwise.
+
+ @retval A poitner to a string containing the information.
+**/
+CHAR16*
+EFIAPI
+DriverEfiVersionProtocolDumpInformation(
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST BOOLEAN Verbose
+ )
+{
+ EFI_DRIVER_SUPPORTED_EFI_VERSION_PROTOCOL *DriverEfiVersion;
+ EFI_STATUS Status;
+ CHAR16 *RetVal;
+
+ Status = gBS->HandleProtocol(
+ TheHandle,
+ &gEfiDriverSupportedEfiVersionProtocolGuid,
+ (VOID**)&DriverEfiVersion);
+
+ ASSERT_EFI_ERROR(Status);
+
+ RetVal = AllocateZeroPool(VersionStringSize);
+ if (RetVal != NULL) {
+ UnicodeSPrint (RetVal, VersionStringSize, L"0x%08x", DriverEfiVersion->FirmwareVersion);
+ }
+ return (RetVal);
+}
+/**
+ Function to convert device path to string.
+
+ This will allocate the return buffer from boot services pool.
+
+ @param[in] DevPath Pointer to device path instance.
+ @param[in] Verbose TRUE for additional information, FALSE otherwise.
+ @param[in] Length Maximum allowed text length of the device path.
+
+ @retval A pointer to a string containing the information.
+**/
+CHAR16*
+ConvertDevicePathToShortText(
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevPath,
+ IN CONST BOOLEAN Verbose,
+ IN CONST UINTN Length
+ )
+{
+ CHAR16 *Temp;
+ CHAR16 *Temp2;
+ UINTN Size;
+
+ //
+ // I cannot decide whether to allow shortcuts here (the second BOOLEAN on the next line)
+ //
+ Temp = ConvertDevicePathToText(DevPath, TRUE, TRUE);
+ if (!Verbose && Temp != NULL && StrLen(Temp) > Length) {
+ Temp2 = NULL;
+ Size = 0;
+ Temp2 = StrnCatGrow(&Temp2, &Size, L"..", 0);
+ Temp2 = StrnCatGrow(&Temp2, &Size, Temp+(StrLen(Temp) - (Length - 2)), 0);
+ FreePool(Temp);
+ Temp = Temp2;
+ }
+ return (Temp);
+}
+
+/**
+ Function to dump information about DevicePath protocol.
+
+ This will allocate the return buffer from boot services pool.
+
+ @param[in] TheHandle The handle that has the protocol installed.
+ @param[in] Verbose TRUE for additional information, FALSE otherwise.
+
+ @retval A pointer to a string containing the information.
+**/
+CHAR16*
+EFIAPI
+DevicePathProtocolDumpInformation(
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST BOOLEAN Verbose
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+ CHAR16 *Temp;
+ EFI_STATUS Status;
+ Temp = NULL;
+
+ Status = gBS->OpenProtocol(TheHandle, &gEfiDevicePathProtocolGuid, (VOID**)&DevPath, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (!EFI_ERROR(Status)) {
+ Temp = ConvertDevicePathToShortText (DevPath, Verbose, 30);
+ gBS->CloseProtocol(TheHandle, &gEfiDevicePathProtocolGuid, gImageHandle, NULL);
+ }
+ return (Temp);
+}
+
+/**
+ Function to dump information about LoadedImageDevicePath protocol.
+
+ This will allocate the return buffer from boot services pool.
+
+ @param[in] TheHandle The handle that has the protocol installed.
+ @param[in] Verbose TRUE for additional information, FALSE otherwise.
+
+ @retval A pointer to a string containing the information.
+**/
+CHAR16*
+EFIAPI
+LoadedImageDevicePathProtocolDumpInformation(
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST BOOLEAN Verbose
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+ CHAR16 *Temp;
+ EFI_STATUS Status;
+ Temp = NULL;
+
+ Status = gBS->OpenProtocol(TheHandle, &gEfiLoadedImageDevicePathProtocolGuid, (VOID**)&DevPath, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (!EFI_ERROR(Status)) {
+ Temp = ConvertDevicePathToShortText (DevPath, Verbose, 30);
+ gBS->CloseProtocol(TheHandle, &gEfiDevicePathProtocolGuid, gImageHandle, NULL);
+ }
+ return (Temp);
+}
+
+/**
+ Function to dump information about EfiAdapterInformation Protocol.
+
+ @param[in] TheHandle The handle that has the protocol installed.
+ @param[in] Verbose TRUE for additional information, FALSE otherwise.
+
+ @retval A pointer to a string containing the information.
+**/
+CHAR16*
+EFIAPI
+AdapterInformationDumpInformation (
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST BOOLEAN Verbose
+ )
+{
+ EFI_STATUS Status;
+ EFI_ADAPTER_INFORMATION_PROTOCOL *EfiAdptrInfoProtocol;
+ UINTN InfoTypesBufferCount;
+ UINTN GuidIndex;
+ EFI_GUID *InfoTypesBuffer;
+ CHAR16 *GuidStr;
+ CHAR16 *TempStr;
+ CHAR16 *RetVal;
+ CHAR16 *TempRetVal;
+ VOID *InformationBlock;
+ UINTN InformationBlockSize;
+
+ if (!Verbose) {
+ return (CatSPrint(NULL, L"AdapterInfo"));
+ }
+
+ InfoTypesBuffer = NULL;
+ InformationBlock = NULL;
+
+
+ Status = gBS->OpenProtocol (
+ (EFI_HANDLE) (TheHandle),
+ &gEfiAdapterInformationProtocolGuid,
+ (VOID **) &EfiAdptrInfoProtocol,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ //
+ // Get a list of supported information types for this instance of the protocol.
+ //
+ Status = EfiAdptrInfoProtocol->GetSupportedTypes (
+ EfiAdptrInfoProtocol,
+ &InfoTypesBuffer,
+ &InfoTypesBufferCount
+ );
+ RetVal = NULL;
+ if (EFI_ERROR (Status)) {
+ TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_GET_SUPP_TYPES_FAILED), NULL);
+ if (TempStr != NULL) {
+ RetVal = CatSPrint (NULL, TempStr, Status);
+ } else {
+ goto ERROR_EXIT;
+ }
+ } else {
+ TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_SUPP_TYPE_HEADER), NULL);
+ if (TempStr == NULL) {
+ goto ERROR_EXIT;
+ }
+ RetVal = CatSPrint (NULL, TempStr);
+ SHELL_FREE_NON_NULL (TempStr);
+
+ for (GuidIndex = 0; GuidIndex < InfoTypesBufferCount; GuidIndex++) {
+ TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_GUID_NUMBER), NULL);
+ if (TempStr == NULL) {
+ goto ERROR_EXIT;
+ }
+ TempRetVal = CatSPrint (RetVal, TempStr, (GuidIndex + 1), &InfoTypesBuffer[GuidIndex]);
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+ SHELL_FREE_NON_NULL (TempStr);
+
+ TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_GUID_STRING), NULL);
+ if (TempStr == NULL) {
+ goto ERROR_EXIT;
+ }
+
+ if (CompareGuid (&InfoTypesBuffer[GuidIndex], &gEfiAdapterInfoMediaStateGuid)) {
+ TempRetVal = CatSPrint (RetVal, TempStr, L"gEfiAdapterInfoMediaStateGuid");
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+ } else if (CompareGuid (&InfoTypesBuffer[GuidIndex], &gEfiAdapterInfoNetworkBootGuid)) {
+ TempRetVal = CatSPrint (RetVal, TempStr, L"gEfiAdapterInfoNetworkBootGuid");
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+ } else if (CompareGuid (&InfoTypesBuffer[GuidIndex], &gEfiAdapterInfoSanMacAddressGuid)) {
+ TempRetVal = CatSPrint (RetVal, TempStr, L"gEfiAdapterInfoSanMacAddressGuid");
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+ } else if (CompareGuid (&InfoTypesBuffer[GuidIndex], &gEfiAdapterInfoUndiIpv6SupportGuid)) {
+ TempRetVal = CatSPrint (RetVal, TempStr, L"gEfiAdapterInfoUndiIpv6SupportGuid");
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+ } else {
+
+ GuidStr = GetStringNameFromGuid (&InfoTypesBuffer[GuidIndex], NULL);
+
+ if (GuidStr != NULL) {
+ if (StrCmp(GuidStr, L"UnknownDevice") == 0) {
+ TempRetVal = CatSPrint (RetVal, TempStr, L"UnknownInfoType");
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+
+ SHELL_FREE_NON_NULL (TempStr);
+ SHELL_FREE_NON_NULL(GuidStr);
+ //
+ // So that we never have to pass this UnknownInfoType to the parsing function "GetInformation" service of AIP
+ //
+ continue;
+ } else {
+ TempRetVal = CatSPrint (RetVal, TempStr, GuidStr);
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+ SHELL_FREE_NON_NULL(GuidStr);
+ }
+ }
+ }
+
+ SHELL_FREE_NON_NULL (TempStr);
+
+ Status = EfiAdptrInfoProtocol->GetInformation (
+ EfiAdptrInfoProtocol,
+ &InfoTypesBuffer[GuidIndex],
+ &InformationBlock,
+ &InformationBlockSize
+ );
+
+ if (EFI_ERROR (Status)) {
+ TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_GETINFO_FAILED), NULL);
+ if (TempStr == NULL) {
+ goto ERROR_EXIT;
+ }
+ TempRetVal = CatSPrint (RetVal, TempStr, Status);
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+ } else {
+ if (CompareGuid (&InfoTypesBuffer[GuidIndex], &gEfiAdapterInfoMediaStateGuid)) {
+ TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_MEDIA_STATE), NULL);
+ if (TempStr == NULL) {
+ goto ERROR_EXIT;
+ }
+ TempRetVal = CatSPrint (
+ RetVal,
+ TempStr,
+ ((EFI_ADAPTER_INFO_MEDIA_STATE *)InformationBlock)->MediaState,
+ ((EFI_ADAPTER_INFO_MEDIA_STATE *)InformationBlock)->MediaState
+ );
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+ } else if (CompareGuid (&InfoTypesBuffer[GuidIndex], &gEfiAdapterInfoNetworkBootGuid)) {
+ TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_NETWORK_BOOT_INFO), NULL);
+ if (TempStr == NULL) {
+ goto ERROR_EXIT;
+ }
+ TempRetVal = CatSPrint (
+ RetVal,
+ TempStr,
+ ((EFI_ADAPTER_INFO_NETWORK_BOOT *)InformationBlock)->iScsiIpv4BootCapablity,
+ ((EFI_ADAPTER_INFO_NETWORK_BOOT *)InformationBlock)->iScsiIpv6BootCapablity,
+ ((EFI_ADAPTER_INFO_NETWORK_BOOT *)InformationBlock)->FCoeBootCapablity,
+ ((EFI_ADAPTER_INFO_NETWORK_BOOT *)InformationBlock)->OffloadCapability,
+ ((EFI_ADAPTER_INFO_NETWORK_BOOT *)InformationBlock)->iScsiMpioCapability,
+ ((EFI_ADAPTER_INFO_NETWORK_BOOT *)InformationBlock)->iScsiIpv4Boot,
+ ((EFI_ADAPTER_INFO_NETWORK_BOOT *)InformationBlock)->iScsiIpv6Boot,
+ ((EFI_ADAPTER_INFO_NETWORK_BOOT *)InformationBlock)->FCoeBoot
+ );
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+ } else if (CompareGuid (&InfoTypesBuffer[GuidIndex], &gEfiAdapterInfoSanMacAddressGuid) == TRUE) {
+ TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_SAN_MAC_ADDRESS_INFO), NULL);
+ if (TempStr == NULL) {
+ goto ERROR_EXIT;
+ }
+ TempRetVal = CatSPrint (
+ RetVal,
+ TempStr,
+ ((EFI_ADAPTER_INFO_SAN_MAC_ADDRESS *)InformationBlock)->SanMacAddress.Addr[0],
+ ((EFI_ADAPTER_INFO_SAN_MAC_ADDRESS *)InformationBlock)->SanMacAddress.Addr[1],
+ ((EFI_ADAPTER_INFO_SAN_MAC_ADDRESS *)InformationBlock)->SanMacAddress.Addr[2],
+ ((EFI_ADAPTER_INFO_SAN_MAC_ADDRESS *)InformationBlock)->SanMacAddress.Addr[3],
+ ((EFI_ADAPTER_INFO_SAN_MAC_ADDRESS *)InformationBlock)->SanMacAddress.Addr[4],
+ ((EFI_ADAPTER_INFO_SAN_MAC_ADDRESS *)InformationBlock)->SanMacAddress.Addr[5]
+ );
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+ } else if (CompareGuid (&InfoTypesBuffer[GuidIndex], &gEfiAdapterInfoUndiIpv6SupportGuid) == TRUE) {
+ TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_UNDI_IPV6_INFO), NULL);
+ if (TempStr == NULL) {
+ goto ERROR_EXIT;
+ }
+
+ TempRetVal = CatSPrint (
+ RetVal,
+ TempStr,
+ ((EFI_ADAPTER_INFO_UNDI_IPV6_SUPPORT *)InformationBlock)->Ipv6Support
+ );
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+ } else {
+ TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_UNKNOWN_INFO_TYPE), NULL);
+ if (TempStr == NULL) {
+ goto ERROR_EXIT;
+ }
+ TempRetVal = CatSPrint (RetVal, TempStr, &InfoTypesBuffer[GuidIndex]);
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+ }
+ }
+ SHELL_FREE_NON_NULL (TempStr);
+ SHELL_FREE_NON_NULL (InformationBlock);
+ }
+ }
+
+ SHELL_FREE_NON_NULL (InfoTypesBuffer);
+ return RetVal;
+
+ERROR_EXIT:
+ SHELL_FREE_NON_NULL (RetVal);
+ SHELL_FREE_NON_NULL (InfoTypesBuffer);
+ SHELL_FREE_NON_NULL (InformationBlock);
+ return NULL;
+}
+
+/**
+ Function to dump information about EFI_FIRMWARE_MANAGEMENT_PROTOCOL Protocol.
+
+ @param[in] TheHandle The handle that has the protocol installed.
+ @param[in] Verbose TRUE for additional information, FALSE otherwise.
+
+ @retval A pointer to a string containing the information.
+**/
+CHAR16*
+EFIAPI
+FirmwareManagementDumpInformation (
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST BOOLEAN Verbose
+ )
+{
+ EFI_STATUS Status;
+ EFI_FIRMWARE_MANAGEMENT_PROTOCOL *EfiFwMgmtProtocol;
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR *ImageInfo;
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR_V1 *ImageInfoV1;
+ EFI_FIRMWARE_IMAGE_DESCRIPTOR_V2 *ImageInfoV2;
+ UINT64 AttributeSetting;
+ UINTN ImageInfoSize;
+ UINTN DescriptorSize;
+ UINT32 DescriptorVersion;
+ UINT32 PackageVersion;
+ UINT8 DescriptorCount;
+ UINT8 Index;
+ UINT8 Index1;
+ UINT8 ImageCount;
+ CHAR16 *PackageVersionName;
+ CHAR16 *TempStr;
+ CHAR16 *RetVal;
+ CHAR16 *TempRetVal;
+ CHAR16 *AttributeSettingStr;
+ BOOLEAN Found;
+ BOOLEAN AttributeSupported;
+
+ //
+ // Initialize local variables
+ //
+ ImageCount = 0;
+ ImageInfoSize = 1;
+ AttributeSetting = 0;
+ Found = FALSE;
+ AttributeSupported = FALSE;
+ ImageInfo = NULL;
+ ImageInfoV1 = NULL;
+ ImageInfoV2 = NULL;
+ PackageVersionName = NULL;
+ RetVal = NULL;
+ TempRetVal = NULL;
+ TempStr = NULL;
+ AttributeSettingStr = NULL;
+
+ if (!Verbose) {
+ return (CatSPrint(NULL, L"FirmwareManagement"));
+ }
+
+ Status = gBS->OpenProtocol (
+ (EFI_HANDLE) (TheHandle),
+ &gEfiFirmwareManagementProtocolGuid,
+ (VOID **) &EfiFwMgmtProtocol,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ Status = EfiFwMgmtProtocol->GetImageInfo (
+ EfiFwMgmtProtocol,
+ &ImageInfoSize,
+ ImageInfo,
+ &DescriptorVersion,
+ &DescriptorCount,
+ &DescriptorSize,
+ &PackageVersion,
+ &PackageVersionName
+ );
+
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ ImageInfo = AllocateZeroPool (ImageInfoSize);
+
+ if (ImageInfo == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ Status = EfiFwMgmtProtocol->GetImageInfo (
+ EfiFwMgmtProtocol,
+ &ImageInfoSize,
+ ImageInfo,
+ &DescriptorVersion,
+ &DescriptorCount,
+ &DescriptorSize,
+ &PackageVersion,
+ &PackageVersionName
+ );
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ goto ERROR_EXIT;
+ }
+
+ //
+ // Decode Image Descriptor data only if its version is supported
+ //
+ if (DescriptorVersion <= EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION) {
+
+ if (ImageInfo == NULL) {
+ goto ERROR_EXIT;
+ }
+
+ ImageInfoV1 = (EFI_FIRMWARE_IMAGE_DESCRIPTOR_V1 *)ImageInfo;
+ ImageInfoV2 = (EFI_FIRMWARE_IMAGE_DESCRIPTOR_V2 *)ImageInfo;
+
+ //
+ // Set ImageInfoSize in return buffer
+ //
+ TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_FMP_IMAGE_INFO_SIZE), NULL);
+ if (TempStr == NULL) {
+ goto ERROR_EXIT;
+ }
+ RetVal = CatSPrint (NULL, TempStr, ImageInfoSize);
+ SHELL_FREE_NON_NULL (TempStr);
+
+ //
+ // Set DescriptorVersion in return buffer
+ //
+ TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_FMP_DESCRIPTOR_VERSION), NULL);
+ if (TempStr == NULL) {
+ goto ERROR_EXIT;
+ }
+ TempRetVal = CatSPrint (RetVal, TempStr, DescriptorVersion);
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+ SHELL_FREE_NON_NULL (TempStr);
+
+ //
+ // Set DescriptorCount in return buffer
+ //
+ TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_FMP_DESCRIPTOR_COUNT), NULL);
+ if (TempStr == NULL) {
+ goto ERROR_EXIT;
+ }
+ TempRetVal = CatSPrint (RetVal, TempStr, DescriptorCount);
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+ SHELL_FREE_NON_NULL (TempStr);
+
+
+ //
+ // Set DescriptorSize in return buffer
+ //
+ TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_FMP_DESCRIPTOR_SIZE), NULL);
+ if (TempStr == NULL) {
+ goto ERROR_EXIT;
+ }
+ TempRetVal = CatSPrint (RetVal, TempStr, DescriptorSize);
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+ SHELL_FREE_NON_NULL (TempStr);
+
+ //
+ // Set PackageVersion in return buffer
+ //
+ TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_FMP_PACKAGE_VERSION), NULL);
+ if (TempStr == NULL) {
+ goto ERROR_EXIT;
+ }
+ TempRetVal = CatSPrint (RetVal, TempStr, PackageVersion);
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+ SHELL_FREE_NON_NULL (TempStr);
+
+ //
+ // Set PackageVersionName in return buffer
+ //
+ TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_FMP_PACKAGE_VERSION_NAME), NULL);
+ if (TempStr == NULL) {
+ goto ERROR_EXIT;
+ }
+ TempRetVal = CatSPrint (RetVal, TempStr, PackageVersionName);
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+ SHELL_FREE_NON_NULL (TempStr);
+
+ for (Index = 0; Index < DescriptorCount; Index++) {
+ //
+ // First check if Attribute is supported
+ // and generate a string for AttributeSetting field
+ //
+ SHELL_FREE_NON_NULL (AttributeSettingStr);
+ AttributeSupported = FALSE;
+ AttributeSetting = 0;
+ if (DescriptorVersion == EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION_V1) {
+ if (ImageInfoV1[Index].AttributesSupported != 0x0) {
+ AttributeSupported = TRUE;
+ AttributeSetting = ImageInfoV1[Index].AttributesSetting;
+ }
+ } else if (DescriptorVersion == EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION_V2) {
+ if (ImageInfoV2[Index].AttributesSupported != 0x0) {
+ AttributeSupported = TRUE;
+ AttributeSetting = ImageInfoV2[Index].AttributesSetting;
+ }
+ } else {
+ if (ImageInfo[Index].AttributesSupported != 0x0) {
+ AttributeSupported = TRUE;
+ AttributeSetting = ImageInfo[Index].AttributesSetting;
+ }
+ }
+
+ if (!AttributeSupported) {
+ AttributeSettingStr = CatSPrint (NULL, L"None");
+ } else {
+ AttributeSettingStr = CatSPrint (NULL, L"(");
+
+ if ((AttributeSetting & IMAGE_ATTRIBUTE_IMAGE_UPDATABLE) != 0x0) {
+ TempRetVal = CatSPrint (AttributeSettingStr, L" IMAGE_ATTRIBUTE_IMAGE_UPDATABLE");
+ SHELL_FREE_NON_NULL (AttributeSettingStr);
+ AttributeSettingStr = TempRetVal;
+ }
+ if ((AttributeSetting & IMAGE_ATTRIBUTE_RESET_REQUIRED) != 0x0) {
+ TempRetVal = CatSPrint (AttributeSettingStr, L" IMAGE_ATTRIBUTE_RESET_REQUIRED");
+ SHELL_FREE_NON_NULL (AttributeSettingStr);
+ AttributeSettingStr = TempRetVal;
+ }
+ if ((AttributeSetting & IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED) != 0x0) {
+ TempRetVal = CatSPrint (AttributeSettingStr, L" IMAGE_ATTRIBUTE_AUTHENTICATION_REQUIRED");
+ SHELL_FREE_NON_NULL (AttributeSettingStr);
+ AttributeSettingStr = TempRetVal;
+ }
+ if ((AttributeSetting & IMAGE_ATTRIBUTE_IN_USE) != 0x0) {
+ TempRetVal = CatSPrint (AttributeSettingStr, L" IMAGE_ATTRIBUTE_IN_USE");
+ SHELL_FREE_NON_NULL (AttributeSettingStr);
+ AttributeSettingStr = TempRetVal;
+ }
+ if ((AttributeSetting & IMAGE_ATTRIBUTE_UEFI_IMAGE) != 0x0) {
+ TempRetVal = CatSPrint (AttributeSettingStr, L" IMAGE_ATTRIBUTE_UEFI_IMAGE");
+ SHELL_FREE_NON_NULL (AttributeSettingStr);
+ AttributeSettingStr = TempRetVal;
+ }
+ TempRetVal = CatSPrint (AttributeSettingStr, L" )");
+ SHELL_FREE_NON_NULL (AttributeSettingStr);
+ AttributeSettingStr = TempRetVal;
+ }
+
+ if (DescriptorVersion == EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION_V1) {
+ if (ImageInfoV1[Index].ImageIndex != 0x0) {
+ ImageCount++;
+ }
+
+ TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_FMP_IMAGE_DESCRIPTOR_INFO_V1), NULL);
+ if (TempStr == NULL) {
+ goto ERROR_EXIT;
+ }
+ TempRetVal = CatSPrint (
+ RetVal,
+ TempStr,
+ Index,
+ ImageInfoV1[Index].ImageIndex,
+ &ImageInfoV1[Index].ImageTypeId,
+ ImageInfoV1[Index].ImageId,
+ ImageInfoV1[Index].ImageIdName,
+ ImageInfoV1[Index].Version,
+ ImageInfoV1[Index].VersionName,
+ ImageInfoV1[Index].Size,
+ ImageInfoV1[Index].AttributesSupported,
+ AttributeSettingStr,
+ ImageInfoV1[Index].Compatibilities
+ );
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+ SHELL_FREE_NON_NULL (TempStr);
+ } else if (DescriptorVersion == EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION_V2) {
+ if (ImageInfoV2[Index].ImageIndex != 0x0) {
+ ImageCount++;
+ }
+
+ TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_FMP_IMAGE_DESCRIPTOR_INFO_V2), NULL);
+ if (TempStr == NULL) {
+ goto ERROR_EXIT;
+ }
+ TempRetVal = CatSPrint (
+ RetVal,
+ TempStr,
+ Index,
+ ImageInfoV2[Index].ImageIndex,
+ &ImageInfoV2[Index].ImageTypeId,
+ ImageInfoV2[Index].ImageId,
+ ImageInfoV2[Index].ImageIdName,
+ ImageInfoV2[Index].Version,
+ ImageInfoV2[Index].VersionName,
+ ImageInfoV2[Index].Size,
+ ImageInfoV2[Index].AttributesSupported,
+ AttributeSettingStr,
+ ImageInfoV2[Index].Compatibilities,
+ ImageInfoV2[Index].LowestSupportedImageVersion
+ );
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+ SHELL_FREE_NON_NULL (TempStr);
+ } else {
+ if (ImageInfo[Index].ImageIndex != 0x0) {
+ ImageCount++;
+ }
+
+ TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_FMP_IMAGE_DESCRIPTOR_INFO), NULL);
+ if (TempStr == NULL) {
+ goto ERROR_EXIT;
+ }
+ TempRetVal = CatSPrint (
+ RetVal,
+ TempStr,
+ Index,
+ ImageInfo[Index].ImageIndex,
+ &ImageInfo[Index].ImageTypeId,
+ ImageInfo[Index].ImageId,
+ ImageInfo[Index].ImageIdName,
+ ImageInfo[Index].Version,
+ ImageInfo[Index].VersionName,
+ ImageInfo[Index].Size,
+ ImageInfo[Index].AttributesSupported,
+ AttributeSettingStr,
+ ImageInfo[Index].Compatibilities,
+ ImageInfo[Index].LowestSupportedImageVersion,
+ ImageInfo[Index].LastAttemptVersion,
+ ImageInfo[Index].LastAttemptStatus,
+ ImageInfo[Index].HardwareInstance
+ );
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+ SHELL_FREE_NON_NULL (TempStr);
+ }
+ }
+ }
+
+ if (ImageCount > 0) {
+ for (Index=0; Index<DescriptorCount; Index++) {
+ for (Index1=Index+1; Index1<DescriptorCount; Index1++) {
+ if (DescriptorVersion == EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION_V1) {
+ if (ImageInfoV1[Index].ImageId == ImageInfoV1[Index1].ImageId) {
+ Found = TRUE;
+ //
+ // At least one match found indicating presense of non unique ImageId values so no more comparisons needed
+ //
+ goto ENDLOOP;
+ }
+ } else if (DescriptorVersion == EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION_V2) {
+ if (ImageInfoV2[Index].ImageId == ImageInfoV2[Index1].ImageId) {
+ Found = TRUE;
+ //
+ // At least one match found indicating presense of non unique ImageId values so no more comparisons needed
+ //
+ goto ENDLOOP;
+ }
+ } else {
+ if (ImageInfo[Index].ImageId == ImageInfo[Index1].ImageId) {
+ Found = TRUE;
+ //
+ // At least one match found indicating presense of non unique ImageId values so no more comparisons needed
+ //
+ goto ENDLOOP;
+ }
+ }
+ }
+ }
+ }
+
+ENDLOOP:
+ //
+ // Check if ImageId with duplicate value was found
+ //
+ if (Found) {
+ TempStr = HiiGetString (mHandleParsingHiiHandle, STRING_TOKEN(STR_FMP_IMAGEID_NON_UNIQUE), NULL);
+ if (TempStr == NULL) {
+ goto ERROR_EXIT;
+ }
+ TempRetVal = CatSPrint (RetVal, TempStr);
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+ SHELL_FREE_NON_NULL (TempStr);
+ }
+
+ SHELL_FREE_NON_NULL (ImageInfo);
+ SHELL_FREE_NON_NULL (PackageVersionName);
+ SHELL_FREE_NON_NULL (AttributeSettingStr);
+
+ return RetVal;
+
+ERROR_EXIT:
+ SHELL_FREE_NON_NULL (RetVal);
+ SHELL_FREE_NON_NULL (ImageInfo);
+ SHELL_FREE_NON_NULL (PackageVersionName);
+ SHELL_FREE_NON_NULL (AttributeSettingStr);
+
+ return NULL;
+}
+
+//
+// Put the information on the NT32 protocol GUIDs here so we are not dependant on the Nt32Pkg
+//
+#define LOCAL_EFI_WIN_NT_THUNK_PROTOCOL_GUID \
+ { \
+ 0x58c518b1, 0x76f3, 0x11d4, { 0xbc, 0xea, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \
+ }
+
+#define LOCAL_EFI_WIN_NT_BUS_DRIVER_IO_PROTOCOL_GUID \
+ { \
+ 0x96eb4ad6, 0xa32a, 0x11d4, { 0xbc, 0xfd, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \
+ }
+
+#define LOCAL_EFI_WIN_NT_SERIAL_PORT_GUID \
+ { \
+ 0xc95a93d, 0xa006, 0x11d4, { 0xbc, 0xfa, 0x0, 0x80, 0xc7, 0x3c, 0x88, 0x81 } \
+ }
+STATIC CONST EFI_GUID WinNtThunkProtocolGuid = LOCAL_EFI_WIN_NT_THUNK_PROTOCOL_GUID;
+STATIC CONST EFI_GUID WinNtIoProtocolGuid = LOCAL_EFI_WIN_NT_BUS_DRIVER_IO_PROTOCOL_GUID;
+STATIC CONST EFI_GUID WinNtSerialPortGuid = LOCAL_EFI_WIN_NT_SERIAL_PORT_GUID;
+
+//
+// Deprecated protocols we dont want to link from IntelFrameworkModulePkg
+//
+#define LOCAL_EFI_ISA_IO_PROTOCOL_GUID \
+ { \
+ 0x7ee2bd44, 0x3da0, 0x11d4, { 0x9a, 0x38, 0x0, 0x90, 0x27, 0x3f, 0xc1, 0x4d } \
+ }
+#define LOCAL_EFI_ISA_ACPI_PROTOCOL_GUID \
+ { \
+ 0x64a892dc, 0x5561, 0x4536, { 0x92, 0xc7, 0x79, 0x9b, 0xfc, 0x18, 0x33, 0x55 } \
+ }
+STATIC CONST EFI_GUID EfiIsaIoProtocolGuid = LOCAL_EFI_ISA_IO_PROTOCOL_GUID;
+STATIC CONST EFI_GUID EfiIsaAcpiProtocolGuid = LOCAL_EFI_ISA_ACPI_PROTOCOL_GUID;
+
+
+STATIC CONST GUID_INFO_BLOCK mGuidStringListNT[] = {
+ {STRING_TOKEN(STR_WINNT_THUNK), (EFI_GUID*)&WinNtThunkProtocolGuid, NULL},
+ {STRING_TOKEN(STR_WINNT_DRIVER_IO), (EFI_GUID*)&WinNtIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_WINNT_SERIAL_PORT), (EFI_GUID*)&WinNtSerialPortGuid, NULL},
+ {STRING_TOKEN(STR_UNKNOWN_DEVICE), NULL, NULL},
+};
+
+STATIC CONST GUID_INFO_BLOCK mGuidStringList[] = {
+ {STRING_TOKEN(STR_LOADED_IMAGE), &gEfiLoadedImageProtocolGuid, LoadedImageProtocolDumpInformation},
+ {STRING_TOKEN(STR_DEVICE_PATH), &gEfiDevicePathProtocolGuid, DevicePathProtocolDumpInformation},
+ {STRING_TOKEN(STR_IMAGE_PATH), &gEfiLoadedImageDevicePathProtocolGuid, LoadedImageDevicePathProtocolDumpInformation},
+ {STRING_TOKEN(STR_DEVICE_PATH_UTIL), &gEfiDevicePathUtilitiesProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DEVICE_PATH_TXT), &gEfiDevicePathToTextProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DEVICE_PATH_FTXT), &gEfiDevicePathFromTextProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DEVICE_PATH_PC), &gEfiPcAnsiGuid, NULL},
+ {STRING_TOKEN(STR_DEVICE_PATH_VT100), &gEfiVT100Guid, NULL},
+ {STRING_TOKEN(STR_DEVICE_PATH_VT100P), &gEfiVT100PlusGuid, NULL},
+ {STRING_TOKEN(STR_DEVICE_PATH_VTUTF8), &gEfiVTUTF8Guid, NULL},
+ {STRING_TOKEN(STR_DRIVER_BINDING), &gEfiDriverBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_PLATFORM_OVERRIDE), &gEfiPlatformDriverOverrideProtocolGuid, NULL},
+ {STRING_TOKEN(STR_BUS_OVERRIDE), &gEfiBusSpecificDriverOverrideProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DRIVER_DIAG), &gEfiDriverDiagnosticsProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DRIVER_DIAG2), &gEfiDriverDiagnostics2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DRIVER_CN), &gEfiComponentNameProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DRIVER_CN2), &gEfiComponentName2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_PLAT_DRV_CFG), &gEfiPlatformToDriverConfigurationProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DRIVER_VERSION), &gEfiDriverSupportedEfiVersionProtocolGuid, DriverEfiVersionProtocolDumpInformation},
+ {STRING_TOKEN(STR_TXT_IN), &gEfiSimpleTextInProtocolGuid, NULL},
+ {STRING_TOKEN(STR_TXT_IN_EX), &gEfiSimpleTextInputExProtocolGuid, NULL},
+ {STRING_TOKEN(STR_TXT_OUT), &gEfiSimpleTextOutProtocolGuid, TxtOutProtocolDumpInformation},
+ {STRING_TOKEN(STR_SIM_POINTER), &gEfiSimplePointerProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ABS_POINTER), &gEfiAbsolutePointerProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SERIAL_IO), &gEfiSerialIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_GRAPHICS_OUTPUT), &gEfiGraphicsOutputProtocolGuid, GraphicsOutputProtocolDumpInformation},
+ {STRING_TOKEN(STR_EDID_DISCOVERED), &gEfiEdidDiscoveredProtocolGuid, EdidDiscoveredProtocolDumpInformation},
+ {STRING_TOKEN(STR_EDID_ACTIVE), &gEfiEdidActiveProtocolGuid, EdidActiveProtocolDumpInformation},
+ {STRING_TOKEN(STR_EDID_OVERRIDE), &gEfiEdidOverrideProtocolGuid, NULL},
+ {STRING_TOKEN(STR_CON_IN), &gEfiConsoleInDeviceGuid, NULL},
+ {STRING_TOKEN(STR_CON_OUT), &gEfiConsoleOutDeviceGuid, NULL},
+ {STRING_TOKEN(STR_STD_ERR), &gEfiStandardErrorDeviceGuid, NULL},
+ {STRING_TOKEN(STR_LOAD_FILE), &gEfiLoadFileProtocolGuid, NULL},
+ {STRING_TOKEN(STR_LOAD_FILE2), &gEfiLoadFile2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SIMPLE_FILE_SYS), &gEfiSimpleFileSystemProtocolGuid, NULL},
+ {STRING_TOKEN(STR_TAPE_IO), &gEfiTapeIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DISK_IO), &gEfiDiskIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_BLK_IO), &gEfiBlockIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_UC), &gEfiUnicodeCollationProtocolGuid, NULL},
+ {STRING_TOKEN(STR_UC2), &gEfiUnicodeCollation2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_PCIRB_IO), &gEfiPciRootBridgeIoProtocolGuid, PciRootBridgeIoDumpInformation},
+ {STRING_TOKEN(STR_PCI_IO), &gEfiPciIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SCSI_PT), &gEfiScsiPassThruProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SCSI_IO), &gEfiScsiIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SCSI_PT_EXT), &gEfiExtScsiPassThruProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ISCSI), &gEfiIScsiInitiatorNameProtocolGuid, NULL},
+ {STRING_TOKEN(STR_USB_IO), &gEfiUsbIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_USB_HC), &gEfiUsbHcProtocolGuid, NULL},
+ {STRING_TOKEN(STR_USB_HC2), &gEfiUsb2HcProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DEBUG_SUPPORT), &gEfiDebugSupportProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DEBUG_PORT), &gEfiDebugPortProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DECOMPRESS), &gEfiDecompressProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ACPI_TABLE), &gEfiAcpiTableProtocolGuid, NULL},
+ {STRING_TOKEN(STR_EBC_INTERPRETER), &gEfiEbcProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SNP), &gEfiSimpleNetworkProtocolGuid, NULL},
+ {STRING_TOKEN(STR_NII), &gEfiNetworkInterfaceIdentifierProtocolGuid, NULL},
+ {STRING_TOKEN(STR_NII_31), &gEfiNetworkInterfaceIdentifierProtocolGuid_31, NULL},
+ {STRING_TOKEN(STR_PXE_BC), &gEfiPxeBaseCodeProtocolGuid, NULL},
+ {STRING_TOKEN(STR_PXE_CB), &gEfiPxeBaseCodeCallbackProtocolGuid, NULL},
+ {STRING_TOKEN(STR_BIS), &gEfiBisProtocolGuid, NULL},
+ {STRING_TOKEN(STR_MNP_SB), &gEfiManagedNetworkServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_MNP), &gEfiManagedNetworkProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ARP_SB), &gEfiArpServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ARP), &gEfiArpProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DHCPV4_SB), &gEfiDhcp4ServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DHCPV4), &gEfiDhcp4ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_TCPV4_SB), &gEfiTcp4ServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_TCPV4), &gEfiTcp4ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_IPV4_SB), &gEfiIp4ServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_IPV4), &gEfiIp4ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_IPV4_CFG), &gEfiIp4ConfigProtocolGuid, NULL},
+ {STRING_TOKEN(STR_IPV4_CFG2), &gEfiIp4Config2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_UDPV4_SB), &gEfiUdp4ServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_UDPV4), &gEfiUdp4ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_MTFTPV4_SB), &gEfiMtftp4ServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_MTFTPV4), &gEfiMtftp4ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_AUTH_INFO), &gEfiAuthenticationInfoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_HASH_SB), &gEfiHashServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_HASH), &gEfiHashProtocolGuid, NULL},
+ {STRING_TOKEN(STR_HII_FONT), &gEfiHiiFontProtocolGuid, NULL},
+ {STRING_TOKEN(STR_HII_STRING), &gEfiHiiStringProtocolGuid, NULL},
+ {STRING_TOKEN(STR_HII_IMAGE), &gEfiHiiImageProtocolGuid, NULL},
+ {STRING_TOKEN(STR_HII_DATABASE), &gEfiHiiDatabaseProtocolGuid, NULL},
+ {STRING_TOKEN(STR_HII_CONFIG_ROUT), &gEfiHiiConfigRoutingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_HII_CONFIG_ACC), &gEfiHiiConfigAccessProtocolGuid, NULL},
+ {STRING_TOKEN(STR_HII_FORM_BROWSER2), &gEfiFormBrowser2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DRIVER_FAM_OVERRIDE), &gEfiDriverFamilyOverrideProtocolGuid, NULL},
+ {STRING_TOKEN(STR_PCD), &gPcdProtocolGuid, NULL},
+ {STRING_TOKEN(STR_TCG), &gEfiTcgProtocolGuid, NULL},
+ {STRING_TOKEN(STR_HII_PACKAGE_LIST), &gEfiHiiPackageListProtocolGuid, NULL},
+
+//
+// the ones under this are deprecated by the current UEFI Spec, but may be found anyways...
+//
+ {STRING_TOKEN(STR_SHELL_INTERFACE), &gEfiShellInterfaceGuid, NULL},
+ {STRING_TOKEN(STR_SHELL_ENV2), &gEfiShellEnvironment2Guid, NULL},
+ {STRING_TOKEN(STR_SHELL_ENV), &gEfiShellEnvironment2Guid, NULL},
+ {STRING_TOKEN(STR_DEVICE_IO), &gEfiDeviceIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_UGA_DRAW), &gEfiUgaDrawProtocolGuid, NULL},
+ {STRING_TOKEN(STR_UGA_IO), &gEfiUgaIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ESP), &gEfiPartTypeSystemPartGuid, NULL},
+ {STRING_TOKEN(STR_GPT_NBR), &gEfiPartTypeLegacyMbrGuid, NULL},
+ {STRING_TOKEN(STR_DRIVER_CONFIG), &gEfiDriverConfigurationProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DRIVER_CONFIG2), &gEfiDriverConfiguration2ProtocolGuid, NULL},
+
+//
+// these are using local (non-global) definitions to reduce package dependancy.
+//
+ {STRING_TOKEN(STR_ISA_IO), (EFI_GUID*)&EfiIsaIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ISA_ACPI), (EFI_GUID*)&EfiIsaAcpiProtocolGuid, NULL},
+
+//
+// the ones under this are GUID identified structs, not protocols
+//
+ {STRING_TOKEN(STR_FILE_INFO), &gEfiFileInfoGuid, NULL},
+ {STRING_TOKEN(STR_FILE_SYS_INFO), &gEfiFileSystemInfoGuid, NULL},
+
+//
+// the ones under this are misc GUIDS.
+//
+ {STRING_TOKEN(STR_EFI_GLOBAL_VARIABLE), &gEfiGlobalVariableGuid, NULL},
+
+//
+// UEFI 2.2
+//
+ {STRING_TOKEN(STR_IP6_SB), &gEfiIp6ServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_IP6), &gEfiIp6ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_IP6_CONFIG), &gEfiIp6ConfigProtocolGuid, NULL},
+ {STRING_TOKEN(STR_MTFTP6_SB), &gEfiMtftp6ServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_MTFTP6), &gEfiMtftp6ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DHCP6_SB), &gEfiDhcp6ServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DHCP6), &gEfiDhcp6ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_UDP6_SB), &gEfiUdp6ServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_UDP6), &gEfiUdp6ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_TCP6_SB), &gEfiTcp6ServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_TCP6), &gEfiTcp6ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_VLAN_CONFIG), &gEfiVlanConfigProtocolGuid, NULL},
+ {STRING_TOKEN(STR_EAP), &gEfiEapProtocolGuid, NULL},
+ {STRING_TOKEN(STR_EAP_MGMT), &gEfiEapManagementProtocolGuid, NULL},
+ {STRING_TOKEN(STR_FTP4_SB), &gEfiFtp4ServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_FTP4), &gEfiFtp4ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_IP_SEC_CONFIG), &gEfiIpSecConfigProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DH), &gEfiDriverHealthProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DEF_IMG_LOAD), &gEfiDeferredImageLoadProtocolGuid, NULL},
+ {STRING_TOKEN(STR_USER_CRED), &gEfiUserCredentialProtocolGuid, NULL},
+ {STRING_TOKEN(STR_USER_MNGR), &gEfiUserManagerProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ATA_PASS_THRU), &gEfiAtaPassThruProtocolGuid, NULL},
+
+//
+// UEFI 2.3
+//
+ {STRING_TOKEN(STR_FW_MGMT), &gEfiFirmwareManagementProtocolGuid, FirmwareManagementDumpInformation},
+ {STRING_TOKEN(STR_IP_SEC), &gEfiIpSecProtocolGuid, NULL},
+ {STRING_TOKEN(STR_IP_SEC2), &gEfiIpSec2ProtocolGuid, NULL},
+
+//
+// UEFI 2.3.1
+//
+ {STRING_TOKEN(STR_KMS), &gEfiKmsProtocolGuid, NULL},
+ {STRING_TOKEN(STR_BLK_IO2), &gEfiBlockIo2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SSC), &gEfiStorageSecurityCommandProtocolGuid, NULL},
+ {STRING_TOKEN(STR_UCRED2), &gEfiUserCredential2ProtocolGuid, NULL},
+
+//
+// UEFI 2.4
+//
+ {STRING_TOKEN(STR_DISK_IO2), &gEfiDiskIo2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ADAPTER_INFO), &gEfiAdapterInformationProtocolGuid, AdapterInformationDumpInformation},
+
+//
+// PI Spec ones
+//
+ {STRING_TOKEN(STR_IDE_CONT_INIT), &gEfiIdeControllerInitProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DISK_INFO), &gEfiDiskInfoProtocolGuid, NULL},
+
+//
+// PI Spec 1.0
+//
+ {STRING_TOKEN(STR_BDS_ARCH), &gEfiBdsArchProtocolGuid, NULL},
+ {STRING_TOKEN(STR_CPU_ARCH), &gEfiCpuArchProtocolGuid, NULL},
+ {STRING_TOKEN(STR_MET_ARCH), &gEfiMetronomeArchProtocolGuid, NULL},
+ {STRING_TOKEN(STR_MON_ARCH), &gEfiMonotonicCounterArchProtocolGuid, NULL},
+ {STRING_TOKEN(STR_RTC_ARCH), &gEfiRealTimeClockArchProtocolGuid, NULL},
+ {STRING_TOKEN(STR_RESET_ARCH), &gEfiResetArchProtocolGuid, NULL},
+ {STRING_TOKEN(STR_RT_ARCH), &gEfiRuntimeArchProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SEC_ARCH), &gEfiSecurityArchProtocolGuid, NULL},
+ {STRING_TOKEN(STR_TIMER_ARCH), &gEfiTimerArchProtocolGuid, NULL},
+ {STRING_TOKEN(STR_VAR_ARCH), &gEfiVariableWriteArchProtocolGuid, NULL},
+ {STRING_TOKEN(STR_V_ARCH), &gEfiVariableArchProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SECP), &gEfiSecurityPolicyProtocolGuid, NULL},
+ {STRING_TOKEN(STR_WDT_ARCH), &gEfiWatchdogTimerArchProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SCR), &gEfiStatusCodeRuntimeProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SMB_HC), &gEfiSmbusHcProtocolGuid, NULL},
+ {STRING_TOKEN(STR_FV_2), &gEfiFirmwareVolume2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_FV_BLOCK), &gEfiFirmwareVolumeBlockProtocolGuid, NULL},
+ {STRING_TOKEN(STR_CAP_ARCH), &gEfiCapsuleArchProtocolGuid, NULL},
+ {STRING_TOKEN(STR_MP_SERVICE), &gEfiMpServiceProtocolGuid, NULL},
+ {STRING_TOKEN(STR_HBRAP), &gEfiPciHostBridgeResourceAllocationProtocolGuid, NULL},
+ {STRING_TOKEN(STR_PCIP), &gEfiPciPlatformProtocolGuid, NULL},
+ {STRING_TOKEN(STR_PCIO), &gEfiPciOverrideProtocolGuid, NULL},
+ {STRING_TOKEN(STR_PCIE), &gEfiPciEnumerationCompleteProtocolGuid, NULL},
+ {STRING_TOKEN(STR_IPCID), &gEfiIncompatiblePciDeviceSupportProtocolGuid, NULL},
+ {STRING_TOKEN(STR_PCIHPI), &gEfiPciHotPlugInitProtocolGuid, NULL},
+ {STRING_TOKEN(STR_PCIHPR), &gEfiPciHotPlugRequestProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SMBIOS), &gEfiSmbiosProtocolGuid, NULL},
+ {STRING_TOKEN(STR_S3_SAVE), &gEfiS3SaveStateProtocolGuid, NULL},
+ {STRING_TOKEN(STR_S3_S_SMM), &gEfiS3SmmSaveStateProtocolGuid, NULL},
+ {STRING_TOKEN(STR_RSC), &gEfiRscHandlerProtocolGuid, NULL},
+ {STRING_TOKEN(STR_S_RSC), &gEfiSmmRscHandlerProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ACPI_SDT), &gEfiAcpiSdtProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SIO), &gEfiSioProtocolGuid, NULL},
+ {STRING_TOKEN(STR_S_CPU2), &gEfiSmmCpuIo2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_S_BASE2), &gEfiSmmBase2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_S_ACC_2), &gEfiSmmAccess2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_S_CON_2), &gEfiSmmControl2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_S_CONFIG), &gEfiSmmConfigurationProtocolGuid, NULL},
+ {STRING_TOKEN(STR_S_RTL), &gEfiSmmReadyToLockProtocolGuid, NULL},
+ {STRING_TOKEN(STR_DS_RTL), &gEfiDxeSmmReadyToLockProtocolGuid, NULL},
+ {STRING_TOKEN(STR_S_COMM), &gEfiSmmCommunicationProtocolGuid, NULL},
+ {STRING_TOKEN(STR_S_STAT), &gEfiSmmStatusCodeProtocolGuid, NULL},
+ {STRING_TOKEN(STR_S_CPU), &gEfiSmmCpuProtocolGuid, NULL},
+ {STRING_TOKEN(STR_S_PCIRBIO), &gEfiPciRootBridgeIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_S_SWD), &gEfiSmmSwDispatch2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_S_SXD), &gEfiSmmSxDispatch2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_S_PTD2), &gEfiSmmPeriodicTimerDispatch2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_S_UD2), &gEfiSmmUsbDispatch2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_S_GD2), &gEfiSmmGpiDispatch2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_S_SBD2), &gEfiSmmStandbyButtonDispatch2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_S_PBD2), &gEfiSmmPowerButtonDispatch2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_S_ITD2), &gEfiSmmIoTrapDispatch2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_PCD), &gEfiPcdProtocolGuid, NULL},
+ {STRING_TOKEN(STR_FVB2), &gEfiFirmwareVolumeBlock2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_CPUIO2), &gEfiCpuIo2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_LEGACY_R2), &gEfiLegacyRegion2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SAL_MIP), &gEfiSalMcaInitPmiProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ES_BS), &gEfiExtendedSalBootServiceProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ES_BIO), &gEfiExtendedSalBaseIoServicesProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ES_STALL), &gEfiExtendedSalStallServicesProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ES_RTC), &gEfiExtendedSalRtcServicesProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ES_VS), &gEfiExtendedSalVariableServicesProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ES_MTC), &gEfiExtendedSalMtcServicesProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ES_RESET), &gEfiExtendedSalResetServicesProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ES_SC), &gEfiExtendedSalStatusCodeServicesProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ES_FBS), &gEfiExtendedSalFvBlockServicesProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ES_MP), &gEfiExtendedSalMpServicesProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ES_PAL), &gEfiExtendedSalPalServicesProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ES_BASE), &gEfiExtendedSalBaseServicesProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ES_MCA), &gEfiExtendedSalMcaServicesProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ES_PCI), &gEfiExtendedSalPciServicesProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ES_CACHE), &gEfiExtendedSalCacheServicesProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ES_MCA_LOG), &gEfiExtendedSalMcaLogServicesProtocolGuid, NULL},
+ {STRING_TOKEN(STR_S2ARCH), &gEfiSecurity2ArchProtocolGuid, NULL},
+ {STRING_TOKEN(STR_EODXE), &gEfiSmmEndOfDxeProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ISAHC), &gEfiIsaHcProtocolGuid, NULL},
+ {STRING_TOKEN(STR_ISAHC_B), &gEfiIsaHcServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SIO_C), &gEfiSioControlProtocolGuid, NULL},
+ {STRING_TOKEN(STR_GET_PCD), &gEfiGetPcdInfoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_I2C_M), &gEfiI2cMasterProtocolGuid, NULL},
+ {STRING_TOKEN(STR_I2CIO), &gEfiI2cIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_I2CEN), &gEfiI2cEnumerateProtocolGuid, NULL},
+ {STRING_TOKEN(STR_I2C_H), &gEfiI2cHostProtocolGuid, NULL},
+ {STRING_TOKEN(STR_I2C_BCM), &gEfiI2cBusConfigurationManagementProtocolGuid, NULL},
+ {STRING_TOKEN(STR_TREE), &gEfiTrEEProtocolGuid, NULL},
+ {STRING_TOKEN(STR_TCG2), &gEfiTcg2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_TIMESTAMP), &gEfiTimestampProtocolGuid, NULL},
+ {STRING_TOKEN(STR_RNG), &gEfiRngProtocolGuid, NULL},
+ {STRING_TOKEN(STR_NVMEPT), &gEfiNvmExpressPassThruProtocolGuid, NULL},
+ {STRING_TOKEN(STR_H2_SB), &gEfiHash2ServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_HASH2), &gEfiHash2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_BIO_C), &gEfiBlockIoCryptoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SCR), &gEfiSmartCardReaderProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SCE), &gEfiSmartCardEdgeProtocolGuid, NULL},
+ {STRING_TOKEN(STR_USB_FIO), &gEfiUsbFunctionIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_BC_HC), &gEfiBluetoothHcProtocolGuid, NULL},
+ {STRING_TOKEN(STR_BC_IO_SB), &gEfiBluetoothIoServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_BC_IO), &gEfiBluetoothIoProtocolGuid, NULL},
+ {STRING_TOKEN(STR_BC_C), &gEfiBluetoothConfigProtocolGuid, NULL},
+ {STRING_TOKEN(STR_REG_EXP), &gEfiRegularExpressionProtocolGuid, NULL},
+ {STRING_TOKEN(STR_B_MGR_P), &gEfiBootManagerPolicyProtocolGuid, NULL},
+ {STRING_TOKEN(STR_CKH), &gEfiConfigKeywordHandlerProtocolGuid, NULL},
+ {STRING_TOKEN(STR_WIFI), &gEfiWiFiProtocolGuid, NULL},
+ {STRING_TOKEN(STR_EAP_M), &gEfiEapManagement2ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_EAP_C), &gEfiEapConfigurationProtocolGuid, NULL},
+ {STRING_TOKEN(STR_PKCS7), &gEfiPkcs7VerifyProtocolGuid, NULL},
+ {STRING_TOKEN(STR_NET_DNS4_SB), &gEfiDns4ServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_NET_DNS4), &gEfiDns4ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_NET_DNS6_SB), &gEfiDns6ServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_NET_DNS6), &gEfiDns6ProtocolGuid, NULL},
+ {STRING_TOKEN(STR_NET_HTTP_SB), &gEfiHttpServiceBindingProtocolGuid, NULL},
+ {STRING_TOKEN(STR_NET_HTTP), &gEfiHttpProtocolGuid, NULL},
+ {STRING_TOKEN(STR_NET_HTTP_U), &gEfiHttpUtilitiesProtocolGuid, NULL},
+ {STRING_TOKEN(STR_REST), &gEfiRestProtocolGuid, NULL},
+
+//
+// UEFI Shell Spec 2.0
+//
+ {STRING_TOKEN(STR_SHELL_PARAMETERS), &gEfiShellParametersProtocolGuid, NULL},
+ {STRING_TOKEN(STR_SHELL), &gEfiShellProtocolGuid, NULL},
+
+//
+// UEFI Shell Spec 2.1
+//
+ {STRING_TOKEN(STR_SHELL_DYNAMIC), &gEfiShellDynamicCommandProtocolGuid, NULL},
+
+//
+// Misc
+//
+ {STRING_TOKEN(STR_PCDINFOPROT), &gGetPcdInfoProtocolGuid, NULL},
+
+//
+// terminator
+//
+ {STRING_TOKEN(STR_UNKNOWN_DEVICE), NULL, NULL},
+};
+
+/**
+ Function to get the node for a protocol or struct from it's GUID.
+
+ if Guid is NULL, then ASSERT.
+
+ @param[in] Guid The GUID to look for the name of.
+
+ @return The node.
+**/
+CONST GUID_INFO_BLOCK *
+EFIAPI
+InternalShellGetNodeFromGuid(
+ IN CONST EFI_GUID* Guid
+ )
+{
+ CONST GUID_INFO_BLOCK *ListWalker;
+ UINTN LoopCount;
+
+ ASSERT(Guid != NULL);
+
+ for (LoopCount = 0, ListWalker = GuidList; GuidList != NULL && LoopCount < GuidListCount; LoopCount++, ListWalker++) {
+ if (CompareGuid(ListWalker->GuidId, Guid)) {
+ return (ListWalker);
+ }
+ }
+
+ if (PcdGetBool(PcdShellIncludeNtGuids)) {
+ for (ListWalker = mGuidStringListNT ; ListWalker != NULL && ListWalker->GuidId != NULL ; ListWalker++) {
+ if (CompareGuid(ListWalker->GuidId, Guid)) {
+ return (ListWalker);
+ }
+ }
+ }
+ for (ListWalker = mGuidStringList ; ListWalker != NULL && ListWalker->GuidId != NULL ; ListWalker++) {
+ if (CompareGuid(ListWalker->GuidId, Guid)) {
+ return (ListWalker);
+ }
+ }
+ return (NULL);
+}
+
+/**
+Function to add a new GUID/Name mapping.
+
+@param[in] Guid The Guid
+@param[in] NameID The STRING id of the HII string to use
+@param[in] DumpFunc The pointer to the dump function
+
+
+@retval EFI_SUCCESS The operation was sucessful
+@retval EFI_OUT_OF_RESOURCES A memory allocation failed
+@retval EFI_INVALID_PARAMETER Guid NameId was invalid
+**/
+EFI_STATUS
+EFIAPI
+InsertNewGuidNameMapping(
+ IN CONST EFI_GUID *Guid,
+ IN CONST EFI_STRING_ID NameID,
+ IN CONST DUMP_PROTOCOL_INFO DumpFunc OPTIONAL
+ )
+{
+ ASSERT(Guid != NULL);
+ ASSERT(NameID != 0);
+
+ GuidList = ReallocatePool(GuidListCount * sizeof(GUID_INFO_BLOCK), GuidListCount+1 * sizeof(GUID_INFO_BLOCK), GuidList);
+ if (GuidList == NULL) {
+ GuidListCount = 0;
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ GuidListCount++;
+
+ GuidList[GuidListCount - 1].GuidId = AllocateCopyPool(sizeof(EFI_GUID), Guid);
+ GuidList[GuidListCount - 1].StringId = NameID;
+ GuidList[GuidListCount - 1].DumpInfo = DumpFunc;
+
+ if (GuidList[GuidListCount - 1].GuidId == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to add a new GUID/Name mapping.
+
+ This cannot overwrite an existing mapping.
+
+ @param[in] Guid The Guid
+ @param[in] TheName The Guid's name
+ @param[in] Lang RFC4646 language code list or NULL
+
+ @retval EFI_SUCCESS The operation was sucessful
+ @retval EFI_ACCESS_DENIED There was a duplicate
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed
+ @retval EFI_INVALID_PARAMETER Guid or TheName was NULL
+**/
+EFI_STATUS
+EFIAPI
+AddNewGuidNameMapping(
+ IN CONST EFI_GUID *Guid,
+ IN CONST CHAR16 *TheName,
+ IN CONST CHAR8 *Lang OPTIONAL
+ )
+{
+ EFI_STRING_ID NameID;
+
+ HandleParsingHiiInit();
+
+ if (Guid == NULL || TheName == NULL){
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ if ((InternalShellGetNodeFromGuid(Guid)) != NULL) {
+ return (EFI_ACCESS_DENIED);
+ }
+
+ NameID = HiiSetString(mHandleParsingHiiHandle, 0, (CHAR16*)TheName, Lang);
+ if (NameID == 0) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ return (InsertNewGuidNameMapping(Guid, NameID, NULL));
+}
+
+/**
+ Function to get the name of a protocol or struct from it's GUID.
+
+ if Guid is NULL, then ASSERT.
+
+ @param[in] Guid The GUID to look for the name of.
+ @param[in] Lang The language to use.
+
+ @return pointer to string of the name. The caller
+ is responsible to free this memory.
+**/
+CHAR16*
+EFIAPI
+GetStringNameFromGuid(
+ IN CONST EFI_GUID *Guid,
+ IN CONST CHAR8 *Lang OPTIONAL
+ )
+{
+ CONST GUID_INFO_BLOCK *Id;
+
+ HandleParsingHiiInit();
+
+ Id = InternalShellGetNodeFromGuid(Guid);
+ return (HiiGetString(mHandleParsingHiiHandle, Id==NULL?STRING_TOKEN(STR_UNKNOWN_DEVICE):Id->StringId, Lang));
+}
+
+/**
+ Function to dump protocol information from a handle.
+
+ This function will return a allocated string buffer containing the
+ information. The caller is responsible for freeing the memory.
+
+ If Guid is NULL, ASSERT().
+ If TheHandle is NULL, ASSERT().
+
+ @param[in] TheHandle The handle to dump information from.
+ @param[in] Guid The GUID of the protocol to dump.
+ @param[in] Verbose TRUE for extra info. FALSE otherwise.
+
+ @return The pointer to string.
+ @retval NULL An error was encountered.
+**/
+CHAR16*
+EFIAPI
+GetProtocolInformationDump(
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST EFI_GUID *Guid,
+ IN CONST BOOLEAN Verbose
+ )
+{
+ CONST GUID_INFO_BLOCK *Id;
+
+ ASSERT(TheHandle != NULL);
+ ASSERT(Guid != NULL);
+
+ if (TheHandle == NULL || Guid == NULL) {
+ return (NULL);
+ }
+
+ Id = InternalShellGetNodeFromGuid(Guid);
+ if (Id != NULL && Id->DumpInfo != NULL) {
+ return (Id->DumpInfo(TheHandle, Verbose));
+ }
+ return (NULL);
+}
+
+/**
+ Function to get the Guid for a protocol or struct based on it's string name.
+
+ do not modify the returned Guid.
+
+ @param[in] Name The pointer to the string name.
+ @param[in] Lang The pointer to the language code.
+ @param[out] Guid The pointer to the Guid.
+
+ @retval EFI_SUCCESS The operation was sucessful.
+**/
+EFI_STATUS
+EFIAPI
+GetGuidFromStringName(
+ IN CONST CHAR16 *Name,
+ IN CONST CHAR8 *Lang OPTIONAL,
+ OUT EFI_GUID **Guid
+ )
+{
+ CONST GUID_INFO_BLOCK *ListWalker;
+ CHAR16 *String;
+ UINTN LoopCount;
+
+ HandleParsingHiiInit();
+
+ ASSERT(Guid != NULL);
+ if (Guid == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+ *Guid = NULL;
+
+ if (PcdGetBool(PcdShellIncludeNtGuids)) {
+ for (ListWalker = mGuidStringListNT ; ListWalker != NULL && ListWalker->GuidId != NULL ; ListWalker++) {
+ String = HiiGetString(mHandleParsingHiiHandle, ListWalker->StringId, Lang);
+ if (Name != NULL && String != NULL && StringNoCaseCompare (&Name, &String) == 0) {
+ *Guid = ListWalker->GuidId;
+ }
+ SHELL_FREE_NON_NULL(String);
+ if (*Guid != NULL) {
+ return (EFI_SUCCESS);
+ }
+ }
+ }
+ for (ListWalker = mGuidStringList ; ListWalker != NULL && ListWalker->GuidId != NULL ; ListWalker++) {
+ String = HiiGetString(mHandleParsingHiiHandle, ListWalker->StringId, Lang);
+ if (Name != NULL && String != NULL && StringNoCaseCompare (&Name, &String) == 0) {
+ *Guid = ListWalker->GuidId;
+ }
+ SHELL_FREE_NON_NULL(String);
+ if (*Guid != NULL) {
+ return (EFI_SUCCESS);
+ }
+ }
+
+ for (LoopCount = 0, ListWalker = GuidList; GuidList != NULL && LoopCount < GuidListCount; LoopCount++, ListWalker++) {
+ String = HiiGetString(mHandleParsingHiiHandle, ListWalker->StringId, Lang);
+ if (Name != NULL && String != NULL && StringNoCaseCompare (&Name, &String) == 0) {
+ *Guid = ListWalker->GuidId;
+ }
+ SHELL_FREE_NON_NULL(String);
+ if (*Guid != NULL) {
+ return (EFI_SUCCESS);
+ }
+ }
+
+ return (EFI_NOT_FOUND);
+}
+
+/**
+ Get best support language for this driver.
+
+ First base on the user input language to search, second base on the current
+ platform used language to search, third get the first language from the
+ support language list. The caller need to free the buffer of the best language.
+
+ @param[in] SupportedLanguages The support languages for this driver.
+ @param[in] InputLanguage The user input language.
+ @param[in] Iso639Language Whether get language for ISO639.
+
+ @return The best support language for this driver.
+**/
+CHAR8 *
+EFIAPI
+GetBestLanguageForDriver (
+ IN CONST CHAR8 *SupportedLanguages,
+ IN CONST CHAR8 *InputLanguage,
+ IN BOOLEAN Iso639Language
+ )
+{
+ CHAR8 *LanguageVariable;
+ CHAR8 *BestLanguage;
+
+ GetVariable2 (Iso639Language ? L"Lang" : L"PlatformLang", &gEfiGlobalVariableGuid, (VOID**)&LanguageVariable, NULL);
+
+ BestLanguage = GetBestLanguage(
+ SupportedLanguages,
+ Iso639Language,
+ (InputLanguage != NULL) ? InputLanguage : "",
+ (LanguageVariable != NULL) ? LanguageVariable : "",
+ SupportedLanguages,
+ NULL
+ );
+
+ if (LanguageVariable != NULL) {
+ FreePool (LanguageVariable);
+ }
+
+ return BestLanguage;
+}
+
+/**
+ Function to retrieve the driver name (if possible) from the ComponentName or
+ ComponentName2 protocol
+
+ @param[in] TheHandle The driver handle to get the name of.
+ @param[in] Language The language to use.
+
+ @retval NULL The name could not be found.
+ @return A pointer to the string name. Do not de-allocate the memory.
+**/
+CONST CHAR16*
+EFIAPI
+GetStringNameFromHandle(
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST CHAR8 *Language
+ )
+{
+ EFI_COMPONENT_NAME2_PROTOCOL *CompNameStruct;
+ EFI_STATUS Status;
+ CHAR16 *RetVal;
+ CHAR8 *BestLang;
+
+ BestLang = NULL;
+
+ Status = gBS->OpenProtocol(
+ TheHandle,
+ &gEfiComponentName2ProtocolGuid,
+ (VOID**)&CompNameStruct,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (!EFI_ERROR(Status)) {
+ BestLang = GetBestLanguageForDriver (CompNameStruct->SupportedLanguages, Language, FALSE);
+ Status = CompNameStruct->GetDriverName(CompNameStruct, BestLang, &RetVal);
+ if (BestLang != NULL) {
+ FreePool (BestLang);
+ BestLang = NULL;
+ }
+ if (!EFI_ERROR(Status)) {
+ return (RetVal);
+ }
+ }
+ Status = gBS->OpenProtocol(
+ TheHandle,
+ &gEfiComponentNameProtocolGuid,
+ (VOID**)&CompNameStruct,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (!EFI_ERROR(Status)) {
+ BestLang = GetBestLanguageForDriver (CompNameStruct->SupportedLanguages, Language, FALSE);
+ Status = CompNameStruct->GetDriverName(CompNameStruct, BestLang, &RetVal);
+ if (BestLang != NULL) {
+ FreePool (BestLang);
+ }
+ if (!EFI_ERROR(Status)) {
+ return (RetVal);
+ }
+ }
+ return (NULL);
+}
+
+/**
+ Function to initialize the file global mHandleList object for use in
+ vonverting handles to index and index to handle.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+InternalShellInitHandleList(
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+ HANDLE_LIST *ListWalker;
+
+ if (mHandleList.NextIndex != 0) {
+ return EFI_SUCCESS;
+ }
+ InitializeListHead(&mHandleList.List.Link);
+ mHandleList.NextIndex = 1;
+ Status = gBS->LocateHandleBuffer (
+ AllHandles,
+ NULL,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR(Status)) {
+ return (Status);
+ }
+ for (mHandleList.NextIndex = 1 ; mHandleList.NextIndex <= HandleCount ; mHandleList.NextIndex++){
+ ListWalker = AllocateZeroPool(sizeof(HANDLE_LIST));
+ if (ListWalker != NULL) {
+ ListWalker->TheHandle = HandleBuffer[mHandleList.NextIndex - 1];
+ ListWalker->TheIndex = mHandleList.NextIndex;
+ InsertTailList (&mHandleList.List.Link, &ListWalker->Link);
+ }
+ }
+ FreePool(HandleBuffer);
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to retrieve the human-friendly index of a given handle. If the handle
+ does not have a index one will be automatically assigned. The index value is valid
+ until the termination of the shell application.
+
+ @param[in] TheHandle The handle to retrieve an index for.
+
+ @retval 0 A memory allocation failed.
+ @return The index of the handle.
+
+**/
+UINTN
+EFIAPI
+ConvertHandleToHandleIndex(
+ IN CONST EFI_HANDLE TheHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_GUID **ProtocolBuffer;
+ UINTN ProtocolCount;
+ HANDLE_LIST *ListWalker;
+
+ if (TheHandle == NULL) {
+ return 0;
+ }
+
+ InternalShellInitHandleList();
+
+ for (ListWalker = (HANDLE_LIST*)GetFirstNode(&mHandleList.List.Link)
+ ; !IsNull(&mHandleList.List.Link,&ListWalker->Link)
+ ; ListWalker = (HANDLE_LIST*)GetNextNode(&mHandleList.List.Link,&ListWalker->Link)
+ ){
+ if (ListWalker->TheHandle == TheHandle) {
+ //
+ // Verify that TheHandle is still present in the Handle Database
+ //
+ Status = gBS->ProtocolsPerHandle(TheHandle, &ProtocolBuffer, &ProtocolCount);
+ if (EFI_ERROR (Status)) {
+ //
+ // TheHandle is not present in the Handle Database, so delete from the handle list
+ //
+ RemoveEntryList (&ListWalker->Link);
+ return 0;
+ }
+ FreePool (ProtocolBuffer);
+ return (ListWalker->TheIndex);
+ }
+ }
+
+ //
+ // Verify that TheHandle is valid handle
+ //
+ Status = gBS->ProtocolsPerHandle(TheHandle, &ProtocolBuffer, &ProtocolCount);
+ if (EFI_ERROR (Status)) {
+ //
+ // TheHandle is not valid, so do not add to handle list
+ //
+ return 0;
+ }
+ FreePool (ProtocolBuffer);
+
+ ListWalker = AllocateZeroPool(sizeof(HANDLE_LIST));
+ if (ListWalker == NULL) {
+ return 0;
+ }
+ ListWalker->TheHandle = TheHandle;
+ ListWalker->TheIndex = mHandleList.NextIndex++;
+ InsertTailList(&mHandleList.List.Link,&ListWalker->Link);
+ return (ListWalker->TheIndex);
+}
+
+
+
+/**
+ Function to retrieve the EFI_HANDLE from the human-friendly index.
+
+ @param[in] TheIndex The index to retrieve the EFI_HANDLE for.
+
+ @retval NULL The index was invalid.
+ @return The EFI_HANDLE that index represents.
+
+**/
+EFI_HANDLE
+EFIAPI
+ConvertHandleIndexToHandle(
+ IN CONST UINTN TheIndex
+ )
+{
+ EFI_STATUS Status;
+ EFI_GUID **ProtocolBuffer;
+ UINTN ProtocolCount;
+ HANDLE_LIST *ListWalker;
+
+ InternalShellInitHandleList();
+
+ if (TheIndex >= mHandleList.NextIndex) {
+ return NULL;
+ }
+
+ for (ListWalker = (HANDLE_LIST*)GetFirstNode(&mHandleList.List.Link)
+ ; !IsNull(&mHandleList.List.Link,&ListWalker->Link)
+ ; ListWalker = (HANDLE_LIST*)GetNextNode(&mHandleList.List.Link,&ListWalker->Link)
+ ){
+ if (ListWalker->TheIndex == TheIndex && ListWalker->TheHandle != NULL) {
+ //
+ // Verify that LinkWalker->TheHandle is valid handle
+ //
+ Status = gBS->ProtocolsPerHandle(ListWalker->TheHandle, &ProtocolBuffer, &ProtocolCount);
+ if (EFI_ERROR (Status)) {
+ //
+ // TheHandle is not valid, so do not add to handle list
+ //
+ ListWalker->TheHandle = NULL;
+ }
+ return (ListWalker->TheHandle);
+ }
+ }
+ return NULL;
+}
+
+/**
+ Gets all the related EFI_HANDLEs based on the mask supplied.
+
+ This function scans all EFI_HANDLES in the UEFI environment's handle database
+ and returns the ones with the specified relationship (Mask) to the specified
+ controller handle.
+
+ If both DriverBindingHandle and ControllerHandle are NULL, then ASSERT.
+ If MatchingHandleCount is NULL, then ASSERT.
+
+ If MatchingHandleBuffer is not NULL upon a successful return the memory must be
+ caller freed.
+
+ @param[in] DriverBindingHandle The handle with Driver Binding protocol on it.
+ @param[in] ControllerHandle The handle with Device Path protocol on it.
+ @param[in] MatchingHandleCount The pointer to UINTN that specifies the number of HANDLES in
+ MatchingHandleBuffer.
+ @param[out] MatchingHandleBuffer On a successful return, a buffer of MatchingHandleCount
+ EFI_HANDLEs with a terminating NULL EFI_HANDLE.
+ @param[out] HandleType An array of type information.
+
+ @retval EFI_SUCCESS The operation was successful, and any related handles
+ are in MatchingHandleBuffer.
+ @retval EFI_NOT_FOUND No matching handles were found.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid or out of range.
+**/
+EFI_STATUS
+EFIAPI
+ParseHandleDatabaseByRelationshipWithType (
+ IN CONST EFI_HANDLE DriverBindingHandle OPTIONAL,
+ IN CONST EFI_HANDLE ControllerHandle OPTIONAL,
+ IN UINTN *HandleCount,
+ OUT EFI_HANDLE **HandleBuffer,
+ OUT UINTN **HandleType
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleIndex;
+ EFI_GUID **ProtocolGuidArray;
+ UINTN ArrayCount;
+ UINTN ProtocolIndex;
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;
+ UINTN OpenInfoCount;
+ UINTN OpenInfoIndex;
+ UINTN ChildIndex;
+ INTN DriverBindingHandleIndex;
+
+ ASSERT(HandleCount != NULL);
+ ASSERT(HandleBuffer != NULL);
+ ASSERT(HandleType != NULL);
+ ASSERT(DriverBindingHandle != NULL || ControllerHandle != NULL);
+
+ *HandleCount = 0;
+ *HandleBuffer = NULL;
+ *HandleType = NULL;
+
+ //
+ // Retrieve the list of all handles from the handle database
+ //
+ Status = gBS->LocateHandleBuffer (
+ AllHandles,
+ NULL,
+ NULL,
+ HandleCount,
+ HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return (Status);
+ }
+
+ *HandleType = AllocateZeroPool (*HandleCount * sizeof (UINTN));
+ if (*HandleType == NULL) {
+ SHELL_FREE_NON_NULL (*HandleBuffer);
+ *HandleCount = 0;
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ DriverBindingHandleIndex = -1;
+ for (HandleIndex = 0; HandleIndex < *HandleCount; HandleIndex++) {
+ if (DriverBindingHandle != NULL && (*HandleBuffer)[HandleIndex] == DriverBindingHandle) {
+ DriverBindingHandleIndex = (INTN)HandleIndex;
+ }
+ }
+
+ for (HandleIndex = 0; HandleIndex < *HandleCount; HandleIndex++) {
+ //
+ // Retrieve the list of all the protocols on each handle
+ //
+ Status = gBS->ProtocolsPerHandle (
+ (*HandleBuffer)[HandleIndex],
+ &ProtocolGuidArray,
+ &ArrayCount
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {
+
+ //
+ // Set the bit describing what this handle has
+ //
+ if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiLoadedImageProtocolGuid) ) {
+ (*HandleType)[HandleIndex] |= (UINTN)HR_IMAGE_HANDLE;
+ } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverBindingProtocolGuid) ) {
+ (*HandleType)[HandleIndex] |= (UINTN)HR_DRIVER_BINDING_HANDLE;
+ } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverConfiguration2ProtocolGuid)) {
+ (*HandleType)[HandleIndex] |= (UINTN)HR_DRIVER_CONFIGURATION_HANDLE;
+ } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverConfigurationProtocolGuid) ) {
+ (*HandleType)[HandleIndex] |= (UINTN)HR_DRIVER_CONFIGURATION_HANDLE;
+ } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverDiagnostics2ProtocolGuid) ) {
+ (*HandleType)[HandleIndex] |= (UINTN)HR_DRIVER_DIAGNOSTICS_HANDLE;
+ } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDriverDiagnosticsProtocolGuid) ) {
+ (*HandleType)[HandleIndex] |= (UINTN)HR_DRIVER_DIAGNOSTICS_HANDLE;
+ } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiComponentName2ProtocolGuid) ) {
+ (*HandleType)[HandleIndex] |= (UINTN)HR_COMPONENT_NAME_HANDLE;
+ } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiComponentNameProtocolGuid) ) {
+ (*HandleType)[HandleIndex] |= (UINTN)HR_COMPONENT_NAME_HANDLE;
+ } else if (CompareGuid (ProtocolGuidArray[ProtocolIndex], &gEfiDevicePathProtocolGuid) ) {
+ (*HandleType)[HandleIndex] |= (UINTN)HR_DEVICE_HANDLE;
+ }
+ //
+ // Retrieve the list of agents that have opened each protocol
+ //
+ Status = gBS->OpenProtocolInformation (
+ (*HandleBuffer)[HandleIndex],
+ ProtocolGuidArray[ProtocolIndex],
+ &OpenInfo,
+ &OpenInfoCount
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if (ControllerHandle == NULL) {
+ //
+ // ControllerHandle == NULL and DriverBindingHandle != NULL.
+ // Return information on all the controller handles that the driver specified by DriverBindingHandle is managing
+ //
+ for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
+ if (OpenInfo[OpenInfoIndex].AgentHandle == DriverBindingHandle && (OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
+ (*HandleType)[HandleIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_CONTROLLER_HANDLE);
+ if (DriverBindingHandleIndex != -1) {
+ (*HandleType)[DriverBindingHandleIndex] |= (UINTN)HR_DEVICE_DRIVER;
+ }
+ }
+ if (OpenInfo[OpenInfoIndex].AgentHandle == DriverBindingHandle && (OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
+ (*HandleType)[HandleIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_CONTROLLER_HANDLE);
+ if (DriverBindingHandleIndex != -1) {
+ (*HandleType)[DriverBindingHandleIndex] |= (UINTN)(HR_BUS_DRIVER | HR_DEVICE_DRIVER);
+ }
+ for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) {
+ if (OpenInfo[OpenInfoIndex].ControllerHandle == (*HandleBuffer)[ChildIndex]) {
+ (*HandleType)[ChildIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_CHILD_HANDLE);
+ }
+ }
+ }
+ }
+ }
+ if (DriverBindingHandle == NULL && ControllerHandle != NULL) {
+ if (ControllerHandle == (*HandleBuffer)[HandleIndex]) {
+ (*HandleType)[HandleIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_CONTROLLER_HANDLE);
+ for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
+ if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
+ for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) {
+ if (OpenInfo[OpenInfoIndex].AgentHandle == (*HandleBuffer)[ChildIndex]) {
+ (*HandleType)[ChildIndex] |= (UINTN)HR_DEVICE_DRIVER;
+ }
+ }
+ }
+ if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
+ for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) {
+ if (OpenInfo[OpenInfoIndex].AgentHandle == (*HandleBuffer)[ChildIndex]) {
+ (*HandleType)[ChildIndex] |= (UINTN)(HR_BUS_DRIVER | HR_DEVICE_DRIVER);
+ }
+ if (OpenInfo[OpenInfoIndex].ControllerHandle == (*HandleBuffer)[ChildIndex]) {
+ (*HandleType)[ChildIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_CHILD_HANDLE);
+ }
+ }
+ }
+ }
+ } else {
+ for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
+ if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
+ if (OpenInfo[OpenInfoIndex].ControllerHandle == ControllerHandle) {
+ (*HandleType)[HandleIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_PARENT_HANDLE);
+ }
+ }
+ }
+ }
+ }
+ if (DriverBindingHandle != NULL && ControllerHandle != NULL) {
+ if (ControllerHandle == (*HandleBuffer)[HandleIndex]) {
+ (*HandleType)[HandleIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_CONTROLLER_HANDLE);
+ for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
+ if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_DRIVER) != 0) {
+ if (OpenInfo[OpenInfoIndex].AgentHandle == DriverBindingHandle) {
+ if (DriverBindingHandleIndex != -1) {
+ (*HandleType)[DriverBindingHandleIndex] |= (UINTN)HR_DEVICE_DRIVER;
+ }
+ }
+ }
+ if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
+ if (OpenInfo[OpenInfoIndex].AgentHandle == DriverBindingHandle) {
+ for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) {
+ if (OpenInfo[OpenInfoIndex].ControllerHandle == (*HandleBuffer)[ChildIndex]) {
+ (*HandleType)[ChildIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_CHILD_HANDLE);
+ }
+ }
+ }
+
+ for (ChildIndex = 0; ChildIndex < *HandleCount; ChildIndex++) {
+ if (OpenInfo[OpenInfoIndex].AgentHandle == (*HandleBuffer)[ChildIndex]) {
+ (*HandleType)[ChildIndex] |= (UINTN)(HR_BUS_DRIVER | HR_DEVICE_DRIVER);
+ }
+ }
+ }
+ }
+ } else {
+ for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
+ if ((OpenInfo[OpenInfoIndex].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
+ if (OpenInfo[OpenInfoIndex].ControllerHandle == ControllerHandle) {
+ (*HandleType)[HandleIndex] |= (UINTN)(HR_DEVICE_HANDLE | HR_PARENT_HANDLE);
+ }
+ }
+ }
+ }
+ }
+ FreePool (OpenInfo);
+ }
+ FreePool (ProtocolGuidArray);
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Gets all the related EFI_HANDLEs based on the single EFI_HANDLE and the mask
+ supplied.
+
+ This function will scan all EFI_HANDLES in the UEFI environment's handle database
+ and return all the ones with the specified relationship (Mask) to the specified
+ controller handle.
+
+ If both DriverBindingHandle and ControllerHandle are NULL, then ASSERT.
+ If MatchingHandleCount is NULL, then ASSERT.
+
+ If MatchingHandleBuffer is not NULL upon a sucessful return the memory must be
+ caller freed.
+
+ @param[in] DriverBindingHandle Handle to a object with Driver Binding protocol
+ on it.
+ @param[in] ControllerHandle Handle to a device with Device Path protocol on it.
+ @param[in] Mask Mask of what relationship(s) is desired.
+ @param[in] MatchingHandleCount Poitner to UINTN specifying number of HANDLES in
+ MatchingHandleBuffer.
+ @param[out] MatchingHandleBuffer On a sucessful return a buffer of MatchingHandleCount
+ EFI_HANDLEs and a terminating NULL EFI_HANDLE.
+
+ @retval EFI_SUCCESS The operation was sucessful and any related handles
+ are in MatchingHandleBuffer;
+ @retval EFI_NOT_FOUND No matching handles were found.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid or out of range.
+**/
+EFI_STATUS
+EFIAPI
+ParseHandleDatabaseByRelationship (
+ IN CONST EFI_HANDLE DriverBindingHandle OPTIONAL,
+ IN CONST EFI_HANDLE ControllerHandle OPTIONAL,
+ IN CONST UINTN Mask,
+ IN UINTN *MatchingHandleCount,
+ OUT EFI_HANDLE **MatchingHandleBuffer OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN *HandleType;
+ UINTN HandleIndex;
+
+ ASSERT(MatchingHandleCount != NULL);
+ ASSERT(DriverBindingHandle != NULL || ControllerHandle != NULL);
+
+ if ((Mask & HR_VALID_MASK) != Mask) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ if ((Mask & HR_CHILD_HANDLE) != 0 && DriverBindingHandle == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ *MatchingHandleCount = 0;
+ if (MatchingHandleBuffer != NULL) {
+ *MatchingHandleBuffer = NULL;
+ }
+
+ HandleBuffer = NULL;
+ HandleType = NULL;
+
+ Status = ParseHandleDatabaseByRelationshipWithType (
+ DriverBindingHandle,
+ ControllerHandle,
+ &HandleCount,
+ &HandleBuffer,
+ &HandleType
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // Count the number of handles that match the attributes in Mask
+ //
+ for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
+ if ((HandleType[HandleIndex] & Mask) == Mask) {
+ (*MatchingHandleCount)++;
+ }
+ }
+ //
+ // If no handles match the attributes in Mask then return EFI_NOT_FOUND
+ //
+ if (*MatchingHandleCount == 0) {
+ Status = EFI_NOT_FOUND;
+ } else {
+
+ if (MatchingHandleBuffer == NULL) {
+ //
+ // Someone just wanted the count...
+ //
+ Status = EFI_SUCCESS;
+ } else {
+ //
+ // Allocate a handle buffer for the number of handles that matched the attributes in Mask
+ //
+ *MatchingHandleBuffer = AllocateZeroPool ((*MatchingHandleCount +1)* sizeof (EFI_HANDLE));
+ if (*MatchingHandleBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ for (HandleIndex = 0, *MatchingHandleCount = 0
+ ; HandleIndex < HandleCount
+ ; HandleIndex++
+ ) {
+ //
+ // Fill the allocated buffer with the handles that matched the attributes in Mask
+ //
+ if ((HandleType[HandleIndex] & Mask) == Mask) {
+ (*MatchingHandleBuffer)[(*MatchingHandleCount)++] = HandleBuffer[HandleIndex];
+ }
+ }
+
+ //
+ // Make the last one NULL
+ //
+ (*MatchingHandleBuffer)[*MatchingHandleCount] = NULL;
+
+ Status = EFI_SUCCESS;
+ } // *MatchingHandleBuffer == NULL (ELSE)
+ } // MacthingHandleBuffer == NULL (ELSE)
+ } // *MatchingHandleCount == 0 (ELSE)
+ } // no error on ParseHandleDatabaseByRelationshipWithType
+
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+
+ if (HandleType != NULL) {
+ FreePool (HandleType);
+ }
+
+ ASSERT ((MatchingHandleBuffer == NULL) ||
+ (*MatchingHandleCount == 0 && *MatchingHandleBuffer == NULL) ||
+ (*MatchingHandleCount != 0 && *MatchingHandleBuffer != NULL));
+ return Status;
+}
+
+/**
+ Gets handles for any child controllers of the passed in controller.
+
+ @param[in] ControllerHandle The handle of the "parent controller"
+ @param[in] MatchingHandleCount Pointer to the number of handles in
+ MatchingHandleBuffer on return.
+ @param[out] MatchingHandleBuffer Buffer containing handles on a successful
+ return.
+
+
+ @retval EFI_SUCCESS The operation was sucessful.
+**/
+EFI_STATUS
+EFIAPI
+ParseHandleDatabaseForChildControllers(
+ IN CONST EFI_HANDLE ControllerHandle,
+ IN UINTN *MatchingHandleCount,
+ OUT EFI_HANDLE **MatchingHandleBuffer OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleIndex;
+ UINTN DriverBindingHandleCount;
+ EFI_HANDLE *DriverBindingHandleBuffer;
+ UINTN DriverBindingHandleIndex;
+ UINTN ChildControllerHandleCount;
+ EFI_HANDLE *ChildControllerHandleBuffer;
+ UINTN ChildControllerHandleIndex;
+ EFI_HANDLE *HandleBufferForReturn;
+
+ if (MatchingHandleCount == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+ *MatchingHandleCount = 0;
+
+ Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (
+ ControllerHandle,
+ &DriverBindingHandleCount,
+ &DriverBindingHandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Get a buffer big enough for all the controllers.
+ //
+ HandleBufferForReturn = GetHandleListByProtocol(NULL);
+ if (HandleBufferForReturn == NULL) {
+ FreePool (DriverBindingHandleBuffer);
+ return (EFI_NOT_FOUND);
+ }
+
+ for (DriverBindingHandleIndex = 0; DriverBindingHandleIndex < DriverBindingHandleCount; DriverBindingHandleIndex++) {
+ Status = PARSE_HANDLE_DATABASE_MANAGED_CHILDREN (
+ DriverBindingHandleBuffer[DriverBindingHandleIndex],
+ ControllerHandle,
+ &ChildControllerHandleCount,
+ &ChildControllerHandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ for (ChildControllerHandleIndex = 0;
+ ChildControllerHandleIndex < ChildControllerHandleCount;
+ ChildControllerHandleIndex++
+ ) {
+ for (HandleIndex = 0; HandleIndex < *MatchingHandleCount; HandleIndex++) {
+ if (HandleBufferForReturn[HandleIndex] == ChildControllerHandleBuffer[ChildControllerHandleIndex]) {
+ break;
+ }
+ }
+ if (HandleIndex >= *MatchingHandleCount) {
+ HandleBufferForReturn[(*MatchingHandleCount)++] = ChildControllerHandleBuffer[ChildControllerHandleIndex];
+ }
+ }
+
+ FreePool (ChildControllerHandleBuffer);
+ }
+
+ FreePool (DriverBindingHandleBuffer);
+
+ if (MatchingHandleBuffer != NULL) {
+ *MatchingHandleBuffer = HandleBufferForReturn;
+ } else {
+ FreePool(HandleBufferForReturn);
+ }
+ ASSERT ((MatchingHandleBuffer == NULL) ||
+ (*MatchingHandleCount == 0 && *MatchingHandleBuffer == NULL) ||
+ (*MatchingHandleCount != 0 && *MatchingHandleBuffer != NULL));
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Appends 1 buffer to another buffer. This will re-allocate the destination buffer
+ if necessary to fit all of the data.
+
+ If DestinationBuffer is NULL, then ASSERT().
+
+ @param[in, out] DestinationBuffer The pointer to the pointer to the buffer to append onto.
+ @param[in, out] DestinationSize The pointer to the size of DestinationBuffer.
+ @param[in] SourceBuffer The pointer to the buffer to append onto DestinationBuffer.
+ @param[in] SourceSize The number of bytes of SourceBuffer to append.
+
+ @retval NULL A memory allocation failed.
+ @retval NULL A parameter was invalid.
+ @return A pointer to (*DestinationBuffer).
+**/
+VOID*
+EFIAPI
+BuffernCatGrow (
+ IN OUT VOID **DestinationBuffer,
+ IN OUT UINTN *DestinationSize,
+ IN VOID *SourceBuffer,
+ IN UINTN SourceSize
+ )
+{
+ UINTN LocalDestinationSize;
+ UINTN LocalDestinationFinalSize;
+
+ ASSERT(DestinationBuffer != NULL);
+
+ if (SourceSize == 0 || SourceBuffer == NULL) {
+ return (*DestinationBuffer);
+ }
+
+ if (DestinationSize == NULL) {
+ LocalDestinationSize = 0;
+ } else {
+ LocalDestinationSize = *DestinationSize;
+ }
+
+ LocalDestinationFinalSize = LocalDestinationSize + SourceSize;
+
+ if (DestinationSize != NULL) {
+ *DestinationSize = LocalDestinationSize;
+ }
+
+ if (LocalDestinationSize == 0) {
+ // allcoate
+ *DestinationBuffer = AllocateZeroPool(LocalDestinationFinalSize);
+ } else {
+ // reallocate
+ *DestinationBuffer = ReallocatePool(LocalDestinationSize, LocalDestinationFinalSize, *DestinationBuffer);
+ }
+
+ ASSERT(*DestinationBuffer != NULL);
+
+ // copy
+ return (CopyMem(((UINT8*)(*DestinationBuffer)) + LocalDestinationSize, SourceBuffer, SourceSize));
+}
+
+/**
+ Gets handles for any child devices produced by the passed in driver.
+
+ @param[in] DriverHandle The handle of the driver.
+ @param[in] MatchingHandleCount Pointer to the number of handles in
+ MatchingHandleBuffer on return.
+ @param[out] MatchingHandleBuffer Buffer containing handles on a successful
+ return.
+ @retval EFI_SUCCESS The operation was sucessful.
+ @sa ParseHandleDatabaseByRelationship
+**/
+EFI_STATUS
+EFIAPI
+ParseHandleDatabaseForChildDevices(
+ IN CONST EFI_HANDLE DriverHandle,
+ IN UINTN *MatchingHandleCount,
+ OUT EFI_HANDLE **MatchingHandleBuffer OPTIONAL
+ )
+{
+ EFI_HANDLE *Buffer;
+ EFI_HANDLE *Buffer2;
+ UINTN Count1;
+ UINTN Count2;
+ UINTN HandleIndex;
+ EFI_STATUS Status;
+ UINTN HandleBufferSize;
+
+ ASSERT(MatchingHandleCount != NULL);
+
+ HandleBufferSize = 0;
+ Buffer = NULL;
+ Buffer2 = NULL;
+ *MatchingHandleCount = 0;
+
+ Status = PARSE_HANDLE_DATABASE_DEVICES (
+ DriverHandle,
+ &Count1,
+ &Buffer
+ );
+ if (!EFI_ERROR (Status)) {
+ for (HandleIndex = 0; HandleIndex < Count1; HandleIndex++) {
+ //
+ // now find the children
+ //
+ Status = PARSE_HANDLE_DATABASE_MANAGED_CHILDREN (
+ DriverHandle,
+ Buffer[HandleIndex],
+ &Count2,
+ &Buffer2
+ );
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+ //
+ // save out required and optional data elements
+ //
+ *MatchingHandleCount += Count2;
+ if (MatchingHandleBuffer != NULL) {
+ *MatchingHandleBuffer = BuffernCatGrow((VOID**)MatchingHandleBuffer, &HandleBufferSize, Buffer2, Count2 * sizeof(Buffer2[0]));
+ }
+
+ //
+ // free the memory
+ //
+ if (Buffer2 != NULL) {
+ FreePool(Buffer2);
+ }
+ }
+ }
+
+ if (Buffer != NULL) {
+ FreePool(Buffer);
+ }
+ return (Status);
+}
+
+/**
+ Function to get all handles that support a given protocol or all handles.
+
+ @param[in] ProtocolGuid The guid of the protocol to get handles for. If NULL
+ then the function will return all handles.
+
+ @retval NULL A memory allocation failed.
+ @return A NULL terminated list of handles.
+**/
+EFI_HANDLE*
+EFIAPI
+GetHandleListByProtocol (
+ IN CONST EFI_GUID *ProtocolGuid OPTIONAL
+ )
+{
+ EFI_HANDLE *HandleList;
+ UINTN Size;
+ EFI_STATUS Status;
+
+ Size = 0;
+ HandleList = NULL;
+
+ //
+ // We cannot use LocateHandleBuffer since we need that NULL item on the ends of the list!
+ //
+ if (ProtocolGuid == NULL) {
+ Status = gBS->LocateHandle(AllHandles, NULL, NULL, &Size, HandleList);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HandleList = AllocateZeroPool(Size + sizeof(EFI_HANDLE));
+ if (HandleList == NULL) {
+ return (NULL);
+ }
+ Status = gBS->LocateHandle(AllHandles, NULL, NULL, &Size, HandleList);
+ HandleList[Size/sizeof(EFI_HANDLE)] = NULL;
+ }
+ } else {
+ Status = gBS->LocateHandle(ByProtocol, (EFI_GUID*)ProtocolGuid, NULL, &Size, HandleList);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HandleList = AllocateZeroPool(Size + sizeof(EFI_HANDLE));
+ if (HandleList == NULL) {
+ return (NULL);
+ }
+ Status = gBS->LocateHandle(ByProtocol, (EFI_GUID*)ProtocolGuid, NULL, &Size, HandleList);
+ HandleList[Size/sizeof(EFI_HANDLE)] = NULL;
+ }
+ }
+ if (EFI_ERROR(Status)) {
+ if (HandleList != NULL) {
+ FreePool(HandleList);
+ }
+ return (NULL);
+ }
+ return (HandleList);
+}
+
+/**
+ Function to get all handles that support some protocols.
+
+ @param[in] ProtocolGuids A NULL terminated list of protocol GUIDs.
+
+ @retval NULL A memory allocation failed.
+ @retval NULL ProtocolGuids was NULL.
+ @return A NULL terminated list of EFI_HANDLEs.
+**/
+EFI_HANDLE*
+EFIAPI
+GetHandleListByProtocolList (
+ IN CONST EFI_GUID **ProtocolGuids
+ )
+{
+ EFI_HANDLE *HandleList;
+ UINTN Size;
+ UINTN TotalSize;
+ UINTN TempSize;
+ EFI_STATUS Status;
+ CONST EFI_GUID **GuidWalker;
+ EFI_HANDLE *HandleWalker1;
+ EFI_HANDLE *HandleWalker2;
+
+ Size = 0;
+ HandleList = NULL;
+ TotalSize = sizeof(EFI_HANDLE);
+
+ for (GuidWalker = ProtocolGuids ; GuidWalker != NULL && *GuidWalker != NULL ; GuidWalker++,Size = 0){
+ Status = gBS->LocateHandle(ByProtocol, (EFI_GUID*)(*GuidWalker), NULL, &Size, NULL);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ TotalSize += Size;
+ }
+ }
+
+ //
+ // No handles were found...
+ //
+ if (TotalSize == sizeof(EFI_HANDLE)) {
+ return (NULL);
+ }
+
+ HandleList = AllocateZeroPool(TotalSize);
+ if (HandleList == NULL) {
+ return (NULL);
+ }
+
+ Size = 0;
+ for (GuidWalker = ProtocolGuids ; GuidWalker != NULL && *GuidWalker != NULL ; GuidWalker++){
+ TempSize = TotalSize - Size;
+ Status = gBS->LocateHandle(ByProtocol, (EFI_GUID*)(*GuidWalker), NULL, &TempSize, HandleList+(Size/sizeof(EFI_HANDLE)));
+
+ //
+ // Allow for missing protocols... Only update the 'used' size upon success.
+ //
+ if (!EFI_ERROR(Status)) {
+ Size += TempSize;
+ }
+ }
+ ASSERT(HandleList[(TotalSize/sizeof(EFI_HANDLE))-1] == NULL);
+
+ for (HandleWalker1 = HandleList ; HandleWalker1 != NULL && *HandleWalker1 != NULL ; HandleWalker1++) {
+ for (HandleWalker2 = HandleWalker1 + 1; HandleWalker2 != NULL && *HandleWalker2 != NULL ; HandleWalker2++) {
+ if (*HandleWalker1 == *HandleWalker2) {
+ //
+ // copy memory back 1 handle width.
+ //
+ CopyMem(HandleWalker2, HandleWalker2 + 1, TotalSize - ((HandleWalker2-HandleList+1)*sizeof(EFI_HANDLE)));
+ }
+ }
+ }
+
+ return (HandleList);
+}
diff --git a/Core/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.h b/Core/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.h
new file mode 100644
index 0000000000..9a45076e07
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.h
@@ -0,0 +1,298 @@
+/** @file
+ Provides interface to advanced shell functionality for parsing both handle and protocol database.
+
+ Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+ (C) Copyright 2013-2016 Hewlett-Packard Development Company, L.P.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _UEFI_HANDLE_PARSING_LIB_INTERNAL_H_
+#define _UEFI_HANDLE_PARSING_LIB_INTERNAL_H_
+
+#include <Uefi.h>
+
+#include <Guid/FileInfo.h>
+#include <Guid/ConsoleInDevice.h>
+#include <Guid/ConsoleOutDevice.h>
+#include <Guid/StandardErrorDevice.h>
+#include <Guid/GlobalVariable.h>
+#include <Guid/Gpt.h>
+#include <Guid/FileSystemInfo.h>
+#include <Guid/ShellLibHiiGuid.h>
+
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/EfiShellInterface.h>
+#include <Protocol/EfiShellEnvironment2.h>
+#include <Protocol/EfiShell.h>
+#include <Protocol/EfiShellParameters.h>
+#include <Protocol/DevicePathToText.h>
+#include <Protocol/DriverBinding.h>
+#include <Protocol/DriverConfiguration2.h>
+#include <Protocol/DriverConfiguration.h>
+#include <Protocol/DriverDiagnostics2.h>
+#include <Protocol/DriverDiagnostics.h>
+#include <Protocol/ComponentName2.h>
+#include <Protocol/ComponentName.h>
+#include <Protocol/PlatformDriverOverride.h>
+#include <Protocol/DevicePathUtilities.h>
+#include <Protocol/DevicePathFromText.h>
+#include <Protocol/BusSpecificDriverOverride.h>
+#include <Protocol/PlatformToDriverConfiguration.h>
+#include <Protocol/DriverSupportedEfiVersion.h>
+#include <Protocol/SimpleTextInEx.h>
+#include <Protocol/SimplePointer.h>
+#include <Protocol/SerialIo.h>
+#include <Protocol/AbsolutePointer.h>
+#include <Protocol/GraphicsOutput.h>
+#include <Protocol/EdidDiscovered.h>
+#include <Protocol/EdidActive.h>
+#include <Protocol/EdidOverride.h>
+#include <Protocol/LoadFile.h>
+#include <Protocol/LoadFile2.h>
+#include <Protocol/TapeIo.h>
+#include <Protocol/DiskIo.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/UnicodeCollation.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/ScsiPassThru.h>
+#include <Protocol/ScsiPassThruExt.h>
+#include <Protocol/ScsiIo.h>
+#include <Protocol/IScsiInitiatorName.h>
+#include <Protocol/UsbIo.h>
+#include <Protocol/UsbHostController.h>
+#include <Protocol/Usb2HostController.h>
+#include <Protocol/DebugSupport.h>
+#include <Protocol/DebugPort.h>
+#include <Protocol/Decompress.h>
+#include <Protocol/AcpiTable.h>
+#include <Protocol/Ebc.h>
+#include <Protocol/SimpleNetwork.h>
+#include <Protocol/NetworkInterfaceIdentifier.h>
+#include <Protocol/PxeBaseCode.h>
+#include <Protocol/PxeBaseCodeCallBack.h>
+#include <Protocol/Bis.h>
+#include <Protocol/ManagedNetwork.h>
+#include <Protocol/Arp.h>
+#include <Protocol/Dhcp4.h>
+#include <Protocol/Tcp4.h>
+#include <Protocol/Ip4.h>
+#include <Protocol/Ip4Config.h>
+#include <Protocol/Ip4Config2.h>
+#include <Protocol/Udp4.h>
+#include <Protocol/Mtftp4.h>
+#include <Protocol/AuthenticationInfo.h>
+#include <Protocol/Hash.h>
+#include <Protocol/HiiFont.h>
+#include <Protocol/HiiString.h>
+#include <Protocol/HiiImage.h>
+#include <Protocol/HiiDatabase.h>
+#include <Protocol/HiiConfigRouting.h>
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/FormBrowser2.h>
+#include <Protocol/DeviceIo.h>
+#include <Protocol/UgaDraw.h>
+#include <Protocol/UgaIo.h>
+#include <Protocol/DriverConfiguration.h>
+#include <Protocol/DriverConfiguration2.h>
+#include <Protocol/DevicePathUtilities.h>
+//#include <Protocol/FirmwareVolume.h>
+//#include <Protocol/FirmwareVolume2.h>
+#include <Protocol/DriverFamilyOverride.h>
+#include <Protocol/Pcd.h>
+#include <Protocol/TcgService.h>
+#include <Protocol/HiiPackageList.h>
+#include <Protocol/Ip6.h>
+#include <Protocol/Ip6Config.h>
+#include <Protocol/Mtftp6.h>
+#include <Protocol/Dhcp6.h>
+#include <Protocol/Udp6.h>
+#include <Protocol/Tcp6.h>
+#include <Protocol/VlanConfig.h>
+#include <Protocol/Eap.h>
+#include <Protocol/EapManagement.h>
+#include <Protocol/Ftp4.h>
+#include <Protocol/IpSecConfig.h>
+#include <Protocol/DriverHealth.h>
+#include <Protocol/DeferredImageLoad.h>
+#include <Protocol/UserCredential.h>
+#include <Protocol/UserManager.h>
+#include <Protocol/AtaPassThru.h>
+#include <Protocol/FirmwareManagement.h>
+#include <Protocol/IpSec.h>
+#include <Protocol/Kms.h>
+#include <Protocol/BlockIo2.h>
+#include <Protocol/StorageSecurityCommand.h>
+#include <Protocol/UserCredential2.h>
+#include <Protocol/IdeControllerInit.h>
+#include <Protocol/DiskIo2.h>
+#include <Protocol/AdapterInformation.h>
+#include <Protocol/EfiShellDynamicCommand.h>
+#include <Protocol/DiskInfo.h>
+
+#include <Library/HandleParsingLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PcdLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiLib.h>
+#include <Library/HiiLib.h>
+#include <Library/ShellLib.h>
+#include <Library/SortLib.h>
+#include <Library/ShellCommandLib.h>
+
+#define EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION_V1 1
+#define EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION_V2 2
+
+///
+/// EFI_FIRMWARE_IMAGE_DESCRIPTOR in UEFI spec < 2.4a
+///
+typedef struct {
+ ///
+ /// A unique number identifying the firmware image within the device. The number is
+ /// between 1 and DescriptorCount.
+ ///
+ UINT8 ImageIndex;
+ ///
+ /// A unique number identifying the firmware image type.
+ ///
+ EFI_GUID ImageTypeId;
+ ///
+ /// A unique number identifying the firmware image.
+ ///
+ UINT64 ImageId;
+ ///
+ /// A pointer to a null-terminated string representing the firmware image name.
+ ///
+ CHAR16 *ImageIdName;
+ ///
+ /// Identifies the version of the device firmware. The format is vendor specific and new
+ /// version must have a greater value than an old version.
+ ///
+ UINT32 Version;
+ ///
+ /// A pointer to a null-terminated string representing the firmware image version name.
+ ///
+ CHAR16 *VersionName;
+ ///
+ /// Size of the image in bytes. If size=0, then only ImageIndex and ImageTypeId are valid.
+ ///
+ UINTN Size;
+ ///
+ /// Image attributes that are supported by this device. See 'Image Attribute Definitions'
+ /// for possible returned values of this parameter. A value of 1 indicates the attribute is
+ /// supported and the current setting value is indicated in AttributesSetting. A
+ /// value of 0 indicates the attribute is not supported and the current setting value in
+ /// AttributesSetting is meaningless.
+ ///
+ UINT64 AttributesSupported;
+ ///
+ /// Image attributes. See 'Image Attribute Definitions' for possible returned values of
+ /// this parameter.
+ ///
+ UINT64 AttributesSetting;
+ ///
+ /// Image compatibilities. See 'Image Compatibility Definitions' for possible returned
+ /// values of this parameter.
+ ///
+ UINT64 Compatibilities;
+} EFI_FIRMWARE_IMAGE_DESCRIPTOR_V1;
+
+
+///
+/// EFI_FIRMWARE_IMAGE_DESCRIPTOR in UEFI spec > 2.4a and < 2.5
+///
+typedef struct {
+ ///
+ /// A unique number identifying the firmware image within the device. The number is
+ /// between 1 and DescriptorCount.
+ ///
+ UINT8 ImageIndex;
+ ///
+ /// A unique number identifying the firmware image type.
+ ///
+ EFI_GUID ImageTypeId;
+ ///
+ /// A unique number identifying the firmware image.
+ ///
+ UINT64 ImageId;
+ ///
+ /// A pointer to a null-terminated string representing the firmware image name.
+ ///
+ CHAR16 *ImageIdName;
+ ///
+ /// Identifies the version of the device firmware. The format is vendor specific and new
+ /// version must have a greater value than an old version.
+ ///
+ UINT32 Version;
+ ///
+ /// A pointer to a null-terminated string representing the firmware image version name.
+ ///
+ CHAR16 *VersionName;
+ ///
+ /// Size of the image in bytes. If size=0, then only ImageIndex and ImageTypeId are valid.
+ ///
+ UINTN Size;
+ ///
+ /// Image attributes that are supported by this device. See 'Image Attribute Definitions'
+ /// for possible returned values of this parameter. A value of 1 indicates the attribute is
+ /// supported and the current setting value is indicated in AttributesSetting. A
+ /// value of 0 indicates the attribute is not supported and the current setting value in
+ /// AttributesSetting is meaningless.
+ ///
+ UINT64 AttributesSupported;
+ ///
+ /// Image attributes. See 'Image Attribute Definitions' for possible returned values of
+ /// this parameter.
+ ///
+ UINT64 AttributesSetting;
+ ///
+ /// Image compatibilities. See 'Image Compatibility Definitions' for possible returned
+ /// values of this parameter.
+ ///
+ UINT64 Compatibilities;
+ ///
+ /// Describes the lowest ImageDescriptor version that the device will accept. Only
+ /// present in version 2 or higher.
+ UINT32 LowestSupportedImageVersion;
+} EFI_FIRMWARE_IMAGE_DESCRIPTOR_V2;
+
+typedef struct {
+ LIST_ENTRY Link;
+ EFI_HANDLE TheHandle;
+ UINTN TheIndex;
+}HANDLE_LIST;
+
+typedef struct {
+ HANDLE_LIST List;
+ UINTN NextIndex;
+} HANDLE_INDEX_LIST;
+
+typedef
+CHAR16 *
+(EFIAPI *DUMP_PROTOCOL_INFO)(
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST BOOLEAN Verbose
+ );
+
+typedef struct _GUID_INFO_BLOCK{
+ EFI_STRING_ID StringId;
+ EFI_GUID *GuidId;
+ DUMP_PROTOCOL_INFO DumpInfo;
+} GUID_INFO_BLOCK;
+
+#endif
+
diff --git a/Core/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf b/Core/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
new file mode 100644
index 0000000000..3bd4dbe423
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
@@ -0,0 +1,317 @@
+## @file
+# Provides interface to advanced shell functionality for parsing both handle and protocol database.
+# Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved. <BR>
+# (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
+# (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = UefiHandleParsingLib
+ FILE_GUID = 3CDC7177-CC2A-4678-BA8F-1A936A093FA4
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = HandleParsingLib|UEFI_APPLICATION UEFI_DRIVER DXE_RUNTIME_DRIVER
+ CONSTRUCTOR = HandleParsingLibConstructor
+ DESTRUCTOR = HandleParsingLibDestructor
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ UefiHandleParsingLib.c
+ UefiHandleParsingLib.h
+ UefiHandleParsingLib.uni
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ShellPkg/ShellPkg.dec
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ DevicePathLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ FileHandleLib
+ PrintLib
+ UefiLib
+ HiiLib
+ SortLib
+
+[Protocols]
+ gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES
+
+ # shell 2.0
+ gEfiShellProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiShellParametersProtocolGuid ## SOMETIMES_CONSUMES
+
+ # 'old' shell
+ gEfiShellEnvironment2Guid ## SOMETIMES_CONSUMES
+ gEfiShellInterfaceGuid ## SOMETIMES_CONSUMES
+
+ gEfiUnicodeCollation2ProtocolGuid ## UNDEFINED
+ gEfiDevicePathToTextProtocolGuid ## UNDEFINED
+ gEfiBusSpecificDriverOverrideProtocolGuid ## UNDEFINED
+ gEfiDevicePathUtilitiesProtocolGuid ## UNDEFINED
+ gEfiDevicePathFromTextProtocolGuid ## UNDEFINED
+ gEfiPlatformDriverOverrideProtocolGuid ## UNDEFINED
+ gEfiSimpleTextInProtocolGuid ## UNDEFINED
+ gEfiPlatformToDriverConfigurationProtocolGuid ## UNDEFINED
+ gEfiDriverSupportedEfiVersionProtocolGuid ## UNDEFINED
+ gEfiLoadedImageProtocolGuid ## CONSUMES
+ gEfiDevicePathProtocolGuid ## CONSUMES
+ gEfiLoadedImageDevicePathProtocolGuid ## UNDEFINED
+ gEfiSimpleTextOutProtocolGuid ## UNDEFINED
+ gEfiSimplePointerProtocolGuid ## UNDEFINED
+ gEfiAbsolutePointerProtocolGuid ## UNDEFINED
+ gEfiSerialIoProtocolGuid ## UNDEFINED
+ gEfiEdidDiscoveredProtocolGuid ## UNDEFINED
+ gEfiEdidActiveProtocolGuid ## UNDEFINED
+ gEfiEdidOverrideProtocolGuid ## UNDEFINED
+ gEfiLoadFileProtocolGuid ## UNDEFINED
+ gEfiLoadFile2ProtocolGuid ## UNDEFINED
+ gEfiTapeIoProtocolGuid ## UNDEFINED
+ gEfiDiskIoProtocolGuid ## UNDEFINED
+ gEfiBlockIoProtocolGuid ## UNDEFINED
+ gEfiUnicodeCollationProtocolGuid ## UNDEFINED
+ gEfiPciRootBridgeIoProtocolGuid ## UNDEFINED
+ gEfiPciIoProtocolGuid ## UNDEFINED
+ gEfiScsiPassThruProtocolGuid ## UNDEFINED
+ gEfiScsiIoProtocolGuid ## UNDEFINED
+ gEfiExtScsiPassThruProtocolGuid ## UNDEFINED
+ gEfiIScsiInitiatorNameProtocolGuid ## UNDEFINED
+ gEfiUsbIoProtocolGuid ## UNDEFINED
+ gEfiUsbHcProtocolGuid ## UNDEFINED
+ gEfiUsb2HcProtocolGuid ## UNDEFINED
+ gEfiDebugSupportProtocolGuid ## UNDEFINED
+ gEfiDebugPortProtocolGuid ## UNDEFINED
+ gEfiDecompressProtocolGuid ## UNDEFINED
+ gEfiAcpiTableProtocolGuid ## UNDEFINED
+ gEfiEbcProtocolGuid ## UNDEFINED
+ gEfiSimpleNetworkProtocolGuid ## UNDEFINED
+ gEfiNetworkInterfaceIdentifierProtocolGuid ## UNDEFINED
+ gEfiNetworkInterfaceIdentifierProtocolGuid_31 ## UNDEFINED
+ gEfiPxeBaseCodeProtocolGuid ## UNDEFINED
+ gEfiPxeBaseCodeCallbackProtocolGuid ## UNDEFINED
+ gEfiBisProtocolGuid ## UNDEFINED
+ gEfiManagedNetworkServiceBindingProtocolGuid ## UNDEFINED
+ gEfiManagedNetworkProtocolGuid ## UNDEFINED
+ gEfiArpServiceBindingProtocolGuid ## UNDEFINED
+ gEfiArpProtocolGuid ## UNDEFINED
+ gEfiDhcp4ServiceBindingProtocolGuid ## UNDEFINED
+ gEfiDhcp4ProtocolGuid ## UNDEFINED
+ gEfiTcp4ServiceBindingProtocolGuid ## UNDEFINED
+ gEfiTcp4ProtocolGuid ## UNDEFINED
+ gEfiIp4ServiceBindingProtocolGuid ## UNDEFINED
+ gEfiIp4ProtocolGuid ## UNDEFINED
+ gEfiIp4ConfigProtocolGuid ## UNDEFINED
+ gEfiIp4Config2ProtocolGuid ## UNDEFINED
+ gEfiUdp4ServiceBindingProtocolGuid ## UNDEFINED
+ gEfiUdp4ProtocolGuid ## UNDEFINED
+ gEfiMtftp4ServiceBindingProtocolGuid ## UNDEFINED
+ gEfiMtftp4ProtocolGuid ## UNDEFINED
+ gEfiAuthenticationInfoProtocolGuid ## UNDEFINED
+ gEfiHashServiceBindingProtocolGuid ## UNDEFINED
+ gEfiHashProtocolGuid ## UNDEFINED
+ gEfiHiiFontProtocolGuid ## UNDEFINED
+ gEfiHiiStringProtocolGuid ## UNDEFINED
+ gEfiHiiImageProtocolGuid ## UNDEFINED
+ gEfiHiiConfigRoutingProtocolGuid ## UNDEFINED
+ gEfiHiiConfigAccessProtocolGuid ## UNDEFINED
+ gEfiFormBrowser2ProtocolGuid ## UNDEFINED
+ gEfiDeviceIoProtocolGuid ## UNDEFINED
+ gEfiUgaDrawProtocolGuid ## UNDEFINED
+ gEfiUgaIoProtocolGuid ## UNDEFINED
+ gEfiDriverConfigurationProtocolGuid ## UNDEFINED
+ gEfiDriverConfiguration2ProtocolGuid ## UNDEFINED
+ gEfiSimpleTextInputExProtocolGuid ## UNDEFINED
+ gEfiIp6ServiceBindingProtocolGuid ## UNDEFINED
+ gEfiIp6ProtocolGuid ## UNDEFINED
+ gEfiIp6ConfigProtocolGuid ## UNDEFINED
+ gEfiMtftp6ServiceBindingProtocolGuid ## UNDEFINED
+ gEfiMtftp6ProtocolGuid ## UNDEFINED
+ gEfiDhcp6ServiceBindingProtocolGuid ## UNDEFINED
+ gEfiDhcp6ProtocolGuid ## UNDEFINED
+ gEfiUdp6ServiceBindingProtocolGuid ## UNDEFINED
+ gEfiUdp6ProtocolGuid ## UNDEFINED
+ gEfiTcp6ServiceBindingProtocolGuid ## UNDEFINED
+ gEfiTcp6ProtocolGuid ## UNDEFINED
+ gEfiVlanConfigProtocolGuid ## UNDEFINED
+ gEfiEapProtocolGuid ## UNDEFINED
+ gEfiEapManagementProtocolGuid ## UNDEFINED
+ gEfiFtp4ServiceBindingProtocolGuid ## UNDEFINED
+ gEfiFtp4ProtocolGuid ## UNDEFINED
+ gEfiIpSecConfigProtocolGuid ## UNDEFINED
+ gEfiDriverHealthProtocolGuid ## UNDEFINED
+ gEfiDeferredImageLoadProtocolGuid ## UNDEFINED
+ gEfiUserCredentialProtocolGuid ## UNDEFINED
+ gEfiUserManagerProtocolGuid ## UNDEFINED
+ gEfiAtaPassThruProtocolGuid ## UNDEFINED
+ gEfiFirmwareManagementProtocolGuid ## UNDEFINED
+ gEfiIpSecProtocolGuid ## UNDEFINED
+ gEfiIpSec2ProtocolGuid ## UNDEFINED
+ gEfiKmsProtocolGuid ## UNDEFINED
+ gEfiBlockIo2ProtocolGuid ## UNDEFINED
+ gEfiStorageSecurityCommandProtocolGuid ## UNDEFINED
+ gEfiUserCredential2ProtocolGuid ## UNDEFINED
+ gPcdProtocolGuid ## UNDEFINED
+ gEfiTcgProtocolGuid ## UNDEFINED
+ gEfiHiiPackageListProtocolGuid ## UNDEFINED
+ gEfiDriverFamilyOverrideProtocolGuid ## UNDEFINED
+ gEfiIdeControllerInitProtocolGuid ## UNDEFINED
+ gEfiDiskIo2ProtocolGuid ## UNDEFINED
+ gEfiAdapterInformationProtocolGuid ## UNDEFINED
+ gEfiShellDynamicCommandProtocolGuid ## UNDEFINED
+ gEfiDiskInfoProtocolGuid ## UNDEFINED
+ gGetPcdInfoProtocolGuid ## UNDEFINED
+ gEfiBdsArchProtocolGuid ## UNDEFINED
+ gEfiCpuArchProtocolGuid ## UNDEFINED
+ gEfiMetronomeArchProtocolGuid ## UNDEFINED
+ gEfiMonotonicCounterArchProtocolGuid ## UNDEFINED
+ gEfiRealTimeClockArchProtocolGuid ## UNDEFINED
+ gEfiResetArchProtocolGuid ## UNDEFINED
+ gEfiRuntimeArchProtocolGuid ## UNDEFINED
+ gEfiSecurityArchProtocolGuid ## UNDEFINED
+ gEfiTimerArchProtocolGuid ## UNDEFINED
+ gEfiVariableWriteArchProtocolGuid ## UNDEFINED
+ gEfiVariableArchProtocolGuid ## UNDEFINED
+ gEfiSecurityPolicyProtocolGuid ## UNDEFINED
+ gEfiWatchdogTimerArchProtocolGuid ## UNDEFINED
+ gEfiStatusCodeRuntimeProtocolGuid ## UNDEFINED
+ gEfiSmbusHcProtocolGuid ## UNDEFINED
+ gEfiFirmwareVolume2ProtocolGuid ## UNDEFINED
+ gEfiFirmwareVolumeBlockProtocolGuid ## UNDEFINED
+ gEfiCapsuleArchProtocolGuid ## UNDEFINED
+ gEfiMpServiceProtocolGuid ## UNDEFINED
+ gEfiPciHostBridgeResourceAllocationProtocolGuid ## UNDEFINED
+ gEfiPciPlatformProtocolGuid ## UNDEFINED
+ gEfiPciOverrideProtocolGuid ## UNDEFINED
+ gEfiPciEnumerationCompleteProtocolGuid ## UNDEFINED
+ gEfiIncompatiblePciDeviceSupportProtocolGuid ## UNDEFINED
+ gEfiPciHotPlugInitProtocolGuid ## UNDEFINED
+ gEfiPciHotPlugRequestProtocolGuid ## UNDEFINED
+ gEfiSmbiosProtocolGuid ## UNDEFINED
+ gEfiS3SaveStateProtocolGuid ## UNDEFINED
+ gEfiS3SmmSaveStateProtocolGuid ## UNDEFINED
+ gEfiRscHandlerProtocolGuid ## UNDEFINED
+ gEfiSmmRscHandlerProtocolGuid ## UNDEFINED
+ gEfiAcpiSdtProtocolGuid ## UNDEFINED
+ gEfiSioProtocolGuid ## UNDEFINED
+ gEfiSmmCpuIo2ProtocolGuid ## UNDEFINED
+ gEfiSmmBase2ProtocolGuid ## UNDEFINED
+ gEfiSmmAccess2ProtocolGuid ## UNDEFINED
+ gEfiSmmControl2ProtocolGuid ## UNDEFINED
+ gEfiSmmConfigurationProtocolGuid ## UNDEFINED
+ gEfiSmmReadyToLockProtocolGuid ## UNDEFINED
+ gEfiDxeSmmReadyToLockProtocolGuid ## UNDEFINED
+ gEfiSmmCommunicationProtocolGuid ## UNDEFINED
+ gEfiSmmStatusCodeProtocolGuid ## UNDEFINED
+ gEfiSmmCpuProtocolGuid ## UNDEFINED
+ gEfiSmmPciRootBridgeIoProtocolGuid ## UNDEFINED
+ gEfiSmmSwDispatch2ProtocolGuid ## UNDEFINED
+ gEfiSmmSxDispatch2ProtocolGuid ## UNDEFINED
+ gEfiSmmPeriodicTimerDispatch2ProtocolGuid ## UNDEFINED
+ gEfiSmmUsbDispatch2ProtocolGuid ## UNDEFINED
+ gEfiSmmGpiDispatch2ProtocolGuid ## UNDEFINED
+ gEfiSmmStandbyButtonDispatch2ProtocolGuid ## UNDEFINED
+ gEfiSmmPowerButtonDispatch2ProtocolGuid ## UNDEFINED
+ gEfiSmmIoTrapDispatch2ProtocolGuid ## UNDEFINED
+ gEfiPcdProtocolGuid ## UNDEFINED
+ gEfiFirmwareVolumeBlock2ProtocolGuid ## UNDEFINED
+ gEfiCpuIo2ProtocolGuid ## UNDEFINED
+ gEfiLegacyRegion2ProtocolGuid ## UNDEFINED
+ gEfiSalMcaInitPmiProtocolGuid ## UNDEFINED
+ gEfiExtendedSalBootServiceProtocolGuid ## UNDEFINED
+ gEfiExtendedSalBaseIoServicesProtocolGuid ## UNDEFINED
+ gEfiExtendedSalStallServicesProtocolGuid ## UNDEFINED
+ gEfiExtendedSalRtcServicesProtocolGuid ## UNDEFINED
+ gEfiExtendedSalVariableServicesProtocolGuid ## UNDEFINED
+ gEfiExtendedSalMtcServicesProtocolGuid ## UNDEFINED
+ gEfiExtendedSalResetServicesProtocolGuid ## UNDEFINED
+ gEfiExtendedSalStatusCodeServicesProtocolGuid ## UNDEFINED
+ gEfiExtendedSalFvBlockServicesProtocolGuid ## UNDEFINED
+ gEfiExtendedSalMpServicesProtocolGuid ## UNDEFINED
+ gEfiExtendedSalPalServicesProtocolGuid ## UNDEFINED
+ gEfiExtendedSalBaseServicesProtocolGuid ## UNDEFINED
+ gEfiExtendedSalMcaServicesProtocolGuid ## UNDEFINED
+ gEfiExtendedSalPciServicesProtocolGuid ## UNDEFINED
+ gEfiExtendedSalCacheServicesProtocolGuid ## UNDEFINED
+ gEfiExtendedSalMcaLogServicesProtocolGuid ## UNDEFINED
+ gEfiSecurity2ArchProtocolGuid ## UNDEFINED
+ gEfiSmmEndOfDxeProtocolGuid ## UNDEFINED
+ gEfiIsaHcProtocolGuid ## UNDEFINED
+ gEfiIsaHcServiceBindingProtocolGuid ## UNDEFINED
+ gEfiSioControlProtocolGuid ## UNDEFINED
+ gEfiGetPcdInfoProtocolGuid ## UNDEFINED
+ gEfiI2cMasterProtocolGuid ## UNDEFINED
+ gEfiI2cIoProtocolGuid ## UNDEFINED
+ gEfiI2cEnumerateProtocolGuid ## UNDEFINED
+ gEfiI2cHostProtocolGuid ## UNDEFINED
+ gEfiI2cBusConfigurationManagementProtocolGuid ## UNDEFINED
+ gEfiTrEEProtocolGuid ## UNDEFINED
+ gEfiTcg2ProtocolGuid ## UNDEFINED
+ gEfiTimestampProtocolGuid ## UNDEFINED
+ gEfiRngProtocolGuid ## UNDEFINED
+ gEfiNvmExpressPassThruProtocolGuid ## UNDEFINED
+ gEfiHash2ServiceBindingProtocolGuid ## UNDEFINED
+ gEfiHash2ProtocolGuid ## UNDEFINED
+ gEfiBlockIoCryptoProtocolGuid ## UNDEFINED
+ gEfiSmartCardReaderProtocolGuid ## UNDEFINED
+ gEfiSmartCardEdgeProtocolGuid ## UNDEFINED
+ gEfiUsbFunctionIoProtocolGuid ## UNDEFINED
+ gEfiBluetoothHcProtocolGuid ## UNDEFINED
+ gEfiBluetoothIoServiceBindingProtocolGuid ## UNDEFINED
+ gEfiBluetoothIoProtocolGuid ## UNDEFINED
+ gEfiBluetoothConfigProtocolGuid ## UNDEFINED
+ gEfiRegularExpressionProtocolGuid ## UNDEFINED
+ gEfiBootManagerPolicyProtocolGuid ## UNDEFINED
+ gEfiConfigKeywordHandlerProtocolGuid ## UNDEFINED
+ gEfiWiFiProtocolGuid ## UNDEFINED
+ gEfiEapManagement2ProtocolGuid ## UNDEFINED
+ gEfiEapConfigurationProtocolGuid ## UNDEFINED
+ gEfiPkcs7VerifyProtocolGuid ## UNDEFINED
+ gEfiDns4ServiceBindingProtocolGuid ## UNDEFINED
+ gEfiDns4ProtocolGuid ## UNDEFINED
+ gEfiDns6ServiceBindingProtocolGuid ## UNDEFINED
+ gEfiDns6ProtocolGuid ## UNDEFINED
+ gEfiHttpServiceBindingProtocolGuid ## UNDEFINED
+ gEfiHttpProtocolGuid ## UNDEFINED
+ gEfiHttpUtilitiesProtocolGuid ## UNDEFINED
+ gEfiRestProtocolGuid ## UNDEFINED
+
+[Guids]
+ gEfiFileInfoGuid ## UNDEFINED
+ gEfiShellEnvironment2ExtGuid ## CONSUMES ## GUID
+ gEfiPcAnsiGuid ## UNDEFINED
+ gEfiVT100Guid ## UNDEFINED
+ gEfiVT100PlusGuid ## UNDEFINED
+ gEfiVTUTF8Guid ## UNDEFINED
+ gEfiStandardErrorDeviceGuid ## UNDEFINED
+ gEfiConsoleInDeviceGuid ## UNDEFINED
+ gEfiConsoleOutDeviceGuid ## UNDEFINED
+ gEfiFileSystemInfoGuid ## UNDEFINED
+ gEfiGlobalVariableGuid ## UNDEFINED
+ gEfiPartTypeSystemPartGuid ## UNDEFINED
+ gEfiPartTypeLegacyMbrGuid ## UNDEFINED
+ gHandleParsingHiiGuid ## UNDEFINED
+ gEfiAdapterInfoMediaStateGuid ## SOMETIMES_CONSUMES ## GUID
+ gEfiAdapterInfoNetworkBootGuid ## SOMETIMES_CONSUMES ## GUID
+ gEfiAdapterInfoSanMacAddressGuid ## SOMETIMES_CONSUMES ## GUID
+ gEfiAdapterInfoUndiIpv6SupportGuid ## SOMETIMES_CONSUMES ## GUID
+
+[Pcd.common]
+ gEfiShellPkgTokenSpaceGuid.PcdShellPrintBufferSize ## CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdShellIncludeNtGuids ## CONSUMES \ No newline at end of file
diff --git a/Core/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.uni b/Core/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.uni
new file mode 100644
index 0000000000..aa6663d247
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.uni
@@ -0,0 +1,463 @@
+// /**
+//
+// Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved. <BR>
+// (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
+// (C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// Module Name:
+//
+// UefiHandleParsingLib.uni
+//
+// Abstract:
+//
+//
+//
+// **/
+
+/=#
+
+#langdef en-US "english"
+
+//
+// Protocol names used making the GUID <-> Name bi-directional list
+//
+
+// basics Images & Device Path
+#string STR_LOADED_IMAGE #language en-US "LoadedImage"
+#string STR_DEVICE_PATH #language en-US "DevicePath"
+#string STR_IMAGE_PATH #language en-US "ImageDevicePath"
+#string STR_DEVICE_PATH_UTIL #language en-US "DevicePathUtilities"
+#string STR_DEVICE_PATH_TXT #language en-US "DevicePathToText"
+#string STR_DEVICE_PATH_FTXT #language en-US "DevicePathFromText"
+#string STR_DEVICE_PATH_PC #language en-US "DevicePathPCAnsi"
+#string STR_DEVICE_PATH_VT100 #language en-US "DevicePathVT100"
+#string STR_DEVICE_PATH_VT100P #language en-US "DevicePathVT100+"
+#string STR_DEVICE_PATH_VTUTF8 #language en-US "DevicePathVTUTF8"
+
+// Drivers
+#string STR_DRIVER_BINDING #language en-US "DriverBinding"
+#string STR_PLATFORM_OVERRIDE #language en-US "PlatformOverride"
+#string STR_BUS_OVERRIDE #language en-US "BusSpecificDriverOverride"
+#string STR_DRIVER_DIAG #language en-US "DriverDiagnostics"
+#string STR_DRIVER_DIAG2 #language en-US "DriverDiagnostics2"
+#string STR_DRIVER_CN #language en-US "ComponentName"
+#string STR_DRIVER_CN2 #language en-US "ComponentName2"
+#string STR_PLAT_DRV_CFG #language en-US "PlatformtoDriverConfiguration"
+#string STR_DRIVER_VERSION #language en-US "SupportedEfiSpecVersion"
+
+// Console
+#string STR_TXT_IN #language en-US "SimpleTextIn"
+#string STR_TXT_IN_EX #language en-US "SimpleTextInEx"
+#string STR_TXT_OUT #language en-US "SimpleTextOut"
+#string STR_SIM_POINTER #language en-US "SimplePointer"
+#string STR_ABS_POINTER #language en-US "AbsolutePointer"
+#string STR_SERIAL_IO #language en-US "SerialIO"
+#string STR_GRAPHICS_OUTPUT #language en-US "GraphicsOutput"
+#string STR_EDID_DISCOVERED #language en-US "EDIDDiscovered"
+#string STR_EDID_ACTIVE #language en-US "EDIDActive"
+#string STR_EDID_OVERRIDE #language en-US "EDIDOverride"
+#string STR_CON_IN #language en-US "ConsoleIn"
+#string STR_CON_OUT #language en-US "ConsoleOut"
+#string STR_STD_ERR #language en-US "StdErr"
+
+// Media
+#string STR_LOAD_FILE #language en-US "LoadFile"
+#string STR_LOAD_FILE2 #language en-US "LoadFile2"
+#string STR_SIMPLE_FILE_SYS #language en-US "SimpleFileSystem"
+#string STR_FILE_INFO #language en-US "FileInfo"
+#string STR_FILE_SYS_INFO #language en-US "FileSystemInfo"
+#string STR_TAPE_IO #language en-US "TapeIO"
+#string STR_DISK_IO #language en-US "DiskIO"
+#string STR_DISK_IO2 #language en-US "DiskIO2"
+#string STR_BLK_IO #language en-US "BlockIO"
+#string STR_UC #language en-US "UnicodeCollation"
+#string STR_UC2 #language en-US "UnicodeCollation2"
+#string STR_ADAPTER_INFO #language en-US "AdapterInfo"
+
+// PCI
+#string STR_PCIRB_IO #language en-US "PCIRootBridgeIO"
+#string STR_PCI_IO #language en-US "PCIIO"
+
+// SCSI
+#string STR_SCSI_PT #language en-US "SCSIPassThru"
+#string STR_SCSI_IO #language en-US "SCSIIO"
+#string STR_SCSI_PT_EXT #language en-US "ExtendedSCSIPassThru"
+
+// iSCSI
+#string STR_ISCSI #language en-US "iSCSIInitiatorName"
+
+// USB
+#string STR_USB_IO #language en-US "USBIO"
+#string STR_USB_HC #language en-US "USBHostControler"
+#string STR_USB_HC2 #language en-US "USBHostController2"
+
+// Debug
+#string STR_DEBUG_SUPPORT #language en-US "DebugSupport"
+#string STR_DEBUG_PORT #language en-US "DebugPort"
+
+#string STR_DECOMPRESS #language en-US "Decompress"
+
+#string STR_ACPI_TABLE #language en-US "AcpiTable"
+
+#string STR_EBC_INTERPRETER #language en-US "EBCInterpreter"
+
+// Network
+#string STR_SNP #language en-US "SimpleNetwork"
+#string STR_NII #language en-US "NetworkInterfaceIdentifier"
+#string STR_NII_31 #language en-US "NetworkInterfaceIdentifier31"
+#string STR_PXE_BC #language en-US "PXEBaseCode"
+#string STR_PXE_CB #language en-US "PXECallback"
+#string STR_BIS #language en-US "BIS"
+#string STR_MNP_SB #language en-US "ManagedNetworkServiceBinding"
+#string STR_MNP #language en-US "ManagedNetwork"
+
+#string STR_ARP_SB #language en-US "ARPServiceBinding"
+#string STR_ARP #language en-US "ARP"
+#string STR_DHCPV4_SB #language en-US "DHCPv4ServiceBinding"
+#string STR_DHCPV4 #language en-US "DHCPv4"
+#string STR_TCPV4_SB #language en-US "TCPv4ServiceBinding"
+#string STR_TCPV4 #language en-US "TCPv4"
+#string STR_IPV4_SB #language en-US "IPv4ServiceBinding"
+#string STR_IPV4 #language en-US "IPv4"
+#string STR_IPV4_CFG #language en-US "IPv4Config"
+#string STR_IPV4_CFG2 #language en-US "IPv4Config2"
+#string STR_UDPV4_SB #language en-US "UDPv4ServiceBinding"
+#string STR_UDPV4 #language en-US "UDPv4"
+#string STR_MTFTPV4_SB #language en-US "MTFTPv4ServiceBinding"
+#string STR_MTFTPV4 #language en-US "MTFTPv4"
+
+// Security
+#string STR_HASH_SB #language en-US "HashServiceBinding"
+#string STR_HASH #language en-US "Hash"
+#string STR_AUTH_INFO #language en-US "AuthenticationInfo"
+
+// HII
+#string STR_HII_FONT #language en-US "HIIFont"
+#string STR_HII_STRING #language en-US "HIIString"
+#string STR_HII_IMAGE #language en-US "HIIImage"
+#string STR_HII_DATABASE #language en-US "HIIDatabase"
+#string STR_HII_CONFIG_ROUT #language en-US "HIIConfigRouting"
+#string STR_HII_CONFIG_ACC #language en-US "HIIConfigAccess"
+#string STR_HII_FORM_BROWSER2 #language en-US "HIIFormBrowser2"
+
+// Shell
+#string STR_SHELL_PARAMETERS #language en-US "ShellParameters"
+#string STR_SHELL #language en-US "Shell"
+#string STR_SHELL_DYNAMIC #language en-US "ShellDynamicCommand"
+
+#string STR_EFI_GLOBAL_VARIABLE #language en-US "EFIGlobalVariable"
+
+// NT32 emulation
+#string STR_WINNT_THUNK #language en-US "WinNTThunk"
+#string STR_WINNT_DRIVER_IO #language en-US "WinNTDriverIO"
+#string STR_WINNT_SERIAL_PORT #language en-US "WinNTSerialPort"
+
+#string STR_UNKNOWN_DEVICE #language en-US "UnknownDevice"
+
+// deprecated protocols
+#string STR_SHELL_INTERFACE #language en-US "ShellInterface"
+#string STR_SHELL_ENV #language en-US "ShellEnvironment"
+#string STR_SHELL_ENV2 #language en-US "ShellEnvironment2"
+#string STR_SHELL_DP_MAP #language en-US "ShellDevicePathMap"
+#string STR_SHELL_ALIAS #language en-US "ShellAlias"
+#string STR_DEVICE_IO #language en-US "DeviceIO"
+#string STR_TCP #language en-US "TCP"
+#string STR_UGA_DRAW #language en-US "UGADraw"
+#string STR_UGA_IO #language en-US "UGAIO"
+#string STR_ESP #language en-US "EFISystemPartition"
+#string STR_GPT_NBR #language en-US "LegacyMBR"
+#string STR_DRIVER_CONFIG #language en-US "DriverConfiguration"
+#string STR_DRIVER_CONFIG2 #language en-US "DriverConfiguration2"
+#string STR_ISA_IO #language en-US "ISAIO"
+#string STR_ISA_ACPI #language en-US "ISAACPI"
+#string STR_HII_FORM_BROWSER #language en-US "HIIFormBrowser"
+#string STR_HII #language en-US "HII"
+#string STR_HII_FORM_CALLBACK #language en-US "HIICallback"
+
+#string STR_TXT_OUT_DUMP_HEADER #language en-US " Address: %%H%X%%N Attrib %02x\r\n"
+#string STR_TXT_OUT_DUMP_LINE #language en-US " %c mode %d: Col %d Row %d\r\n"
+
+#string STR_DRIVER_FAM_OVERRIDE #language en-US "DriverFamilyOverride"
+#string STR_PCD #language en-US "Pcd"
+#string STR_TCG #language en-US "Tcg"
+#string STR_HII_PACKAGE_LIST #language en-US "HiiPackageList"
+
+#string STR_IP6_SB #language en-US "Ip6ServiceBinding"
+#string STR_IP6 #language en-US "Ip6"
+#string STR_IP6_CONFIG #language en-US "Ip6Config"
+#string STR_MTFTP6_SB #language en-US "Mtftp6ServiceBinding"
+#string STR_MTFTP6 #language en-US "Mtftp6"
+#string STR_DHCP6_SB #language en-US "Dhcp6ServiceBinding"
+#string STR_DHCP6 #language en-US "Dhcp6"
+#string STR_UDP6_SB #language en-US "Udp6ServiceBinding"
+#string STR_UDP6 #language en-US "Udp6"
+#string STR_TCP6_SB #language en-US "Tcp6ServiceBinding"
+#string STR_TCP6 #language en-US "Tcp6"
+#string STR_VLAN_CONFIG #language en-US "VlanConfig"
+#string STR_EAP #language en-US "Eap"
+#string STR_EAP_MGMT #language en-US "EapManagement"
+#string STR_FTP4_SB #language en-US "Ftp4ServiceBinding"
+#string STR_FTP4 #language en-US "Ftp4"
+#string STR_IP_SEC_CONFIG #language en-US "IpSecConfig"
+#string STR_DH #language en-US "DriverHealth"
+#string STR_DEF_IMG_LOAD #language en-US "DeferredImageLoad"
+#string STR_USER_CRED #language en-US "UserCredential"
+#string STR_USER_MNGR #language en-US "UserManager"
+#string STR_ATA_PASS_THRU #language en-US "AtaPassThru"
+#string STR_FW_MGMT #language en-US "FirmwareManagement"
+#string STR_IP_SEC #language en-US "IpSec"
+#string STR_IP_SEC2 #language en-US "IpSec2"
+#string STR_KMS #language en-US "Kms"
+#string STR_BLK_IO2 #language en-US "BlockIo2"
+#string STR_SSC #language en-US "StorageSecurityCommand"
+#string STR_UCRED2 #language en-US "UserCredential2"
+
+#string STR_PCDINFOPROT #language en-US "GetPcdInfoProtocol"
+#string STR_BDS_ARCH #language en-US "BdsArch"
+#string STR_CPU_ARCH #language en-US "CpuArch"
+#string STR_MET_ARCH #language en-US "MetronomeArch"
+#string STR_MON_ARCH #language en-US "MonotonicCounterArch"
+#string STR_RTC_ARCH #language en-US "RealTimeClockArch"
+#string STR_RESET_ARCH #language en-US "ResetArch"
+#string STR_RT_ARCH #language en-US "RuntimeArch"
+#string STR_SEC_ARCH #language en-US "SecurityArch"
+#string STR_TIMER_ARCH #language en-US "TimerArch"
+#string STR_VAR_ARCH #language en-US "VariableWriteArch"
+#string STR_V_ARCH #language en-US "VariableArch"
+#string STR_SECP #language en-US "SecurityPolicy"
+#string STR_WDT_ARCH #language en-US "WatchdogTimerArch"
+#string STR_SCR #language en-US "StatusCodeRuntime"
+#string STR_SMB_HC #language en-US "SmbusHc"
+#string STR_FV_2 #language en-US "FirmwareVolume2"
+#string STR_FV_BLOCK #language en-US "FirmwareVolumeBlock"
+#string STR_CAP_ARCH #language en-US "CapsuleArch"
+#string STR_MP_SERVICE #language en-US "MpService"
+#string STR_HBRAP #language en-US "PciHostBridgeResourceAllocation"
+#string STR_PCIP #language en-US "PciPlatform"
+#string STR_PCIO #language en-US "PciOverride"
+#string STR_PCIE #language en-US "PciEnumerationComplete"
+#string STR_IPCID #language en-US "IncompatiblePciDeviceSupport"
+#string STR_PCIHPI #language en-US "PciHotPlugInit"
+#string STR_PCIHPR #language en-US "PciHotPlugRequest"
+#string STR_SMBIOS #language en-US "Smbios"
+#string STR_S3_SAVE #language en-US "S3SaveState"
+#string STR_S3_S_SMM #language en-US "S3SmmSaveState"
+#string STR_RSC #language en-US "RscHandler"
+#string STR_S_RSC #language en-US "SmmRscHandler"
+#string STR_ACPI_SDT #language en-US "AcpiSdt"
+#string STR_SIO #language en-US "Sio"
+#string STR_S_CPU2 #language en-US "SmmCpuIo2"
+#string STR_S_BASE2 #language en-US "SmmBase2"
+#string STR_S_ACC_2 #language en-US "SmmAccess2"
+#string STR_S_CON_2 #language en-US "SmmControl2"
+#string STR_S_CONFIG #language en-US "SmmConfig"
+#string STR_S_RTL #language en-US "SmmReadyToLock"
+#string STR_DS_RTL #language en-US "DxeSmmReadyToLock"
+#string STR_S_COMM #language en-US "SmmCommunication"
+#string STR_S_STAT #language en-US "SmmStatusCode"
+#string STR_S_CPU #language en-US "SmmCpu"
+#string STR_S_PCIRBIO #language en-US "SmmPCIRootBridgeIO"
+#string STR_S_SWD #language en-US "SmmSwDispatch2"
+#string STR_S_SXD #language en-US "SmmSxDispatch2"
+#string STR_S_PTD2 #language en-US "SmmPeriodicTimerDispatch2"
+#string STR_S_UD2 #language en-US "SmmUsbDispatch2"
+#string STR_S_GD2 #language en-US "SmmGpiDispatch2"
+#string STR_S_SBD2 #language en-US "SmmStandbyButtonDispatch2"
+#string STR_S_PBD2 #language en-US "SmmPowerButtonDispatch2"
+#string STR_S_ITD2 #language en-US "SmmIoTrapDispatch2"
+#string STR_PCD #language en-US "Pcd"
+#string STR_FVB2 #language en-US "FirmwareVolumeBlock2"
+#string STR_CPUIO2 #language en-US "CpuIo2"
+#string STR_LEGACY_R2 #language en-US "LegacyRegion2"
+#string STR_SAL_MIP #language en-US "SalMcaInitPmi"
+#string STR_ES_BS #language en-US "ExtendedSalBootService"
+#string STR_ES_BIO #language en-US "ExtendedSalBaseIoServices"
+#string STR_ES_STALL #language en-US "ExtendedSalStallServices"
+#string STR_ES_RTC #language en-US "ExtendedSalRtcServices"
+#string STR_ES_VS #language en-US "ExtendedSalVariableServices"
+#string STR_ES_MTC #language en-US "ExtendedSalMtcServices"
+#string STR_ES_RESET #language en-US "ExtendedSalResetServices"
+#string STR_ES_SC #language en-US "ExtendedSalStatusCodeServices"
+#string STR_ES_FBS #language en-US "ExtendedSalFvBlockServices"
+#string STR_ES_MP #language en-US "ExtendedSalMpServices"
+#string STR_ES_PAL #language en-US "ExtendedSalPalServices"
+#string STR_ES_BASE #language en-US "ExtendedSalBaseServices"
+#string STR_ES_MCA #language en-US "ExtendedSalMcaServices"
+#string STR_ES_PCI #language en-US "ExtendedSalPciServices"
+#string STR_ES_CACHE #language en-US "ExtendedSalCacheServices"
+#string STR_ES_MCA_LOG #language en-US "ExtendedSalMcaLogServices"
+#string STR_S2ARCH #language en-US "Security2Arch"
+#string STR_EODXE #language en-US "SmmEndOfDxe"
+#string STR_ISAHC #language en-US "IsaHc"
+#string STR_ISAHC_B #language en-US "IsaHcServiceBinding"
+#string STR_SIO_C #language en-US "SioControl"
+#string STR_GET_PCD #language en-US "GetPcdInfo"
+#string STR_I2C_M #language en-US "I2cMaster"
+#string STR_I2CIO #language en-US "I2cIo"
+#string STR_I2CEN #language en-US "I2cEnumerate"
+#string STR_I2C_H #language en-US "I2cHost"
+#string STR_I2C_BCM #language en-US "I2cBusConfigurationManagement"
+#string STR_TREE #language en-US "TrEE"
+#string STR_TCG2 #language en-US "Tcg2"
+#string STR_TIMESTAMP #language en-US "Timestamp"
+#string STR_RNG #language en-US "Rng"
+#string STR_NVMEPT #language en-US "NvmExpressPassThru"
+#string STR_H2_SB #language en-US "Hash2ServiceBinding"
+#string STR_HASH2 #language en-US "Hash2"
+#string STR_BIO_C #language en-US "BlockIoCrypto"
+#string STR_SCR #language en-US "SmartCardReader"
+#string STR_SCE #language en-US "SmartCardEdge"
+#string STR_USB_FIO #language en-US "UsbFunctionIo"
+#string STR_BC_HC #language en-US "BluetoothHc"
+#string STR_BC_IO_SB #language en-US "BluetoothIoServiceBinding"
+#string STR_BC_IO #language en-US "BluetoothIo"
+#string STR_BC_C #language en-US "BluetoothConfig"
+#string STR_REG_EXP #language en-US "RegularExpression"
+#string STR_B_MGR_P #language en-US "BootManagerPolicy"
+#string STR_CKH #language en-US "ConfigKeywordHandler"
+#string STR_WIFI #language en-US "WiFi"
+#string STR_EAP_M #language en-US "EapManagement2"
+#string STR_EAP_C #language en-US "EapConfiguration"
+#string STR_PKCS7 #language en-US "Pkcs7Verify"
+#string STR_NET_DNS4_SB #language en-US "Dns4ServiceBinding"
+#string STR_NET_DNS4 #language en-US "Dns4"
+#string STR_NET_DNS6_SB #language en-US "Dns6ServiceBinding"
+#string STR_NET_DNS6 #language en-US "Dns6"
+#string STR_NET_HTTP_SB #language en-US "HttpServiceBinding"
+#string STR_NET_HTTP #language en-US "Http"
+#string STR_NET_HTTP_U #language en-US "HttpUtilities"
+#string STR_REST #language en-US "Rest"
+
+#string STR_IDE_CONT_INIT #language en-US "IdeControllerInit"
+#string STR_DISK_INFO #language en-US "DiskInfo"
+
+#string STR_PCIRB_DUMP_PH #language en-US " ParentHandle..: %H%x%N\r\n"
+#string STR_PCIRB_DUMP_SEG #language en-US " Segment #.....: %H%x%N\r\n"
+#string STR_PCIRB_DUMP_ATT #language en-US " Attributes....: %H%x%N\r\n"
+#string STR_PCIRB_DUMP_SUPPORTS #language en-US " Supports......: %H%x%N\r\n"
+#string STR_PCIRB_DUMP_BUS #language en-US " BUS : "
+#string STR_PCIRB_DUMP_MEM #language en-US " MEM : "
+#string STR_PCIRB_DUMP_IO #language en-US " IO : "
+#string STR_PCIRB_DUMP_TITLE #language en-US " Type Flag Base Limit Gran\r\n"
+ " ==== ==== ================ ================ ====\r\n"
+
+
+
+#string STR_LI_DUMP_MAIN #language en-US " Revision......: %%H0x%08x%%N\r\n"
+ " ParentHandle..: %%H%x%%N\r\n"
+ " SystemTable...: %%H%x%%N\r\n"
+ " DeviceHandle..: %%H%x%%N\r\n"
+ " FilePath......: %%H%x%%N\r\n"
+ " OptionsSize...: %%H%x%%N\r\n"
+ " LoadOptions...: %%H%s%%N\r\n"
+ " ImageBase.....: %%H%x%%N\r\n"
+ " ImageSize.....: %%H%Lx%%N\r\n"
+ " CodeType......: %%H%s%%N\r\n"
+ " DataType......: %%H%s%%N\r\n"
+ " Unload........: %%H%x%%N\r\n"
+
+#string STR_GOP_DUMP_MAIN #language en-US " Max Mode............: %%H0x%08x%%N\r\n"
+ " Current Mode........: %%H0x%08x%%N\r\n"
+ " Frame Buffer Base...: %%H0x%L016x%%N\r\n"
+ " Frame Buffer Size...: %%H0x%L016x%%N\r\n"
+ " Mode Info Size......: %%H0x%L016x%%N\r\n"
+ " Information\r\n"
+ " Version...........: %%H0x%08x%%N\r\n"
+ " Res Hor...........: %%H0x%08x%%N\r\n"
+ " Res Ver...........: %%H0x%08x%%N\r\n"
+ " Pixel Format......: %%H%s%%N\r\n"
+ " Pixels / Scan Line: %%H0x%08x%%N\r\n"
+ " Pixel Info\r\n"
+ " RedMask.........: %%H0x%08x%%N\r\n"
+ " GreenMask.......: %%H0x%08x%%N\r\n"
+ " BlueMask........: %%H0x%08x%%N\r\n"
+
+#string STR_GOP_RES_LIST_MAIN #language en-US " Supported Resolution List\r\n"
+#string STR_GOP_RES_LIST_ENTRY #language en-US " Resolution[%%H%d%%N]:\r\n"
+ " Res Hor.........: %%H0x%08x%%N\r\n"
+ " Res Ver.........: %%H0x%08x%%N\r\n"
+
+#string STR_EDID_DISCOVERED_MAIN #language en-US " EDID Discovered Size : %%H0x%08x%%N\r\n"
+#string STR_EDID_DISCOVERED_DATA #language en-US " EDID Discovered Data :\r\n"
+#string STR_EDID_ACTIVE_MAIN #language en-US " EDID Active Size : %%H0x%08x%%N\r\n"
+#string STR_EDID_ACTIVE_DATA #language en-US " EDID Active Data :\r\n"
+
+#string STR_GET_SUPP_TYPES_FAILED #language en-US "Unable to get supported types - %%H%r%%N\r\n"
+#string STR_SUPP_TYPE_HEADER #language en-US " Supported Information Types: \r\n"
+#string STR_GUID_NUMBER #language en-US " Guid[%%H%d%%N] : %g"
+#string STR_GUID_STRING #language en-US " - %%B%s%%N\r\n"
+#string STR_GETINFO_FAILED #language en-US " Unable to get information - %%H%r%%N\r\n"
+#string STR_MEDIA_STATE #language en-US " MediaState: %%H0x%08x - %r%%N\r\n"
+#string STR_NETWORK_BOOT_INFO #language en-US ""
+ " iSsciIpv4BootCapablity : %%H%d%%N\r\n"
+ " iScsiIpv6BootCapablity : %%H%d%%N\r\n"
+ " FCoeBootCapablity : %%H%d%%N\r\n"
+ " OffloadCapability : %%H%d%%N\r\n"
+ " iScsiMpioCapability : %%H%d%%N\r\n"
+ " iScsiIpv4Boot : %%H%d%%N\r\n"
+ " iScsiIpv6Boot : %%H%d%%N\r\n"
+ " FCoeBoot : %%H%d%%N\r\n"
+#string STR_SAN_MAC_ADDRESS_INFO #language en-US " SanMacAddress: %%H%02x-%02x-%02x-%02x-%02x-%02x%%N \r\n"
+#string STR_UNDI_IPV6_INFO #language en-US " UNDI IPv6 Supported: %%H%d%%N \r\n"
+#string STR_UNKNOWN_INFO_TYPE #language en-US " The 'InformationType' - %%H%g%%N can't be recongnized\r\n"
+
+#string STR_FMP_IMAGEID_NON_UNIQUE #language en-US " The ImageId value for each Firmware Image is not unique.\r\n"
+#string STR_FMP_IMAGE_INFO_SIZE #language en-US " ImageInfoSize: %%H0x%L016x%%N\r\n"
+#string STR_FMP_DESCRIPTOR_VERSION #language en-US " DescriptorVersion: %%H%d%%N\r\n"
+#string STR_FMP_DESCRIPTOR_COUNT #language en-US " DescriptorCount : %%H%d%%N\r\n"
+#string STR_FMP_DESCRIPTOR_SIZE #language en-US " DescriptorSize : %%H0x%Lx%%N\r\n"
+#string STR_FMP_PACKAGE_VERSION #language en-US " PackageVersion : %%H0x%08x%%N\r\n"
+#string STR_FMP_PACKAGE_VERSION_NAME #language en-US " PackageVersionName : %%H%s%%N\r\n"
+#string STR_FMP_IMAGE_DESCRIPTOR_INFO #language en-US ""
+ " ImageInfo[%%H%d%%N]:\r\n"
+ " =============\r\n"
+ " ImageIndex : %%H%d%%N\r\n"
+ " ImageTypeId : %%H%g%%N\r\n"
+ " ImageId : %%H%L016x%%N\r\n"
+ " ImageIdName : %%H%s%%N\r\n"
+ " Version : %%H0x%08x%%N\r\n"
+ " VersionName : %%H%s%%N\r\n"
+ " Size : %%H0x%L016x%%N\r\n"
+ " AttributesSupported : %%H0x%L016x%%N\r\n"
+ " AttributesSetting : %%H%s%%N\r\n"
+ " Compatibilities : %%H0x%L016x%%N\r\n"
+ " LowestSupportedImageVersion : %%H0x%08x%%N\r\n"
+ " LastAttemptVersion : %%H0x%08x%%N\r\n"
+ " LastAttemptStatus : %%H0x%08x%%N\r\n"
+ " HardwareInstance : %%H0x%08x%%N\r\n"
+
+#string STR_FMP_IMAGE_DESCRIPTOR_INFO_V1 #language en-US ""
+ " ImageInfo[%%H%d%%N]:\r\n"
+ " =============\r\n"
+ " ImageIndex : %%H%d%%N\r\n"
+ " ImageTypeId : %%H%g%%N\r\n"
+ " ImageId : %%H%L016x%%N\r\n"
+ " ImageIdName : %%H%s%%N\r\n"
+ " Version : %%H0x%08x%%N\r\n"
+ " VersionName : %%H%s%%N\r\n"
+ " Size : %%H0x%L016x%%N\r\n"
+ " AttributesSupported : %%H0x%L016x%%N\r\n"
+ " AttributesSetting : %%H%s%%N\r\n"
+ " Compatibilities : %%H0x%L016x%%N\r\n"
+
+#string STR_FMP_IMAGE_DESCRIPTOR_INFO_V2 #language en-US ""
+ " ImageInfo[%%H%d%%N]:\r\n"
+ " =============\r\n"
+ " ImageIndex : %%H%d%%N\r\n"
+ " ImageTypeId : %%H%g%%N\r\n"
+ " ImageId : %%H%L016x%%N\r\n"
+ " ImageIdName : %%H%s%%N\r\n"
+ " Version : %%H0x%08x%%N\r\n"
+ " VersionName : %%H%s%%N\r\n"
+ " Size : %%H0x%L016x%%N\r\n"
+ " AttributesSupported : %%H0x%L016x%%N\r\n"
+ " AttributesSetting : %%H%s%%N\r\n"
+ " Compatibilities : %%H0x%L016x%%N\r\n"
+ " LowestSupportedImageVersion : %%H0x%08x%%N\r\n"
diff --git a/Core/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c b/Core/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c
new file mode 100644
index 0000000000..9baeecc339
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.c
@@ -0,0 +1,1560 @@
+/** @file
+ Main file for BCFG command.
+
+ (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include <Uefi.h>
+#include <ShellBase.h>
+
+#include <Guid/GlobalVariable.h>
+#include <Guid/ShellLibHiiGuid.h>
+
+#include <Protocol/EfiShell.h>
+#include <Protocol/EfiShellParameters.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/UnicodeCollation.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/ShellCommandLib.h>
+#include <Library/ShellLib.h>
+#include <Library/SortLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HiiLib.h>
+#include <Library/FileHandleLib.h>
+#include <Library/PrintLib.h>
+#include <Library/HandleParsingLib.h>
+#include <Library/DevicePathLib.h>
+
+STATIC CONST CHAR16 mFileName[] = L"ShellCommands";
+STATIC EFI_HANDLE gShellBcfgHiiHandle = NULL;
+
+typedef enum {
+ BcfgTargetBootOrder = 0,
+ BcfgTargetDriverOrder = 1,
+ BcfgTargetMax = 2
+} BCFG_OPERATION_TARGET;
+
+typedef enum {
+ BcfgTypeDump = 0,
+ BcfgTypeAdd = 1,
+ BcfgTypeAddp = 2,
+ BcfgTypeAddh = 3,
+ BcfgTypeRm = 4,
+ BcfgTypeMv = 5,
+ BcfgTypeOpt = 6,
+ BcfgTypeMax = 7
+} BCFG_OPERATION_TYPE;
+
+typedef struct {
+ BCFG_OPERATION_TARGET Target;
+ BCFG_OPERATION_TYPE Type;
+ UINT16 Number1;
+ UINT16 Number2;
+ UINTN HandleIndex;
+ CHAR16 *FileName;
+ CHAR16 *Description;
+ UINT16 *Order;
+ CONST CHAR16 *OptData;
+} BGFG_OPERATION;
+
+/**
+ Update the optional data for a boot or driver option.
+
+ If optional data exists it will be changed.
+
+ @param[in] Index The boot or driver option index update.
+ @param[in] DataSize The size in bytes of Data.
+ @param[in] Data The buffer for the optioanl data.
+ @param[in] Target The target of the operation.
+
+ @retval EFI_SUCCESS The data was sucessfully updated.
+ @retval other A error occured.
+**/
+EFI_STATUS
+EFIAPI
+UpdateOptionalData(
+ UINT16 Index,
+ UINTN DataSize,
+ UINT8 *Data,
+ IN CONST BCFG_OPERATION_TARGET Target
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 VariableName[12];
+ UINTN OriginalSize;
+ UINT8 *OriginalData;
+ UINTN NewSize;
+ UINT8 *NewData;
+ UINTN OriginalOptionDataSize;
+
+ UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", Index);
+
+ OriginalSize = 0;
+ OriginalData = NULL;
+ NewData = NULL;
+ NewSize = 0;
+
+ Status = gRT->GetVariable(
+ VariableName,
+ (EFI_GUID*)&gEfiGlobalVariableGuid,
+ NULL,
+ &OriginalSize,
+ OriginalData);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ OriginalData = AllocateZeroPool(OriginalSize);
+ if (OriginalData == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ Status = gRT->GetVariable(
+ VariableName,
+ (EFI_GUID*)&gEfiGlobalVariableGuid,
+ NULL,
+ &OriginalSize,
+ OriginalData);
+ }
+
+ if (!EFI_ERROR(Status)) {
+ //
+ // Allocate new struct and discard old optional data.
+ //
+ ASSERT (OriginalData != NULL);
+ OriginalOptionDataSize = sizeof(UINT32) + sizeof(UINT16) + StrSize(((CHAR16*)(OriginalData + sizeof(UINT32) + sizeof(UINT16))));
+ OriginalOptionDataSize += (*(UINT16*)(OriginalData + sizeof(UINT32)));
+ OriginalOptionDataSize -= OriginalSize;
+ NewSize = OriginalSize - OriginalOptionDataSize + DataSize;
+ NewData = AllocateCopyPool(NewSize, OriginalData);
+ if (NewData == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ CopyMem(NewData + OriginalSize - OriginalOptionDataSize, Data, DataSize);
+ }
+ }
+
+ if (!EFI_ERROR(Status)) {
+ //
+ // put the data back under the variable
+ //
+ Status = gRT->SetVariable(
+ VariableName,
+ (EFI_GUID*)&gEfiGlobalVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
+ NewSize,
+ NewData);
+ }
+
+ SHELL_FREE_NON_NULL(OriginalData);
+ SHELL_FREE_NON_NULL(NewData);
+ return (Status);
+}
+
+/**
+ This function will get a CRC for a boot option.
+
+ @param[in, out] Crc The CRC value to return.
+ @param[in] BootIndex The boot option index to CRC.
+
+ @retval EFI_SUCCESS The CRC was sucessfully returned.
+ @retval other A error occured.
+**/
+EFI_STATUS
+EFIAPI
+GetBootOptionCrc(
+ UINT32 *Crc,
+ UINT16 BootIndex
+ )
+{
+ CHAR16 VariableName[12];
+ EFI_STATUS Status;
+ UINT8 *Buffer;
+ UINTN BufferSize;
+
+ Buffer = NULL;
+ BufferSize = 0;
+
+ //
+ // Get the data Buffer
+ //
+ UnicodeSPrint(VariableName, sizeof(VariableName), L"%Boot%04x", BootIndex);
+ Status = gRT->GetVariable(
+ VariableName,
+ (EFI_GUID*)&gEfiGlobalVariableGuid,
+ NULL,
+ &BufferSize,
+ NULL);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ Buffer = AllocateZeroPool(BufferSize);
+ Status = gRT->GetVariable(
+ VariableName,
+ (EFI_GUID*)&gEfiGlobalVariableGuid,
+ NULL,
+ &BufferSize,
+ Buffer);
+ }
+
+ //
+ // Get the CRC computed
+ //
+ if (!EFI_ERROR(Status)) {
+ Status = gBS->CalculateCrc32 (Buffer, BufferSize, Crc);
+ }
+
+ SHELL_FREE_NON_NULL(Buffer);
+ return EFI_SUCCESS;
+}
+
+/**
+ This function will populate the device path protocol parameter based on TheHandle.
+
+ @param[in] TheHandle Driver handle.
+ @param[in, out] FilePath On a sucessful return the device path to the handle.
+
+ @retval EFI_SUCCESS The device path was sucessfully returned.
+ @retval other A error from gBS->HandleProtocol.
+
+ @sa HandleProtocol
+**/
+EFI_STATUS
+EFIAPI
+GetDevicePathForDriverHandle (
+ IN EFI_HANDLE TheHandle,
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath
+ )
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath;
+
+ Status = gBS->OpenProtocol (
+ TheHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID**)&LoadedImage,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->OpenProtocol (
+ LoadedImage->DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID**)&ImageDevicePath,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+// *DevPath = DuplicateDevicePath (ImageDevicePath);
+// *FilePath = DuplicateDevicePath (LoadedImage->FilePath);
+ *FilePath = AppendDevicePath(ImageDevicePath,LoadedImage->FilePath);
+ gBS->CloseProtocol(
+ LoadedImage->DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ gImageHandle,
+ NULL);
+ }
+ gBS->CloseProtocol(
+ TheHandle,
+ &gEfiLoadedImageProtocolGuid,
+ gImageHandle,
+ NULL);
+ }
+ return (Status);
+}
+
+/**
+ Function to add a option.
+
+ @param[in] Position The position to add Target at.
+ @param[in] File The file to make the target.
+ @param[in] Desc The description text.
+ @param[in] CurrentOrder The pointer to the current order of items.
+ @param[in] OrderCount The number if items in CurrentOrder.
+ @param[in] Target The info on the option to add.
+ @param[in] UseHandle TRUE to use HandleNumber, FALSE to use File and Desc.
+ @param[in] UsePath TRUE to convert to devicepath.
+ @param[in] HandleNumber The handle number to add.
+
+ @retval SHELL_SUCCESS The operation was successful.
+ @retval SHELL_INVALID_PARAMETER A parameter was invalid.
+**/
+SHELL_STATUS
+EFIAPI
+BcfgAdd(
+ IN UINTN Position,
+ IN CONST CHAR16 *File,
+ IN CONST CHAR16 *Desc,
+ IN CONST UINT16 *CurrentOrder,
+ IN CONST UINTN OrderCount,
+ IN CONST BCFG_OPERATION_TARGET Target,
+ IN CONST BOOLEAN UseHandle,
+ IN CONST BOOLEAN UsePath,
+ IN CONST UINTN HandleNumber
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+ EFI_DEVICE_PATH_PROTOCOL *FilePath;
+ CHAR16 *Str;
+ UINT8 *TempByteBuffer;
+ UINT8 *TempByteStart;
+ EFI_SHELL_FILE_INFO *Arg;
+ EFI_SHELL_FILE_INFO *FileList;
+ CHAR16 OptionStr[40];
+ UINTN DescSize, FilePathSize;
+ BOOLEAN Found;
+ UINTN TargetLocation;
+ UINTN Index;
+ EFI_HANDLE *Handles;
+ EFI_HANDLE CurHandle;
+ UINTN DriverBindingHandleCount;
+ UINTN ParentControllerHandleCount;
+ UINTN ChildControllerHandleCount;
+ SHELL_STATUS ShellStatus;
+ UINT16 *NewOrder;
+
+ if (!UseHandle) {
+ if (File == NULL || Desc == NULL) {
+ return (SHELL_INVALID_PARAMETER);
+ }
+ } else {
+ if (HandleNumber == 0) {
+ return (SHELL_INVALID_PARAMETER);
+ }
+ }
+
+ if (Position > OrderCount) {
+ Position = OrderCount;
+ }
+
+ Str = NULL;
+ FilePath = NULL;
+ FileList = NULL;
+ Handles = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ TargetLocation = 0xFFFF;
+
+ if (UseHandle) {
+ CurHandle = ConvertHandleIndexToHandle(HandleNumber);
+ if (CurHandle == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Handle Number");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ if (Target == BcfgTargetBootOrder) {
+ //
+ //Make sure that the handle should point to a real controller
+ //
+ Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (
+ CurHandle,
+ &DriverBindingHandleCount,
+ NULL);
+
+ Status = PARSE_HANDLE_DATABASE_PARENTS (
+ CurHandle,
+ &ParentControllerHandleCount,
+ NULL);
+
+ Status = ParseHandleDatabaseForChildControllers (
+ CurHandle,
+ &ChildControllerHandleCount,
+ NULL);
+
+ if (DriverBindingHandleCount > 0
+ || ParentControllerHandleCount > 0
+ || ChildControllerHandleCount > 0) {
+ FilePath = NULL;
+ Status = gBS->HandleProtocol (
+ CurHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID**)&FilePath);
+ }
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_HANDLE), gShellBcfgHiiHandle, L"bcfg", HandleNumber);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ } else {
+ //
+ //Make sure that the handle should point to driver, not a controller.
+ //
+ Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (
+ CurHandle,
+ &DriverBindingHandleCount,
+ NULL);
+
+ Status = PARSE_HANDLE_DATABASE_PARENTS (
+ CurHandle,
+ &ParentControllerHandleCount,
+ NULL);
+
+ Status = ParseHandleDatabaseForChildControllers (
+ CurHandle,
+ &ChildControllerHandleCount,
+ NULL);
+
+ Status = gBS->HandleProtocol (
+ CurHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID**)&FilePath);
+
+ if (DriverBindingHandleCount > 0
+ || ParentControllerHandleCount > 0
+ || ChildControllerHandleCount > 0
+ || !EFI_ERROR(Status) ) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Handle Number");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // Get the DevicePath from the loaded image information.
+ //
+ Status = GetDevicePathForDriverHandle(CurHandle, &FilePath);
+ }
+ }
+ }
+ } else {
+ //
+ // Get file info
+ //
+ ShellOpenFileMetaArg ((CHAR16*)File, EFI_FILE_MODE_READ, &FileList);
+
+ if (FileList == NULL) {
+ //
+ // If filename matched nothing fail
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellBcfgHiiHandle, L"bcfg", File);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (FileList->Link.ForwardLink != FileList->Link.BackLink) {
+ //
+ // If filename expanded to multiple names, fail
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE), gShellBcfgHiiHandle, L"bcfg", File);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Arg = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link);
+ if (EFI_ERROR(Arg->Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_OPEN), gShellBcfgHiiHandle, L"bcfg", File);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // Build FilePath to the filename
+ //
+
+ //
+ // get the device path
+ //
+ DevicePath = gEfiShellProtocol->GetDevicePathFromFilePath(Arg->FullName);
+ if (DevicePath == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_FILE_DP), gShellBcfgHiiHandle, L"bcfg", Arg->FullName);
+ ShellStatus = SHELL_UNSUPPORTED;
+ } else {
+ if (UsePath) {
+ DevPath = DevicePath;
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ while (!IsDevicePathEnd(DevPath)) {
+ if ((DevicePathType(DevPath) == MEDIA_DEVICE_PATH) &&
+ (DevicePathSubType(DevPath) == MEDIA_HARDDRIVE_DP)) {
+
+ //
+ // If we find it use it instead
+ //
+ ShellStatus = SHELL_SUCCESS;
+ FilePath = DuplicateDevicePath (DevPath);
+ break;
+ }
+ DevPath = NextDevicePathNode(DevPath);
+ }
+ } else {
+ FilePath = DuplicateDevicePath(DevicePath);
+ }
+ FreePool(DevicePath);
+ }
+ }
+ }
+ }
+
+
+ if (ShellStatus == SHELL_SUCCESS) {
+ //
+ // Find a free target ,a brute force implementation
+ //
+ Found = FALSE;
+ for (TargetLocation=0; TargetLocation < 0xFFFF; TargetLocation++) {
+ Found = TRUE;
+ for (Index=0; Index < OrderCount; Index++) {
+ if (CurrentOrder[Index] == TargetLocation) {
+ Found = FALSE;
+ break;
+ }
+ }
+
+ if (Found) {
+ break;
+ }
+ }
+
+ if (TargetLocation == 0xFFFF) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET_NF), gShellBcfgHiiHandle, L"bcfg");
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_TARGET), gShellBcfgHiiHandle, TargetLocation);
+ }
+ }
+
+ if (ShellStatus == SHELL_SUCCESS) {
+ //
+ // Add the option
+ //
+ DescSize = StrSize(Desc);
+ FilePathSize = GetDevicePathSize (FilePath);
+
+ TempByteBuffer = AllocateZeroPool(sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize);
+ if (TempByteBuffer != NULL) {
+ TempByteStart = TempByteBuffer;
+ *((UINT32 *) TempByteBuffer) = LOAD_OPTION_ACTIVE; // Attributes
+ TempByteBuffer += sizeof (UINT32);
+
+ *((UINT16 *) TempByteBuffer) = (UINT16)FilePathSize; // FilePathListLength
+ TempByteBuffer += sizeof (UINT16);
+
+ CopyMem (TempByteBuffer, Desc, DescSize);
+ TempByteBuffer += DescSize;
+ ASSERT (FilePath != NULL);
+ CopyMem (TempByteBuffer, FilePath, FilePathSize);
+
+ UnicodeSPrint (OptionStr, sizeof(OptionStr), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", TargetLocation);
+ Status = gRT->SetVariable (
+ OptionStr,
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof(UINT32) + sizeof(UINT16) + DescSize + FilePathSize,
+ TempByteStart
+ );
+
+ FreePool(TempByteStart);
+ } else {
+ Status = EFI_OUT_OF_RESOURCES;
+ }
+
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", OptionStr);
+ } else {
+ NewOrder = AllocateZeroPool ((OrderCount + 1) * sizeof (NewOrder[0]));
+ if (NewOrder != NULL) {
+ CopyMem (NewOrder, CurrentOrder, (OrderCount) * sizeof (NewOrder[0]));
+
+ //
+ // Insert target into order list
+ //
+ for (Index = OrderCount; Index > Position; Index--) {
+ NewOrder[Index] = NewOrder[Index - 1];
+ }
+
+ NewOrder[Position] = (UINT16) TargetLocation;
+ Status = gRT->SetVariable (
+ Target == BcfgTargetBootOrder ? L"BootOrder" : L"DriverOrder",
+ &gEfiGlobalVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE | EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_RUNTIME_ACCESS,
+ (OrderCount + 1) * sizeof (UINT16),
+ NewOrder
+ );
+
+ FreePool (NewOrder);
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", Target == BcfgTargetBootOrder ? L"BootOrder" : L"DriverOrder");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Print (L"bcfg: Add %s as %x\n", OptionStr, Position);
+ }
+ }
+ }
+ }
+
+//
+//If always Free FilePath, will free devicepath in system when use "addh"
+//
+ if (FilePath!=NULL && !UseHandle) {
+ FreePool (FilePath);
+ }
+
+ if (Str != NULL) {
+ FreePool(Str);
+ }
+
+ if (Handles != NULL) {
+ FreePool (Handles);
+ }
+
+ if (FileList != NULL) {
+ ShellCloseFileMetaArg (&FileList);
+ }
+
+ return (ShellStatus);
+}
+
+/**
+ Funciton to remove an item.
+
+ @param[in] Target The target item to move.
+ @param[in] CurrentOrder The pointer to the current order of items.
+ @param[in] OrderCount The number if items in CurrentOrder.
+ @param[in] Location The current location of the Target.
+
+ @retval SHELL_SUCCESS The operation was successful.
+ @retval SHELL_INVALID_PARAMETER A parameter was invalid.
+**/
+SHELL_STATUS
+EFIAPI
+BcfgRemove(
+ IN CONST BCFG_OPERATION_TARGET Target,
+ IN CONST UINT16 *CurrentOrder,
+ IN CONST UINTN OrderCount,
+ IN CONST UINT16 Location
+ )
+{
+ CHAR16 VariableName[12];
+ UINT16 *NewOrder;
+ EFI_STATUS Status;
+ UINTN NewCount;
+
+ UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Target == BcfgTargetBootOrder?L"Boot":L"Driver", CurrentOrder[Location]);
+ Status = gRT->SetVariable(
+ VariableName,
+ (EFI_GUID*)&gEfiGlobalVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
+ 0,
+ NULL);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName);
+ return (SHELL_INVALID_PARAMETER);
+ }
+ NewOrder = AllocateZeroPool(OrderCount*sizeof(CurrentOrder[0]));
+ if (NewOrder != NULL) {
+ NewCount = OrderCount;
+ CopyMem(NewOrder, CurrentOrder, OrderCount*sizeof(CurrentOrder[0]));
+ CopyMem(NewOrder+Location, NewOrder+Location+1, (OrderCount - Location - 1)*sizeof(CurrentOrder[0]));
+ NewCount--;
+
+ Status = gRT->SetVariable(
+ Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",
+ (EFI_GUID*)&gEfiGlobalVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
+ NewCount*sizeof(NewOrder[0]),
+ NewOrder);
+ FreePool(NewOrder);
+ } else {
+ Status = EFI_OUT_OF_RESOURCES;
+ }
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder");
+ return (SHELL_INVALID_PARAMETER);
+ }
+ return (SHELL_SUCCESS);
+}
+
+/**
+ Funciton to move a item to another location.
+
+ @param[in] Target The target item to move.
+ @param[in] CurrentOrder The pointer to the current order of items.
+ @param[in] OrderCount The number if items in CurrentOrder.
+ @param[in] OldLocation The current location of the Target.
+ @param[in] NewLocation The desired location of the Target.
+
+ @retval SHELL_SUCCESS The operation was successful.
+ @retval SHELL_INVALID_PARAMETER A parameter was invalid.
+**/
+SHELL_STATUS
+EFIAPI
+BcfgMove(
+ IN CONST BCFG_OPERATION_TARGET Target,
+ IN CONST UINT16 *CurrentOrder,
+ IN CONST UINTN OrderCount,
+ IN CONST UINT16 OldLocation,
+ IN UINT16 NewLocation
+ )
+{
+ UINT16 *NewOrder;
+ EFI_STATUS Status;
+ UINT16 Temp;
+
+ NewOrder = AllocateCopyPool(OrderCount*sizeof(CurrentOrder[0]), CurrentOrder);
+ if (NewOrder == NULL) {
+ return (SHELL_OUT_OF_RESOURCES);
+ }
+
+ //
+ // correct the new location
+ //
+ if (NewLocation >= OrderCount) {
+ if (OrderCount > 0) {
+ NewLocation = (UINT16)OrderCount - 1;
+ } else {
+ NewLocation = 0;
+ }
+ }
+
+ Temp = CurrentOrder[OldLocation];
+ CopyMem(NewOrder+OldLocation, NewOrder+OldLocation+1, (OrderCount - OldLocation - 1)*sizeof(CurrentOrder[0]));
+ CopyMem(NewOrder+NewLocation+1, NewOrder+NewLocation, (OrderCount - NewLocation - 1)*sizeof(CurrentOrder[0]));
+ NewOrder[NewLocation] = Temp;
+
+ Status = gRT->SetVariable(
+ Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",
+ (EFI_GUID*)&gEfiGlobalVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
+ OrderCount*sizeof(CurrentOrder[0]),
+ NewOrder);
+
+ FreePool(NewOrder);
+
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_WRITE_FAIL), gShellBcfgHiiHandle, L"bcfg", Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder");
+ return (SHELL_INVALID_PARAMETER);
+ }
+ return (SHELL_SUCCESS);
+}
+
+/**
+ Function to add optional data to an option.
+
+ @param[in] OptData The optional data to add.
+ @param[in] CurrentOrder The pointer to the current order of items.
+ @param[in] OrderCount The number if items in CurrentOrder.
+ @param[in] Target The target of the operation.
+
+ @retval SHELL_SUCCESS The operation was succesful.
+**/
+SHELL_STATUS
+EFIAPI
+BcfgAddOpt(
+ IN CONST CHAR16 *OptData,
+ IN CONST UINT16 *CurrentOrder,
+ IN CONST UINTN OrderCount,
+ IN CONST BCFG_OPERATION_TARGET Target
+ )
+{
+ EFI_KEY_OPTION NewKeyOption;
+ EFI_KEY_OPTION *KeyOptionBuffer;
+ SHELL_STATUS ShellStatus;
+ EFI_STATUS Status;
+ UINT16 OptionIndex;
+ UINT16 LoopCounter;
+ UINT64 Intermediate;
+ CONST CHAR16 *Temp;
+ CONST CHAR16 *Walker;
+ CHAR16 *FileName;
+ CHAR16 *Temp2;
+ CHAR16 *Data;
+ UINT32 KeyIndex;
+ CHAR16 VariableName[12];
+ VOID *VariableData;
+
+ SHELL_FILE_HANDLE FileHandle;
+
+ Status = EFI_SUCCESS;
+ ShellStatus = SHELL_SUCCESS;
+ Walker = OptData;
+ FileName = NULL;
+ Data = NULL;
+ KeyOptionBuffer = NULL;
+ VariableData = NULL;
+
+ ZeroMem(&NewKeyOption, sizeof(EFI_KEY_OPTION));
+ ZeroMem(VariableName, sizeof(VariableName));
+
+ while(Walker[0] == L' ') {
+ Walker++;
+ }
+
+ //
+ // Get the index of the variable we are changing.
+ //
+ Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE);
+ if (EFI_ERROR(Status) || (((UINT16)Intermediate) != Intermediate) || StrStr(Walker, L" ") == NULL || ((UINT16)Intermediate) > ((UINT16)OrderCount)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Option Index");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ return (ShellStatus);
+ }
+ OptionIndex = (UINT16)Intermediate;
+
+ Temp = StrStr(Walker, L" ");
+ if (Temp != NULL) {
+ Walker = Temp;
+ }
+ while(Walker[0] == L' ') {
+ Walker++;
+ }
+
+ //
+ // determine whether we have file with data, quote delimited information, or a hot-key
+ //
+ if (Walker[0] == L'\"') {
+ //
+ // quoted filename or quoted information.
+ //
+ Temp = StrStr(Walker+1, L"\"");
+ if (Temp == NULL || StrLen(Temp) != 1) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ FileName = StrnCatGrow(&FileName, NULL, Walker+1, 0);
+ if (FileName == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellBcfgHiiHandle, L"bcfg");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ return (ShellStatus);
+ }
+ Temp2 = StrStr(FileName, L"\"");
+ ASSERT(Temp2 != NULL);
+ Temp2[0] = CHAR_NULL;
+ Temp2++;
+ if (StrLen(Temp2)>0) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ if (EFI_ERROR(ShellFileExists(Walker))) {
+ //
+ // Not a file. must be misc information.
+ //
+ Data = FileName;
+ FileName = NULL;
+ } else {
+ FileName = StrnCatGrow(&FileName, NULL, Walker, 0);
+ }
+ }
+ } else {
+ //
+ // filename or hot key information.
+ //
+ if (StrStr(Walker, L" ") == NULL) {
+ //
+ // filename
+ //
+ if (EFI_ERROR(ShellFileExists(Walker))) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FIND_FAIL), gShellBcfgHiiHandle, L"bcfg", Walker);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ FileName = StrnCatGrow(&FileName, NULL, Walker, 0);
+ }
+ } else {
+ if (Target != BcfgTargetBootOrder) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_BOOT_ONLY), gShellBcfgHiiHandle, L"bcfg");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+
+ if (ShellStatus == SHELL_SUCCESS) {
+ //
+ // Get hot key information
+ //
+ Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE);
+ if (EFI_ERROR(Status) || (((UINT32)Intermediate) != Intermediate) || StrStr(Walker, L" ") == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ NewKeyOption.KeyData.PackedValue = (UINT32)Intermediate;
+ Temp = StrStr(Walker, L" ");
+ if (Temp != NULL) {
+ Walker = Temp;
+ }
+ while(Walker[0] == L' ') {
+ Walker++;
+ }
+ }
+
+ if (ShellStatus == SHELL_SUCCESS) {
+ //
+ // Now we know how many EFI_INPUT_KEY structs we need to attach to the end of the EFI_KEY_OPTION struct.
+ // Re-allocate with the added information.
+ //
+ KeyOptionBuffer = AllocateCopyPool(sizeof(EFI_KEY_OPTION) + (sizeof(EFI_INPUT_KEY) * NewKeyOption.KeyData.Options.InputKeyCount), &NewKeyOption);
+ if (KeyOptionBuffer == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellBcfgHiiHandle, L"bcfg");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ }
+ }
+ for (LoopCounter = 0 ; ShellStatus == SHELL_SUCCESS && LoopCounter < NewKeyOption.KeyData.Options.InputKeyCount; LoopCounter++) {
+ //
+ // ScanCode
+ //
+ Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE);
+ if (EFI_ERROR(Status) || (((UINT16)Intermediate) != Intermediate) || StrStr(Walker, L" ") == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ ((EFI_INPUT_KEY*)(((UINT8*)KeyOptionBuffer) + sizeof(EFI_KEY_OPTION)))[LoopCounter].ScanCode = (UINT16)Intermediate;
+ Temp = StrStr(Walker, L" ");
+ if (Temp != NULL) {
+ Walker = Temp;
+ }
+ while(Walker[0] == L' ') {
+ Walker++;
+ }
+
+ //
+ // UnicodeChar
+ //
+ Status = ShellConvertStringToUint64(Walker, &Intermediate, FALSE, TRUE);
+ if (EFI_ERROR(Status) || (((UINT16)Intermediate) != Intermediate)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", Walker);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ ((EFI_INPUT_KEY*)(((UINT8*)KeyOptionBuffer) + sizeof(EFI_KEY_OPTION)))[LoopCounter].UnicodeChar = (UINT16)Intermediate;
+ Temp = StrStr(Walker, L" ");
+ if (Temp != NULL) {
+ Walker = Temp;
+ }
+ while(Walker[0] == L' ') {
+ Walker++;
+ }
+ }
+
+ if (ShellStatus == SHELL_SUCCESS) {
+ //
+ // Now do the BootOption / BootOptionCrc
+ //
+ ASSERT (OptionIndex <= OrderCount);
+ KeyOptionBuffer->BootOption = CurrentOrder[OptionIndex];
+ Status = GetBootOptionCrc(&(KeyOptionBuffer->BootOptionCrc), KeyOptionBuffer->BootOption);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"Option Index");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ }
+
+ if (ShellStatus == SHELL_SUCCESS) {
+ for (Temp2 = NULL, KeyIndex = 0 ; KeyIndex <= 0xFFFF ; KeyIndex++) {
+ UnicodeSPrint(VariableName, sizeof(VariableName), L"Key%04x", KeyIndex);
+ Status = GetEfiGlobalVariable2 (VariableName, &VariableData, NULL);
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ }
+ if (!EFI_ERROR(Status)) {
+ SHELL_FREE_NON_NULL(VariableData);
+ }
+ }
+ if (KeyIndex <= 0xFFFF) {
+ Status = gRT->SetVariable(
+ VariableName,
+ (EFI_GUID*)&gEfiGlobalVariableGuid,
+ EFI_VARIABLE_NON_VOLATILE|EFI_VARIABLE_BOOTSERVICE_ACCESS|EFI_VARIABLE_RUNTIME_ACCESS,
+ sizeof(EFI_KEY_OPTION) + (sizeof(EFI_INPUT_KEY) * NewKeyOption.KeyData.Options.InputKeyCount),
+ KeyOptionBuffer);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_VAR_NO_NUM), gShellBcfgHiiHandle, L"bcfg");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ ASSERT(FileName == NULL && Data == NULL);
+ }
+ }
+ }
+
+ //
+ // Shouldn't be possible to have have both. Neither is ok though.
+ //
+ ASSERT(FileName == NULL || Data == NULL);
+
+ if (ShellStatus == SHELL_SUCCESS && (FileName != NULL || Data != NULL)) {
+ if (FileName != NULL) {
+ //
+ // Open the file and populate the data buffer.
+ //
+ Status = ShellOpenFileByName(
+ FileName,
+ &FileHandle,
+ EFI_FILE_MODE_READ,
+ 0);
+ if (!EFI_ERROR(Status)) {
+ Status = ShellGetFileSize(FileHandle, &Intermediate);
+ }
+ Data = AllocateZeroPool((UINTN)Intermediate);
+ if (Data == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellBcfgHiiHandle, L"bcfg");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ }
+ if (!EFI_ERROR(Status)) {
+ Status = ShellReadFile(FileHandle, (UINTN *)&Intermediate, Data);
+ }
+ } else {
+ Intermediate = StrSize(Data);
+ }
+
+ if (!EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS && Data != NULL) {
+ Status = UpdateOptionalData(CurrentOrder[OptionIndex], (UINTN)Intermediate, (UINT8*)Data, Target);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ }
+ if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_SET_VAR_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ }
+
+ SHELL_FREE_NON_NULL(Data);
+ SHELL_FREE_NON_NULL(KeyOptionBuffer);
+ SHELL_FREE_NON_NULL(FileName);
+ return ShellStatus;
+}
+
+/**
+ Function to dump the Bcfg information.
+
+ @param[in] Op The operation.
+ @param[in] OrderCount How many to dump.
+ @param[in] CurrentOrder The pointer to the current order of items.
+ @param[in] VerboseOutput TRUE for extra output. FALSE otherwise.
+
+ @retval SHELL_SUCCESS The dump was successful.
+ @retval SHELL_INVALID_PARAMETER A parameter was invalid.
+**/
+SHELL_STATUS
+EFIAPI
+BcfgDisplayDump(
+ IN CONST CHAR16 *Op,
+ IN CONST UINTN OrderCount,
+ IN CONST UINT16 *CurrentOrder,
+ IN CONST BOOLEAN VerboseOutput
+ )
+{
+ EFI_STATUS Status;
+ UINT8 *Buffer;
+ UINTN BufferSize;
+ CHAR16 VariableName[12];
+ UINTN LoopVar;
+ CHAR16 *DevPathString;
+ VOID *FilePathList;
+ UINTN Errors;
+ EFI_LOAD_OPTION *LoadOption;
+ CHAR16 *Description;
+ UINTN DescriptionSize;
+ UINTN OptionalDataOffset;
+
+ if (OrderCount == 0) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_BCFG_NONE), gShellBcfgHiiHandle, L"bcfg");
+ return (SHELL_SUCCESS);
+ }
+
+ Errors = 0;
+
+ for (LoopVar = 0 ; LoopVar < OrderCount ; LoopVar++) {
+ Buffer = NULL;
+ BufferSize = 0;
+ DevPathString = NULL;
+
+ UnicodeSPrint(VariableName, sizeof(VariableName), L"%s%04x", Op, CurrentOrder[LoopVar]);
+
+ Status = gRT->GetVariable(
+ VariableName,
+ (EFI_GUID*)&gEfiGlobalVariableGuid,
+ NULL,
+ &BufferSize,
+ Buffer);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ Buffer = AllocateZeroPool(BufferSize);
+ Status = gRT->GetVariable(
+ VariableName,
+ (EFI_GUID*)&gEfiGlobalVariableGuid,
+ NULL,
+ &BufferSize,
+ Buffer);
+ }
+
+ if (EFI_ERROR(Status) || Buffer == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_READ_FAIL), gShellBcfgHiiHandle, L"bcfg", VariableName);
+ ++Errors;
+ goto Cleanup;
+ }
+
+ //
+ // We expect the Attributes, FilePathListLength, and L'\0'-terminated
+ // Description fields to be present.
+ //
+ if (BufferSize < sizeof *LoadOption + sizeof (CHAR16)) {
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_BCFG_VAR_CORRUPT),
+ gShellBcfgHiiHandle,
+ L"bcfg",
+ VariableName
+ );
+ ++Errors;
+ goto Cleanup;
+ }
+
+ LoadOption = (EFI_LOAD_OPTION *)Buffer;
+ Description = (CHAR16*)(Buffer + sizeof (EFI_LOAD_OPTION));
+ DescriptionSize = StrSize (Description);
+
+ if (LoadOption->FilePathListLength != 0) {
+ FilePathList = (UINT8 *)Description + DescriptionSize;
+ DevPathString = ConvertDevicePathToText(FilePathList, TRUE, FALSE);
+ }
+
+ OptionalDataOffset = sizeof *LoadOption + DescriptionSize +
+ LoadOption->FilePathListLength;
+
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_BCFG_LOAD_OPTIONS),
+ gShellBcfgHiiHandle,
+ LoopVar,
+ VariableName,
+ Description,
+ DevPathString,
+ OptionalDataOffset >= BufferSize ? L'N' : L'Y'
+ );
+ if (VerboseOutput && (OptionalDataOffset < BufferSize)) {
+ DumpHex (
+ 2, // Indent
+ 0, // Offset (displayed)
+ BufferSize - OptionalDataOffset, // DataSize
+ Buffer + OptionalDataOffset // UserData
+ );
+ }
+
+Cleanup:
+ if (Buffer != NULL) {
+ FreePool(Buffer);
+ }
+ if (DevPathString != NULL) {
+ FreePool(DevPathString);
+ }
+ }
+ return (Errors > 0) ? SHELL_INVALID_PARAMETER : SHELL_SUCCESS;
+}
+
+/**
+ Function to initialize the BCFG operation structure.
+
+ @param[in] Struct The stuct to initialize.
+**/
+VOID
+EFIAPI
+InitBcfgStruct(
+ IN BGFG_OPERATION *Struct
+ )
+{
+ ASSERT(Struct != NULL);
+ Struct->Target = BcfgTargetMax;
+ Struct->Type = BcfgTypeMax;
+ Struct->Number1 = 0;
+ Struct->Number2 = 0;
+ Struct->HandleIndex = 0;
+ Struct->FileName = NULL;
+ Struct->Description = NULL;
+ Struct->Order = NULL;
+ Struct->OptData = NULL;
+}
+
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-v", TypeFlag},
+ {L"-opt", TypeMaxValue},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'bcfg' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunBcfg (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ UINTN ParamNumber;
+ CONST CHAR16 *CurrentParam;
+ BGFG_OPERATION CurrentOperation;
+ UINTN Length;
+ UINT64 Intermediate;
+ UINT16 Count;
+
+ Length = 0;
+ ProblemParam = NULL;
+ Package = NULL;
+ ShellStatus = SHELL_SUCCESS;
+
+ InitBcfgStruct(&CurrentOperation);
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellBcfgHiiHandle, L"bcfg", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // Read in if we are doing -OPT
+ //
+ if (ShellCommandLineGetFlag(Package, L"-opt")) {
+ CurrentOperation.OptData = ShellCommandLineGetValue(Package, L"-opt");
+ if (CurrentOperation.OptData == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellBcfgHiiHandle, L"bcfg", L"-opt");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ CurrentOperation.Type = BcfgTypeOpt;
+ }
+
+ //
+ // small block to read the target of the operation
+ //
+ if ((ShellCommandLineGetCount(Package) < 3 && CurrentOperation.Type != BcfgTypeOpt) ||
+ (ShellCommandLineGetCount(Package) < 2 && CurrentOperation.Type == BcfgTypeOpt)
+ ){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)ShellCommandLineGetRawValue(Package, 1), L"driver") == 0) {
+ CurrentOperation.Target = BcfgTargetDriverOrder;
+ } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)ShellCommandLineGetRawValue(Package, 1), L"boot") == 0) {
+ CurrentOperation.Target = BcfgTargetBootOrder;
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_DRIVER_BOOT), gShellBcfgHiiHandle, L"bcfg");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+
+
+ //
+ // Read in the boot or driver order environment variable (not needed for opt)
+ //
+ if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax) {
+ Length = 0;
+ Status = gRT->GetVariable(
+ CurrentOperation.Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",
+ (EFI_GUID*)&gEfiGlobalVariableGuid,
+ NULL,
+ &Length,
+ CurrentOperation.Order);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ CurrentOperation.Order = AllocateZeroPool(Length+(4*sizeof(CurrentOperation.Order[0])));
+ if (CurrentOperation.Order == NULL) {
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ } else {
+ Status = gRT->GetVariable(
+ CurrentOperation.Target == BcfgTargetBootOrder?(CHAR16*)L"BootOrder":(CHAR16*)L"DriverOrder",
+ (EFI_GUID*)&gEfiGlobalVariableGuid,
+ NULL,
+ &Length,
+ CurrentOperation.Order);
+ }
+ }
+ }
+
+ Count = (UINT16) (Length / sizeof(CurrentOperation.Order[0]));
+
+ //
+ // large block to read the type of operation and verify parameter types for the info.
+ //
+ if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax) {
+ for (ParamNumber = 2 ; ParamNumber < ShellCommandLineGetCount(Package) && ShellStatus == SHELL_SUCCESS; ParamNumber++) {
+ CurrentParam = ShellCommandLineGetRawValue(Package, ParamNumber);
+ if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"dump") == 0) {
+ CurrentOperation.Type = BcfgTypeDump;
+ } else if (ShellCommandLineGetFlag(Package, L"-v")) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", L"-v (without dump)");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"add") == 0) {
+ if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ CurrentOperation.Type = BcfgTypeAdd;
+ CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
+ if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
+ CurrentOperation.Number1 = (UINT16)Intermediate;
+ ASSERT(CurrentOperation.FileName == NULL);
+ CurrentOperation.FileName = StrnCatGrow(&CurrentOperation.FileName , NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
+ ASSERT(CurrentOperation.Description == NULL);
+ CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
+ }
+ } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"addp") == 0) {
+ if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ CurrentOperation.Type = BcfgTypeAddp;
+ CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
+ if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
+ CurrentOperation.Number1 = (UINT16)Intermediate;
+ ASSERT(CurrentOperation.FileName == NULL);
+ CurrentOperation.FileName = StrnCatGrow(&CurrentOperation.FileName , NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
+ ASSERT(CurrentOperation.Description == NULL);
+ CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
+ }
+ } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"addh") == 0) {
+ if ((ParamNumber + 3) >= ShellCommandLineGetCount(Package)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ CurrentOperation.Type = BcfgTypeAddh;
+ CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
+ if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
+ CurrentOperation.Number1 = (UINT16)Intermediate;
+ CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
+ if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
+ CurrentOperation.HandleIndex = (UINT16)Intermediate;
+ ASSERT(CurrentOperation.Description == NULL);
+ CurrentOperation.Description = StrnCatGrow(&CurrentOperation.Description, NULL, ShellCommandLineGetRawValue(Package, ++ParamNumber), 0);
+ }
+ }
+ } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"rm") == 0) {
+ if ((ParamNumber + 1) >= ShellCommandLineGetCount(Package)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ CurrentOperation.Type = BcfgTypeRm;
+ CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
+ if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
+ CurrentOperation.Number1 = (UINT16)Intermediate;
+ if (CurrentOperation.Number1 >= Count){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ }
+ } else if (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)CurrentParam, L"mv") == 0) {
+ if ((ParamNumber + 2) >= ShellCommandLineGetCount(Package)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellBcfgHiiHandle, L"bcfg");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ CurrentOperation.Type = BcfgTypeMv;
+ CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
+ if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
+ CurrentOperation.Number1 = (UINT16)Intermediate;
+ if (CurrentOperation.Number1 >= Count){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ CurrentParam = ShellCommandLineGetRawValue(Package, ++ParamNumber);
+ if (CurrentParam == NULL || !ShellIsHexOrDecimalNumber(CurrentParam, TRUE, FALSE)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Status = ShellConvertStringToUint64(CurrentParam, &Intermediate, TRUE, FALSE);
+ CurrentOperation.Number2 = (UINT16)Intermediate;
+ }
+ if (CurrentOperation.Number2 == CurrentOperation.Number1
+ ||CurrentOperation.Number2 >= Count
+ ){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_BCFG_NUMB_RANGE), gShellBcfgHiiHandle, L"bcfg", Count);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ }
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellBcfgHiiHandle, L"bcfg", CurrentParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ }
+ }
+ if (ShellStatus == SHELL_SUCCESS && CurrentOperation.Target < BcfgTargetMax && CurrentOperation.Type < BcfgTypeMax) {
+ //
+ // we have all the info. Do the work
+ //
+ switch (CurrentOperation.Type) {
+ case BcfgTypeDump:
+ ShellStatus = BcfgDisplayDump(
+ CurrentOperation.Target == BcfgTargetBootOrder?L"Boot":L"Driver",
+ Count,
+ CurrentOperation.Order,
+ ShellCommandLineGetFlag(Package, L"-v"));
+ break;
+ case BcfgTypeMv:
+ ShellStatus = BcfgMove(
+ CurrentOperation.Target,
+ CurrentOperation.Order,
+ Count,
+ CurrentOperation.Number1,
+ CurrentOperation.Number2);
+ break;
+ case BcfgTypeRm:
+ ShellStatus = BcfgRemove(
+ CurrentOperation.Target,
+ CurrentOperation.Order,
+ Count,
+ CurrentOperation.Number1);
+ break;
+ case BcfgTypeAdd:
+ case BcfgTypeAddp:
+ case BcfgTypeAddh:
+ ShellStatus = BcfgAdd(
+ CurrentOperation.Number1,
+ CurrentOperation.FileName,
+ CurrentOperation.Description==NULL?L"":CurrentOperation.Description,
+ CurrentOperation.Order,
+ Count,
+ CurrentOperation.Target,
+ (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddh),
+ (BOOLEAN)(CurrentOperation.Type == BcfgTypeAddp),
+ CurrentOperation.HandleIndex);
+ break;
+ case BcfgTypeOpt:
+ ShellStatus = BcfgAddOpt(
+ CurrentOperation.OptData,
+ CurrentOperation.Order,
+ Count,
+ CurrentOperation.Target);
+ break;
+ default:
+ ASSERT(FALSE);
+ }
+ }
+ }
+
+ if (Package != NULL) {
+ ShellCommandLineFreeVarList (Package);
+ }
+ if (CurrentOperation.FileName != NULL) {
+ FreePool(CurrentOperation.FileName);
+ }
+ if (CurrentOperation.Description != NULL) {
+ FreePool(CurrentOperation.Description);
+ }
+ if (CurrentOperation.Order != NULL) {
+ FreePool(CurrentOperation.Order);
+ }
+
+ return (ShellStatus);
+}
+
+
+/**
+ Function to get the filename with help context if HII will not be used.
+
+ @return The filename with help text in it.
+**/
+CONST CHAR16*
+EFIAPI
+ShellCommandGetManFileNameBcfg (
+ VOID
+ )
+{
+ return (mFileName);
+}
+
+/**
+ "Constructor" for the library.
+
+ This will register the handler for the bcfg command.
+
+ @param[in] ImageHandle the image handle of the process
+ @param[in] SystemTable the EFI System Table pointer
+ @param[in] Name the profile name to use
+
+ @retval EFI_SUCCESS the shell command handlers were installed sucessfully
+ @retval EFI_UNSUPPORTED the shell level required was not found.
+**/
+EFI_STATUS
+EFIAPI
+BcfgLibraryRegisterBcfgCommand (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable,
+ IN CONST CHAR16 *Name
+ )
+{
+ if (gShellBcfgHiiHandle != NULL) {
+ return (EFI_SUCCESS);
+ }
+
+ gShellBcfgHiiHandle = HiiAddPackages (&gShellBcfgHiiGuid, gImageHandle, UefiShellBcfgCommandLibStrings, NULL);
+ if (gShellBcfgHiiHandle == NULL) {
+ return (EFI_DEVICE_ERROR);
+ }
+
+ //
+ // install our shell command handler
+ //
+ ShellCommandRegisterCommandName(L"bcfg", ShellCommandRunBcfg , ShellCommandGetManFileNameBcfg, 0, Name, FALSE, gShellBcfgHiiHandle, STRING_TOKEN(STR_GET_HELP_BCFG));
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Destructor for the library. free any resources.
+
+ @param ImageHandle The image handle of the process.
+ @param SystemTable The EFI System Table pointer.
+**/
+EFI_STATUS
+EFIAPI
+BcfgLibraryUnregisterBcfgCommand (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ if (gShellBcfgHiiHandle != NULL) {
+ HiiRemovePackages(gShellBcfgHiiHandle);
+ }
+ gShellBcfgHiiHandle = NULL;
+ return (EFI_SUCCESS);
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf b/Core/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf
new file mode 100644
index 0000000000..44c8b7e405
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf
@@ -0,0 +1,46 @@
+## @file
+# Provides shell install1 functions
+#
+# Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved. <BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = UefiShellBcfgCommandLib
+ FILE_GUID = F6A3BF5D-4095-4E4F-9670-408770C2DBDF
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.1
+ LIBRARY_CLASS = BcfgCommandLib|UEFI_APPLICATION UEFI_DRIVER
+
+[Sources.common]
+ UefiShellBcfgCommandLib.c
+ UefiShellBcfgCommandLib.uni
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ ShellCommandLib
+ ShellLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ SortLib
+ PrintLib
+
+[Guids]
+ gShellBcfgHiiGuid ## SOMETIMES_CONSUMES ## HII
diff --git a/Core/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.uni b/Core/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.uni
new file mode 100644
index 0000000000..282494b2f4
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.uni
@@ -0,0 +1,158 @@
+// /**
+//
+// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.<BR>
+// Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// Module Name:
+//
+// UefiBcfgCommandsLib.uni
+//
+// Abstract:
+//
+// String definitions for UEFI Shell 2.0 BCFG command
+//
+//
+// **/
+
+/=#
+
+#langdef en-US "english"
+
+#string STR_GEN_NO_MEM #language en-US "%H%s%N: Memory is not available.\r\n"
+#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n"
+#string STR_GEN_NO_VALUE #language en-US "%H%s%N: Missing argument for flag - '%H%s%N'\r\n"
+#string STR_GEN_PARAM_INV #language en-US "%H%s%N: Invalid argument - '%H%s%N'\r\n"
+#string STR_GEN_NO_DRIVER_BOOT #language en-US "%H%s%N: Driver or Boot must be selected.\r\n"
+#string STR_GEN_BOOT_ONLY #language en-US "%H%s%N: Boot must be selected for hot key options.\r\n"
+#string STR_GEN_TOO_FEW #language en-US "%H%s%N: Too few arguments.\r\n"
+#string STR_GEN_FILE_OPEN_FAIL #language en-US "%H%s%N: Cannot open file - '%H%s%N'\r\n"
+#string STR_GEN_FIND_FAIL #language en-US "%H%s%N: File not found - '%H%s%N'\r\n"
+#string STR_GEN_OUT_MEM #language en-US "%H%s%N: Memory allocation was not successful.\r\n"
+#string STR_BCFG_WRITE_FAIL #language en-US "%H%s%N: Unable to write to '%H%s%N'\r\n"
+#string STR_BCFG_READ_FAIL #language en-US "%H%s%N: Unable to read from '%H%s%N'\r\n"
+#string STR_BCFG_VAR_CORRUPT #language en-US "%H%s%N: Variable '%H%s%N' corrupt.\r\n"
+#string STR_BCFG_HANDLE #language en-US "%H%s%N: The handle [%H%02x%N] does not have DevicePath.\r\n"
+#string STR_BCFG_FILE #language en-US "%H%s%N: The file '%H%s%N' matches multiple files.\r\n"
+#string STR_BCFG_FILE_OPEN #language en-US "%H%s%N: The file '%H%s%N' did not open.\r\n"
+#string STR_BCFG_FILE_DP #language en-US "%H%s%N: The file '%H%s%N' could not convert to DevPath.\r\n"
+#string STR_BCFG_TARGET_NF #language en-US "%H%s%N: Could not find unused target index.\r\n"
+#string STR_BCFG_TARGET #language en-US "Target = %04x.\r\n"
+#string STR_BCFG_SET_VAR_FAIL #language en-US "%H%s%N: Unable to set %H%s%N\r\n"
+#string STR_BCFG_VAR_NO_NUM #language en-US "%H%s%N: Cannot create Key#### variable: All the numbers from 0x0000 - 0xFFFF have been used.\r\n"
+#string STR_BCFG_NUMB_RANGE #language en-US "%H%s%N: Numbers must be under %d.\r\n"
+#string STR_BCFG_NONE #language en-US "No options found.\r\n"
+
+#string STR_BCFG_LOAD_OPTIONS #language en-US "Option: %B%02x%N. Variable: %B%-11s%N\r\n"
+ " Desc - %s\r\n"
+ " DevPath - %s\r\n"
+ " Optional- %c\r\n"
+#string STR_GET_HELP_BCFG #language en-US ""
+".TH bcfg 0 "configure boot and driver"\r\n"
+".SH NAME\r\n"
+"Manages the boot and driver options that are stored in NVRAM.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"BCFG driver|boot [dump [-v]] [add # file "desc"] [addp # file "desc"] \r\n"
+" [addh # handle "desc"] [rm #] [mv # #] \r\n"
+" [-opt # [[filename]|["data"]] | \r\n"
+" [KeyData <ScanCode UnicodeChar>]]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -v - Displays verbose information about options, including the optional\r\n"
+" data.\r\n"
+" -opt - Displays or modifies the optional data associated with a \r\n"
+" driver or boot option. This parameter is followed by the file name of the\r\n"
+" file that contains the binary data to be associated with the\r\n"
+" driver or boot option optional data, or the quote\r\n"
+" delimited data to be associated with the driver or\r\n"
+" boot option optional data.\r\n"
+" driver - Displays or modifies the driver option list.\r\n"
+" boot - Displays or modifies the boot option list.\r\n"
+" dump - Displays the option list.\r\n"
+" add - Adds an option. The # is the number of options to add in\r\n"
+" hexadecimal format. The file name is the name of the UEFI application/driver for\r\n"
+" the option. The quoted parameter is the description of the\r\n"
+" option to be added.\r\n"
+" addh - Adds an option that refers to the driver specified by a handle.\r\n"
+" The # is the number of options to add, in hexadecimal format. The\r\n"
+" handle is the driver handle, in hexadecimal format. The device path\r\n"
+" for the option is retrieved from the handle. The quoted\r\n"
+" parameter is the description of the option to be added.\r\n"
+" addp - Adds an option that refers to a specific file. Only the portion\r\n"
+" of the device path starting with the hard drive partition is\r\n"
+" placed in the option. The # is the number of options to add,\r\n"
+" in hexadecimal format. The quoted parameter is the description of the\r\n"
+" option being added.\r\n"
+" rm - Removes an option. The parameter lists the number of the options\r\n"
+" to remove in hexadecimal format.\r\n"
+" mv - Moves an option. The first numeric parameter is the number of\r\n"
+" the option to move in hexadecimal format. The second numeric parameter\r\n"
+" is the new number of the option to be moved.\r\n"
+" KeyData - Specifies the packed value associated with a hot-key.\r\n"
+" ScanCode - Specifies the UEFI-defined scan code portion of the\r\n"
+" EFI_INPUT_KEY instruction. This value is directly associated\r\n"
+" with the preceding KeyData value. When one instance of this\r\n"
+" parameter has a non-zero value, the paired UnicodeChar value\r\n"
+" will have a zero-based value.\r\n"
+" UnicodeChar - Specifies the Unicode value for the character associated with\r\n"
+" the preceding KeyData value. When one instance of this\r\n"
+" parameter has a non-zero value, the paired ScanCode value\r\n"
+" will have a zero-based value.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command manages the boot and driver options stored in NVRAM.\r\n"
+" 2. Use the dump option to display Boot#### or Driver#### environment variables.\r\n"
+" 3. Use the add option to add a new Boot#### or Driver#### \r\n"
+" environment variable.\r\n"
+" 4. Use the rm option to delete a Boot#### or Driver#### \r\n"
+" environment variable, and then the mv option to reorder\r\n"
+" the Boot#### and Driver#### environment variables.\r\n"
+" 5. The add, rm, and mv options also update the BootOrder or DriverOrder\r\n"
+" environment variables, as appropriate.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display driver options:\r\n"
+" Shell> bcfg driver dump\r\n"
+" \r\n"
+" * To display boot options:\r\n"
+" Shell> bcfg boot dump\r\n"
+" \r\n"
+" * To display verbose information about boot options:\r\n"
+" Shell> bcfg boot dump -v\r\n"
+" \r\n"
+" * To add a driver option #5:\r\n"
+" Shell> bcfg driver add 5 mydriver.efi "My Driver"\r\n"
+" \r\n"
+" * To add a boot option #3:\r\n"
+" Shell> bcfg boot add 3 osloader.efi "My OS"\r\n"
+" \r\n"
+" * To remove boot option #3:\r\n"
+" Shell> bcfg boot rm 3\r\n"
+" \r\n"
+" * To move boot option #3 to boot option #7:\r\n"
+" Shell> bcfg boot mv 3 7\r\n"
+" \r\n"
+" * To assign a CTRL-B hot-key to boot option #3:\r\n"
+" Shell> bcfg boot -opt 3 0x40000200 0 0x42\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_NOT_FOUND The requested option was not found.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+" SHELL_UNSUPPORTED The action as requested was unsupported.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_OUT_OF_RESOURCES There was insufficient free space for the request\r\n"
+" to be completed.\r\n"
+
diff --git a/Core/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.c b/Core/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.c
new file mode 100644
index 0000000000..525c1f14cf
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.c
@@ -0,0 +1,99 @@
+/** @file
+ Provides application point extension for "C" style main funciton
+
+ Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Base.h>
+
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/EfiShellInterface.h>
+#include <Protocol/EfiShellParameters.h>
+
+#include <Library/ShellCEntryLib.h>
+#include <Library/DebugLib.h>
+
+/**
+ UEFI entry point for an application that will in turn call the
+ ShellAppMain function which has parameters similar to a standard C
+ main function.
+
+ An application that uses UefiShellCEntryLib must have a ShellAppMain
+ function as prototyped in Include/Library/ShellCEntryLib.h.
+
+ Note that the Shell uses POSITIVE integers for error values, while UEFI
+ uses NEGATIVE values. If the application is to be used within a script,
+ it needs to return one of the SHELL_STATUS values defined in ShellBase.h.
+
+ @param ImageHandle The image handle of the UEFI Application.
+ @param SystemTable A pointer to the EFI System Table.
+
+ @retval EFI_SUCCESS The application exited normally.
+ @retval Other An error occurred.
+
+**/
+EFI_STATUS
+EFIAPI
+ShellCEntryLib (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ INTN ReturnFromMain;
+ EFI_SHELL_PARAMETERS_PROTOCOL *EfiShellParametersProtocol;
+ EFI_SHELL_INTERFACE *EfiShellInterface;
+ EFI_STATUS Status;
+
+ ReturnFromMain = -1;
+ EfiShellParametersProtocol = NULL;
+ EfiShellInterface = NULL;
+
+ Status = SystemTable->BootServices->OpenProtocol(ImageHandle,
+ &gEfiShellParametersProtocolGuid,
+ (VOID **)&EfiShellParametersProtocol,
+ ImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR(Status)) {
+ //
+ // use shell 2.0 interface
+ //
+ ReturnFromMain = ShellAppMain (
+ EfiShellParametersProtocol->Argc,
+ EfiShellParametersProtocol->Argv
+ );
+ } else {
+ //
+ // try to get shell 1.0 interface instead.
+ //
+ Status = SystemTable->BootServices->OpenProtocol(ImageHandle,
+ &gEfiShellInterfaceGuid,
+ (VOID **)&EfiShellInterface,
+ ImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR(Status)) {
+ //
+ // use shell 1.0 interface
+ //
+ ReturnFromMain = ShellAppMain (
+ EfiShellInterface->Argc,
+ EfiShellInterface->Argv
+ );
+ } else {
+ ASSERT(FALSE);
+ }
+ }
+ return ReturnFromMain;
+}
diff --git a/Core/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf b/Core/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
new file mode 100644
index 0000000000..500b1663ca
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
@@ -0,0 +1,44 @@
+## @file
+# Provides interface to shell functionality for shell commands and applications.
+#
+# Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved. <BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = UefiShellCEntryLib
+ FILE_GUID = 0e205c8a-8586-4dec-9f5c-4f9e394aefe8
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = ShellCEntryLib|UEFI_APPLICATION UEFI_DRIVER
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ UefiShellCEntryLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+
+[LibraryClasses]
+ UefiApplicationEntryPoint
+ DebugLib
+
+
+[Protocols]
+ gEfiShellParametersProtocolGuid ## CONSUMES
+ gEfiShellInterfaceGuid ## SOMETIMES_CONSUMES
+
+
diff --git a/Core/ShellPkg/Library/UefiShellCommandLib/ConsistMapping.c b/Core/ShellPkg/Library/UefiShellCommandLib/ConsistMapping.c
new file mode 100644
index 0000000000..d157ebbb2a
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellCommandLib/ConsistMapping.c
@@ -0,0 +1,1707 @@
+/** @file
+ Main file for support of shell consist mapping.
+
+ Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include "UefiShellCommandLib.h"
+#include <Library/DevicePathLib.h>
+#include <Library/SortLib.h>
+#include <Library/UefiLib.h>
+#include <Protocol/UsbIo.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/SimpleFileSystem.h>
+
+
+
+typedef enum {
+ MTDTypeUnknown,
+ MTDTypeFloppy,
+ MTDTypeHardDisk,
+ MTDTypeCDRom,
+ MTDTypeEnd
+} MTD_TYPE;
+
+typedef struct {
+ CHAR16 *Str;
+ UINTN Len;
+} POOL_PRINT;
+
+typedef struct {
+ UINTN Hi;
+ MTD_TYPE Mtd;
+ POOL_PRINT Csd;
+ BOOLEAN Digital;
+} DEVICE_CONSIST_MAPPING_INFO;
+
+typedef struct {
+ MTD_TYPE MTDType;
+ CHAR16 *Name;
+} MTD_NAME;
+
+/**
+ Serial Decode function.
+
+ @param DevPath The Device path info.
+ @param MapInfo The map info.
+ @param OrigDevPath The original device path protocol.
+
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_SUCCESS The appending was successful.
+**/
+typedef
+EFI_STATUS
+(*SERIAL_DECODE_FUNCTION) (
+ EFI_DEVICE_PATH_PROTOCOL *DevPath,
+ DEVICE_CONSIST_MAPPING_INFO *MapInfo,
+ EFI_DEVICE_PATH_PROTOCOL *OrigDevPath
+ );
+
+typedef struct {
+ UINT8 Type;
+ UINT8 SubType;
+ SERIAL_DECODE_FUNCTION SerialFun;
+ INTN (EFIAPI *CompareFun) (EFI_DEVICE_PATH_PROTOCOL *DevPath, EFI_DEVICE_PATH_PROTOCOL *DevPath2);
+} DEV_PATH_CONSIST_MAPPING_TABLE;
+
+
+/**
+ Concatenates a formatted unicode string to allocated pool.
+ The caller must free the resulting buffer.
+
+ @param Str Tracks the allocated pool, size in use, and amount of pool allocated.
+ @param Fmt The format string
+ @param ... The data will be printed.
+
+ @retval EFI_SUCCESS The string is concatenated successfully.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+
+**/
+EFI_STATUS
+CatPrint (
+ IN OUT POOL_PRINT *Str,
+ IN CHAR16 *Fmt,
+ ...
+ )
+{
+ UINT16 *AppendStr;
+ VA_LIST Args;
+ UINTN StringSize;
+ CHAR16 *NewStr;
+
+ AppendStr = AllocateZeroPool (0x1000);
+ if (AppendStr == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ VA_START (Args, Fmt);
+ UnicodeVSPrint (AppendStr, 0x1000, Fmt, Args);
+ VA_END (Args);
+ if (NULL == Str->Str) {
+ StringSize = StrSize (AppendStr);
+ NewStr = AllocateZeroPool (StringSize);
+ } else {
+ StringSize = StrSize (AppendStr);
+ StringSize += (StrSize (Str->Str) - sizeof (UINT16));
+
+ NewStr = ReallocatePool (
+ StrSize (Str->Str),
+ StringSize,
+ Str->Str
+ );
+ }
+ if (NewStr == NULL) {
+ FreePool (AppendStr);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Str->Str = NewStr;
+ StrCatS (Str->Str, StringSize/sizeof(CHAR16), AppendStr);
+ Str->Len = StringSize;
+
+ FreePool (AppendStr);
+ return EFI_SUCCESS;
+}
+
+MTD_NAME mMTDName[] = {
+ {
+ MTDTypeUnknown,
+ L"F"
+ },
+ {
+ MTDTypeFloppy,
+ L"FP"
+ },
+ {
+ MTDTypeHardDisk,
+ L"HD"
+ },
+ {
+ MTDTypeCDRom,
+ L"CD"
+ },
+ {
+ MTDTypeEnd,
+ NULL
+ }
+};
+
+/**
+ Function to append a 64 bit number / 25 onto the string.
+
+ @param[in, out] Str The string so append onto.
+ @param[in] Num The number to divide and append.
+
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_SUCCESS The appending was successful.
+**/
+EFI_STATUS
+AppendCSDNum2 (
+ IN OUT POOL_PRINT *Str,
+ IN UINT64 Num
+ )
+{
+ EFI_STATUS Status;
+ UINT64 Result;
+ UINT32 Rem;
+
+ ASSERT (Str != NULL);
+
+ Result = DivU64x32Remainder (Num, 25, &Rem);
+ if (Result > 0) {
+ Status = AppendCSDNum2 (Str, Result);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+
+ return CatPrint (Str, L"%c", Rem + 'a');
+}
+
+/**
+ Function to append a 64 bit number onto the mapping info.
+
+ @param[in, out] MappingItem The mapping info object to append onto.
+ @param[in] Num The info to append.
+
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_SUCCESS The appending was successful.
+
+**/
+EFI_STATUS
+AppendCSDNum (
+ IN OUT DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ IN UINT64 Num
+ )
+{
+ EFI_STATUS Status;
+ ASSERT (MappingItem != NULL);
+
+ if (MappingItem->Digital) {
+ Status = CatPrint (&MappingItem->Csd, L"%ld", Num);
+ } else {
+ Status = AppendCSDNum2 (&MappingItem->Csd, Num);
+ }
+
+ if (!EFI_ERROR (Status)) {
+ MappingItem->Digital = (BOOLEAN) !(MappingItem->Digital);
+ }
+
+ return Status;
+}
+
+/**
+ Function to append string into the mapping info.
+
+ @param[in, out] MappingItem The mapping info object to append onto.
+ @param[in] Str The info to append.
+
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_SUCCESS The appending was successful.
+**/
+EFI_STATUS
+AppendCSDStr (
+ IN OUT DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ IN CHAR16 *Str
+ )
+{
+ CHAR16 *Index;
+ EFI_STATUS Status;
+
+ ASSERT (Str != NULL && MappingItem != NULL);
+
+ Status = EFI_SUCCESS;
+
+ if (MappingItem->Digital) {
+ //
+ // To aVOID mult-meaning, the mapping is:
+ // 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ // 0 16 2 3 4 5 6 7 8 9 10 11 12 13 14 15
+ //
+ for (Index = Str; *Index != 0; Index++) {
+ switch (*Index) {
+ case '0':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ Status = CatPrint (&MappingItem->Csd, L"%c", *Index);
+ break;
+
+ case '1':
+ Status = CatPrint (&MappingItem->Csd, L"16");
+ break;
+
+ case 'a':
+ case 'b':
+ case 'c':
+ case 'd':
+ case 'e':
+ case 'f':
+ Status = CatPrint (&MappingItem->Csd, L"1%c", *Index - 'a' + '0');
+ break;
+
+ case 'A':
+ case 'B':
+ case 'C':
+ case 'D':
+ case 'E':
+ case 'F':
+ Status = CatPrint (&MappingItem->Csd, L"1%c", *Index - 'A' + '0');
+ break;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ } else {
+ for (Index = Str; *Index != 0; Index++) {
+ //
+ // The mapping is:
+ // 0 1 2 3 4 5 6 7 8 9 a b c d e f
+ // a b c d e f g h i j k l m n o p
+ //
+ if (*Index >= '0' && *Index <= '9') {
+ Status = CatPrint (&MappingItem->Csd, L"%c", *Index - '0' + 'a');
+ } else if (*Index >= 'a' && *Index <= 'f') {
+ Status = CatPrint (&MappingItem->Csd, L"%c", *Index - 'a' + 'k');
+ } else if (*Index >= 'A' && *Index <= 'F') {
+ Status = CatPrint (&MappingItem->Csd, L"%c", *Index - 'A' + 'k');
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ }
+
+ MappingItem->Digital = (BOOLEAN)!(MappingItem->Digital);
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to append a Guid to the mapping item.
+
+ @param[in, out] MappingItem The item to append onto.
+ @param[in] Guid The guid to append.
+
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_SUCCESS The appending was successful.
+**/
+EFI_STATUS
+AppendCSDGuid (
+ DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ EFI_GUID *Guid
+ )
+{
+ CHAR16 Buffer[64];
+
+ ASSERT (Guid != NULL && MappingItem != NULL);
+
+ UnicodeSPrint (
+ Buffer,
+ 0,
+ L"%g",
+ Guid
+ );
+
+ return AppendCSDStr (MappingItem, Buffer);
+}
+
+/**
+ Function to compare 2 APCI device paths.
+
+ @param[in] DevicePath1 The first device path to compare.
+ @param[in] DevicePath2 The second device path to compare.
+
+ @retval 0 The device paths represent the same device.
+ @return Non zero if the devices are different, zero otherwise.
+**/
+INTN
+EFIAPI
+DevPathCompareAcpi (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2
+ )
+{
+ ACPI_HID_DEVICE_PATH *Acpi1;
+ ACPI_HID_DEVICE_PATH *Acpi2;
+
+ if (DevicePath1 == NULL || DevicePath2 == NULL) {
+ return (-2);
+ }
+
+ Acpi1 = (ACPI_HID_DEVICE_PATH *) DevicePath1;
+ Acpi2 = (ACPI_HID_DEVICE_PATH *) DevicePath2;
+ if (Acpi1->HID > Acpi2->HID || (Acpi1->HID == Acpi2->HID && Acpi1->UID > Acpi2->UID)) {
+ return 1;
+ }
+
+ if (Acpi1->HID == Acpi2->HID && Acpi1->UID == Acpi2->UID) {
+ return 0;
+ }
+
+ return -1;
+}
+
+/**
+ Function to compare 2 PCI device paths.
+
+ @param[in] DevicePath1 The first device path to compare.
+ @param[in] DevicePath2 The second device path to compare.
+
+ @retval 0 The device paths represent the same device.
+ @return Non zero if the devices are different, zero otherwise.
+**/
+INTN
+EFIAPI
+DevPathComparePci (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2
+ )
+{
+ PCI_DEVICE_PATH *Pci1;
+ PCI_DEVICE_PATH *Pci2;
+
+ ASSERT(DevicePath1 != NULL);
+ ASSERT(DevicePath2 != NULL);
+
+ Pci1 = (PCI_DEVICE_PATH *) DevicePath1;
+ Pci2 = (PCI_DEVICE_PATH *) DevicePath2;
+ if (Pci1->Device > Pci2->Device || (Pci1->Device == Pci2->Device && Pci1->Function > Pci2->Function)) {
+ return 1;
+ }
+
+ if (Pci1->Device == Pci2->Device && Pci1->Function == Pci2->Function) {
+ return 0;
+ }
+
+ return -1;
+}
+
+/**
+ Do a comparison on 2 device paths.
+
+ @param[in] DevicePath1 The first device path.
+ @param[in] DevicePath2 The second device path.
+
+ @retval 0 The 2 device paths are the same.
+ @retval <0 DevicePath2 is greater than DevicePath1.
+ @retval >0 DevicePath1 is greater than DevicePath2.
+**/
+INTN
+EFIAPI
+DevPathCompareDefault (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath1,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath2
+ )
+{
+ UINTN DevPathSize1;
+ UINTN DevPathSize2;
+
+ ASSERT(DevicePath1 != NULL);
+ ASSERT(DevicePath2 != NULL);
+
+ DevPathSize1 = DevicePathNodeLength (DevicePath1);
+ DevPathSize2 = DevicePathNodeLength (DevicePath2);
+ if (DevPathSize1 > DevPathSize2) {
+ return 1;
+ } else if (DevPathSize1 < DevPathSize2) {
+ return -1;
+ } else {
+ return CompareMem (DevicePath1, DevicePath2, DevPathSize1);
+ }
+}
+
+/**
+ DevicePathNode must be SerialHDD Channel type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+ @param[in] DevicePath Ignored.
+
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_SUCCESS The appending was successful.
+**/
+EFI_STATUS
+DevPathSerialHardDrive (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ HARDDRIVE_DEVICE_PATH *Hd;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Hd = (HARDDRIVE_DEVICE_PATH *) DevicePathNode;
+ if (MappingItem->Mtd == MTDTypeUnknown) {
+ MappingItem->Mtd = MTDTypeHardDisk;
+ }
+
+ return AppendCSDNum (MappingItem, Hd->PartitionNumber);
+}
+
+/**
+ DevicePathNode must be SerialAtapi Channel type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+ @param[in] DevicePath Ignored.
+
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_SUCCESS The appending was successful.
+**/
+EFI_STATUS
+DevPathSerialAtapi (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ ATAPI_DEVICE_PATH *Atapi;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Atapi = (ATAPI_DEVICE_PATH *) DevicePathNode;
+ return AppendCSDNum (MappingItem, (Atapi->PrimarySecondary * 2 + Atapi->SlaveMaster));
+}
+
+/**
+ DevicePathNode must be SerialCDROM Channel type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+ @param[in] DevicePath Ignored.
+
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_SUCCESS The appending was successful.
+**/
+EFI_STATUS
+DevPathSerialCdRom (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ CDROM_DEVICE_PATH *Cd;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Cd = (CDROM_DEVICE_PATH *) DevicePathNode;
+ MappingItem->Mtd = MTDTypeCDRom;
+ return AppendCSDNum (MappingItem, Cd->BootEntry);
+}
+
+/**
+ DevicePathNode must be SerialFibre Channel type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+ @param[in] DevicePath Ignored.
+
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_SUCCESS The appending was successful.
+**/
+EFI_STATUS
+DevPathSerialFibre (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_STATUS Status;
+ FIBRECHANNEL_DEVICE_PATH *Fibre;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Fibre = (FIBRECHANNEL_DEVICE_PATH *) DevicePathNode;
+ Status = AppendCSDNum (MappingItem, Fibre->WWN);
+ if (!EFI_ERROR (Status)) {
+ Status = AppendCSDNum (MappingItem, Fibre->Lun);
+ }
+ return Status;
+}
+
+/**
+ DevicePathNode must be SerialUart type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+ @param[in] DevicePath Ignored.
+
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_SUCCESS The appending was successful.
+**/
+EFI_STATUS
+DevPathSerialUart (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_STATUS Status;
+ UART_DEVICE_PATH *Uart;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Uart = (UART_DEVICE_PATH *) DevicePathNode;
+ Status = AppendCSDNum (MappingItem, Uart->BaudRate);
+ if (!EFI_ERROR (Status)) {
+ Status = AppendCSDNum (MappingItem, Uart->DataBits);
+ }
+ if (!EFI_ERROR (Status)) {
+ Status = AppendCSDNum (MappingItem, Uart->Parity);
+ }
+ if (!EFI_ERROR (Status)) {
+ Status = AppendCSDNum (MappingItem, Uart->StopBits);
+ }
+ return Status;
+}
+
+/**
+ DevicePathNode must be SerialUSB type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+ @param[in] DevicePath Ignored.
+
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_SUCCESS The appending was successful.
+**/
+EFI_STATUS
+DevPathSerialUsb (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ USB_DEVICE_PATH *Usb;
+ EFI_USB_IO_PROTOCOL *UsbIo;
+ EFI_HANDLE TempHandle;
+ EFI_STATUS Status;
+ USB_INTERFACE_DESCRIPTOR InterfaceDesc;
+
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Usb = (USB_DEVICE_PATH *) DevicePathNode;
+ Status = AppendCSDNum (MappingItem, Usb->ParentPortNumber);
+ if (!EFI_ERROR (Status)) {
+ Status = AppendCSDNum (MappingItem, Usb->InterfaceNumber);
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (PcdGetBool(PcdUsbExtendedDecode)) {
+ Status = gBS->LocateDevicePath( &gEfiUsbIoProtocolGuid, &DevicePath, &TempHandle );
+ UsbIo = NULL;
+ if (!EFI_ERROR(Status)) {
+ Status = gBS->OpenProtocol(TempHandle, &gEfiUsbIoProtocolGuid, (VOID**)&UsbIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ }
+
+ if (!EFI_ERROR(Status)) {
+ ASSERT(UsbIo != NULL);
+ Status = UsbIo->UsbGetInterfaceDescriptor(UsbIo, &InterfaceDesc);
+ if (!EFI_ERROR(Status)) {
+ if (InterfaceDesc.InterfaceClass == USB_MASS_STORE_CLASS && MappingItem->Mtd == MTDTypeUnknown) {
+ switch (InterfaceDesc.InterfaceSubClass){
+ case USB_MASS_STORE_SCSI:
+ MappingItem->Mtd = MTDTypeHardDisk;
+ break;
+ case USB_MASS_STORE_8070I:
+ case USB_MASS_STORE_UFI:
+ MappingItem->Mtd = MTDTypeFloppy;
+ break;
+ case USB_MASS_STORE_8020I:
+ MappingItem->Mtd = MTDTypeCDRom;
+ break;
+ }
+ }
+ }
+ }
+ }
+ return Status;
+}
+
+/**
+ DevicePathNode must be SerialVendor type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+ @param[in] DevicePath Ignored.
+
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_SUCCESS The appending was successful.
+**/
+EFI_STATUS
+DevPathSerialVendor (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_STATUS Status;
+ VENDOR_DEVICE_PATH *Vendor;
+ SAS_DEVICE_PATH *Sas;
+ UINTN TargetNameLength;
+ UINTN Index;
+ CHAR16 *Buffer;
+ CHAR16 *NewBuffer;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Vendor = (VENDOR_DEVICE_PATH *) DevicePathNode;
+ Status = AppendCSDGuid (MappingItem, &Vendor->Guid);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (CompareGuid (&gEfiSasDevicePathGuid, &Vendor->Guid)) {
+ Sas = (SAS_DEVICE_PATH *) Vendor;
+ Status = AppendCSDNum (MappingItem, Sas->SasAddress);
+ if (!EFI_ERROR (Status)) {
+ Status = AppendCSDNum (MappingItem, Sas->Lun);
+ }
+ if (!EFI_ERROR (Status)) {
+ Status = AppendCSDNum (MappingItem, Sas->DeviceTopology);
+ }
+ if (!EFI_ERROR (Status)) {
+ Status = AppendCSDNum (MappingItem, Sas->RelativeTargetPort);
+ }
+ } else {
+ TargetNameLength = MIN(DevicePathNodeLength (DevicePathNode) - sizeof (VENDOR_DEVICE_PATH), PcdGet32(PcdShellVendorExtendedDecode));
+ if (TargetNameLength != 0) {
+ //
+ // String is 2 chars per data byte, plus NULL terminator
+ //
+ Buffer = AllocateZeroPool (((TargetNameLength * 2) + 1) * sizeof(CHAR16));
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Build the string data
+ //
+ for (Index = 0; Index < TargetNameLength; Index++) {
+ NewBuffer = CatSPrint (Buffer, L"%02x", *((UINT8*)Vendor + sizeof (VENDOR_DEVICE_PATH) + Index));
+ if (NewBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ }
+ Buffer = NewBuffer;
+ }
+
+ //
+ // Append the new data block
+ //
+ if (!EFI_ERROR (Status)) {
+ Status = AppendCSDStr (MappingItem, Buffer);
+ }
+
+ FreePool(Buffer);
+ }
+ }
+ return Status;
+}
+
+/**
+ DevicePathNode must be SerialLun type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+ @param[in] DevicePath Ignored.
+
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_SUCCESS The appending was successful.
+**/
+EFI_STATUS
+DevPathSerialLun (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ DEVICE_LOGICAL_UNIT_DEVICE_PATH *Lun;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Lun = (DEVICE_LOGICAL_UNIT_DEVICE_PATH *) DevicePathNode;
+ return AppendCSDNum (MappingItem, Lun->Lun);
+}
+
+/**
+ DevicePathNode must be SerialSata type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+ @param[in] DevicePath Ignored.
+
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_SUCCESS The appending was successful.
+**/
+EFI_STATUS
+DevPathSerialSata (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_STATUS Status;
+ SATA_DEVICE_PATH *Sata;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Sata = (SATA_DEVICE_PATH *) DevicePathNode;
+ Status = AppendCSDNum (MappingItem, Sata->HBAPortNumber);
+ if (!EFI_ERROR (Status)) {
+ Status = AppendCSDNum (MappingItem, Sata->PortMultiplierPortNumber);
+ }
+ if (!EFI_ERROR (Status)) {
+ Status = AppendCSDNum (MappingItem, Sata->Lun);
+ }
+ return Status;
+}
+
+/**
+ DevicePathNode must be SerialSCSI type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+ @param[in] DevicePath Ignored.
+
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_SUCCESS The appending was successful.
+**/
+EFI_STATUS
+DevPathSerialIScsi (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_STATUS Status;
+ ISCSI_DEVICE_PATH *IScsi;
+ UINT8 *IScsiTargetName;
+ CHAR16 *TargetName;
+ UINTN TargetNameLength;
+ UINTN Index;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Status = EFI_SUCCESS;
+
+ if (PcdGetBool(PcdShellDecodeIScsiMapNames)) {
+ IScsi = (ISCSI_DEVICE_PATH *) DevicePathNode;
+ Status = AppendCSDNum (MappingItem, IScsi->NetworkProtocol);
+ if (!EFI_ERROR (Status)) {
+ Status = AppendCSDNum (MappingItem, IScsi->LoginOption);
+ }
+ if (!EFI_ERROR (Status)) {
+ Status = AppendCSDNum (MappingItem, IScsi->Lun);
+ }
+ if (!EFI_ERROR (Status)) {
+ Status = AppendCSDNum (MappingItem, IScsi->TargetPortalGroupTag);
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ TargetNameLength = DevicePathNodeLength (DevicePathNode) - sizeof (ISCSI_DEVICE_PATH);
+ if (TargetNameLength > 0) {
+ TargetName = AllocateZeroPool ((TargetNameLength + 1) * sizeof (CHAR16));
+ if (TargetName == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ IScsiTargetName = (UINT8 *) (IScsi + 1);
+ for (Index = 0; Index < TargetNameLength; Index++) {
+ TargetName[Index] = (CHAR16) IScsiTargetName[Index];
+ }
+ Status = AppendCSDStr (MappingItem, TargetName);
+ FreePool (TargetName);
+ }
+ }
+ }
+ return Status;
+}
+
+/**
+ DevicePathNode must be SerialI20 type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+ @param[in] DevicePath Ignored.
+
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_SUCCESS The appending was successful.
+**/
+EFI_STATUS
+DevPathSerialI2O (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ I2O_DEVICE_PATH *DevicePath_I20;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ DevicePath_I20 = (I2O_DEVICE_PATH *) DevicePathNode;
+ return AppendCSDNum (MappingItem, DevicePath_I20->Tid);
+}
+
+/**
+ DevicePathNode must be Mac Address type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+ @param[in] DevicePath Ignored.
+
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_SUCCESS The appending was successful.
+**/
+EFI_STATUS
+DevPathSerialMacAddr (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ MAC_ADDR_DEVICE_PATH *Mac;
+ UINTN HwAddressSize;
+ UINTN Index;
+ CHAR16 Buffer[64];
+ CHAR16 *PBuffer;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Mac = (MAC_ADDR_DEVICE_PATH *) DevicePathNode;
+
+ HwAddressSize = sizeof (EFI_MAC_ADDRESS);
+ if (Mac->IfType == 0x01 || Mac->IfType == 0x00) {
+ HwAddressSize = 6;
+ }
+
+ for (Index = 0, PBuffer = Buffer; Index < HwAddressSize; Index++, PBuffer += 2) {
+ UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) Mac->MacAddress.Addr[Index]);
+ }
+
+ return AppendCSDStr (MappingItem, Buffer);
+}
+
+/**
+ DevicePathNode must be InfiniBand type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+ @param[in] DevicePath Ignored.
+
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_SUCCESS The appending was successful.
+**/
+EFI_STATUS
+DevPathSerialInfiniBand (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_STATUS Status;
+ INFINIBAND_DEVICE_PATH *InfiniBand;
+ UINTN Index;
+ CHAR16 Buffer[64];
+ CHAR16 *PBuffer;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ InfiniBand = (INFINIBAND_DEVICE_PATH *) DevicePathNode;
+ for (Index = 0, PBuffer = Buffer; Index < 16; Index++, PBuffer += 2) {
+ UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) InfiniBand->PortGid[Index]);
+ }
+
+ Status = AppendCSDStr (MappingItem, Buffer);
+ if (!EFI_ERROR (Status)) {
+ Status = AppendCSDNum (MappingItem, InfiniBand->ServiceId);
+ }
+ if (!EFI_ERROR (Status)) {
+ Status = AppendCSDNum (MappingItem, InfiniBand->TargetPortId);
+ }
+ if (!EFI_ERROR (Status)) {
+ Status = AppendCSDNum (MappingItem, InfiniBand->DeviceId);
+ }
+ return Status;
+}
+
+/**
+ DevicePathNode must be IPv4 type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+ @param[in] DevicePath Ignored.
+
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_SUCCESS The appending was successful.
+**/
+EFI_STATUS
+DevPathSerialIPv4 (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_STATUS Status;
+ IPv4_DEVICE_PATH *Ip;
+ CHAR16 Buffer[10];
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Ip = (IPv4_DEVICE_PATH *) DevicePathNode;
+ UnicodeSPrint (
+ Buffer,
+ 0,
+ L"%02x%02x%02x%02x",
+ (UINTN) Ip->LocalIpAddress.Addr[0],
+ (UINTN) Ip->LocalIpAddress.Addr[1],
+ (UINTN) Ip->LocalIpAddress.Addr[2],
+ (UINTN) Ip->LocalIpAddress.Addr[3]
+ );
+ Status = AppendCSDStr (MappingItem, Buffer);
+ if (!EFI_ERROR (Status)) {
+ Status = AppendCSDNum (MappingItem, Ip->LocalPort);
+ }
+ if (!EFI_ERROR (Status)) {
+ UnicodeSPrint (
+ Buffer,
+ 0,
+ L"%02x%02x%02x%02x",
+ (UINTN) Ip->RemoteIpAddress.Addr[0],
+ (UINTN) Ip->RemoteIpAddress.Addr[1],
+ (UINTN) Ip->RemoteIpAddress.Addr[2],
+ (UINTN) Ip->RemoteIpAddress.Addr[3]
+ );
+ Status = AppendCSDStr (MappingItem, Buffer);
+ }
+ if (!EFI_ERROR (Status)) {
+ Status = AppendCSDNum (MappingItem, Ip->RemotePort);
+ }
+ return Status;
+}
+
+/**
+ DevicePathNode must be IPv6 type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+ @param[in] DevicePath Ignored.
+
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_SUCCESS The appending was successful.
+**/
+EFI_STATUS
+DevPathSerialIPv6 (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_STATUS Status;
+ IPv6_DEVICE_PATH *Ip;
+ UINTN Index;
+ CHAR16 Buffer[64];
+ CHAR16 *PBuffer;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Ip = (IPv6_DEVICE_PATH *) DevicePathNode;
+ for (Index = 0, PBuffer = Buffer; Index < 16; Index++, PBuffer += 2) {
+ UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) Ip->LocalIpAddress.Addr[Index]);
+ }
+
+ Status = AppendCSDStr (MappingItem, Buffer);
+ if (!EFI_ERROR (Status)) {
+ Status = AppendCSDNum (MappingItem, Ip->LocalPort);
+ }
+ if (!EFI_ERROR (Status)) {
+ for (Index = 0, PBuffer = Buffer; Index < 16; Index++, PBuffer += 2) {
+ UnicodeSPrint (PBuffer, 0, L"%02x", (UINTN) Ip->RemoteIpAddress.Addr[Index]);
+ }
+
+ Status = AppendCSDStr (MappingItem, Buffer);
+ }
+ if (!EFI_ERROR (Status)) {
+ Status = AppendCSDNum (MappingItem, Ip->RemotePort);
+ }
+ return Status;
+}
+
+/**
+ DevicePathNode must be SCSI type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+ @param[in] DevicePath Ignored.
+
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_SUCCESS The appending was successful.
+**/
+EFI_STATUS
+DevPathSerialScsi (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_STATUS Status;
+ SCSI_DEVICE_PATH *Scsi;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Scsi = (SCSI_DEVICE_PATH *) DevicePathNode;
+ Status = AppendCSDNum (MappingItem, Scsi->Pun);
+ if (!EFI_ERROR (Status)) {
+ Status = AppendCSDNum (MappingItem, Scsi->Lun);
+ }
+ return Status;
+}
+
+/**
+ DevicePathNode must be 1394 type and this will populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+ @param[in] DevicePath Ignored.
+
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_SUCCESS The appending was successful.
+**/
+EFI_STATUS
+DevPathSerial1394 (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ F1394_DEVICE_PATH *DevicePath_F1394;
+ CHAR16 Buffer[20];
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ DevicePath_F1394 = (F1394_DEVICE_PATH *) DevicePathNode;
+ UnicodeSPrint (Buffer, 0, L"%lx", DevicePath_F1394->Guid);
+ return AppendCSDStr (MappingItem, Buffer);
+}
+
+/**
+ If the node is floppy type then populate the MappingItem.
+
+ @param[in] DevicePathNode The node to get info on.
+ @param[in] MappingItem The info item to populate.
+ @param[in] DevicePath Ignored.
+
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_SUCCESS The appending was successful.
+**/
+EFI_STATUS
+DevPathSerialAcpi (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ ACPI_HID_DEVICE_PATH *Acpi;
+
+ ASSERT(DevicePathNode != NULL);
+ ASSERT(MappingItem != NULL);
+
+ Acpi = (ACPI_HID_DEVICE_PATH *) DevicePathNode;
+ if ((Acpi->HID & PNP_EISA_ID_MASK) == PNP_EISA_ID_CONST) {
+ if (EISA_ID_TO_NUM (Acpi->HID) == 0x0604) {
+ MappingItem->Mtd = MTDTypeFloppy;
+ return AppendCSDNum (MappingItem, Acpi->UID);
+ }
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Empty function used for unknown devices.
+
+ @param[in] DevicePathNode Ignored.
+ @param[in] MappingItem Ignored.
+ @param[in] DevicePath Ignored.
+
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_SUCCESS The appending was successful.
+**/
+EFI_STATUS
+DevPathSerialDefault (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode,
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ return EFI_SUCCESS;
+}
+
+DEV_PATH_CONSIST_MAPPING_TABLE DevPathConsistMappingTable[] = {
+ {
+ HARDWARE_DEVICE_PATH,
+ HW_PCI_DP,
+ DevPathSerialDefault,
+ DevPathComparePci
+ },
+ {
+ ACPI_DEVICE_PATH,
+ ACPI_DP,
+ DevPathSerialAcpi,
+ DevPathCompareAcpi
+ },
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_ATAPI_DP,
+ DevPathSerialAtapi,
+ DevPathCompareDefault
+ },
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_SCSI_DP,
+ DevPathSerialScsi,
+ DevPathCompareDefault
+ },
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_FIBRECHANNEL_DP,
+ DevPathSerialFibre,
+ DevPathCompareDefault
+ },
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_1394_DP,
+ DevPathSerial1394,
+ DevPathCompareDefault
+ },
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_USB_DP,
+ DevPathSerialUsb,
+ DevPathCompareDefault
+ },
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_I2O_DP,
+ DevPathSerialI2O,
+ DevPathCompareDefault
+ },
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_MAC_ADDR_DP,
+ DevPathSerialMacAddr,
+ DevPathCompareDefault
+ },
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_IPv4_DP,
+ DevPathSerialIPv4,
+ DevPathCompareDefault
+ },
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_IPv6_DP,
+ DevPathSerialIPv6,
+ DevPathCompareDefault
+ },
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_INFINIBAND_DP,
+ DevPathSerialInfiniBand,
+ DevPathCompareDefault
+ },
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_UART_DP,
+ DevPathSerialUart,
+ DevPathCompareDefault
+ },
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_VENDOR_DP,
+ DevPathSerialVendor,
+ DevPathCompareDefault
+ },
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_DEVICE_LOGICAL_UNIT_DP,
+ DevPathSerialLun,
+ DevPathCompareDefault
+ },
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_SATA_DP,
+ DevPathSerialSata,
+ DevPathCompareDefault
+ },
+ {
+ MESSAGING_DEVICE_PATH,
+ MSG_ISCSI_DP,
+ DevPathSerialIScsi,
+ DevPathCompareDefault
+ },
+ {
+ MEDIA_DEVICE_PATH,
+ MEDIA_HARDDRIVE_DP,
+ DevPathSerialHardDrive,
+ DevPathCompareDefault
+ },
+ {
+ MEDIA_DEVICE_PATH,
+ MEDIA_CDROM_DP,
+ DevPathSerialCdRom,
+ DevPathCompareDefault
+ },
+ {
+ MEDIA_DEVICE_PATH,
+ MEDIA_VENDOR_DP,
+ DevPathSerialVendor,
+ DevPathCompareDefault
+ },
+ {
+ 0,
+ 0,
+ NULL,
+ NULL
+ }
+};
+
+/**
+ Function to determine if a device path node is Hi or not.
+
+ @param[in] DevicePathNode The node to check.
+
+ @retval TRUE The node is Hi.
+ @retval FALSE The node is not Hi.
+**/
+BOOLEAN
+EFIAPI
+IsHIDevicePathNode (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathNode
+ )
+{
+ ACPI_HID_DEVICE_PATH *Acpi;
+
+ ASSERT(DevicePathNode != NULL);
+
+ if (DevicePathNode->Type == HARDWARE_DEVICE_PATH) {
+ return TRUE;
+ }
+
+ if (DevicePathNode->Type == ACPI_DEVICE_PATH) {
+ Acpi = (ACPI_HID_DEVICE_PATH *) DevicePathNode;
+ switch (EISA_ID_TO_NUM (Acpi->HID)) {
+ case 0x0301:
+ case 0x0401:
+ case 0x0501:
+ case 0x0604:
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Function to convert a standard device path structure into a Hi version.
+
+ @param[in] DevicePath The device path to convert.
+
+ @return the device path portion that is Hi.
+**/
+EFI_DEVICE_PATH_PROTOCOL *
+EFIAPI
+GetHIDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ UINTN NonHIDevicePathNodeCount;
+ UINTN Index;
+ EFI_DEV_PATH Node;
+ EFI_DEVICE_PATH_PROTOCOL *HIDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *TempDevicePath;
+
+ ASSERT(DevicePath != NULL);
+
+ NonHIDevicePathNodeCount = 0;
+
+ HIDevicePath = AllocateZeroPool (sizeof (EFI_DEVICE_PATH_PROTOCOL));
+ SetDevicePathEndNode (HIDevicePath);
+
+ Node.DevPath.Type = END_DEVICE_PATH_TYPE;
+ Node.DevPath.SubType = END_INSTANCE_DEVICE_PATH_SUBTYPE;
+ Node.DevPath.Length[0] = (UINT8)sizeof (EFI_DEVICE_PATH_PROTOCOL);
+ Node.DevPath.Length[1] = 0;
+
+ while (!IsDevicePathEnd (DevicePath)) {
+ if (IsHIDevicePathNode (DevicePath)) {
+ for (Index = 0; Index < NonHIDevicePathNodeCount; Index++) {
+ TempDevicePath = AppendDevicePathNode (HIDevicePath, &Node.DevPath);
+ FreePool (HIDevicePath);
+ HIDevicePath = TempDevicePath;
+ }
+
+ TempDevicePath = AppendDevicePathNode (HIDevicePath, DevicePath);
+ FreePool (HIDevicePath);
+ HIDevicePath = TempDevicePath;
+ } else {
+ NonHIDevicePathNodeCount++;
+ }
+ //
+ // Next device path node
+ //
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (DevicePath);
+ }
+
+ return HIDevicePath;
+}
+
+/**
+ Function to walk the device path looking for a dumpable node.
+
+ @param[in] MappingItem The Item to fill with data.
+ @param[in] DevicePath The path of the item to get data on.
+
+ @return EFI_SUCCESS Always returns success.
+**/
+EFI_STATUS
+EFIAPI
+GetDeviceConsistMappingInfo (
+ IN DEVICE_CONSIST_MAPPING_INFO *MappingItem,
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ EFI_STATUS Status;
+ SERIAL_DECODE_FUNCTION SerialFun;
+ UINTN Index;
+ EFI_DEVICE_PATH_PROTOCOL *OriginalDevicePath;
+
+ ASSERT(DevicePath != NULL);
+ ASSERT(MappingItem != NULL);
+
+ SetMem (&MappingItem->Csd, sizeof (POOL_PRINT), 0);
+ OriginalDevicePath = DevicePath;
+
+ while (!IsDevicePathEnd (DevicePath)) {
+ //
+ // Find the handler to dump this device path node and
+ // initialize with generic function in case nothing is found
+ //
+ for (SerialFun = DevPathSerialDefault, Index = 0; DevPathConsistMappingTable[Index].SerialFun != NULL; Index += 1) {
+
+ if (DevicePathType (DevicePath) == DevPathConsistMappingTable[Index].Type &&
+ DevicePathSubType (DevicePath) == DevPathConsistMappingTable[Index].SubType
+ ) {
+ SerialFun = DevPathConsistMappingTable[Index].SerialFun;
+ break;
+ }
+ }
+
+ Status = SerialFun (DevicePath, MappingItem, OriginalDevicePath);
+ if (EFI_ERROR (Status)) {
+ SHELL_FREE_NON_NULL (MappingItem->Csd.Str);
+ return Status;
+ }
+
+ //
+ // Next device path node
+ //
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) NextDevicePathNode (DevicePath);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Function to initialize the table for creating consistent map names.
+
+ @param[out] Table The pointer to pointer to pointer to DevicePathProtocol object.
+
+ @retval EFI_SUCCESS The table was created successfully.
+**/
+EFI_STATUS
+EFIAPI
+ShellCommandConsistMappingInitialize (
+ OUT EFI_DEVICE_PATH_PROTOCOL ***Table
+ )
+{
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleNum;
+ UINTN HandleLoop;
+ EFI_DEVICE_PATH_PROTOCOL **TempTable;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *HIDevicePath;
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem;
+ UINTN Index;
+ EFI_STATUS Status;
+
+ HandleBuffer = NULL;
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiDevicePathProtocolGuid,
+ NULL,
+ &HandleNum,
+ &HandleBuffer
+ );
+ ASSERT_EFI_ERROR(Status);
+
+ TempTable = AllocateZeroPool ((HandleNum + 1) * sizeof (EFI_DEVICE_PATH_PROTOCOL *));
+ if (TempTable == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (HandleLoop = 0 ; HandleLoop < HandleNum ; HandleLoop++) {
+ DevicePath = DevicePathFromHandle (HandleBuffer[HandleLoop]);
+ if (DevicePath == NULL) {
+ continue;
+ }
+
+ HIDevicePath = GetHIDevicePath (DevicePath);
+ if (HIDevicePath == NULL) {
+ continue;
+ }
+
+ Status = gBS->HandleProtocol( HandleBuffer[HandleLoop],
+ &gEfiBlockIoProtocolGuid,
+ (VOID **)&BlockIo
+ );
+ if (EFI_ERROR(Status)) {
+ Status = gBS->HandleProtocol( HandleBuffer[HandleLoop],
+ &gEfiSimpleFileSystemProtocolGuid,
+ (VOID **)&SimpleFileSystem
+ );
+ if (EFI_ERROR(Status)) {
+ FreePool (HIDevicePath);
+ continue;
+ }
+ }
+
+ for (Index = 0; TempTable[Index] != NULL; Index++) {
+ if (DevicePathCompare (&TempTable[Index], &HIDevicePath) == 0) {
+ FreePool (HIDevicePath);
+ break;
+ }
+ }
+
+ if (TempTable[Index] == NULL) {
+ TempTable[Index] = HIDevicePath;
+ }
+ }
+
+ for (Index = 0; TempTable[Index] != NULL; Index++);
+ PerformQuickSort(TempTable, Index, sizeof(EFI_DEVICE_PATH_PROTOCOL*), DevicePathCompare);
+ *Table = TempTable;
+
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Function to uninitialize the table for creating consistent map names.
+
+ The parameter must have been received from ShellCommandConsistMappingInitialize.
+
+ @param[out] Table The pointer to pointer to DevicePathProtocol object.
+
+ @retval EFI_SUCCESS The table was deleted successfully.
+**/
+EFI_STATUS
+EFIAPI
+ShellCommandConsistMappingUnInitialize (
+ EFI_DEVICE_PATH_PROTOCOL **Table
+ )
+{
+ UINTN Index;
+
+ ASSERT(Table != NULL);
+
+ for (Index = 0; Table[Index] != NULL; Index++) {
+ FreePool (Table[Index]);
+ }
+
+ FreePool (Table);
+ return EFI_SUCCESS;
+}
+
+/**
+ Create a consistent mapped name for the device specified by DevicePath
+ based on the Table.
+
+ This must be called after ShellCommandConsistMappingInitialize() and
+ before ShellCommandConsistMappingUnInitialize() is called.
+
+ @param[in] DevicePath The pointer to the dev path for the device.
+ @param[in] Table The Table of mapping information.
+
+ @retval NULL A consistent mapped name could not be created.
+ @return A pointer to a string allocated from pool with the device name.
+**/
+CHAR16 *
+EFIAPI
+ShellCommandConsistMappingGenMappingName (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN EFI_DEVICE_PATH_PROTOCOL **Table
+ )
+{
+ EFI_STATUS Status;
+ POOL_PRINT Str;
+ DEVICE_CONSIST_MAPPING_INFO MappingInfo;
+ EFI_DEVICE_PATH_PROTOCOL *HIDevicePath;
+ UINTN Index;
+ CHAR16 *NewStr;
+
+ ASSERT(DevicePath != NULL);
+ ASSERT(Table != NULL);
+
+ HIDevicePath = GetHIDevicePath (DevicePath);
+ if (HIDevicePath == NULL) {
+ return NULL;
+ }
+
+ for (Index = 0; Table[Index] != NULL; Index++) {
+ if (DevicePathCompare (&Table[Index], &HIDevicePath) == 0) {
+ break;
+ }
+ }
+
+ FreePool (HIDevicePath);
+ if (Table[Index] == NULL) {
+ return NULL;
+ }
+
+ MappingInfo.Hi = Index;
+ MappingInfo.Mtd = MTDTypeUnknown;
+ MappingInfo.Digital = FALSE;
+
+ Status = GetDeviceConsistMappingInfo (&MappingInfo, DevicePath);
+ if (EFI_ERROR (Status)) {
+ return NULL;
+ }
+
+ SetMem (&Str, sizeof (Str), 0);
+ for (Index = 0; mMTDName[Index].MTDType != MTDTypeEnd; Index++) {
+ if (MappingInfo.Mtd == mMTDName[Index].MTDType) {
+ break;
+ }
+ }
+
+ if (mMTDName[Index].MTDType != MTDTypeEnd) {
+ Status = CatPrint (&Str, L"%s", mMTDName[Index].Name);
+ }
+
+ if (!EFI_ERROR (Status)) {
+ Status = CatPrint (&Str, L"%d", (UINTN) MappingInfo.Hi);
+ }
+ if (!EFI_ERROR (Status) && MappingInfo.Csd.Str != NULL) {
+ Status = CatPrint (&Str, L"%s", MappingInfo.Csd.Str);
+ FreePool (MappingInfo.Csd.Str);
+ }
+
+ if (!EFI_ERROR (Status) && Str.Str != NULL) {
+ Status = CatPrint (&Str, L":");
+ }
+ if (EFI_ERROR (Status)) {
+ SHELL_FREE_NON_NULL (Str.Str);
+ return NULL;
+ }
+
+ NewStr = ReallocatePool (Str.Len * sizeof (CHAR16), (Str.Len + 1) * sizeof (CHAR16), Str.Str);
+ if (NewStr == NULL) {
+ SHELL_FREE_NON_NULL (Str.Str);
+ return (NULL);
+ }
+ NewStr[Str.Len] = CHAR_NULL;
+ return NewStr;
+}
+
+/**
+ Function to search the list of mappings for the node on the list based on the key.
+
+ @param[in] MapKey String Key to search for on the map
+
+ @return the node on the list.
+**/
+SHELL_MAP_LIST *
+EFIAPI
+ShellCommandFindMapItem (
+ IN CONST CHAR16 *MapKey
+ )
+{
+ SHELL_MAP_LIST *MapListItem;
+
+ for ( MapListItem = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link)
+ ; !IsNull(&gShellMapList.Link, &MapListItem->Link)
+ ; MapListItem = (SHELL_MAP_LIST *)GetNextNode(&gShellMapList.Link, &MapListItem->Link)
+ ){
+ if (gUnicodeCollation->StriColl(gUnicodeCollation,MapListItem->MapName,(CHAR16*)MapKey) == 0) {
+ return (MapListItem);
+ }
+ }
+ return (NULL);
+}
+
+
diff --git a/Core/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c b/Core/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c
new file mode 100644
index 0000000000..7fe908cb57
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.c
@@ -0,0 +1,2053 @@
+/** @file
+ Provides interface to shell internal functions for shell commands.
+
+ Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellCommandLib.h"
+
+// STATIC local variables
+STATIC SHELL_COMMAND_INTERNAL_LIST_ENTRY mCommandList;
+STATIC SCRIPT_FILE_LIST mScriptList;
+STATIC ALIAS_LIST mAliasList;
+STATIC BOOLEAN mEchoState;
+STATIC BOOLEAN mExitRequested;
+STATIC UINT64 mExitCode;
+STATIC BOOLEAN mExitScript;
+STATIC CHAR16 *mProfileList;
+STATIC UINTN mProfileListSize;
+STATIC UINTN mFsMaxCount = 0;
+STATIC UINTN mBlkMaxCount = 0;
+STATIC BUFFER_LIST mFileHandleList;
+STATIC CHAR16 *mRawCmdLine = NULL;
+
+STATIC CONST CHAR8 Hex[] = {
+ '0',
+ '1',
+ '2',
+ '3',
+ '4',
+ '5',
+ '6',
+ '7',
+ '8',
+ '9',
+ 'A',
+ 'B',
+ 'C',
+ 'D',
+ 'E',
+ 'F'
+};
+
+// global variables required by library class.
+EFI_UNICODE_COLLATION_PROTOCOL *gUnicodeCollation = NULL;
+SHELL_MAP_LIST gShellMapList;
+SHELL_MAP_LIST *gShellCurDir = NULL;
+
+CONST CHAR16* SupportLevel[] = {
+ L"Minimal",
+ L"Scripting",
+ L"Basic",
+ L"Interactive"
+};
+
+/**
+ Function to make sure that the global protocol pointers are valid.
+ must be called after constructor before accessing the pointers.
+**/
+EFI_STATUS
+EFIAPI
+CommandInit(
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ if (gUnicodeCollation == NULL) {
+ Status = gBS->LocateProtocol(&gEfiUnicodeCollation2ProtocolGuid, NULL, (VOID**)&gUnicodeCollation);
+ if (EFI_ERROR(Status)) {
+ return (EFI_DEVICE_ERROR);
+ }
+ }
+ return (EFI_SUCCESS);
+}
+
+/**
+ Return the pointer to the first occurrence of any character from a list of characters.
+
+ @param[in] String The string to parse
+ @param[in] CharacterList The list of character to look for
+ @param[in] IgnoreEscapedCharacter TRUE to ignore escaped characters
+
+ @return The location of the first character in the String.
+ @return Pointer to the ending NULL character of the String.
+**/
+CONST CHAR16*
+EFIAPI
+ShellFindFirstCharacter (
+ IN CONST CHAR16 *String,
+ IN CONST CHAR16 *CharacterList,
+ IN CONST BOOLEAN IgnoreEscapedCharacter
+ )
+{
+ UINTN WalkChar;
+ UINTN WalkStr;
+
+ for (WalkStr = 0; WalkStr < StrLen (String); WalkStr++) {
+ if (IgnoreEscapedCharacter && (String[WalkStr] == L'^')) {
+ WalkStr++;
+ continue;
+ }
+ for (WalkChar = 0; WalkChar < StrLen (CharacterList); WalkChar++) {
+ if (String[WalkStr] == CharacterList[WalkChar]) {
+ return &String[WalkStr];
+ }
+ }
+ }
+ return &String[WalkStr];
+}
+
+/**
+ Return the next parameter's end from a command line string.
+
+ @param[in] String the string to parse
+**/
+CONST CHAR16*
+FindEndOfParameter(
+ IN CONST CHAR16 *String
+ )
+{
+ CONST CHAR16 *First;
+ CONST CHAR16 *CloseQuote;
+
+ First = ShellFindFirstCharacter (String, L" \"", TRUE);
+
+ //
+ // nothing, all one parameter remaining
+ //
+ if (*First == CHAR_NULL) {
+ return (First);
+ }
+
+ //
+ // If space before a quote (or neither found, i.e. both CHAR_NULL),
+ // then that's the end.
+ //
+ if (*First == L' ') {
+ return (First);
+ }
+
+ CloseQuote = ShellFindFirstCharacter (First+1, L"\"", TRUE);
+
+ //
+ // We did not find a terminator...
+ //
+ if (*CloseQuote == CHAR_NULL) {
+ return (NULL);
+ }
+
+ return (FindEndOfParameter (CloseQuote+1));
+}
+
+/**
+ Return the next parameter from a command line string.
+
+ This function moves the next parameter from Walker into NextParameter and moves
+ Walker up past that parameter for recursive calling. When the final parameter
+ is moved *Walker will be set to NULL;
+
+ This will also remove all remaining ^ characters after processing.
+
+ @param[in, out] Walker pointer to string of command line. Adjusted to
+ reminaing command line on return
+ @param[in, out] NextParameter pointer to string of command line item extracted.
+ @param[in] Length buffer size of TempParameter.
+ @param[in] StripQuotation if TRUE then strip the quotation marks surrounding
+ the parameters.
+
+ @return EFI_INALID_PARAMETER A required parameter was NULL or pointed to a NULL or empty string.
+ @return EFI_NOT_FOUND A closing " could not be found on the specified string
+**/
+EFI_STATUS
+EFIAPI
+ShellGetNextParameter (
+ IN OUT CHAR16 **Walker,
+ IN OUT CHAR16 *NextParameter,
+ IN CONST UINTN Length,
+ IN BOOLEAN StripQuotation
+ )
+{
+ CONST CHAR16 *NextDelim;
+
+ if (Walker == NULL
+ ||*Walker == NULL
+ ||NextParameter == NULL
+ ){
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // make sure we dont have any leading spaces
+ //
+ while ((*Walker)[0] == L' ') {
+ (*Walker)++;
+ }
+
+ //
+ // make sure we still have some params now...
+ //
+ if (StrLen(*Walker) == 0) {
+ DEBUG_CODE (
+ *Walker = NULL;
+ );
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ NextDelim = FindEndOfParameter(*Walker);
+
+ if (NextDelim == NULL){
+ DEBUG_CODE (
+ *Walker = NULL;
+ );
+ return (EFI_NOT_FOUND);
+ }
+
+ StrnCpyS(NextParameter, Length / sizeof(CHAR16), (*Walker), NextDelim - *Walker);
+
+ //
+ // Add a CHAR_NULL if we didnt get one via the copy
+ //
+ if (*NextDelim != CHAR_NULL) {
+ NextParameter[NextDelim - *Walker] = CHAR_NULL;
+ }
+
+ //
+ // Update Walker for the next iteration through the function
+ //
+ *Walker = (CHAR16*)NextDelim;
+
+ //
+ // Remove any non-escaped quotes in the string
+ // Remove any remaining escape characters in the string
+ //
+ for (NextDelim = ShellFindFirstCharacter(NextParameter, L"\"^", FALSE)
+ ; *NextDelim != CHAR_NULL
+ ; NextDelim = ShellFindFirstCharacter(NextDelim, L"\"^", FALSE)
+ ) {
+ if (*NextDelim == L'^') {
+
+ //
+ // eliminate the escape ^
+ //
+ CopyMem ((CHAR16*)NextDelim, NextDelim + 1, StrSize (NextDelim + 1));
+ NextDelim++;
+ } else if (*NextDelim == L'\"') {
+
+ //
+ // eliminate the unescaped quote
+ //
+ if (StripQuotation) {
+ CopyMem ((CHAR16*)NextDelim, NextDelim + 1, StrSize (NextDelim + 1));
+ } else {
+ NextDelim++;
+ }
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Constructor for the Shell Command library.
+
+ Initialize the library and determine if the underlying is a UEFI Shell 2.0 or an EFI shell.
+
+ @param ImageHandle the image handle of the process
+ @param SystemTable the EFI System Table pointer
+
+ @retval EFI_SUCCESS the initialization was complete sucessfully
+**/
+RETURN_STATUS
+EFIAPI
+ShellCommandLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ InitializeListHead(&gShellMapList.Link);
+ InitializeListHead(&mCommandList.Link);
+ InitializeListHead(&mAliasList.Link);
+ InitializeListHead(&mScriptList.Link);
+ InitializeListHead(&mFileHandleList.Link);
+ mEchoState = TRUE;
+
+ mExitRequested = FALSE;
+ mExitScript = FALSE;
+ mProfileListSize = 0;
+ mProfileList = NULL;
+
+ if (gUnicodeCollation == NULL) {
+ Status = gBS->LocateProtocol(&gEfiUnicodeCollation2ProtocolGuid, NULL, (VOID**)&gUnicodeCollation);
+ if (EFI_ERROR(Status)) {
+ return (EFI_DEVICE_ERROR);
+ }
+ }
+
+ return (RETURN_SUCCESS);
+}
+
+/**
+ Frees list of file handles.
+
+ @param[in] List The list to free.
+**/
+VOID
+EFIAPI
+FreeFileHandleList (
+ IN BUFFER_LIST *List
+ )
+{
+ BUFFER_LIST *BufferListEntry;
+
+ if (List == NULL){
+ return;
+ }
+ //
+ // enumerate through the buffer list and free all memory
+ //
+ for ( BufferListEntry = ( BUFFER_LIST *)GetFirstNode(&List->Link)
+ ; !IsListEmpty (&List->Link)
+ ; BufferListEntry = (BUFFER_LIST *)GetFirstNode(&List->Link)
+ ){
+ RemoveEntryList(&BufferListEntry->Link);
+ ASSERT(BufferListEntry->Buffer != NULL);
+ SHELL_FREE_NON_NULL(((SHELL_COMMAND_FILE_HANDLE*)(BufferListEntry->Buffer))->Path);
+ SHELL_FREE_NON_NULL(BufferListEntry->Buffer);
+ SHELL_FREE_NON_NULL(BufferListEntry);
+ }
+}
+
+/**
+ Destructor for the library. free any resources.
+
+ @param ImageHandle the image handle of the process
+ @param SystemTable the EFI System Table pointer
+
+ @retval RETURN_SUCCESS this function always returns success
+**/
+RETURN_STATUS
+EFIAPI
+ShellCommandLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
+ ALIAS_LIST *Node2;
+ SCRIPT_FILE_LIST *Node3;
+ SHELL_MAP_LIST *MapNode;
+ //
+ // enumerate throught the list and free all the memory
+ //
+ while (!IsListEmpty (&mCommandList.Link)) {
+ Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode(&mCommandList.Link);
+ RemoveEntryList(&Node->Link);
+ SHELL_FREE_NON_NULL(Node->CommandString);
+ FreePool(Node);
+ DEBUG_CODE(Node = NULL;);
+ }
+
+ //
+ // enumerate through the alias list and free all memory
+ //
+ while (!IsListEmpty (&mAliasList.Link)) {
+ Node2 = (ALIAS_LIST *)GetFirstNode(&mAliasList.Link);
+ RemoveEntryList(&Node2->Link);
+ SHELL_FREE_NON_NULL(Node2->CommandString);
+ SHELL_FREE_NON_NULL(Node2->Alias);
+ SHELL_FREE_NON_NULL(Node2);
+ DEBUG_CODE(Node2 = NULL;);
+ }
+
+ //
+ // enumerate throught the list and free all the memory
+ //
+ while (!IsListEmpty (&mScriptList.Link)) {
+ Node3 = (SCRIPT_FILE_LIST *)GetFirstNode(&mScriptList.Link);
+ RemoveEntryList(&Node3->Link);
+ DeleteScriptFileStruct(Node3->Data);
+ FreePool(Node3);
+ }
+
+ //
+ // enumerate throught the mappings list and free all the memory
+ //
+ if (!IsListEmpty(&gShellMapList.Link)) {
+ for (MapNode = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link)
+ ; !IsListEmpty (&gShellMapList.Link)
+ ; MapNode = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link)
+ ){
+ ASSERT(MapNode != NULL);
+ RemoveEntryList(&MapNode->Link);
+ SHELL_FREE_NON_NULL(MapNode->DevicePath);
+ SHELL_FREE_NON_NULL(MapNode->MapName);
+ SHELL_FREE_NON_NULL(MapNode->CurrentDirectoryPath);
+ FreePool(MapNode);
+ }
+ }
+ if (!IsListEmpty(&mFileHandleList.Link)){
+ FreeFileHandleList(&mFileHandleList);
+ }
+
+ if (mProfileList != NULL) {
+ FreePool(mProfileList);
+ }
+
+ gUnicodeCollation = NULL;
+ gShellCurDir = NULL;
+
+ return (RETURN_SUCCESS);
+}
+
+/**
+ Find a dynamic command protocol instance given a command name string.
+
+ @param CommandString the command name string
+
+ @return instance the command protocol instance, if dynamic command instance found
+ @retval NULL no dynamic command protocol instance found for name
+**/
+CONST EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *
+EFIAPI
+ShellCommandFindDynamicCommand (
+ IN CONST CHAR16 *CommandString
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *CommandHandleList;
+ EFI_HANDLE *NextCommand;
+ EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *DynamicCommand;
+
+ CommandHandleList = GetHandleListByProtocol(&gEfiShellDynamicCommandProtocolGuid);
+ if (CommandHandleList == NULL) {
+ //
+ // not found or out of resources
+ //
+ return NULL;
+ }
+
+ for (NextCommand = CommandHandleList; *NextCommand != NULL; NextCommand++) {
+ Status = gBS->HandleProtocol(
+ *NextCommand,
+ &gEfiShellDynamicCommandProtocolGuid,
+ (VOID **)&DynamicCommand
+ );
+
+ if (EFI_ERROR(Status)) {
+ continue;
+ }
+
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)CommandString,
+ (CHAR16*)DynamicCommand->CommandName) == 0
+ ){
+ FreePool(CommandHandleList);
+ return (DynamicCommand);
+ }
+ }
+
+ FreePool(CommandHandleList);
+ return (NULL);
+}
+
+/**
+ Checks if a command exists as a dynamic command protocol instance
+
+ @param[in] CommandString The command string to check for on the list.
+**/
+BOOLEAN
+EFIAPI
+ShellCommandDynamicCommandExists (
+ IN CONST CHAR16 *CommandString
+ )
+{
+ return (BOOLEAN) ((ShellCommandFindDynamicCommand(CommandString) != NULL));
+}
+
+/**
+ Checks if a command is already on the internal command list.
+
+ @param[in] CommandString The command string to check for on the list.
+**/
+BOOLEAN
+EFIAPI
+ShellCommandIsCommandOnInternalList(
+ IN CONST CHAR16 *CommandString
+ )
+{
+ SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
+
+ //
+ // assert for NULL parameter
+ //
+ ASSERT(CommandString != NULL);
+
+ //
+ // check for the command
+ //
+ for ( Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode(&mCommandList.Link)
+ ; !IsNull(&mCommandList.Link, &Node->Link)
+ ; Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode(&mCommandList.Link, &Node->Link)
+ ){
+ ASSERT(Node->CommandString != NULL);
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)CommandString,
+ Node->CommandString) == 0
+ ){
+ return (TRUE);
+ }
+ }
+ return (FALSE);
+}
+
+/**
+ Checks if a command exists, either internally or through the dynamic command protocol.
+
+ @param[in] CommandString The command string to check for on the list.
+**/
+BOOLEAN
+EFIAPI
+ShellCommandIsCommandOnList(
+ IN CONST CHAR16 *CommandString
+ )
+{
+ if (ShellCommandIsCommandOnInternalList(CommandString)) {
+ return TRUE;
+ }
+
+ return ShellCommandDynamicCommandExists(CommandString);
+}
+
+/**
+ Get the help text for a dynamic command.
+
+ @param[in] CommandString The command name.
+
+ @retval NULL No help text was found.
+ @return String of help text. Caller required to free.
+**/
+CHAR16*
+EFIAPI
+ShellCommandGetDynamicCommandHelp(
+ IN CONST CHAR16 *CommandString
+ )
+{
+ EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *DynamicCommand;
+
+ DynamicCommand = (EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *)ShellCommandFindDynamicCommand(CommandString);
+ if (DynamicCommand == NULL) {
+ return (NULL);
+ }
+
+ //
+ // TODO: how to get proper language?
+ //
+ return DynamicCommand->GetHelp(DynamicCommand, "en");
+}
+
+/**
+ Get the help text for an internal command.
+
+ @param[in] CommandString The command name.
+
+ @retval NULL No help text was found.
+ @return String of help text. Caller reuiqred to free.
+**/
+CHAR16*
+EFIAPI
+ShellCommandGetInternalCommandHelp(
+ IN CONST CHAR16 *CommandString
+ )
+{
+ SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
+
+ //
+ // assert for NULL parameter
+ //
+ ASSERT(CommandString != NULL);
+
+ //
+ // check for the command
+ //
+ for ( Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode(&mCommandList.Link)
+ ; !IsNull(&mCommandList.Link, &Node->Link)
+ ; Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode(&mCommandList.Link, &Node->Link)
+ ){
+ ASSERT(Node->CommandString != NULL);
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)CommandString,
+ Node->CommandString) == 0
+ ){
+ return (HiiGetString(Node->HiiHandle, Node->ManFormatHelp, NULL));
+ }
+ }
+ return (NULL);
+}
+
+/**
+ Get the help text for a command.
+
+ @param[in] CommandString The command name.
+
+ @retval NULL No help text was found.
+ @return String of help text.Caller reuiqred to free.
+**/
+CHAR16*
+EFIAPI
+ShellCommandGetCommandHelp (
+ IN CONST CHAR16 *CommandString
+ )
+{
+ CHAR16 *HelpStr;
+ HelpStr = ShellCommandGetInternalCommandHelp(CommandString);
+
+ if (HelpStr == NULL) {
+ HelpStr = ShellCommandGetDynamicCommandHelp(CommandString);
+ }
+
+ return HelpStr;
+}
+
+
+/**
+ Registers handlers of type SHELL_RUN_COMMAND and
+ SHELL_GET_MAN_FILENAME for each shell command.
+
+ If the ShellSupportLevel is greater than the value of the
+ PcdShellSupportLevel then return RETURN_UNSUPPORTED.
+
+ Registers the handlers specified by GetHelpInfoHandler and CommandHandler
+ with the command specified by CommandString. If the command named by
+ CommandString has already been registered, then return
+ RETURN_ALREADY_STARTED.
+
+ If there are not enough resources available to register the handlers then
+ RETURN_OUT_OF_RESOURCES is returned.
+
+ If CommandString is NULL, then ASSERT().
+ If GetHelpInfoHandler is NULL, then ASSERT().
+ If CommandHandler is NULL, then ASSERT().
+ If ProfileName is NULL, then ASSERT().
+
+ @param[in] CommandString Pointer to the command name. This is the
+ name to look for on the command line in
+ the shell.
+ @param[in] CommandHandler Pointer to a function that runs the
+ specified command.
+ @param[in] GetManFileName Pointer to a function that provides man
+ filename.
+ @param[in] ShellMinSupportLevel minimum Shell Support Level which has this
+ function.
+ @param[in] ProfileName profile name to require for support of this
+ function.
+ @param[in] CanAffectLE indicates whether this command's return value
+ can change the LASTERROR environment variable.
+ @param[in] HiiHandle Handle of this command's HII entry.
+ @param[in] ManFormatHelp HII locator for the help text.
+
+ @retval RETURN_SUCCESS The handlers were registered.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to
+ register the shell command.
+ @retval RETURN_UNSUPPORTED the ShellMinSupportLevel was higher than the
+ currently allowed support level.
+ @retval RETURN_ALREADY_STARTED The CommandString represents a command that
+ is already registered. Only 1 handler set for
+ a given command is allowed.
+ @sa SHELL_GET_MAN_FILENAME
+ @sa SHELL_RUN_COMMAND
+**/
+RETURN_STATUS
+EFIAPI
+ShellCommandRegisterCommandName (
+ IN CONST CHAR16 *CommandString,
+ IN SHELL_RUN_COMMAND CommandHandler,
+ IN SHELL_GET_MAN_FILENAME GetManFileName,
+ IN UINT32 ShellMinSupportLevel,
+ IN CONST CHAR16 *ProfileName,
+ IN CONST BOOLEAN CanAffectLE,
+ IN CONST EFI_HANDLE HiiHandle,
+ IN CONST EFI_STRING_ID ManFormatHelp
+ )
+{
+ SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
+ SHELL_COMMAND_INTERNAL_LIST_ENTRY *Command;
+ SHELL_COMMAND_INTERNAL_LIST_ENTRY *PrevCommand;
+ INTN LexicalMatchValue;
+
+ //
+ // Initialize local variables.
+ //
+ Command = NULL;
+ PrevCommand = NULL;
+ LexicalMatchValue = 0;
+
+ //
+ // ASSERTs for NULL parameters
+ //
+ ASSERT(CommandString != NULL);
+ ASSERT(GetManFileName != NULL);
+ ASSERT(CommandHandler != NULL);
+ ASSERT(ProfileName != NULL);
+
+ //
+ // check for shell support level
+ //
+ if (PcdGet8(PcdShellSupportLevel) < ShellMinSupportLevel) {
+ return (RETURN_UNSUPPORTED);
+ }
+
+ //
+ // check for already on the list
+ //
+ if (ShellCommandIsCommandOnList(CommandString)) {
+ return (RETURN_ALREADY_STARTED);
+ }
+
+ //
+ // allocate memory for new struct
+ //
+ Node = AllocateZeroPool(sizeof(SHELL_COMMAND_INTERNAL_LIST_ENTRY));
+ if (Node == NULL) {
+ return RETURN_OUT_OF_RESOURCES;
+ }
+ Node->CommandString = AllocateCopyPool(StrSize(CommandString), CommandString);
+ if (Node->CommandString == NULL) {
+ FreePool (Node);
+ return RETURN_OUT_OF_RESOURCES;
+ }
+
+ Node->GetManFileName = GetManFileName;
+ Node->CommandHandler = CommandHandler;
+ Node->LastError = CanAffectLE;
+ Node->HiiHandle = HiiHandle;
+ Node->ManFormatHelp = ManFormatHelp;
+
+ if ( StrLen(ProfileName)>0
+ && ((mProfileList != NULL
+ && StrStr(mProfileList, ProfileName) == NULL) || mProfileList == NULL)
+ ){
+ ASSERT((mProfileList == NULL && mProfileListSize == 0) || (mProfileList != NULL));
+ if (mProfileList == NULL) {
+ //
+ // If this is the first make a leading ';'
+ //
+ StrnCatGrow(&mProfileList, &mProfileListSize, L";", 0);
+ }
+ StrnCatGrow(&mProfileList, &mProfileListSize, ProfileName, 0);
+ StrnCatGrow(&mProfileList, &mProfileListSize, L";", 0);
+ }
+
+ //
+ // Insert a new entry on top of the list
+ //
+ InsertHeadList (&mCommandList.Link, &Node->Link);
+
+ //
+ // Move a new registered command to its sorted ordered location in the list
+ //
+ for (Command = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode (&mCommandList.Link),
+ PrevCommand = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode (&mCommandList.Link)
+ ; !IsNull (&mCommandList.Link, &Command->Link)
+ ; Command = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode (&mCommandList.Link, &Command->Link)) {
+
+ //
+ // Get Lexical Comparison Value between PrevCommand and Command list entry
+ //
+ LexicalMatchValue = gUnicodeCollation->StriColl (
+ gUnicodeCollation,
+ PrevCommand->CommandString,
+ Command->CommandString
+ );
+
+ //
+ // Swap PrevCommand and Command list entry if PrevCommand list entry
+ // is alphabetically greater than Command list entry
+ //
+ if (LexicalMatchValue > 0){
+ Command = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *) SwapListEntries (&PrevCommand->Link, &Command->Link);
+ } else if (LexicalMatchValue < 0) {
+ //
+ // PrevCommand entry is lexically lower than Command entry
+ //
+ break;
+ }
+ }
+
+ return (RETURN_SUCCESS);
+}
+
+/**
+ Function to get the current Profile string.
+
+ @retval NULL There are no installed profiles.
+ @return A semi-colon delimited list of profiles.
+**/
+CONST CHAR16 *
+EFIAPI
+ShellCommandGetProfileList (
+ VOID
+ )
+{
+ return (mProfileList);
+}
+
+/**
+ Checks if a command string has been registered for CommandString and if so it runs
+ the previously registered handler for that command with the command line.
+
+ If CommandString is NULL, then ASSERT().
+
+ If Sections is specified, then each section name listed will be compared in a casesensitive
+ manner, to the section names described in Appendix B UEFI Shell 2.0 spec. If the section exists,
+ it will be appended to the returned help text. If the section does not exist, no
+ information will be returned. If Sections is NULL, then all help text information
+ available will be returned.
+
+ @param[in] CommandString Pointer to the command name. This is the name
+ found on the command line in the shell.
+ @param[in, out] RetVal Pointer to the return vaule from the command handler.
+
+ @param[in, out] CanAffectLE indicates whether this command's return value
+ needs to be placed into LASTERROR environment variable.
+
+ @retval RETURN_SUCCESS The handler was run.
+ @retval RETURN_NOT_FOUND The CommandString did not match a registered
+ command name.
+ @sa SHELL_RUN_COMMAND
+**/
+RETURN_STATUS
+EFIAPI
+ShellCommandRunCommandHandler (
+ IN CONST CHAR16 *CommandString,
+ IN OUT SHELL_STATUS *RetVal,
+ IN OUT BOOLEAN *CanAffectLE OPTIONAL
+ )
+{
+ SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
+ EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *DynamicCommand;
+
+ //
+ // assert for NULL parameters
+ //
+ ASSERT(CommandString != NULL);
+
+ //
+ // check for the command
+ //
+ for ( Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode(&mCommandList.Link)
+ ; !IsNull(&mCommandList.Link, &Node->Link)
+ ; Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode(&mCommandList.Link, &Node->Link)
+ ){
+ ASSERT(Node->CommandString != NULL);
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)CommandString,
+ Node->CommandString) == 0
+ ){
+ if (CanAffectLE != NULL) {
+ *CanAffectLE = Node->LastError;
+ }
+ if (RetVal != NULL) {
+ *RetVal = Node->CommandHandler(NULL, gST);
+ } else {
+ Node->CommandHandler(NULL, gST);
+ }
+ return (RETURN_SUCCESS);
+ }
+ }
+
+ //
+ // An internal command was not found, try to find a dynamic command
+ //
+ DynamicCommand = (EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *)ShellCommandFindDynamicCommand(CommandString);
+ if (DynamicCommand != NULL) {
+ if (RetVal != NULL) {
+ *RetVal = DynamicCommand->Handler(DynamicCommand, gST, gEfiShellParametersProtocol, gEfiShellProtocol);
+ } else {
+ DynamicCommand->Handler(DynamicCommand, gST, gEfiShellParametersProtocol, gEfiShellProtocol);
+ }
+ return (RETURN_SUCCESS);
+ }
+
+ return (RETURN_NOT_FOUND);
+}
+
+/**
+ Checks if a command string has been registered for CommandString and if so it
+ returns the MAN filename specified for that command.
+
+ If CommandString is NULL, then ASSERT().
+
+ @param[in] CommandString Pointer to the command name. This is the name
+ found on the command line in the shell.\
+
+ @retval NULL the commandString was not a registered command.
+ @return other the name of the MAN file.
+ @sa SHELL_GET_MAN_FILENAME
+**/
+CONST CHAR16*
+EFIAPI
+ShellCommandGetManFileNameHandler (
+ IN CONST CHAR16 *CommandString
+ )
+{
+ SHELL_COMMAND_INTERNAL_LIST_ENTRY *Node;
+
+ //
+ // assert for NULL parameters
+ //
+ ASSERT(CommandString != NULL);
+
+ //
+ // check for the command
+ //
+ for ( Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetFirstNode(&mCommandList.Link)
+ ; !IsNull(&mCommandList.Link, &Node->Link)
+ ; Node = (SHELL_COMMAND_INTERNAL_LIST_ENTRY *)GetNextNode(&mCommandList.Link, &Node->Link)
+ ){
+ ASSERT(Node->CommandString != NULL);
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)CommandString,
+ Node->CommandString) == 0
+ ){
+ return (Node->GetManFileName());
+ }
+ }
+ return (NULL);
+}
+
+/**
+ Get the list of all available shell internal commands. This is a linked list
+ (via LIST_ENTRY structure). enumerate through it using the BaseLib linked
+ list functions. do not modify the values.
+
+ @param[in] Sort TRUE to alphabetically sort the values first. FALSE otherwise.
+
+ @return a Linked list of all available shell commands.
+**/
+CONST COMMAND_LIST*
+EFIAPI
+ShellCommandGetCommandList (
+ IN CONST BOOLEAN Sort
+ )
+{
+// if (!Sort) {
+// return ((COMMAND_LIST*)(&mCommandList));
+// }
+ return ((COMMAND_LIST*)(&mCommandList));
+}
+
+/**
+ Registers aliases to be set as part of the initialization of the shell application.
+
+ If Command is NULL, then ASSERT().
+ If Alias is NULL, then ASSERT().
+
+ @param[in] Command Pointer to the Command
+ @param[in] Alias Pointer to Alias
+
+ @retval RETURN_SUCCESS The handlers were registered.
+ @retval RETURN_OUT_OF_RESOURCES There are not enough resources available to
+ register the shell command.
+**/
+RETURN_STATUS
+EFIAPI
+ShellCommandRegisterAlias (
+ IN CONST CHAR16 *Command,
+ IN CONST CHAR16 *Alias
+ )
+{
+ ALIAS_LIST *Node;
+ ALIAS_LIST *CommandAlias;
+ ALIAS_LIST *PrevCommandAlias;
+ INTN LexicalMatchValue;
+
+ //
+ // Asserts for NULL
+ //
+ ASSERT(Command != NULL);
+ ASSERT(Alias != NULL);
+
+ //
+ // allocate memory for new struct
+ //
+ Node = AllocateZeroPool(sizeof(ALIAS_LIST));
+ if (Node == NULL) {
+ return RETURN_OUT_OF_RESOURCES;
+ }
+ Node->CommandString = AllocateCopyPool(StrSize(Command), Command);
+ if (Node->CommandString == NULL) {
+ FreePool (Node);
+ return RETURN_OUT_OF_RESOURCES;
+ }
+ Node->Alias = AllocateCopyPool(StrSize(Alias), Alias);
+ if (Node->Alias == NULL) {
+ FreePool (Node->CommandString);
+ FreePool (Node);
+ return RETURN_OUT_OF_RESOURCES;
+ }
+
+ InsertHeadList (&mAliasList.Link, &Node->Link);
+
+ //
+ // Move a new pre-defined registered alias to its sorted ordered location in the list
+ //
+ for ( CommandAlias = (ALIAS_LIST *)GetFirstNode (&mAliasList.Link),
+ PrevCommandAlias = (ALIAS_LIST *)GetFirstNode (&mAliasList.Link)
+ ; !IsNull (&mAliasList.Link, &CommandAlias->Link)
+ ; CommandAlias = (ALIAS_LIST *) GetNextNode (&mAliasList.Link, &CommandAlias->Link) ) {
+ //
+ // Get Lexical comparison value between PrevCommandAlias and CommandAlias List Entry
+ //
+ LexicalMatchValue = gUnicodeCollation->StriColl (
+ gUnicodeCollation,
+ PrevCommandAlias->Alias,
+ CommandAlias->Alias
+ );
+
+ //
+ // Swap PrevCommandAlias and CommandAlias list entry if PrevCommandAlias list entry
+ // is alphabetically greater than CommandAlias list entry
+ //
+ if (LexicalMatchValue > 0) {
+ CommandAlias = (ALIAS_LIST *) SwapListEntries (&PrevCommandAlias->Link, &CommandAlias->Link);
+ } else if (LexicalMatchValue < 0) {
+ //
+ // PrevCommandAlias entry is lexically lower than CommandAlias entry
+ //
+ break;
+ }
+ }
+
+ return (RETURN_SUCCESS);
+}
+
+/**
+ Get the list of all shell alias commands. This is a linked list
+ (via LIST_ENTRY structure). enumerate through it using the BaseLib linked
+ list functions. do not modify the values.
+
+ @return a Linked list of all requested shell alias'.
+**/
+CONST ALIAS_LIST*
+EFIAPI
+ShellCommandGetInitAliasList (
+ VOID
+ )
+{
+ return (&mAliasList);
+}
+
+/**
+ Determine if a given alias is on the list of built in alias'.
+
+ @param[in] Alias The alias to test for
+
+ @retval TRUE The alias is a built in alias
+ @retval FALSE The alias is not a built in alias
+**/
+BOOLEAN
+EFIAPI
+ShellCommandIsOnAliasList(
+ IN CONST CHAR16 *Alias
+ )
+{
+ ALIAS_LIST *Node;
+
+ //
+ // assert for NULL parameter
+ //
+ ASSERT(Alias != NULL);
+
+ //
+ // check for the Alias
+ //
+ for ( Node = (ALIAS_LIST *)GetFirstNode(&mAliasList.Link)
+ ; !IsNull(&mAliasList.Link, &Node->Link)
+ ; Node = (ALIAS_LIST *)GetNextNode(&mAliasList.Link, &Node->Link)
+ ){
+ ASSERT(Node->CommandString != NULL);
+ ASSERT(Node->Alias != NULL);
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)Alias,
+ Node->CommandString) == 0
+ ){
+ return (TRUE);
+ }
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)Alias,
+ Node->Alias) == 0
+ ){
+ return (TRUE);
+ }
+ }
+ return (FALSE);
+}
+
+/**
+ Function to determine current state of ECHO. Echo determines if lines from scripts
+ and ECHO commands are enabled.
+
+ @retval TRUE Echo is currently enabled
+ @retval FALSE Echo is currently disabled
+**/
+BOOLEAN
+EFIAPI
+ShellCommandGetEchoState(
+ VOID
+ )
+{
+ return (mEchoState);
+}
+
+/**
+ Function to set current state of ECHO. Echo determines if lines from scripts
+ and ECHO commands are enabled.
+
+ If State is TRUE, Echo will be enabled.
+ If State is FALSE, Echo will be disabled.
+
+ @param[in] State How to set echo.
+**/
+VOID
+EFIAPI
+ShellCommandSetEchoState(
+ IN BOOLEAN State
+ )
+{
+ mEchoState = State;
+}
+
+/**
+ Indicate that the current shell or script should exit.
+
+ @param[in] ScriptOnly TRUE if exiting a script; FALSE otherwise.
+ @param[in] ErrorCode The 64 bit error code to return.
+**/
+VOID
+EFIAPI
+ShellCommandRegisterExit (
+ IN BOOLEAN ScriptOnly,
+ IN CONST UINT64 ErrorCode
+ )
+{
+ mExitRequested = (BOOLEAN)(!mExitRequested);
+ if (mExitRequested) {
+ mExitScript = ScriptOnly;
+ } else {
+ mExitScript = FALSE;
+ }
+ mExitCode = ErrorCode;
+}
+
+/**
+ Retrieve the Exit indicator.
+
+ @retval TRUE Exit was indicated.
+ @retval FALSE Exis was not indicated.
+**/
+BOOLEAN
+EFIAPI
+ShellCommandGetExit (
+ VOID
+ )
+{
+ return (mExitRequested);
+}
+
+/**
+ Retrieve the Exit code.
+
+ If ShellCommandGetExit returns FALSE than the return from this is undefined.
+
+ @return the value passed into RegisterExit.
+**/
+UINT64
+EFIAPI
+ShellCommandGetExitCode (
+ VOID
+ )
+{
+ return (mExitCode);
+}
+/**
+ Retrieve the Exit script indicator.
+
+ If ShellCommandGetExit returns FALSE than the return from this is undefined.
+
+ @retval TRUE ScriptOnly was indicated.
+ @retval FALSE ScriptOnly was not indicated.
+**/
+BOOLEAN
+EFIAPI
+ShellCommandGetScriptExit (
+ VOID
+ )
+{
+ return (mExitScript);
+}
+
+/**
+ Function to cleanup all memory from a SCRIPT_FILE structure.
+
+ @param[in] Script The pointer to the structure to cleanup.
+**/
+VOID
+EFIAPI
+DeleteScriptFileStruct (
+ IN SCRIPT_FILE *Script
+ )
+{
+ UINT8 LoopVar;
+
+ if (Script == NULL) {
+ return;
+ }
+
+ for (LoopVar = 0 ; LoopVar < Script->Argc ; LoopVar++) {
+ SHELL_FREE_NON_NULL(Script->Argv[LoopVar]);
+ }
+ if (Script->Argv != NULL) {
+ SHELL_FREE_NON_NULL(Script->Argv);
+ }
+ Script->CurrentCommand = NULL;
+ while (!IsListEmpty (&Script->CommandList)) {
+ Script->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetFirstNode(&Script->CommandList);
+ if (Script->CurrentCommand != NULL) {
+ RemoveEntryList(&Script->CurrentCommand->Link);
+ if (Script->CurrentCommand->Cl != NULL) {
+ SHELL_FREE_NON_NULL(Script->CurrentCommand->Cl);
+ }
+ if (Script->CurrentCommand->Data != NULL) {
+ SHELL_FREE_NON_NULL(Script->CurrentCommand->Data);
+ }
+ SHELL_FREE_NON_NULL(Script->CurrentCommand);
+ }
+ }
+ SHELL_FREE_NON_NULL(Script->ScriptName);
+ SHELL_FREE_NON_NULL(Script);
+}
+
+/**
+ Function to return a pointer to the currently running script file object.
+
+ @retval NULL A script file is not currently running.
+ @return A pointer to the current script file object.
+**/
+SCRIPT_FILE*
+EFIAPI
+ShellCommandGetCurrentScriptFile (
+ VOID
+ )
+{
+ SCRIPT_FILE_LIST *List;
+ if (IsListEmpty (&mScriptList.Link)) {
+ return (NULL);
+ }
+ List = ((SCRIPT_FILE_LIST*)GetFirstNode(&mScriptList.Link));
+ return (List->Data);
+}
+
+/**
+ Function to set a new script as the currently running one.
+
+ This function will correctly stack and unstack nested scripts.
+
+ @param[in] Script Pointer to new script information structure. if NULL
+ will remove and de-allocate the top-most Script structure.
+
+ @return A pointer to the current running script file after this
+ change. NULL if removing the final script.
+**/
+SCRIPT_FILE*
+EFIAPI
+ShellCommandSetNewScript (
+ IN SCRIPT_FILE *Script OPTIONAL
+ )
+{
+ SCRIPT_FILE_LIST *Node;
+ if (Script == NULL) {
+ if (IsListEmpty (&mScriptList.Link)) {
+ return (NULL);
+ }
+ Node = (SCRIPT_FILE_LIST *)GetFirstNode(&mScriptList.Link);
+ RemoveEntryList(&Node->Link);
+ DeleteScriptFileStruct(Node->Data);
+ FreePool(Node);
+ } else {
+ Node = AllocateZeroPool(sizeof(SCRIPT_FILE_LIST));
+ if (Node == NULL) {
+ return (NULL);
+ }
+ Node->Data = Script;
+ InsertHeadList(&mScriptList.Link, &Node->Link);
+ }
+ return (ShellCommandGetCurrentScriptFile());
+}
+
+/**
+ Function to generate the next default mapping name.
+
+ If the return value is not NULL then it must be callee freed.
+
+ @param Type What kind of mapping name to make.
+
+ @retval NULL a memory allocation failed.
+ @return a new map name string
+**/
+CHAR16*
+EFIAPI
+ShellCommandCreateNewMappingName(
+ IN CONST SHELL_MAPPING_TYPE Type
+ )
+{
+ CHAR16 *String;
+ ASSERT(Type < MappingTypeMax);
+
+ String = NULL;
+
+ String = AllocateZeroPool(PcdGet8(PcdShellMapNameLength) * sizeof(String[0]));
+ UnicodeSPrint(
+ String,
+ PcdGet8(PcdShellMapNameLength) * sizeof(String[0]),
+ Type == MappingTypeFileSystem?L"FS%d:":L"BLK%d:",
+ Type == MappingTypeFileSystem?mFsMaxCount++:mBlkMaxCount++);
+
+ return (String);
+}
+
+/**
+ Function to add a map node to the list of map items and update the "path" environment variable (optionally).
+
+ If Path is TRUE (during initialization only), the path environment variable will also be updated to include
+ default paths on the new map name...
+
+ Path should be FALSE when this function is called from the protocol SetMap function.
+
+ @param[in] Name The human readable mapped name.
+ @param[in] DevicePath The Device Path for this map.
+ @param[in] Flags The Flags attribute for this map item.
+ @param[in] Path TRUE to update path, FALSE to skip this step (should only be TRUE during initialization).
+
+ @retval EFI_SUCCESS The addition was sucessful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.
+**/
+EFI_STATUS
+EFIAPI
+ShellCommandAddMapItemAndUpdatePath(
+ IN CONST CHAR16 *Name,
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath,
+ IN CONST UINT64 Flags,
+ IN CONST BOOLEAN Path
+ )
+{
+ EFI_STATUS Status;
+ SHELL_MAP_LIST *MapListNode;
+ CONST CHAR16 *OriginalPath;
+ CHAR16 *NewPath;
+ UINTN NewPathSize;
+
+ NewPathSize = 0;
+ NewPath = NULL;
+ OriginalPath = NULL;
+ Status = EFI_SUCCESS;
+
+ MapListNode = AllocateZeroPool(sizeof(SHELL_MAP_LIST));
+ if (MapListNode == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ MapListNode->Flags = Flags;
+ MapListNode->MapName = AllocateCopyPool(StrSize(Name), Name);
+ MapListNode->DevicePath = DuplicateDevicePath(DevicePath);
+ if ((MapListNode->MapName == NULL) || (MapListNode->DevicePath == NULL)){
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ InsertTailList(&gShellMapList.Link, &MapListNode->Link);
+ }
+ }
+ if (EFI_ERROR(Status)) {
+ if (MapListNode != NULL) {
+ if (MapListNode->DevicePath != NULL) {
+ FreePool(MapListNode->DevicePath);
+ }
+ if (MapListNode->MapName != NULL) {
+ FreePool(MapListNode->MapName);
+ }
+ FreePool(MapListNode);
+ }
+ } else if (Path) {
+ //
+ // Since there was no error and Path was TRUE
+ // Now add the correct path for that mapping
+ //
+ OriginalPath = gEfiShellProtocol->GetEnv(L"path");
+ ASSERT((NewPath == NULL && NewPathSize == 0) || (NewPath != NULL));
+ if (OriginalPath != NULL) {
+ StrnCatGrow(&NewPath, &NewPathSize, OriginalPath, 0);
+ } else {
+ StrnCatGrow(&NewPath, &NewPathSize, L".\\", 0);
+ }
+ StrnCatGrow(&NewPath, &NewPathSize, L";", 0);
+ StrnCatGrow(&NewPath, &NewPathSize, Name, 0);
+ StrnCatGrow(&NewPath, &NewPathSize, L"\\efi\\tools\\;", 0);
+ StrnCatGrow(&NewPath, &NewPathSize, Name, 0);
+ StrnCatGrow(&NewPath, &NewPathSize, L"\\efi\\boot\\;", 0);
+ StrnCatGrow(&NewPath, &NewPathSize, Name, 0);
+ StrnCatGrow(&NewPath, &NewPathSize, L"\\", 0);
+
+ Status = gEfiShellProtocol->SetEnv(L"path", NewPath, TRUE);
+ ASSERT_EFI_ERROR(Status);
+ FreePool(NewPath);
+ }
+ return (Status);
+}
+
+/**
+ Creates the default map names for each device path in the system with
+ a protocol depending on the Type.
+
+ Creates the consistent map names for each device path in the system with
+ a protocol depending on the Type.
+
+ Note: This will reset all mappings in the system("map -r").
+
+ Also sets up the default path environment variable if Type is FileSystem.
+
+ @retval EFI_SUCCESS All map names were created sucessfully.
+ @retval EFI_NOT_FOUND No protocols were found in the system.
+ @return Error returned from gBS->LocateHandle().
+
+ @sa LocateHandle
+**/
+EFI_STATUS
+EFIAPI
+ShellCommandCreateInitialMappingsAndPaths(
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleList;
+ UINTN Count;
+ EFI_DEVICE_PATH_PROTOCOL **DevicePathList;
+ CHAR16 *NewDefaultName;
+ CHAR16 *NewConsistName;
+ EFI_DEVICE_PATH_PROTOCOL **ConsistMappingTable;
+ SHELL_MAP_LIST *MapListNode;
+
+ HandleList = NULL;
+
+ //
+ // Reset the static members back to zero
+ //
+ mFsMaxCount = 0;
+ mBlkMaxCount = 0;
+
+ gEfiShellProtocol->SetEnv(L"path", L"", TRUE);
+
+ //
+ // First empty out the existing list.
+ //
+ if (!IsListEmpty(&gShellMapList.Link)) {
+ for ( MapListNode = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link)
+ ; !IsListEmpty(&gShellMapList.Link)
+ ; MapListNode = (SHELL_MAP_LIST *)GetFirstNode(&gShellMapList.Link)
+ ){
+ RemoveEntryList(&MapListNode->Link);
+ SHELL_FREE_NON_NULL(MapListNode->DevicePath);
+ SHELL_FREE_NON_NULL(MapListNode->MapName);
+ SHELL_FREE_NON_NULL(MapListNode->CurrentDirectoryPath);
+ FreePool(MapListNode);
+ } // for loop
+ }
+
+ //
+ // Find each handle with Simple File System
+ //
+ HandleList = GetHandleListByProtocol(&gEfiSimpleFileSystemProtocolGuid);
+ if (HandleList != NULL) {
+ //
+ // Do a count of the handles
+ //
+ for (Count = 0 ; HandleList[Count] != NULL ; Count++);
+
+ //
+ // Get all Device Paths
+ //
+ DevicePathList = AllocateZeroPool(sizeof(EFI_DEVICE_PATH_PROTOCOL*) * Count);
+ if (DevicePathList == NULL) {
+ SHELL_FREE_NON_NULL (HandleList);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Count = 0 ; HandleList[Count] != NULL ; Count++) {
+ DevicePathList[Count] = DevicePathFromHandle(HandleList[Count]);
+ }
+
+ //
+ // Sort all DevicePaths
+ //
+ PerformQuickSort(DevicePathList, Count, sizeof(EFI_DEVICE_PATH_PROTOCOL*), DevicePathCompare);
+
+ ShellCommandConsistMappingInitialize(&ConsistMappingTable);
+ //
+ // Assign new Mappings to all...
+ //
+ for (Count = 0 ; HandleList[Count] != NULL ; Count++) {
+ //
+ // Get default name first
+ //
+ NewDefaultName = ShellCommandCreateNewMappingName(MappingTypeFileSystem);
+ ASSERT(NewDefaultName != NULL);
+ Status = ShellCommandAddMapItemAndUpdatePath(NewDefaultName, DevicePathList[Count], 0, TRUE);
+ ASSERT_EFI_ERROR(Status);
+ FreePool(NewDefaultName);
+
+ //
+ // Now do consistent name
+ //
+ NewConsistName = ShellCommandConsistMappingGenMappingName(DevicePathList[Count], ConsistMappingTable);
+ if (NewConsistName != NULL) {
+ Status = ShellCommandAddMapItemAndUpdatePath(NewConsistName, DevicePathList[Count], 0, FALSE);
+ ASSERT_EFI_ERROR(Status);
+ FreePool(NewConsistName);
+ }
+ }
+
+ ShellCommandConsistMappingUnInitialize(ConsistMappingTable);
+
+ SHELL_FREE_NON_NULL(HandleList);
+ SHELL_FREE_NON_NULL(DevicePathList);
+
+ HandleList = NULL;
+ } else {
+ Count = (UINTN)-1;
+ }
+
+ //
+ // Find each handle with Block Io
+ //
+ HandleList = GetHandleListByProtocol(&gEfiBlockIoProtocolGuid);
+ if (HandleList != NULL) {
+ for (Count = 0 ; HandleList[Count] != NULL ; Count++);
+
+ //
+ // Get all Device Paths
+ //
+ DevicePathList = AllocateZeroPool(sizeof(EFI_DEVICE_PATH_PROTOCOL*) * Count);
+ if (DevicePathList == NULL) {
+ SHELL_FREE_NON_NULL (HandleList);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Count = 0 ; HandleList[Count] != NULL ; Count++) {
+ DevicePathList[Count] = DevicePathFromHandle(HandleList[Count]);
+ }
+
+ //
+ // Sort all DevicePaths
+ //
+ PerformQuickSort(DevicePathList, Count, sizeof(EFI_DEVICE_PATH_PROTOCOL*), DevicePathCompare);
+
+ //
+ // Assign new Mappings to all...
+ //
+ for (Count = 0 ; HandleList[Count] != NULL ; Count++) {
+ //
+ // Get default name first
+ //
+ NewDefaultName = ShellCommandCreateNewMappingName(MappingTypeBlockIo);
+ ASSERT(NewDefaultName != NULL);
+ Status = ShellCommandAddMapItemAndUpdatePath(NewDefaultName, DevicePathList[Count], 0, FALSE);
+ ASSERT_EFI_ERROR(Status);
+ FreePool(NewDefaultName);
+ }
+
+ SHELL_FREE_NON_NULL(HandleList);
+ SHELL_FREE_NON_NULL(DevicePathList);
+ } else if (Count == (UINTN)-1) {
+ return (EFI_NOT_FOUND);
+ }
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Add mappings for any devices without one. Do not change any existing maps.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+ShellCommandUpdateMapping (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleList;
+ UINTN Count;
+ EFI_DEVICE_PATH_PROTOCOL **DevicePathList;
+ CHAR16 *NewDefaultName;
+ CHAR16 *NewConsistName;
+ EFI_DEVICE_PATH_PROTOCOL **ConsistMappingTable;
+
+ HandleList = NULL;
+ Status = EFI_SUCCESS;
+
+ //
+ // remove mappings that represent removed devices.
+ //
+
+ //
+ // Find each handle with Simple File System
+ //
+ HandleList = GetHandleListByProtocol(&gEfiSimpleFileSystemProtocolGuid);
+ if (HandleList != NULL) {
+ //
+ // Do a count of the handles
+ //
+ for (Count = 0 ; HandleList[Count] != NULL ; Count++);
+
+ //
+ // Get all Device Paths
+ //
+ DevicePathList = AllocateZeroPool(sizeof(EFI_DEVICE_PATH_PROTOCOL*) * Count);
+ if (DevicePathList == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ for (Count = 0 ; HandleList[Count] != NULL ; Count++) {
+ DevicePathList[Count] = DevicePathFromHandle(HandleList[Count]);
+ }
+
+ //
+ // Sort all DevicePaths
+ //
+ PerformQuickSort(DevicePathList, Count, sizeof(EFI_DEVICE_PATH_PROTOCOL*), DevicePathCompare);
+
+ ShellCommandConsistMappingInitialize(&ConsistMappingTable);
+
+ //
+ // Assign new Mappings to remainders
+ //
+ for (Count = 0 ; !EFI_ERROR(Status) && HandleList[Count] != NULL && !EFI_ERROR(Status); Count++) {
+ //
+ // Skip ones that already have
+ //
+ if (gEfiShellProtocol->GetMapFromDevicePath(&DevicePathList[Count]) != NULL) {
+ continue;
+ }
+ //
+ // Get default name
+ //
+ NewDefaultName = ShellCommandCreateNewMappingName(MappingTypeFileSystem);
+ if (NewDefaultName == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ break;
+ }
+
+ //
+ // Call shell protocol SetMap function now...
+ //
+ Status = gEfiShellProtocol->SetMap(DevicePathList[Count], NewDefaultName);
+
+ if (!EFI_ERROR(Status)) {
+ //
+ // Now do consistent name
+ //
+ NewConsistName = ShellCommandConsistMappingGenMappingName(DevicePathList[Count], ConsistMappingTable);
+ if (NewConsistName != NULL) {
+ Status = gEfiShellProtocol->SetMap(DevicePathList[Count], NewConsistName);
+ FreePool(NewConsistName);
+ }
+ }
+
+ FreePool(NewDefaultName);
+ }
+ ShellCommandConsistMappingUnInitialize(ConsistMappingTable);
+ SHELL_FREE_NON_NULL(HandleList);
+ SHELL_FREE_NON_NULL(DevicePathList);
+
+ HandleList = NULL;
+ } else {
+ Count = (UINTN)-1;
+ }
+ //
+ // Do it all over again for gEfiBlockIoProtocolGuid
+ //
+
+ return (Status);
+}
+
+/**
+ Converts a SHELL_FILE_HANDLE to an EFI_FILE_PROTOCOL*.
+
+ @param[in] Handle The SHELL_FILE_HANDLE to convert.
+
+ @return a EFI_FILE_PROTOCOL* representing the same file.
+**/
+EFI_FILE_PROTOCOL*
+EFIAPI
+ConvertShellHandleToEfiFileProtocol(
+ IN CONST SHELL_FILE_HANDLE Handle
+ )
+{
+ return ((EFI_FILE_PROTOCOL*)(Handle));
+}
+
+/**
+ Converts a EFI_FILE_PROTOCOL* to an SHELL_FILE_HANDLE.
+
+ @param[in] Handle The pointer to EFI_FILE_PROTOCOL to convert.
+ @param[in] Path The path to the file for verification.
+
+ @return A SHELL_FILE_HANDLE representing the same file.
+ @retval NULL There was not enough memory.
+**/
+SHELL_FILE_HANDLE
+EFIAPI
+ConvertEfiFileProtocolToShellHandle(
+ IN CONST EFI_FILE_PROTOCOL *Handle,
+ IN CONST CHAR16 *Path
+ )
+{
+ SHELL_COMMAND_FILE_HANDLE *Buffer;
+ BUFFER_LIST *NewNode;
+
+ if (Path != NULL) {
+ Buffer = AllocateZeroPool(sizeof(SHELL_COMMAND_FILE_HANDLE));
+ if (Buffer == NULL) {
+ return (NULL);
+ }
+ NewNode = AllocateZeroPool(sizeof(BUFFER_LIST));
+ if (NewNode == NULL) {
+ SHELL_FREE_NON_NULL(Buffer);
+ return (NULL);
+ }
+ Buffer->FileHandle = (EFI_FILE_PROTOCOL*)Handle;
+ Buffer->Path = StrnCatGrow(&Buffer->Path, NULL, Path, 0);
+ if (Buffer->Path == NULL) {
+ SHELL_FREE_NON_NULL(NewNode);
+ SHELL_FREE_NON_NULL(Buffer);
+ return (NULL);
+ }
+ NewNode->Buffer = Buffer;
+
+ InsertHeadList(&mFileHandleList.Link, &NewNode->Link);
+ }
+ return ((SHELL_FILE_HANDLE)(Handle));
+}
+
+/**
+ Find the path that was logged with the specified SHELL_FILE_HANDLE.
+
+ @param[in] Handle The SHELL_FILE_HANDLE to query on.
+
+ @return A pointer to the path for the file.
+**/
+CONST CHAR16*
+EFIAPI
+ShellFileHandleGetPath(
+ IN CONST SHELL_FILE_HANDLE Handle
+ )
+{
+ BUFFER_LIST *Node;
+
+ for (Node = (BUFFER_LIST*)GetFirstNode(&mFileHandleList.Link)
+ ; !IsNull(&mFileHandleList.Link, &Node->Link)
+ ; Node = (BUFFER_LIST*)GetNextNode(&mFileHandleList.Link, &Node->Link)
+ ){
+ if ((Node->Buffer) && (((SHELL_COMMAND_FILE_HANDLE *)Node->Buffer)->FileHandle == Handle)){
+ return (((SHELL_COMMAND_FILE_HANDLE *)Node->Buffer)->Path);
+ }
+ }
+ return (NULL);
+}
+
+/**
+ Remove a SHELL_FILE_HANDLE from the list of SHELL_FILE_HANDLES.
+
+ @param[in] Handle The SHELL_FILE_HANDLE to remove.
+
+ @retval TRUE The item was removed.
+ @retval FALSE The item was not found.
+**/
+BOOLEAN
+EFIAPI
+ShellFileHandleRemove(
+ IN CONST SHELL_FILE_HANDLE Handle
+ )
+{
+ BUFFER_LIST *Node;
+
+ for (Node = (BUFFER_LIST*)GetFirstNode(&mFileHandleList.Link)
+ ; !IsNull(&mFileHandleList.Link, &Node->Link)
+ ; Node = (BUFFER_LIST*)GetNextNode(&mFileHandleList.Link, &Node->Link)
+ ){
+ if ((Node->Buffer) && (((SHELL_COMMAND_FILE_HANDLE *)Node->Buffer)->FileHandle == Handle)){
+ RemoveEntryList(&Node->Link);
+ SHELL_FREE_NON_NULL(((SHELL_COMMAND_FILE_HANDLE *)Node->Buffer)->Path);
+ SHELL_FREE_NON_NULL(Node->Buffer);
+ SHELL_FREE_NON_NULL(Node);
+ return (TRUE);
+ }
+ }
+ return (FALSE);
+}
+
+/**
+ Function to determine if a SHELL_FILE_HANDLE is at the end of the file.
+
+ This will NOT work on directories.
+
+ If Handle is NULL, then ASSERT.
+
+ @param[in] Handle the file handle
+
+ @retval TRUE the position is at the end of the file
+ @retval FALSE the position is not at the end of the file
+**/
+BOOLEAN
+EFIAPI
+ShellFileHandleEof(
+ IN SHELL_FILE_HANDLE Handle
+ )
+{
+ EFI_FILE_INFO *Info;
+ UINT64 Pos;
+ BOOLEAN RetVal;
+
+ //
+ // ASSERT if Handle is NULL
+ //
+ ASSERT(Handle != NULL);
+
+ gEfiShellProtocol->GetFilePosition(Handle, &Pos);
+ Info = gEfiShellProtocol->GetFileInfo (Handle);
+ gEfiShellProtocol->SetFilePosition(Handle, Pos);
+
+ if (Info == NULL) {
+ return (FALSE);
+ }
+
+ if (Pos == Info->FileSize) {
+ RetVal = TRUE;
+ } else {
+ RetVal = FALSE;
+ }
+
+ FreePool (Info);
+
+ return (RetVal);
+}
+
+/**
+ Function to get the original CmdLine string for current command.
+
+ @return A pointer to the buffer of the original command string.
+ It's the caller's responsibility to free the buffer.
+**/
+CHAR16*
+EFIAPI
+ShellGetRawCmdLine (
+ VOID
+ )
+{
+ if (mRawCmdLine == NULL) {
+ return NULL;
+ } else {
+ return AllocateCopyPool(StrSize(mRawCmdLine), mRawCmdLine);
+ }
+}
+
+/**
+ Function to store the raw command string.
+
+ The alias and variables have been replaced and spaces are trimmed.
+
+ @param[in] CmdLine the command line string to store.
+**/
+VOID
+EFIAPI
+ShellSetRawCmdLine (
+ IN CONST CHAR16 *CmdLine
+ )
+{
+ SHELL_FREE_NON_NULL(mRawCmdLine);
+
+ if (CmdLine != NULL) {
+ //
+ // The spaces in the beginning and end are trimmed.
+ //
+ ASSERT (*CmdLine != L' ');
+ ASSERT (CmdLine[StrLen (CmdLine) - 1] != L' ');
+ mRawCmdLine = AllocateCopyPool (StrSize(CmdLine), CmdLine);
+ }
+}
+
+/**
+ Frees any BUFFER_LIST defined type.
+
+ @param[in] List The BUFFER_LIST object to free.
+**/
+VOID
+EFIAPI
+FreeBufferList (
+ IN BUFFER_LIST *List
+ )
+{
+ BUFFER_LIST *BufferListEntry;
+
+ if (List == NULL){
+ return;
+ }
+ //
+ // enumerate through the buffer list and free all memory
+ //
+ for ( BufferListEntry = ( BUFFER_LIST *)GetFirstNode(&List->Link)
+ ; !IsListEmpty (&List->Link)
+ ; BufferListEntry = (BUFFER_LIST *)GetFirstNode(&List->Link)
+ ){
+ RemoveEntryList(&BufferListEntry->Link);
+ if (BufferListEntry->Buffer != NULL) {
+ FreePool(BufferListEntry->Buffer);
+ }
+ FreePool(BufferListEntry);
+ }
+}
+
+/**
+ Dump some hexadecimal data to the screen.
+
+ @param[in] Indent How many spaces to indent the output.
+ @param[in] Offset The offset of the printing.
+ @param[in] DataSize The size in bytes of UserData.
+ @param[in] UserData The data to print out.
+**/
+VOID
+DumpHex (
+ IN UINTN Indent,
+ IN UINTN Offset,
+ IN UINTN DataSize,
+ IN VOID *UserData
+ )
+{
+ UINT8 *Data;
+
+ CHAR8 Val[50];
+
+ CHAR8 Str[20];
+
+ UINT8 TempByte;
+ UINTN Size;
+ UINTN Index;
+
+ Data = UserData;
+ while (DataSize != 0) {
+ Size = 16;
+ if (Size > DataSize) {
+ Size = DataSize;
+ }
+
+ for (Index = 0; Index < Size; Index += 1) {
+ TempByte = Data[Index];
+ Val[Index * 3 + 0] = Hex[TempByte >> 4];
+ Val[Index * 3 + 1] = Hex[TempByte & 0xF];
+ Val[Index * 3 + 2] = (CHAR8) ((Index == 7) ? '-' : ' ');
+ Str[Index] = (CHAR8) ((TempByte < ' ' || TempByte > 'z') ? '.' : TempByte);
+ }
+
+ Val[Index * 3] = 0;
+ Str[Index] = 0;
+ ShellPrintEx(-1, -1, L"%*a%08X: %-48a *%a*\r\n", Indent, "", Offset, Val, Str);
+
+ Data += Size;
+ Offset += Size;
+ DataSize -= Size;
+ }
+}
+
+/**
+ Dump HEX data into buffer.
+
+ @param[in] Buffer HEX data to be dumped in Buffer.
+ @param[in] Indent How many spaces to indent the output.
+ @param[in] Offset The offset of the printing.
+ @param[in] DataSize The size in bytes of UserData.
+ @param[in] UserData The data to print out.
+**/
+CHAR16*
+CatSDumpHex (
+ IN CHAR16 *Buffer,
+ IN UINTN Indent,
+ IN UINTN Offset,
+ IN UINTN DataSize,
+ IN VOID *UserData
+ )
+{
+ UINT8 *Data;
+ UINT8 TempByte;
+ UINTN Size;
+ UINTN Index;
+ CHAR8 Val[50];
+ CHAR8 Str[20];
+ CHAR16 *RetVal;
+ CHAR16 *TempRetVal;
+
+ Data = UserData;
+ RetVal = Buffer;
+ while (DataSize != 0) {
+ Size = 16;
+ if (Size > DataSize) {
+ Size = DataSize;
+ }
+
+ for (Index = 0; Index < Size; Index += 1) {
+ TempByte = Data[Index];
+ Val[Index * 3 + 0] = Hex[TempByte >> 4];
+ Val[Index * 3 + 1] = Hex[TempByte & 0xF];
+ Val[Index * 3 + 2] = (CHAR8) ((Index == 7) ? '-' : ' ');
+ Str[Index] = (CHAR8) ((TempByte < ' ' || TempByte > 'z') ? '.' : TempByte);
+ }
+
+ Val[Index * 3] = 0;
+ Str[Index] = 0;
+ TempRetVal = CatSPrint (RetVal, L"%*a%08X: %-48a *%a*\r\n", Indent, "", Offset, Val, Str);
+ SHELL_FREE_NON_NULL (RetVal);
+ RetVal = TempRetVal;
+
+ Data += Size;
+ Offset += Size;
+ DataSize -= Size;
+ }
+
+ return RetVal;
+}
diff --git a/Core/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h b/Core/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h
new file mode 100644
index 0000000000..faf2f51662
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.h
@@ -0,0 +1,71 @@
+/** @file
+ Provides interface to shell internal functions for shell commands.
+
+ Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved. <BR>
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _UEFI_COMMAND_LIB_INTERNAL_HEADER_
+#define _UEFI_COMMAND_LIB_INTERNAL_HEADER_
+
+#include <Uefi.h>
+#include <ShellBase.h>
+
+#include <Guid/FileInfo.h>
+
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/EfiShellInterface.h>
+#include <Protocol/EfiShellEnvironment2.h>
+#include <Protocol/EfiShell.h>
+#include <Protocol/EfiShellParameters.h>
+#include <Protocol/UnicodeCollation.h>
+#include <Protocol/BlockIo.h>
+#include <Protocol/EfiShellDynamicCommand.h>
+
+#include <Library/DevicePathLib.h>
+#include <Library/SortLib.h>
+#include <Library/HandleParsingLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/ShellCommandLib.h>
+#include <Library/PrintLib.h>
+#include <Library/ShellLib.h>
+#include <Library/HiiLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/UefiLib.h>
+
+typedef struct{
+ LIST_ENTRY Link;
+ CHAR16 *CommandString;
+ SHELL_GET_MAN_FILENAME GetManFileName;
+ SHELL_RUN_COMMAND CommandHandler;
+ BOOLEAN LastError;
+ EFI_HANDLE HiiHandle;
+ EFI_STRING_ID ManFormatHelp;
+} SHELL_COMMAND_INTERNAL_LIST_ENTRY;
+
+typedef struct {
+ LIST_ENTRY Link;
+ SCRIPT_FILE *Data;
+} SCRIPT_FILE_LIST;
+
+typedef struct {
+ EFI_FILE_PROTOCOL *FileHandle;
+ CHAR16 *Path;
+} SHELL_COMMAND_FILE_HANDLE;
+
+
+#endif //_UEFI_COMMAND_LIB_INTERNAL_HEADER_
+
diff --git a/Core/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf b/Core/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
new file mode 100644
index 0000000000..b73b5c0e06
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
@@ -0,0 +1,69 @@
+## @file
+# Provides interface to shell internal functions for shell commands.
+#
+# Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved. <BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = UefiShellCommandLib
+ FILE_GUID = 5C12F31F-EBAC-466e-A400-FCA8C9EA3A05
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.1
+ LIBRARY_CLASS = ShellCommandLib|UEFI_APPLICATION UEFI_DRIVER DXE_RUNTIME_DRIVER
+ CONSTRUCTOR = ShellCommandLibConstructor
+ DESTRUCTOR = ShellCommandLibDestructor
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ UefiShellCommandLib.c
+ UefiShellCommandLib.h
+ ConsistMapping.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ PrintLib
+ UefiBootServicesTableLib
+ ShellLib
+ HiiLib
+ HandleParsingLib
+
+[Protocols]
+ gEfiUnicodeCollation2ProtocolGuid ## CONSUMES
+ gEfiShellProtocolGuid ## CONSUMES
+ gEfiShellParametersProtocolGuid ## CONSUMES
+ gEfiShellDynamicCommandProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiUsbIoProtocolGuid ## SOMETIMES_CONSUMES
+
+[Guids]
+ gEfiSasDevicePathGuid ## SOMETIMES_CONSUMES ## GUID
+
+[Pcd.common]
+ gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel ## CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdShellMapNameLength ## CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdUsbExtendedDecode ## SOMETIMES_CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdShellDecodeIScsiMapNames ## SOMETIMES_CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdShellVendorExtendedDecode ## SOMETIMES_CONSUMES
+
+[Depex]
+ gEfiUnicodeCollation2ProtocolGuid
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Comp.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Comp.c
new file mode 100644
index 0000000000..2ab7dd3a5a
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Comp.c
@@ -0,0 +1,277 @@
+/** @file
+ Main file for Comp shell Debug1 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDebug1CommandsLib.h"
+
+/**
+ Function for 'comp' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunComp (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ UINTN LoopVar;
+ SHELL_FILE_HANDLE FileHandle1;
+ SHELL_FILE_HANDLE FileHandle2;
+ UINT8 ErrorCount;
+ UINT64 Size1;
+ UINT64 Size2;
+ UINT8 DataFromFile1;
+ UINT8 DataFromFile2;
+ UINT8 ADF_File11;
+ UINT8 ADF_File12;
+ UINT8 ADF_File13;
+ UINT8 ADF_File21;
+ UINT8 ADF_File22;
+ UINT8 ADF_File23;
+ UINTN DataSizeFromFile1;
+ UINTN DataSizeFromFile2;
+ CHAR16 *FileName1;
+ CHAR16 *FileName2;
+ CONST CHAR16 *TempParam;
+ UINTN ErrorAddress;
+
+ ErrorCount = 0;
+ ShellStatus = SHELL_SUCCESS;
+ Status = EFI_SUCCESS;
+ FileName1 = NULL;
+ FileName2 = NULL;
+ FileHandle1 = NULL;
+ FileHandle2 = NULL;
+ Size1 = 0;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"comp", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetCount(Package) > 3) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"comp");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetCount(Package) < 3) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"comp");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ TempParam = ShellCommandLineGetRawValue(Package, 1);
+ ASSERT(TempParam != NULL);
+ FileName1 = ShellFindFilePath(TempParam);
+ if (FileName1 == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_FIND_FAIL), gShellDebug1HiiHandle, L"comp", TempParam);
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ Status = ShellOpenFileByName(FileName1, &FileHandle1, EFI_FILE_MODE_READ, 0);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"comp", TempParam);
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ }
+ TempParam = ShellCommandLineGetRawValue(Package, 2);
+ ASSERT(TempParam != NULL);
+ FileName2 = ShellFindFilePath(TempParam);
+ if (FileName2 == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_FIND_FAIL), gShellDebug1HiiHandle, L"comp", TempParam);
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ Status = ShellOpenFileByName(FileName2, &FileHandle2, EFI_FILE_MODE_READ, 0);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"comp", TempParam);
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ }
+ if (ShellStatus == SHELL_SUCCESS) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_COMP_HEADER), gShellDebug1HiiHandle, FileName1, FileName2);
+ Status = gEfiShellProtocol->GetFileSize(FileHandle1, &Size1);
+ ASSERT_EFI_ERROR(Status);
+ Status = gEfiShellProtocol->GetFileSize(FileHandle2, &Size2);
+ ASSERT_EFI_ERROR(Status);
+ if (Size1 != Size2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_COMP_SIZE_FAIL), gShellDebug1HiiHandle);
+ ErrorCount++;
+ ShellStatus = SHELL_NOT_EQUAL;
+ }
+ }
+ if (ShellStatus == SHELL_SUCCESS) {
+ for (LoopVar = 0 ; LoopVar < Size1 && ErrorCount <= 10 ; LoopVar++) {
+ DataSizeFromFile1 = 1;
+ DataSizeFromFile2 = 1;
+ Status = gEfiShellProtocol->ReadFile(FileHandle1, &DataSizeFromFile1, &DataFromFile1);
+ ASSERT_EFI_ERROR(Status);
+ Status = gEfiShellProtocol->ReadFile(FileHandle2, &DataSizeFromFile2, &DataFromFile2);
+ ASSERT_EFI_ERROR(Status);
+ if (DataFromFile1 != DataFromFile2) {
+ ErrorAddress = LoopVar;
+ ADF_File11 = 0;
+ ADF_File12 = 0;
+ ADF_File13 = 0;
+ ADF_File21 = 0;
+ ADF_File22 = 0;
+ ADF_File23 = 0;
+
+ //
+ // Now check the next 3 bytes if possible. This will make output
+ // cleaner when there are a sequence of differences.
+ //
+ if (LoopVar + 1 < Size1) {
+ LoopVar++;
+ DataSizeFromFile1 = 1;
+ DataSizeFromFile2 = 1;
+ Status = gEfiShellProtocol->ReadFile(FileHandle1, &DataSizeFromFile1, &ADF_File11);
+ ASSERT_EFI_ERROR(Status);
+ Status = gEfiShellProtocol->ReadFile(FileHandle2, &DataSizeFromFile2, &ADF_File21);
+ ASSERT_EFI_ERROR(Status);
+ if (LoopVar + 1 < Size1) {
+ LoopVar++;
+ DataSizeFromFile1 = 1;
+ DataSizeFromFile2 = 1;
+ Status = gEfiShellProtocol->ReadFile(FileHandle1, &DataSizeFromFile1, &ADF_File12);
+ ASSERT_EFI_ERROR(Status);
+ Status = gEfiShellProtocol->ReadFile(FileHandle2, &DataSizeFromFile2, &ADF_File22);
+ ASSERT_EFI_ERROR(Status);
+ if (LoopVar + 1 < Size1) {
+ LoopVar++;
+ DataSizeFromFile1 = 1;
+ DataSizeFromFile2 = 1;
+ Status = gEfiShellProtocol->ReadFile(FileHandle1, &DataSizeFromFile1, &ADF_File13);
+ ASSERT_EFI_ERROR(Status);
+ Status = gEfiShellProtocol->ReadFile(FileHandle2, &DataSizeFromFile2, &ADF_File23);
+ ASSERT_EFI_ERROR(Status);
+ }
+ }
+ }
+
+ //
+ // Print out based on highest of the 4 bytes that are different.
+ //
+ if (ADF_File13 != ADF_File23) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_COMP_SPOT_FAIL4),
+ gShellDebug1HiiHandle,
+ ++ErrorCount,
+ FileName1,
+ ErrorAddress,
+ DataFromFile1, ADF_File11, ADF_File12, ADF_File13,
+ DataFromFile1, ADF_File11, ADF_File12, ADF_File13,
+ FileName2,
+ ErrorAddress,
+ DataFromFile2, ADF_File21, ADF_File22, ADF_File23,
+ DataFromFile2, ADF_File21, ADF_File22, ADF_File23
+ );
+ } else if (ADF_File12 != ADF_File22) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_COMP_SPOT_FAIL3),
+ gShellDebug1HiiHandle,
+ ++ErrorCount,
+ FileName1,
+ ErrorAddress,
+ DataFromFile1, ADF_File11, ADF_File12,
+ DataFromFile1, ADF_File11, ADF_File12,
+ FileName2,
+ ErrorAddress,
+ DataFromFile2, ADF_File21, ADF_File22,
+ DataFromFile2, ADF_File21, ADF_File22
+ );
+ } else if (ADF_File11 != ADF_File21) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_COMP_SPOT_FAIL2),
+ gShellDebug1HiiHandle,
+ ++ErrorCount,
+ FileName1,
+ ErrorAddress,
+ DataFromFile1, ADF_File11,
+ DataFromFile1, ADF_File11,
+ FileName2,
+ ErrorAddress,
+ DataFromFile2, ADF_File21,
+ DataFromFile2, ADF_File21
+ );
+ } else {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_COMP_SPOT_FAIL1),
+ gShellDebug1HiiHandle,
+ ++ErrorCount,
+ FileName1,
+ ErrorAddress,
+ DataFromFile1,
+ DataFromFile1,
+ FileName2,
+ ErrorAddress,
+ DataFromFile2,
+ DataFromFile2
+ );
+ }
+ ShellStatus = SHELL_NOT_EQUAL;
+ }
+ }
+ if (ErrorCount == 0) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_COMP_FOOTER_PASS), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_COMP_FOOTER_FAIL), gShellDebug1HiiHandle);
+ }
+ }
+ }
+
+ ShellCommandLineFreeVarList (Package);
+ }
+ SHELL_FREE_NON_NULL(FileName1);
+ SHELL_FREE_NON_NULL(FileName2);
+
+ if (FileHandle1 != NULL) {
+ gEfiShellProtocol->CloseFile(FileHandle1);
+ }
+ if (FileHandle2 != NULL) {
+ gEfiShellProtocol->CloseFile(FileHandle2);
+ }
+
+ return (ShellStatus);
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Compress.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Compress.c
new file mode 100644
index 0000000000..2106185798
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Compress.c
@@ -0,0 +1,1417 @@
+/** @file
+ Main file for compression routine.
+
+ Compression routine. The compression algorithm is a mixture of
+ LZ77 and Huffman coding. LZ77 transforms the source data into a
+ sequence of Original Characters and Pointers to repeated strings.
+ This sequence is further divided into Blocks and Huffman codings
+ are applied to each Block.
+
+ Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/MemoryAllocationLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <ShellBase.h>
+#include <Uefi.h>
+
+//
+// Macro Definitions
+//
+typedef INT16 NODE;
+#define UINT8_MAX 0xff
+#define UINT8_BIT 8
+#define THRESHOLD 3
+#define INIT_CRC 0
+#define WNDBIT 13
+#define WNDSIZ (1U << WNDBIT)
+#define MAXMATCH 256
+#define BLKSIZ (1U << 14) // 16 * 1024U
+#define PERC_FLAG 0x8000U
+#define CODE_BIT 16
+#define NIL 0
+#define MAX_HASH_VAL (3 * WNDSIZ + (WNDSIZ / 512 + 1) * UINT8_MAX)
+#define HASH(LoopVar7, LoopVar5) ((LoopVar7) + ((LoopVar5) << (WNDBIT - 9)) + WNDSIZ * 2)
+#define CRCPOLY 0xA001
+#define UPDATE_CRC(LoopVar5) mCrc = mCrcTable[(mCrc ^ (LoopVar5)) & 0xFF] ^ (mCrc >> UINT8_BIT)
+
+//
+// C: the Char&Len Set; P: the Position Set; T: the exTra Set
+//
+#define NC (UINT8_MAX + MAXMATCH + 2 - THRESHOLD)
+#define CBIT 9
+#define NP (WNDBIT + 1)
+#define PBIT 4
+#define NT (CODE_BIT + 3)
+#define TBIT 5
+#if NT > NP
+ #define NPT NT
+#else
+ #define NPT NP
+#endif
+//
+// Function Prototypes
+//
+
+/**
+ Put a dword to output stream
+
+ @param[in] Data The dword to put.
+**/
+VOID
+EFIAPI
+PutDword(
+ IN UINT32 Data
+ );
+
+//
+// Global Variables
+//
+STATIC UINT8 *mSrc;
+STATIC UINT8 *mDst;
+STATIC UINT8 *mSrcUpperLimit;
+STATIC UINT8 *mDstUpperLimit;
+
+STATIC UINT8 *mLevel;
+STATIC UINT8 *mText;
+STATIC UINT8 *mChildCount;
+STATIC UINT8 *mBuf;
+STATIC UINT8 mCLen[NC];
+STATIC UINT8 mPTLen[NPT];
+STATIC UINT8 *mLen;
+STATIC INT16 mHeap[NC + 1];
+STATIC INT32 mRemainder;
+STATIC INT32 mMatchLen;
+STATIC INT32 mBitCount;
+STATIC INT32 mHeapSize;
+STATIC INT32 mTempInt32;
+STATIC UINT32 mBufSiz = 0;
+STATIC UINT32 mOutputPos;
+STATIC UINT32 mOutputMask;
+STATIC UINT32 mSubBitBuf;
+STATIC UINT32 mCrc;
+STATIC UINT32 mCompSize;
+STATIC UINT32 mOrigSize;
+
+STATIC UINT16 *mFreq;
+STATIC UINT16 *mSortPtr;
+STATIC UINT16 mLenCnt[17];
+STATIC UINT16 mLeft[2 * NC - 1];
+STATIC UINT16 mRight[2 * NC - 1];
+STATIC UINT16 mCrcTable[UINT8_MAX + 1];
+STATIC UINT16 mCFreq[2 * NC - 1];
+STATIC UINT16 mCCode[NC];
+STATIC UINT16 mPFreq[2 * NP - 1];
+STATIC UINT16 mPTCode[NPT];
+STATIC UINT16 mTFreq[2 * NT - 1];
+
+STATIC NODE mPos;
+STATIC NODE mMatchPos;
+STATIC NODE mAvail;
+STATIC NODE *mPosition;
+STATIC NODE *mParent;
+STATIC NODE *mPrev;
+STATIC NODE *mNext = NULL;
+INT32 mHuffmanDepth = 0;
+
+/**
+ Make a CRC table.
+
+**/
+VOID
+EFIAPI
+MakeCrcTable (
+ VOID
+ )
+{
+ UINT32 LoopVar1;
+
+ UINT32 LoopVar2;
+
+ UINT32 LoopVar4;
+
+ for (LoopVar1 = 0; LoopVar1 <= UINT8_MAX; LoopVar1++) {
+ LoopVar4 = LoopVar1;
+ for (LoopVar2 = 0; LoopVar2 < UINT8_BIT; LoopVar2++) {
+ if ((LoopVar4 & 1) != 0) {
+ LoopVar4 = (LoopVar4 >> 1) ^ CRCPOLY;
+ } else {
+ LoopVar4 >>= 1;
+ }
+ }
+
+ mCrcTable[LoopVar1] = (UINT16) LoopVar4;
+ }
+}
+
+/**
+ Put a dword to output stream
+
+ @param[in] Data The dword to put.
+**/
+VOID
+EFIAPI
+PutDword (
+ IN UINT32 Data
+ )
+{
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = (UINT8) (((UINT8) (Data)) & 0xff);
+ }
+
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = (UINT8) (((UINT8) (Data >> 0x08)) & 0xff);
+ }
+
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = (UINT8) (((UINT8) (Data >> 0x10)) & 0xff);
+ }
+
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = (UINT8) (((UINT8) (Data >> 0x18)) & 0xff);
+ }
+}
+
+/**
+ Allocate memory spaces for data structures used in compression process.
+
+ @retval EFI_SUCCESS Memory was allocated successfully.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+AllocateMemory (
+ VOID
+ )
+{
+ mText = AllocateZeroPool (WNDSIZ * 2 + MAXMATCH);
+ mLevel = AllocateZeroPool ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mLevel));
+ mChildCount = AllocateZeroPool ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mChildCount));
+ mPosition = AllocateZeroPool ((WNDSIZ + UINT8_MAX + 1) * sizeof (*mPosition));
+ mParent = AllocateZeroPool (WNDSIZ * 2 * sizeof (*mParent));
+ mPrev = AllocateZeroPool (WNDSIZ * 2 * sizeof (*mPrev));
+ mNext = AllocateZeroPool ((MAX_HASH_VAL + 1) * sizeof (*mNext));
+
+ mBufSiz = BLKSIZ;
+ mBuf = AllocateZeroPool (mBufSiz);
+ while (mBuf == NULL) {
+ mBufSiz = (mBufSiz / 10U) * 9U;
+ if (mBufSiz < 4 * 1024U) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ mBuf = AllocateZeroPool (mBufSiz);
+ }
+
+ mBuf[0] = 0;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Called when compression is completed to free memory previously allocated.
+
+**/
+VOID
+EFIAPI
+FreeMemory (
+ VOID
+ )
+{
+ SHELL_FREE_NON_NULL (mText);
+ SHELL_FREE_NON_NULL (mLevel);
+ SHELL_FREE_NON_NULL (mChildCount);
+ SHELL_FREE_NON_NULL (mPosition);
+ SHELL_FREE_NON_NULL (mParent);
+ SHELL_FREE_NON_NULL (mPrev);
+ SHELL_FREE_NON_NULL (mNext);
+ SHELL_FREE_NON_NULL (mBuf);
+}
+
+/**
+ Initialize String Info Log data structures.
+**/
+VOID
+EFIAPI
+InitSlide (
+ VOID
+ )
+{
+ NODE LoopVar1;
+
+ SetMem (mLevel + WNDSIZ, (UINT8_MAX + 1) * sizeof (UINT8), 1);
+ SetMem (mPosition + WNDSIZ, (UINT8_MAX + 1) * sizeof (NODE), 0);
+
+ SetMem (mParent + WNDSIZ, WNDSIZ * sizeof (NODE), 0);
+
+ mAvail = 1;
+ for (LoopVar1 = 1; LoopVar1 < WNDSIZ - 1; LoopVar1++) {
+ mNext[LoopVar1] = (NODE) (LoopVar1 + 1);
+ }
+
+ mNext[WNDSIZ - 1] = NIL;
+ SetMem (mNext + WNDSIZ * 2, (MAX_HASH_VAL - WNDSIZ * 2 + 1) * sizeof (NODE), 0);
+}
+
+/**
+ Find child node given the parent node and the edge character
+
+ @param[in] LoopVar6 The parent node.
+ @param[in] LoopVar5 The edge character.
+
+ @return The child node.
+ @retval NIL(Zero) No child could be found.
+
+**/
+NODE
+EFIAPI
+Child (
+ IN NODE LoopVar6,
+ IN UINT8 LoopVar5
+ )
+{
+ NODE LoopVar4;
+
+ LoopVar4 = mNext[HASH (LoopVar6, LoopVar5)];
+ mParent[NIL] = LoopVar6; /* sentinel */
+ while (mParent[LoopVar4] != LoopVar6) {
+ LoopVar4 = mNext[LoopVar4];
+ }
+
+ return LoopVar4;
+}
+
+/**
+ Create a new child for a given parent node.
+
+ @param[in] LoopVar6 The parent node.
+ @param[in] LoopVar5 The edge character.
+ @param[in] LoopVar4 The child node.
+**/
+VOID
+EFIAPI
+MakeChild (
+ IN NODE LoopVar6,
+ IN UINT8 LoopVar5,
+ IN NODE LoopVar4
+ )
+{
+ NODE LoopVar12;
+
+ NODE LoopVar10;
+
+ LoopVar12 = (NODE) HASH (LoopVar6, LoopVar5);
+ LoopVar10 = mNext[LoopVar12];
+ mNext[LoopVar12] = LoopVar4;
+ mNext[LoopVar4] = LoopVar10;
+ mPrev[LoopVar10] = LoopVar4;
+ mPrev[LoopVar4] = LoopVar12;
+ mParent[LoopVar4] = LoopVar6;
+ mChildCount[LoopVar6]++;
+}
+
+/**
+ Split a node.
+
+ @param[in] Old The node to split.
+**/
+VOID
+EFIAPI
+Split (
+ IN NODE Old
+ )
+{
+ NODE New;
+
+ NODE LoopVar10;
+
+ New = mAvail;
+ mAvail = mNext[New];
+ mChildCount[New] = 0;
+ LoopVar10 = mPrev[Old];
+ mPrev[New] = LoopVar10;
+ mNext[LoopVar10] = New;
+ LoopVar10 = mNext[Old];
+ mNext[New] = LoopVar10;
+ mPrev[LoopVar10] = New;
+ mParent[New] = mParent[Old];
+ mLevel[New] = (UINT8) mMatchLen;
+ mPosition[New] = mPos;
+ MakeChild (New, mText[mMatchPos + mMatchLen], Old);
+ MakeChild (New, mText[mPos + mMatchLen], mPos);
+}
+
+/**
+ Insert string info for current position into the String Info Log.
+
+**/
+VOID
+EFIAPI
+InsertNode (
+ VOID
+ )
+{
+ NODE LoopVar6;
+
+ NODE LoopVar4;
+
+ NODE LoopVar2;
+
+ NODE LoopVar10;
+ UINT8 LoopVar5;
+ UINT8 *TempString3;
+ UINT8 *TempString2;
+
+ if (mMatchLen >= 4) {
+ //
+ // We have just got a long match, the target tree
+ // can be located by MatchPos + 1. Travese the tree
+ // from bottom up to get to a proper starting point.
+ // The usage of PERC_FLAG ensures proper node deletion
+ // in DeleteNode() later.
+ //
+ mMatchLen--;
+ LoopVar4 = (NODE) ((mMatchPos + 1) | WNDSIZ);
+ LoopVar6 = mParent[LoopVar4];
+ while (LoopVar6 == NIL) {
+ LoopVar4 = mNext[LoopVar4];
+ LoopVar6 = mParent[LoopVar4];
+ }
+
+ while (mLevel[LoopVar6] >= mMatchLen) {
+ LoopVar4 = LoopVar6;
+ LoopVar6 = mParent[LoopVar6];
+ }
+
+ LoopVar10 = LoopVar6;
+ while (mPosition[LoopVar10] < 0) {
+ mPosition[LoopVar10] = mPos;
+ LoopVar10 = mParent[LoopVar10];
+ }
+
+ if (LoopVar10 < WNDSIZ) {
+ mPosition[LoopVar10] = (NODE) (mPos | PERC_FLAG);
+ }
+ } else {
+ //
+ // Locate the target tree
+ //
+ LoopVar6 = (NODE) (mText[mPos] + WNDSIZ);
+ LoopVar5 = mText[mPos + 1];
+ LoopVar4 = Child (LoopVar6, LoopVar5);
+ if (LoopVar4 == NIL) {
+ MakeChild (LoopVar6, LoopVar5, mPos);
+ mMatchLen = 1;
+ return ;
+ }
+
+ mMatchLen = 2;
+ }
+ //
+ // Traverse down the tree to find a match.
+ // Update Position value along the route.
+ // Node split or creation is involved.
+ //
+ for (;;) {
+ if (LoopVar4 >= WNDSIZ) {
+ LoopVar2 = MAXMATCH;
+ mMatchPos = LoopVar4;
+ } else {
+ LoopVar2 = mLevel[LoopVar4];
+ mMatchPos = (NODE) (mPosition[LoopVar4] & ~PERC_FLAG);
+ }
+
+ if (mMatchPos >= mPos) {
+ mMatchPos -= WNDSIZ;
+ }
+
+ TempString3 = &mText[mPos + mMatchLen];
+ TempString2 = &mText[mMatchPos + mMatchLen];
+ while (mMatchLen < LoopVar2) {
+ if (*TempString3 != *TempString2) {
+ Split (LoopVar4);
+ return ;
+ }
+
+ mMatchLen++;
+ TempString3++;
+ TempString2++;
+ }
+
+ if (mMatchLen >= MAXMATCH) {
+ break;
+ }
+
+ mPosition[LoopVar4] = mPos;
+ LoopVar6 = LoopVar4;
+ LoopVar4 = Child (LoopVar6, *TempString3);
+ if (LoopVar4 == NIL) {
+ MakeChild (LoopVar6, *TempString3, mPos);
+ return ;
+ }
+
+ mMatchLen++;
+ }
+
+ LoopVar10 = mPrev[LoopVar4];
+ mPrev[mPos] = LoopVar10;
+ mNext[LoopVar10] = mPos;
+ LoopVar10 = mNext[LoopVar4];
+ mNext[mPos] = LoopVar10;
+ mPrev[LoopVar10] = mPos;
+ mParent[mPos] = LoopVar6;
+ mParent[LoopVar4] = NIL;
+
+ //
+ // Special usage of 'next'
+ //
+ mNext[LoopVar4] = mPos;
+
+}
+
+/**
+ Delete outdated string info. (The Usage of PERC_FLAG
+ ensures a clean deletion).
+
+**/
+VOID
+EFIAPI
+DeleteNode (
+ VOID
+ )
+{
+ NODE LoopVar6;
+
+ NODE LoopVar4;
+
+ NODE LoopVar11;
+
+ NODE LoopVar10;
+
+ NODE LoopVar9;
+
+ if (mParent[mPos] == NIL) {
+ return ;
+ }
+
+ LoopVar4 = mPrev[mPos];
+ LoopVar11 = mNext[mPos];
+ mNext[LoopVar4] = LoopVar11;
+ mPrev[LoopVar11] = LoopVar4;
+ LoopVar4 = mParent[mPos];
+ mParent[mPos] = NIL;
+ if (LoopVar4 >= WNDSIZ) {
+ return ;
+ }
+
+ mChildCount[LoopVar4]--;
+ if (mChildCount[LoopVar4] > 1) {
+ return ;
+ }
+
+ LoopVar10 = (NODE) (mPosition[LoopVar4] & ~PERC_FLAG);
+ if (LoopVar10 >= mPos) {
+ LoopVar10 -= WNDSIZ;
+ }
+
+ LoopVar11 = LoopVar10;
+ LoopVar6 = mParent[LoopVar4];
+ LoopVar9 = mPosition[LoopVar6];
+ while ((LoopVar9 & PERC_FLAG) != 0){
+ LoopVar9 &= ~PERC_FLAG;
+ if (LoopVar9 >= mPos) {
+ LoopVar9 -= WNDSIZ;
+ }
+
+ if (LoopVar9 > LoopVar11) {
+ LoopVar11 = LoopVar9;
+ }
+
+ mPosition[LoopVar6] = (NODE) (LoopVar11 | WNDSIZ);
+ LoopVar6 = mParent[LoopVar6];
+ LoopVar9 = mPosition[LoopVar6];
+ }
+
+ if (LoopVar6 < WNDSIZ) {
+ if (LoopVar9 >= mPos) {
+ LoopVar9 -= WNDSIZ;
+ }
+
+ if (LoopVar9 > LoopVar11) {
+ LoopVar11 = LoopVar9;
+ }
+
+ mPosition[LoopVar6] = (NODE) (LoopVar11 | WNDSIZ | PERC_FLAG);
+ }
+
+ LoopVar11 = Child (LoopVar4, mText[LoopVar10 + mLevel[LoopVar4]]);
+ LoopVar10 = mPrev[LoopVar11];
+ LoopVar9 = mNext[LoopVar11];
+ mNext[LoopVar10] = LoopVar9;
+ mPrev[LoopVar9] = LoopVar10;
+ LoopVar10 = mPrev[LoopVar4];
+ mNext[LoopVar10] = LoopVar11;
+ mPrev[LoopVar11] = LoopVar10;
+ LoopVar10 = mNext[LoopVar4];
+ mPrev[LoopVar10] = LoopVar11;
+ mNext[LoopVar11] = LoopVar10;
+ mParent[LoopVar11] = mParent[LoopVar4];
+ mParent[LoopVar4] = NIL;
+ mNext[LoopVar4] = mAvail;
+ mAvail = LoopVar4;
+}
+
+/**
+ Read in source data
+
+ @param[out] LoopVar7 The buffer to hold the data.
+ @param[in] LoopVar8 The number of bytes to read.
+
+ @return The number of bytes actually read.
+**/
+INT32
+EFIAPI
+FreadCrc (
+ OUT UINT8 *LoopVar7,
+ IN INT32 LoopVar8
+ )
+{
+ INT32 LoopVar1;
+
+ for (LoopVar1 = 0; mSrc < mSrcUpperLimit && LoopVar1 < LoopVar8; LoopVar1++) {
+ *LoopVar7++ = *mSrc++;
+ }
+
+ LoopVar8 = LoopVar1;
+
+ LoopVar7 -= LoopVar8;
+ mOrigSize += LoopVar8;
+ LoopVar1--;
+ while (LoopVar1 >= 0) {
+ UPDATE_CRC (*LoopVar7++);
+ LoopVar1--;
+ }
+
+ return LoopVar8;
+}
+
+/**
+ Advance the current position (read in new data if needed).
+ Delete outdated string info. Find a match string for current position.
+
+ @retval TRUE The operation was successful.
+ @retval FALSE The operation failed due to insufficient memory.
+**/
+BOOLEAN
+EFIAPI
+GetNextMatch (
+ VOID
+ )
+{
+ INT32 LoopVar8;
+ VOID *Temp;
+
+ mRemainder--;
+ mPos++;
+ if (mPos == WNDSIZ * 2) {
+ Temp = AllocateZeroPool (WNDSIZ + MAXMATCH);
+ if (Temp == NULL) {
+ return (FALSE);
+ }
+ CopyMem (Temp, &mText[WNDSIZ], WNDSIZ + MAXMATCH);
+ CopyMem (&mText[0], Temp, WNDSIZ + MAXMATCH);
+ FreePool (Temp);
+ LoopVar8 = FreadCrc (&mText[WNDSIZ + MAXMATCH], WNDSIZ);
+ mRemainder += LoopVar8;
+ mPos = WNDSIZ;
+ }
+
+ DeleteNode ();
+ InsertNode ();
+
+ return (TRUE);
+}
+
+/**
+ Send entry LoopVar1 down the queue.
+
+ @param[in] LoopVar1 The index of the item to move.
+**/
+VOID
+EFIAPI
+DownHeap (
+ IN INT32 i
+ )
+{
+ INT32 LoopVar1;
+
+ INT32 LoopVar2;
+
+ //
+ // priority queue: send i-th entry down heap
+ //
+ LoopVar2 = mHeap[i];
+ LoopVar1 = 2 * i;
+ while (LoopVar1 <= mHeapSize) {
+ if (LoopVar1 < mHeapSize && mFreq[mHeap[LoopVar1]] > mFreq[mHeap[LoopVar1 + 1]]) {
+ LoopVar1++;
+ }
+
+ if (mFreq[LoopVar2] <= mFreq[mHeap[LoopVar1]]) {
+ break;
+ }
+
+ mHeap[i] = mHeap[LoopVar1];
+ i = LoopVar1;
+ LoopVar1 = 2 * i;
+ }
+
+ mHeap[i] = (INT16) LoopVar2;
+}
+
+/**
+ Count the number of each code length for a Huffman tree.
+
+ @param[in] LoopVar1 The top node.
+**/
+VOID
+EFIAPI
+CountLen (
+ IN INT32 LoopVar1
+ )
+{
+ if (LoopVar1 < mTempInt32) {
+ mLenCnt[(mHuffmanDepth < 16) ? mHuffmanDepth : 16]++;
+ } else {
+ mHuffmanDepth++;
+ CountLen (mLeft[LoopVar1]);
+ CountLen (mRight[LoopVar1]);
+ mHuffmanDepth--;
+ }
+}
+
+/**
+ Create code length array for a Huffman tree.
+
+ @param[in] Root The root of the tree.
+**/
+VOID
+EFIAPI
+MakeLen (
+ IN INT32 Root
+ )
+{
+ INT32 LoopVar1;
+
+ INT32 LoopVar2;
+ UINT32 Cum;
+
+ for (LoopVar1 = 0; LoopVar1 <= 16; LoopVar1++) {
+ mLenCnt[LoopVar1] = 0;
+ }
+
+ CountLen (Root);
+
+ //
+ // Adjust the length count array so that
+ // no code will be generated longer than its designated length
+ //
+ Cum = 0;
+ for (LoopVar1 = 16; LoopVar1 > 0; LoopVar1--) {
+ Cum += mLenCnt[LoopVar1] << (16 - LoopVar1);
+ }
+
+ while (Cum != (1U << 16)) {
+ mLenCnt[16]--;
+ for (LoopVar1 = 15; LoopVar1 > 0; LoopVar1--) {
+ if (mLenCnt[LoopVar1] != 0) {
+ mLenCnt[LoopVar1]--;
+ mLenCnt[LoopVar1 + 1] += 2;
+ break;
+ }
+ }
+
+ Cum--;
+ }
+
+ for (LoopVar1 = 16; LoopVar1 > 0; LoopVar1--) {
+ LoopVar2 = mLenCnt[LoopVar1];
+ LoopVar2--;
+ while (LoopVar2 >= 0) {
+ mLen[*mSortPtr++] = (UINT8) LoopVar1;
+ LoopVar2--;
+ }
+ }
+}
+
+/**
+ Assign code to each symbol based on the code length array.
+
+ @param[in] LoopVar8 The number of symbols.
+ @param[in] Len The code length array.
+ @param[out] Code The stores codes for each symbol.
+**/
+VOID
+EFIAPI
+MakeCode (
+ IN INT32 LoopVar8,
+ IN UINT8 Len[ ],
+ OUT UINT16 Code[ ]
+ )
+{
+ INT32 LoopVar1;
+ UINT16 Start[18];
+
+ Start[1] = 0;
+ for (LoopVar1 = 1; LoopVar1 <= 16; LoopVar1++) {
+ Start[LoopVar1 + 1] = (UINT16) ((Start[LoopVar1] + mLenCnt[LoopVar1]) << 1);
+ }
+
+ for (LoopVar1 = 0; LoopVar1 < LoopVar8; LoopVar1++) {
+ Code[LoopVar1] = Start[Len[LoopVar1]]++;
+ }
+}
+
+/**
+ Generates Huffman codes given a frequency distribution of symbols.
+
+ @param[in] NParm The number of symbols.
+ @param[in] FreqParm The frequency of each symbol.
+ @param[out] LenParm The code length for each symbol.
+ @param[out] CodeParm The code for each symbol.
+
+ @return The root of the Huffman tree.
+**/
+INT32
+EFIAPI
+MakeTree (
+ IN INT32 NParm,
+ IN UINT16 FreqParm[ ],
+ OUT UINT8 LenParm[ ],
+ OUT UINT16 CodeParm[ ]
+ )
+{
+ INT32 LoopVar1;
+
+ INT32 LoopVar2;
+
+ INT32 LoopVar3;
+
+ INT32 Avail;
+
+ //
+ // make tree, calculate len[], return root
+ //
+ mTempInt32 = NParm;
+ mFreq = FreqParm;
+ mLen = LenParm;
+ Avail = mTempInt32;
+ mHeapSize = 0;
+ mHeap[1] = 0;
+ for (LoopVar1 = 0; LoopVar1 < mTempInt32; LoopVar1++) {
+ mLen[LoopVar1] = 0;
+ if ((mFreq[LoopVar1]) != 0) {
+ mHeapSize++;
+ mHeap[mHeapSize] = (INT16) LoopVar1;
+ }
+ }
+
+ if (mHeapSize < 2) {
+ CodeParm[mHeap[1]] = 0;
+ return mHeap[1];
+ }
+
+ for (LoopVar1 = mHeapSize / 2; LoopVar1 >= 1; LoopVar1--) {
+ //
+ // make priority queue
+ //
+ DownHeap (LoopVar1);
+ }
+
+ mSortPtr = CodeParm;
+ do {
+ LoopVar1 = mHeap[1];
+ if (LoopVar1 < mTempInt32) {
+ *mSortPtr++ = (UINT16) LoopVar1;
+ }
+
+ mHeap[1] = mHeap[mHeapSize--];
+ DownHeap (1);
+ LoopVar2 = mHeap[1];
+ if (LoopVar2 < mTempInt32) {
+ *mSortPtr++ = (UINT16) LoopVar2;
+ }
+
+ LoopVar3 = Avail++;
+ mFreq[LoopVar3] = (UINT16) (mFreq[LoopVar1] + mFreq[LoopVar2]);
+ mHeap[1] = (INT16) LoopVar3;
+ DownHeap (1);
+ mLeft[LoopVar3] = (UINT16) LoopVar1;
+ mRight[LoopVar3] = (UINT16) LoopVar2;
+ } while (mHeapSize > 1);
+
+ mSortPtr = CodeParm;
+ MakeLen (LoopVar3);
+ MakeCode (NParm, LenParm, CodeParm);
+
+ //
+ // return root
+ //
+ return LoopVar3;
+}
+
+/**
+ Outputs rightmost LoopVar8 bits of x
+
+ @param[in] LoopVar8 The rightmost LoopVar8 bits of the data is used.
+ @param[in] x The data.
+**/
+VOID
+EFIAPI
+PutBits (
+ IN INT32 LoopVar8,
+ IN UINT32 x
+ )
+{
+ UINT8 Temp;
+
+ if (LoopVar8 < mBitCount) {
+ mSubBitBuf |= x << (mBitCount -= LoopVar8);
+ } else {
+
+ Temp = (UINT8)(mSubBitBuf | (x >> (LoopVar8 -= mBitCount)));
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = Temp;
+ }
+ mCompSize++;
+
+ if (LoopVar8 < UINT8_BIT) {
+ mSubBitBuf = x << (mBitCount = UINT8_BIT - LoopVar8);
+ } else {
+
+ Temp = (UINT8)(x >> (LoopVar8 - UINT8_BIT));
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = Temp;
+ }
+ mCompSize++;
+
+ mSubBitBuf = x << (mBitCount = 2 * UINT8_BIT - LoopVar8);
+ }
+ }
+}
+
+/**
+ Encode a signed 32 bit number.
+
+ @param[in] LoopVar5 The number to encode.
+**/
+VOID
+EFIAPI
+EncodeC (
+ IN INT32 LoopVar5
+ )
+{
+ PutBits (mCLen[LoopVar5], mCCode[LoopVar5]);
+}
+
+/**
+ Encode a unsigned 32 bit number.
+
+ @param[in] LoopVar7 The number to encode.
+**/
+VOID
+EFIAPI
+EncodeP (
+ IN UINT32 LoopVar7
+ )
+{
+ UINT32 LoopVar5;
+
+ UINT32 LoopVar6;
+
+ LoopVar5 = 0;
+ LoopVar6 = LoopVar7;
+ while (LoopVar6 != 0) {
+ LoopVar6 >>= 1;
+ LoopVar5++;
+ }
+
+ PutBits (mPTLen[LoopVar5], mPTCode[LoopVar5]);
+ if (LoopVar5 > 1) {
+ PutBits(LoopVar5 - 1, LoopVar7 & (0xFFFFU >> (17 - LoopVar5)));
+ }
+}
+
+/**
+ Count the frequencies for the Extra Set.
+
+**/
+VOID
+EFIAPI
+CountTFreq (
+ VOID
+ )
+{
+ INT32 LoopVar1;
+
+ INT32 LoopVar3;
+
+ INT32 LoopVar8;
+
+ INT32 Count;
+
+ for (LoopVar1 = 0; LoopVar1 < NT; LoopVar1++) {
+ mTFreq[LoopVar1] = 0;
+ }
+
+ LoopVar8 = NC;
+ while (LoopVar8 > 0 && mCLen[LoopVar8 - 1] == 0) {
+ LoopVar8--;
+ }
+
+ LoopVar1 = 0;
+ while (LoopVar1 < LoopVar8) {
+ LoopVar3 = mCLen[LoopVar1++];
+ if (LoopVar3 == 0) {
+ Count = 1;
+ while (LoopVar1 < LoopVar8 && mCLen[LoopVar1] == 0) {
+ LoopVar1++;
+ Count++;
+ }
+
+ if (Count <= 2) {
+ mTFreq[0] = (UINT16) (mTFreq[0] + Count);
+ } else if (Count <= 18) {
+ mTFreq[1]++;
+ } else if (Count == 19) {
+ mTFreq[0]++;
+ mTFreq[1]++;
+ } else {
+ mTFreq[2]++;
+ }
+ } else {
+ ASSERT((LoopVar3+2)<(2 * NT - 1));
+ mTFreq[LoopVar3 + 2]++;
+ }
+ }
+}
+
+/**
+ Outputs the code length array for the Extra Set or the Position Set.
+
+ @param[in] LoopVar8 The number of symbols.
+ @param[in] nbit The number of bits needed to represent 'LoopVar8'.
+ @param[in] Special The special symbol that needs to be take care of.
+
+**/
+VOID
+EFIAPI
+WritePTLen (
+ IN INT32 LoopVar8,
+ IN INT32 nbit,
+ IN INT32 Special
+ )
+{
+ INT32 LoopVar1;
+
+ INT32 LoopVar3;
+
+ while (LoopVar8 > 0 && mPTLen[LoopVar8 - 1] == 0) {
+ LoopVar8--;
+ }
+
+ PutBits (nbit, LoopVar8);
+ LoopVar1 = 0;
+ while (LoopVar1 < LoopVar8) {
+ LoopVar3 = mPTLen[LoopVar1++];
+ if (LoopVar3 <= 6) {
+ PutBits (3, LoopVar3);
+ } else {
+ PutBits (LoopVar3 - 3, (1U << (LoopVar3 - 3)) - 2);
+ }
+
+ if (LoopVar1 == Special) {
+ while (LoopVar1 < 6 && mPTLen[LoopVar1] == 0) {
+ LoopVar1++;
+ }
+
+ PutBits (2, (LoopVar1 - 3) & 3);
+ }
+ }
+}
+
+/**
+ Outputs the code length array for Char&Length Set.
+**/
+VOID
+EFIAPI
+WriteCLen (
+ VOID
+ )
+{
+ INT32 LoopVar1;
+
+ INT32 LoopVar3;
+
+ INT32 LoopVar8;
+
+ INT32 Count;
+
+ LoopVar8 = NC;
+ while (LoopVar8 > 0 && mCLen[LoopVar8 - 1] == 0) {
+ LoopVar8--;
+ }
+
+ PutBits (CBIT, LoopVar8);
+ LoopVar1 = 0;
+ while (LoopVar1 < LoopVar8) {
+ LoopVar3 = mCLen[LoopVar1++];
+ if (LoopVar3 == 0) {
+ Count = 1;
+ while (LoopVar1 < LoopVar8 && mCLen[LoopVar1] == 0) {
+ LoopVar1++;
+ Count++;
+ }
+
+ if (Count <= 2) {
+ for (LoopVar3 = 0; LoopVar3 < Count; LoopVar3++) {
+ PutBits (mPTLen[0], mPTCode[0]);
+ }
+ } else if (Count <= 18) {
+ PutBits (mPTLen[1], mPTCode[1]);
+ PutBits (4, Count - 3);
+ } else if (Count == 19) {
+ PutBits (mPTLen[0], mPTCode[0]);
+ PutBits (mPTLen[1], mPTCode[1]);
+ PutBits (4, 15);
+ } else {
+ PutBits (mPTLen[2], mPTCode[2]);
+ PutBits (CBIT, Count - 20);
+ }
+ } else {
+ ASSERT((LoopVar3+2)<NPT);
+ PutBits (mPTLen[LoopVar3 + 2], mPTCode[LoopVar3 + 2]);
+ }
+ }
+}
+
+/**
+ Huffman code the block and output it.
+
+**/
+VOID
+EFIAPI
+SendBlock (
+ VOID
+ )
+{
+ UINT32 LoopVar1;
+
+ UINT32 LoopVar3;
+
+ UINT32 Flags;
+
+ UINT32 Root;
+
+ UINT32 Pos;
+
+ UINT32 Size;
+ Flags = 0;
+
+ Root = MakeTree (NC, mCFreq, mCLen, mCCode);
+ Size = mCFreq[Root];
+ PutBits (16, Size);
+ if (Root >= NC) {
+ CountTFreq ();
+ Root = MakeTree (NT, mTFreq, mPTLen, mPTCode);
+ if (Root >= NT) {
+ WritePTLen (NT, TBIT, 3);
+ } else {
+ PutBits (TBIT, 0);
+ PutBits (TBIT, Root);
+ }
+
+ WriteCLen ();
+ } else {
+ PutBits (TBIT, 0);
+ PutBits (TBIT, 0);
+ PutBits (CBIT, 0);
+ PutBits (CBIT, Root);
+ }
+
+ Root = MakeTree (NP, mPFreq, mPTLen, mPTCode);
+ if (Root >= NP) {
+ WritePTLen (NP, PBIT, -1);
+ } else {
+ PutBits (PBIT, 0);
+ PutBits (PBIT, Root);
+ }
+
+ Pos = 0;
+ for (LoopVar1 = 0; LoopVar1 < Size; LoopVar1++) {
+ if (LoopVar1 % UINT8_BIT == 0) {
+ Flags = mBuf[Pos++];
+ } else {
+ Flags <<= 1;
+ }
+ if ((Flags & (1U << (UINT8_BIT - 1))) != 0){
+ EncodeC(mBuf[Pos++] + (1U << UINT8_BIT));
+ LoopVar3 = mBuf[Pos++] << UINT8_BIT;
+ LoopVar3 += mBuf[Pos++];
+
+ EncodeP (LoopVar3);
+ } else {
+ EncodeC (mBuf[Pos++]);
+ }
+ }
+
+ SetMem (mCFreq, NC * sizeof (UINT16), 0);
+ SetMem (mPFreq, NP * sizeof (UINT16), 0);
+}
+
+/**
+ Start the huffman encoding.
+
+**/
+VOID
+EFIAPI
+HufEncodeStart (
+ VOID
+ )
+{
+ SetMem (mCFreq, NC * sizeof (UINT16), 0);
+ SetMem (mPFreq, NP * sizeof (UINT16), 0);
+
+ mOutputPos = mOutputMask = 0;
+
+ mBitCount = UINT8_BIT;
+ mSubBitBuf = 0;
+}
+
+/**
+ Outputs an Original Character or a Pointer.
+
+ @param[in] LoopVar5 The original character or the 'String Length' element of
+ a Pointer.
+ @param[in] LoopVar7 The 'Position' field of a Pointer.
+**/
+VOID
+EFIAPI
+CompressOutput (
+ IN UINT32 LoopVar5,
+ IN UINT32 LoopVar7
+ )
+{
+ STATIC UINT32 CPos;
+
+ if ((mOutputMask >>= 1) == 0) {
+ mOutputMask = 1U << (UINT8_BIT - 1);
+ if (mOutputPos >= mBufSiz - 3 * UINT8_BIT) {
+ SendBlock ();
+ mOutputPos = 0;
+ }
+
+ CPos = mOutputPos++;
+ mBuf[CPos] = 0;
+ }
+ mBuf[mOutputPos++] = (UINT8) LoopVar5;
+ mCFreq[LoopVar5]++;
+ if (LoopVar5 >= (1U << UINT8_BIT)) {
+ mBuf[CPos] = (UINT8)(mBuf[CPos]|mOutputMask);
+ mBuf[mOutputPos++] = (UINT8)(LoopVar7 >> UINT8_BIT);
+ mBuf[mOutputPos++] = (UINT8) LoopVar7;
+ LoopVar5 = 0;
+ while (LoopVar7!=0) {
+ LoopVar7 >>= 1;
+ LoopVar5++;
+ }
+ mPFreq[LoopVar5]++;
+ }
+}
+
+/**
+ End the huffman encoding.
+
+**/
+VOID
+EFIAPI
+HufEncodeEnd (
+ VOID
+ )
+{
+ SendBlock ();
+
+ //
+ // Flush remaining bits
+ //
+ PutBits (UINT8_BIT - 1, 0);
+}
+
+/**
+ The main controlling routine for compression process.
+
+ @retval EFI_SUCCESS The compression is successful.
+ @retval EFI_OUT_0F_RESOURCES Not enough memory for compression process.
+**/
+EFI_STATUS
+EFIAPI
+Encode (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ INT32 LastMatchLen;
+ NODE LastMatchPos;
+
+ Status = AllocateMemory ();
+ if (EFI_ERROR (Status)) {
+ FreeMemory ();
+ return Status;
+ }
+
+ InitSlide ();
+
+ HufEncodeStart ();
+
+ mRemainder = FreadCrc (&mText[WNDSIZ], WNDSIZ + MAXMATCH);
+
+ mMatchLen = 0;
+ mPos = WNDSIZ;
+ InsertNode ();
+ if (mMatchLen > mRemainder) {
+ mMatchLen = mRemainder;
+ }
+
+ while (mRemainder > 0) {
+ LastMatchLen = mMatchLen;
+ LastMatchPos = mMatchPos;
+ if (!GetNextMatch ()) {
+ Status = EFI_OUT_OF_RESOURCES;
+ }
+ if (mMatchLen > mRemainder) {
+ mMatchLen = mRemainder;
+ }
+
+ if (mMatchLen > LastMatchLen || LastMatchLen < THRESHOLD) {
+ //
+ // Not enough benefits are gained by outputting a pointer,
+ // so just output the original character
+ //
+ CompressOutput(mText[mPos - 1], 0);
+ } else {
+ //
+ // Outputting a pointer is beneficial enough, do it.
+ //
+
+ CompressOutput(LastMatchLen + (UINT8_MAX + 1 - THRESHOLD),
+ (mPos - LastMatchPos - 2) & (WNDSIZ - 1));
+ LastMatchLen--;
+ while (LastMatchLen > 0) {
+ if (!GetNextMatch ()) {
+ Status = EFI_OUT_OF_RESOURCES;
+ }
+ LastMatchLen--;
+ }
+
+ if (mMatchLen > mRemainder) {
+ mMatchLen = mRemainder;
+ }
+ }
+ }
+
+ HufEncodeEnd ();
+ FreeMemory ();
+ return (Status);
+}
+
+/**
+ The compression routine.
+
+ @param[in] SrcBuffer The buffer containing the source data.
+ @param[in] SrcSize The number of bytes in SrcBuffer.
+ @param[in] DstBuffer The buffer to put the compressed image in.
+ @param[in, out] DstSize On input the size (in bytes) of DstBuffer, on
+ return the number of bytes placed in DstBuffer.
+
+ @retval EFI_SUCCESS The compression was sucessful.
+ @retval EFI_BUFFER_TOO_SMALL The buffer was too small. DstSize is required.
+**/
+EFI_STATUS
+EFIAPI
+Compress (
+ IN VOID *SrcBuffer,
+ IN UINT64 SrcSize,
+ IN VOID *DstBuffer,
+ IN OUT UINT64 *DstSize
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Initializations
+ //
+ mBufSiz = 0;
+ mBuf = NULL;
+ mText = NULL;
+ mLevel = NULL;
+ mChildCount = NULL;
+ mPosition = NULL;
+ mParent = NULL;
+ mPrev = NULL;
+ mNext = NULL;
+
+ mSrc = SrcBuffer;
+ mSrcUpperLimit = mSrc + SrcSize;
+ mDst = DstBuffer;
+ mDstUpperLimit = mDst +*DstSize;
+
+ PutDword (0L);
+ PutDword (0L);
+
+ MakeCrcTable ();
+
+ mOrigSize = mCompSize = 0;
+ mCrc = INIT_CRC;
+
+ //
+ // Compress it
+ //
+ Status = Encode ();
+ if (EFI_ERROR (Status)) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // Null terminate the compressed data
+ //
+ if (mDst < mDstUpperLimit) {
+ *mDst++ = 0;
+ }
+ //
+ // Fill in compressed size and original size
+ //
+ mDst = DstBuffer;
+ PutDword (mCompSize + 1);
+ PutDword (mOrigSize);
+
+ //
+ // Return
+ //
+ if (mCompSize + 1 + 8 > *DstSize) {
+ *DstSize = mCompSize + 1 + 8;
+ return EFI_BUFFER_TOO_SMALL;
+ } else {
+ *DstSize = mCompSize + 1 + 8;
+ return EFI_SUCCESS;
+ }
+
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Compress.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Compress.h
new file mode 100644
index 0000000000..39a997178f
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Compress.h
@@ -0,0 +1,40 @@
+/** @file
+ Header file for compression routine.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _EFI_SHELL_COMPRESS_H_
+#define _EFI_SHELL_COMPRESS_H_
+
+/**
+ The compression routine.
+
+ @param[in] SrcBuffer The buffer containing the source data.
+ @param[in] SrcSize Number of bytes in SrcBuffer.
+ @param[in] DstBuffer The buffer to put the compressed image in.
+ @param[in, out] DstSize On input the size (in bytes) of DstBuffer, on
+ return the number of bytes placed in DstBuffer.
+
+ @retval EFI_SUCCESS The compression was sucessful.
+ @retval EFI_BUFFER_TOO_SMALL The buffer was too small. DstSize is required.
+**/
+EFI_STATUS
+EFIAPI
+Compress (
+ IN VOID *SrcBuffer,
+ IN UINT64 SrcSize,
+ IN VOID *DstBuffer,
+ IN OUT UINT64 *DstSize
+ );
+
+#endif
+
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Dblk.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Dblk.c
new file mode 100644
index 0000000000..a1fe9d7bef
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Dblk.c
@@ -0,0 +1,201 @@
+/** @file
+ Main file for Dblk shell Debug1 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDebug1CommandsLib.h"
+#include <Protocol/BlockIo.h>
+
+/**
+ Display blocks to the screen.
+
+ @param[in] DevPath The device path to get the blocks from.
+ @param[in] Lba The Lba number to start from.
+ @param[in] BlockCount How many blocks to display.
+
+ @retval SHELL_SUCCESS The display was successful.
+**/
+SHELL_STATUS
+EFIAPI
+DisplayTheBlocks(
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevPath,
+ IN CONST UINT64 Lba,
+ IN CONST UINT8 BlockCount
+ )
+{
+ EFI_BLOCK_IO_PROTOCOL *BlockIo;
+ EFI_HANDLE BlockIoHandle;
+ EFI_STATUS Status;
+ SHELL_STATUS ShellStatus;
+ UINT8 *Buffer;
+ UINTN BufferSize;
+
+ ShellStatus = SHELL_SUCCESS;
+
+ Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid, (EFI_DEVICE_PATH_PROTOCOL **)&DevPath, &BlockIoHandle);
+ if (EFI_ERROR(Status)) {
+ return (SHELL_NOT_FOUND);
+ }
+
+ Status = gBS->OpenProtocol(BlockIoHandle, &gEfiBlockIoProtocolGuid, (VOID**)&BlockIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR(Status)) {
+ return (SHELL_NOT_FOUND);
+ }
+
+ BufferSize = BlockIo->Media->BlockSize * BlockCount;
+ if (BufferSize > 0) {
+ Buffer = AllocateZeroPool(BufferSize);
+ } else {
+ ShellPrintEx(-1,-1,L" BlockSize: 0x%08x, BlockCount: 0x%08x\r\n", BlockIo->Media->BlockSize, BlockCount);
+ Buffer = NULL;
+ }
+
+ Status = BlockIo->ReadBlocks(BlockIo, BlockIo->Media->MediaId, Lba, BufferSize, Buffer);
+ if (!EFI_ERROR(Status) && Buffer != NULL) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DBLK_HEADER),
+ gShellDebug1HiiHandle,
+ Lba,
+ BufferSize,
+ BlockIo
+ );
+
+ DumpHex(2,0,BufferSize,Buffer);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_READ_FAIL), gShellDebug1HiiHandle, L"dblk", L"BlockIo");
+ ShellStatus = SHELL_DEVICE_ERROR;
+ }
+
+ if (Buffer != NULL) {
+ FreePool(Buffer);
+ }
+
+ gBS->CloseProtocol(BlockIoHandle, &gEfiBlockIoProtocolGuid, gImageHandle, NULL);
+ return (ShellStatus);
+}
+
+/**
+ Function for 'dblk' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDblk (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ CONST CHAR16 *BlockName;
+ CONST CHAR16 *LbaString;
+ CONST CHAR16 *BlockCountString;
+ UINT64 Lba;
+ UINT64 BlockCount;
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+
+ ShellStatus = SHELL_SUCCESS;
+ Status = EFI_SUCCESS;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"dblk", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetCount(Package) > 4) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"dblk");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetCount(Package) < 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"dblk");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // Parse the params
+ //
+ BlockName = ShellCommandLineGetRawValue(Package, 1);
+ LbaString = ShellCommandLineGetRawValue(Package, 2);
+ BlockCountString = ShellCommandLineGetRawValue(Package, 3);
+
+ if (LbaString == NULL) {
+ Lba = 0;
+ } else {
+ if (!ShellIsHexOrDecimalNumber(LbaString, TRUE, FALSE)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"dblk", LbaString);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ ShellConvertStringToUint64(LbaString, &Lba, TRUE, FALSE);
+ }
+
+ if (BlockCountString == NULL) {
+ BlockCount = 1;
+ } else {
+ if (!ShellIsHexOrDecimalNumber(BlockCountString, TRUE, FALSE)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"dblk", BlockCountString);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ ShellConvertStringToUint64(BlockCountString, &BlockCount, TRUE, FALSE);
+ if (BlockCount > 0x10) {
+ BlockCount = 0x10;
+ } else if (BlockCount == 0) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"dblk", BlockCountString);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ }
+
+ if (ShellStatus == SHELL_SUCCESS) {
+ //
+ // do the work if we have a valid block identifier
+ //
+ if (gEfiShellProtocol->GetDevicePathFromMap(BlockName) == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"dblk", BlockName);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ DevPath = (EFI_DEVICE_PATH_PROTOCOL*)gEfiShellProtocol->GetDevicePathFromMap(BlockName);
+ if (gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid, &DevPath, NULL) == EFI_NOT_FOUND) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_MAP_PROTOCOL), gShellDebug1HiiHandle, L"dblk", BlockName, L"BlockIo");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ShellStatus = DisplayTheBlocks(gEfiShellProtocol->GetDevicePathFromMap(BlockName), Lba, (UINT8)BlockCount);
+ }
+ }
+ }
+ }
+
+ ShellCommandLineFreeVarList (Package);
+ }
+ return (ShellStatus);
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Dmem.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Dmem.c
new file mode 100644
index 0000000000..5491f6de57
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Dmem.c
@@ -0,0 +1,235 @@
+/** @file
+ Main file for Dmem shell Debug1 function.
+
+ Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDebug1CommandsLib.h"
+#include <Protocol/PciRootBridgeIo.h>
+#include <Guid/Acpi.h>
+#include <Guid/Mps.h>
+#include <Guid/SmBios.h>
+#include <Guid/SalSystemTable.h>
+
+/**
+ Make a printable character.
+
+ If Char is printable then return it, otherwise return a question mark.
+
+ @param[in] Char The character to make printable.
+
+ @return A printable character representing Char.
+**/
+CHAR16
+EFIAPI
+MakePrintable(
+ IN CONST CHAR16 Char
+ )
+{
+ if ((Char < 0x20 && Char > 0)||(Char > 126)) {
+ return (L'?');
+ }
+ return (Char);
+}
+
+/**
+ Display some Memory-Mapped-IO memory.
+
+ @param[in] Address The starting address to display.
+ @param[in] Size The length of memory to display.
+**/
+SHELL_STATUS
+EFIAPI
+DisplayMmioMemory(
+ IN CONST VOID *Address,
+ IN CONST UINTN Size
+ )
+{
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRbIo;
+ EFI_STATUS Status;
+ VOID *Buffer;
+ SHELL_STATUS ShellStatus;
+
+ ShellStatus = SHELL_SUCCESS;
+
+ Status = gBS->LocateProtocol(&gEfiPciRootBridgeIoProtocolGuid, NULL, (VOID**)&PciRbIo);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PCIRBIO_NF), gShellDebug1HiiHandle, L"dmem");
+ return (SHELL_NOT_FOUND);
+ }
+ Buffer = AllocateZeroPool(Size);
+ if (Buffer == NULL) {
+ return SHELL_OUT_OF_RESOURCES;
+ }
+
+ Status = PciRbIo->Mem.Read(PciRbIo, EfiPciWidthUint8, (UINT64)(UINTN)Address, Size, Buffer);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PCIRBIO_ER), gShellDebug1HiiHandle, L"dmem");
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMEM_MMIO_HEADER_ROW), gShellDebug1HiiHandle, (UINT64)(UINTN)Address, Size);
+ DumpHex(2, (UINTN)Address, Size, Buffer);
+ }
+
+ FreePool(Buffer);
+ return (ShellStatus);
+}
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-mmio", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'dmem' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDmem (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ VOID *Address;
+ UINT64 Size;
+ CONST CHAR16 *Temp1;
+ UINT64 AcpiTableAddress;
+ UINT64 Acpi20TableAddress;
+ UINT64 SalTableAddress;
+ UINT64 SmbiosTableAddress;
+ UINT64 MpsTableAddress;
+ UINTN TableWalker;
+
+ ShellStatus = SHELL_SUCCESS;
+ Status = EFI_SUCCESS;
+ Address = NULL;
+ Size = 0;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"dmem", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetCount(Package) > 3) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"dmem");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Temp1 = ShellCommandLineGetRawValue(Package, 1);
+ if (Temp1 == NULL) {
+ Address = gST;
+ Size = 512;
+ } else {
+ if (!ShellIsHexOrDecimalNumber(Temp1, TRUE, FALSE) || EFI_ERROR(ShellConvertStringToUint64(Temp1, (UINT64*)&Address, TRUE, FALSE))) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"dmem", Temp1);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ Temp1 = ShellCommandLineGetRawValue(Package, 2);
+ if (Temp1 == NULL) {
+ Size = 512;
+ } else {
+ if (!ShellIsHexOrDecimalNumber(Temp1, FALSE, FALSE) || EFI_ERROR(ShellConvertStringToUint64(Temp1, &Size, TRUE, FALSE))) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"dmem", Temp1);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ }
+ }
+ }
+
+ if (ShellStatus == SHELL_SUCCESS) {
+ if (!ShellCommandLineGetFlag(Package, L"-mmio")) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMEM_HEADER_ROW), gShellDebug1HiiHandle, (UINT64)(UINTN)Address, Size);
+ DumpHex(2, (UINTN)Address, (UINTN)Size, Address);
+ if (Address == (VOID*)gST) {
+ Acpi20TableAddress = 0;
+ AcpiTableAddress = 0;
+ SalTableAddress = 0;
+ SmbiosTableAddress = 0;
+ MpsTableAddress = 0;
+ for (TableWalker = 0 ; TableWalker < gST->NumberOfTableEntries ; TableWalker++) {
+ if (CompareGuid(&gST->ConfigurationTable[TableWalker].VendorGuid, &gEfiAcpi20TableGuid)) {
+ Acpi20TableAddress = (UINT64)(UINTN)gST->ConfigurationTable[TableWalker].VendorTable;
+ continue;
+ }
+ if (CompareGuid(&gST->ConfigurationTable[TableWalker].VendorGuid, &gEfiAcpi10TableGuid)) {
+ AcpiTableAddress = (UINT64)(UINTN)gST->ConfigurationTable[TableWalker].VendorTable;
+ continue;
+ }
+ if (CompareGuid(&gST->ConfigurationTable[TableWalker].VendorGuid, &gEfiSalSystemTableGuid)) {
+ SalTableAddress = (UINT64)(UINTN)gST->ConfigurationTable[TableWalker].VendorTable;
+ continue;
+ }
+ if (CompareGuid(&gST->ConfigurationTable[TableWalker].VendorGuid, &gEfiSmbiosTableGuid)) {
+ SmbiosTableAddress = (UINT64)(UINTN)gST->ConfigurationTable[TableWalker].VendorTable;
+ continue;
+ }
+ if (CompareGuid (&gST->ConfigurationTable[TableWalker].VendorGuid, &gEfiSmbios3TableGuid)) {
+ SmbiosTableAddress = (UINT64) (UINTN) gST->ConfigurationTable[TableWalker].VendorTable;
+ continue;
+ }
+ if (CompareGuid(&gST->ConfigurationTable[TableWalker].VendorGuid, &gEfiMpsTableGuid)) {
+ MpsTableAddress = (UINT64)(UINTN)gST->ConfigurationTable[TableWalker].VendorTable;
+ continue;
+ }
+ }
+
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMEM_SYSTEM_TABLE), gShellDebug1HiiHandle,
+ (UINT64)(UINTN)Address,
+ gST->Hdr.HeaderSize,
+ gST->Hdr.Revision,
+ (UINT64)(UINTN)gST->ConIn,
+ (UINT64)(UINTN)gST->ConOut,
+ (UINT64)(UINTN)gST->StdErr,
+ (UINT64)(UINTN)gST->RuntimeServices,
+ (UINT64)(UINTN)gST->BootServices,
+ SalTableAddress,
+ AcpiTableAddress,
+ Acpi20TableAddress,
+ MpsTableAddress,
+ SmbiosTableAddress
+ );
+ }
+ } else {
+ ShellStatus = DisplayMmioMemory(Address, (UINTN)Size);
+ }
+ }
+
+
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ return (ShellStatus);
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/DmpStore.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/DmpStore.c
new file mode 100644
index 0000000000..ac6d0bdb55
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/DmpStore.c
@@ -0,0 +1,769 @@
+/** @file
+ Main file for DmpStore shell Debug1 function.
+
+ (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDebug1CommandsLib.h"
+
+typedef enum {
+ DmpStoreDisplay,
+ DmpStoreDelete,
+ DmpStoreSave,
+ DmpStoreLoad
+} DMP_STORE_TYPE;
+
+typedef struct {
+ UINT32 Signature;
+ CHAR16 *Name;
+ EFI_GUID Guid;
+ UINT32 Attributes;
+ UINT32 DataSize;
+ UINT8 *Data;
+ LIST_ENTRY Link;
+} DMP_STORE_VARIABLE;
+
+#define DMP_STORE_VARIABLE_SIGNATURE SIGNATURE_32 ('_', 'd', 's', 's')
+
+/**
+ Base on the input attribute value to return the attribute string.
+
+ @param[in] Atts The input attribute value
+
+ @retval The attribute string info.
+**/
+CHAR16 *
+EFIAPI
+GetAttrType (
+ IN CONST UINT32 Atts
+ )
+{
+ UINTN BufLen;
+ CHAR16 *RetString;
+
+ BufLen = 0;
+ RetString = NULL;
+
+ if ((Atts & EFI_VARIABLE_NON_VOLATILE) != 0) {
+ StrnCatGrow (&RetString, &BufLen, L"+NV", 0);
+ }
+ if ((Atts & EFI_VARIABLE_RUNTIME_ACCESS) != 0) {
+ StrnCatGrow (&RetString, &BufLen, L"+RT+BS", 0);
+ } else if ((Atts & EFI_VARIABLE_BOOTSERVICE_ACCESS) != 0) {
+ StrnCatGrow (&RetString, &BufLen, L"+BS", 0);
+ }
+ if ((Atts & EFI_VARIABLE_HARDWARE_ERROR_RECORD) != 0) {
+ StrnCatGrow (&RetString, &BufLen, L"+HR", 0);
+ }
+ if ((Atts & EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS) != 0) {
+ StrnCatGrow (&RetString, &BufLen, L"+AW", 0);
+ }
+ if ((Atts & EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS) != 0) {
+ StrnCatGrow (&RetString, &BufLen, L"+AT", 0);
+ }
+
+ if (RetString == NULL) {
+ RetString = StrnCatGrow(&RetString, &BufLen, L"Invalid", 0);
+ }
+
+ if ((RetString != NULL) && (RetString[0] == L'+')) {
+ CopyMem(RetString, RetString + 1, StrSize(RetString + 1));
+ }
+
+ return RetString;
+}
+
+/**
+ Load the variable data from file and set to variable data base.
+
+ @param[in] FileHandle The file to be read.
+ @param[in] Name The name of the variables to be loaded.
+ @param[in] Guid The guid of the variables to be loaded.
+ @param[out] Found TRUE when at least one variable was loaded and set.
+
+ @retval SHELL_DEVICE_ERROR Cannot access the file.
+ @retval SHELL_VOLUME_CORRUPTED The file is in bad format.
+ @retval SHELL_OUT_OF_RESOURCES There is not enough memory to perform the operation.
+ @retval SHELL_SUCCESS Successfully load and set the variables.
+**/
+SHELL_STATUS
+LoadVariablesFromFile (
+ IN SHELL_FILE_HANDLE FileHandle,
+ IN CONST CHAR16 *Name,
+ IN CONST EFI_GUID *Guid,
+ OUT BOOLEAN *Found
+ )
+{
+ EFI_STATUS Status;
+ SHELL_STATUS ShellStatus;
+ UINT32 NameSize;
+ UINT32 DataSize;
+ UINTN BufferSize;
+ UINTN RemainingSize;
+ UINT64 Position;
+ UINT64 FileSize;
+ LIST_ENTRY List;
+ DMP_STORE_VARIABLE *Variable;
+ LIST_ENTRY *Link;
+ CHAR16 *Attributes;
+ UINT8 *Buffer;
+ UINT32 Crc32;
+
+ Status = ShellGetFileSize (FileHandle, &FileSize);
+ if (EFI_ERROR (Status)) {
+ return SHELL_DEVICE_ERROR;
+ }
+
+ ShellStatus = SHELL_SUCCESS;
+
+ InitializeListHead (&List);
+
+ Position = 0;
+ while (Position < FileSize) {
+ //
+ // NameSize
+ //
+ BufferSize = sizeof (NameSize);
+ Status = ShellReadFile (FileHandle, &BufferSize, &NameSize);
+ if (EFI_ERROR (Status) || (BufferSize != sizeof (NameSize))) {
+ ShellStatus = SHELL_VOLUME_CORRUPTED;
+ break;
+ }
+
+ //
+ // DataSize
+ //
+ BufferSize = sizeof (DataSize);
+ Status = ShellReadFile (FileHandle, &BufferSize, &DataSize);
+ if (EFI_ERROR (Status) || (BufferSize != sizeof (DataSize))) {
+ ShellStatus = SHELL_VOLUME_CORRUPTED;
+ break;
+ }
+
+ //
+ // Name, Guid, Attributes, Data, Crc32
+ //
+ RemainingSize = NameSize + sizeof (EFI_GUID) + sizeof (UINT32) + DataSize + sizeof (Crc32);
+ BufferSize = sizeof (NameSize) + sizeof (DataSize) + RemainingSize;
+ Buffer = AllocatePool (BufferSize);
+ if (Buffer == NULL) {
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ break;
+ }
+ BufferSize = RemainingSize;
+ Status = ShellReadFile (FileHandle, &BufferSize, (UINT32 *) Buffer + 2);
+ if (EFI_ERROR (Status) || (BufferSize != RemainingSize)) {
+ ShellStatus = SHELL_VOLUME_CORRUPTED;
+ FreePool (Buffer);
+ break;
+ }
+
+ //
+ // Check Crc32
+ //
+ * (UINT32 *) Buffer = NameSize;
+ * ((UINT32 *) Buffer + 1) = DataSize;
+ BufferSize = RemainingSize + sizeof (NameSize) + sizeof (DataSize) - sizeof (Crc32);
+ gBS->CalculateCrc32 (
+ Buffer,
+ BufferSize,
+ &Crc32
+ );
+ if (Crc32 != * (UINT32 *) (Buffer + BufferSize)) {
+ FreePool (Buffer);
+ ShellStatus = SHELL_VOLUME_CORRUPTED;
+ break;
+ }
+
+ Position += BufferSize + sizeof (Crc32);
+
+ Variable = AllocateZeroPool (sizeof (*Variable) + NameSize + DataSize);
+ if (Variable == NULL) {
+ FreePool (Buffer);
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ break;
+ }
+ Variable->Signature = DMP_STORE_VARIABLE_SIGNATURE;
+ Variable->Name = (CHAR16 *) (Variable + 1);
+ Variable->DataSize = DataSize;
+ Variable->Data = (UINT8 *) Variable->Name + NameSize;
+ CopyMem (Variable->Name, Buffer + sizeof (NameSize) + sizeof (DataSize), NameSize);
+ CopyMem (&Variable->Guid, Buffer + sizeof (NameSize) + sizeof (DataSize) + NameSize, sizeof (EFI_GUID));
+ CopyMem (&Variable->Attributes, Buffer + sizeof (NameSize) + sizeof (DataSize) + NameSize + sizeof (EFI_GUID), sizeof (UINT32));
+ CopyMem (Variable->Data, Buffer + sizeof (NameSize) + sizeof (DataSize) + NameSize + sizeof (EFI_GUID) + sizeof (UINT32), DataSize);
+
+ InsertTailList (&List, &Variable->Link);
+ FreePool (Buffer);
+ }
+
+ if ((Position != FileSize) || (ShellStatus != SHELL_SUCCESS)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_LOAD_BAD_FILE), gShellDebug1HiiHandle, L"dmpstore");
+ if (Position != FileSize) {
+ ShellStatus = SHELL_VOLUME_CORRUPTED;
+ }
+ }
+
+ for ( Link = GetFirstNode (&List)
+ ; !IsNull (&List, Link) && (ShellStatus == SHELL_SUCCESS)
+ ; Link = GetNextNode (&List, Link)
+ ) {
+ Variable = CR (Link, DMP_STORE_VARIABLE, Link, DMP_STORE_VARIABLE_SIGNATURE);
+
+ if (((Name == NULL) || gUnicodeCollation->MetaiMatch (gUnicodeCollation, Variable->Name, (CHAR16 *) Name)) &&
+ ((Guid == NULL) || CompareGuid (&Variable->Guid, Guid))
+ ) {
+ Attributes = GetAttrType (Variable->Attributes);
+ ShellPrintHiiEx (
+ -1, -1, NULL, STRING_TOKEN(STR_DMPSTORE_HEADER_LINE), gShellDebug1HiiHandle,
+ Attributes, &Variable->Guid, Variable->Name, Variable->DataSize
+ );
+ SHELL_FREE_NON_NULL(Attributes);
+
+ *Found = TRUE;
+ Status = gRT->SetVariable (
+ Variable->Name,
+ &Variable->Guid,
+ Variable->Attributes,
+ Variable->DataSize,
+ Variable->Data
+ );
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_LOAD_GEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", Variable->Name, Status);
+ }
+ }
+ }
+
+ for (Link = GetFirstNode (&List); !IsNull (&List, Link); ) {
+ Variable = CR (Link, DMP_STORE_VARIABLE, Link, DMP_STORE_VARIABLE_SIGNATURE);
+ Link = RemoveEntryList (&Variable->Link);
+ FreePool (Variable);
+ }
+
+ return ShellStatus;
+}
+
+/**
+ Append one variable to file.
+
+ @param[in] FileHandle The file to be appended.
+ @param[in] Name The variable name.
+ @param[in] Guid The variable GUID.
+ @param[in] Attributes The variable attributes.
+ @param[in] DataSize The variable data size.
+ @param[in] Data The variable data.
+
+ @retval EFI_OUT_OF_RESOURCES There is not enough memory to perform the operation.
+ @retval EFI_SUCCESS The variable is appended to file successfully.
+ @retval others Failed to append the variable to file.
+**/
+EFI_STATUS
+AppendSingleVariableToFile (
+ IN SHELL_FILE_HANDLE FileHandle,
+ IN CONST CHAR16 *Name,
+ IN CONST EFI_GUID *Guid,
+ IN UINT32 Attributes,
+ IN UINT32 DataSize,
+ IN CONST UINT8 *Data
+ )
+{
+ UINT32 NameSize;
+ UINT8 *Buffer;
+ UINT8 *Ptr;
+ UINTN BufferSize;
+ EFI_STATUS Status;
+
+ NameSize = (UINT32) StrSize (Name);
+ BufferSize = sizeof (NameSize) + sizeof (DataSize)
+ + sizeof (*Guid)
+ + sizeof (Attributes)
+ + NameSize + DataSize
+ + sizeof (UINT32);
+
+ Buffer = AllocatePool (BufferSize);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Ptr = Buffer;
+ //
+ // NameSize and DataSize
+ //
+ * (UINT32 *) Ptr = NameSize;
+ Ptr += sizeof (NameSize);
+ *(UINT32 *) Ptr = DataSize;
+ Ptr += sizeof (DataSize);
+
+ //
+ // Name
+ //
+ CopyMem (Ptr, Name, NameSize);
+ Ptr += NameSize;
+
+ //
+ // Guid
+ //
+ CopyMem (Ptr, Guid, sizeof (*Guid));
+ Ptr += sizeof (*Guid);
+
+ //
+ // Attributes
+ //
+ * (UINT32 *) Ptr = Attributes;
+ Ptr += sizeof (Attributes);
+
+ //
+ // Data
+ //
+ CopyMem (Ptr, Data, DataSize);
+ Ptr += DataSize;
+
+ //
+ // Crc32
+ //
+ gBS->CalculateCrc32 (Buffer, (UINTN) (Ptr - Buffer), (UINT32 *) Ptr);
+
+ Status = ShellWriteFile (FileHandle, &BufferSize, Buffer);
+ FreePool (Buffer);
+
+ if (!EFI_ERROR (Status) &&
+ (BufferSize != sizeof (NameSize) + sizeof (DataSize) + sizeof (*Guid) + sizeof (Attributes) + NameSize + DataSize + sizeof (UINT32))
+ ) {
+ Status = EFI_DEVICE_ERROR;
+ }
+
+ return Status;
+}
+
+/**
+ Recursive function to display or delete variables.
+
+ This function will call itself to create a stack-based list of allt he variables to process,
+ then fromt he last to the first, they will do either printing or deleting.
+
+ This is necessary since once a delete happens GetNextVariableName() will work.
+
+ @param[in] Name The variable name of the EFI variable (or NULL).
+ @param[in] Guid The GUID of the variable set (or NULL).
+ @param[in] Type The operation type.
+ @param[in] FileHandle The file to operate on (or NULL).
+ @param[in] PrevName The previous variable name from GetNextVariableName. L"" to start.
+ @param[in] FoundVarGuid The previous GUID from GetNextVariableName. ignored at start.
+ @param[in] FoundOne If a VariableName or Guid was specified and one was printed or
+ deleted, then set this to TRUE, otherwise ignored.
+
+ @retval SHELL_SUCCESS The operation was successful.
+ @retval SHELL_OUT_OF_RESOURCES A memorty allocation failed.
+ @retval SHELL_ABORTED The abort message was received.
+ @retval SHELL_DEVICE_ERROR UEFI Variable Services returned an error.
+ @retval SHELL_NOT_FOUND the Name/Guid pair could not be found.
+**/
+SHELL_STATUS
+EFIAPI
+CascadeProcessVariables (
+ IN CONST CHAR16 *Name OPTIONAL,
+ IN CONST EFI_GUID *Guid OPTIONAL,
+ IN DMP_STORE_TYPE Type,
+ IN EFI_FILE_PROTOCOL *FileHandle OPTIONAL,
+ IN CONST CHAR16 * CONST PrevName,
+ IN EFI_GUID FoundVarGuid,
+ IN BOOLEAN *FoundOne
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *FoundVarName;
+ UINT8 *DataBuffer;
+ UINTN DataSize;
+ UINT32 Atts;
+ SHELL_STATUS ShellStatus;
+ UINTN NameSize;
+ CHAR16 *RetString;
+
+ if (ShellGetExecutionBreakFlag()) {
+ return (SHELL_ABORTED);
+ }
+
+ NameSize = 0;
+ FoundVarName = NULL;
+
+ if (PrevName!=NULL) {
+ StrnCatGrow(&FoundVarName, &NameSize, PrevName, 0);
+ } else {
+ FoundVarName = AllocateZeroPool(sizeof(CHAR16));
+ }
+
+ Status = gRT->GetNextVariableName (&NameSize, FoundVarName, &FoundVarGuid);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ SHELL_FREE_NON_NULL(FoundVarName);
+ FoundVarName = AllocateZeroPool (NameSize);
+ if (FoundVarName != NULL) {
+ if (PrevName != NULL) {
+ StrnCpyS(FoundVarName, NameSize/sizeof(CHAR16), PrevName, NameSize/sizeof(CHAR16) - 1);
+ }
+
+ Status = gRT->GetNextVariableName (&NameSize, FoundVarName, &FoundVarGuid);
+ } else {
+ Status = EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ //
+ // No more is fine.
+ //
+ if (Status == EFI_NOT_FOUND) {
+ SHELL_FREE_NON_NULL(FoundVarName);
+ return (SHELL_SUCCESS);
+ } else if (EFI_ERROR(Status)) {
+ SHELL_FREE_NON_NULL(FoundVarName);
+ return (SHELL_DEVICE_ERROR);
+ }
+
+ //
+ // Recurse to the next iteration. We know "our" variable's name.
+ //
+ ShellStatus = CascadeProcessVariables(Name, Guid, Type, FileHandle, FoundVarName, FoundVarGuid, FoundOne);
+
+ if (ShellGetExecutionBreakFlag() || (ShellStatus == SHELL_ABORTED)) {
+ SHELL_FREE_NON_NULL(FoundVarName);
+ return (SHELL_ABORTED);
+ }
+
+ //
+ // No matter what happened we process our own variable
+ // Only continue if Guid and VariableName are each either NULL or a match
+ //
+ if ( ( Name == NULL
+ || gUnicodeCollation->MetaiMatch(gUnicodeCollation, FoundVarName, (CHAR16*) Name) )
+ && ( Guid == NULL
+ || CompareGuid(&FoundVarGuid, Guid) )
+ ) {
+ DataSize = 0;
+ DataBuffer = NULL;
+ //
+ // do the print or delete
+ //
+ *FoundOne = TRUE;
+ Status = gRT->GetVariable (FoundVarName, &FoundVarGuid, &Atts, &DataSize, DataBuffer);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ SHELL_FREE_NON_NULL (DataBuffer);
+ DataBuffer = AllocatePool (DataSize);
+ if (DataBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ Status = gRT->GetVariable (FoundVarName, &FoundVarGuid, &Atts, &DataSize, DataBuffer);
+ }
+ }
+ if ((Type == DmpStoreDisplay) || (Type == DmpStoreSave)) {
+ //
+ // Last error check then print this variable out.
+ //
+ if (!EFI_ERROR(Status) && (DataBuffer != NULL) && (FoundVarName != NULL)) {
+ RetString = GetAttrType(Atts);
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_DMPSTORE_HEADER_LINE),
+ gShellDebug1HiiHandle,
+ RetString,
+ &FoundVarGuid,
+ FoundVarName,
+ DataSize);
+ if (Type == DmpStoreDisplay) {
+ DumpHex(2, 0, DataSize, DataBuffer);
+ } else {
+ Status = AppendSingleVariableToFile (
+ FileHandle,
+ FoundVarName,
+ &FoundVarGuid,
+ Atts,
+ (UINT32) DataSize,
+ DataBuffer
+ );
+ }
+ SHELL_FREE_NON_NULL(RetString);
+ }
+ } else if (Type == DmpStoreDelete) {
+ //
+ // We only need name to delete it...
+ //
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_DMPSTORE_DELETE_LINE),
+ gShellDebug1HiiHandle,
+ &FoundVarGuid,
+ FoundVarName,
+ gRT->SetVariable (FoundVarName, &FoundVarGuid, Atts, 0, NULL)
+ );
+ }
+ SHELL_FREE_NON_NULL(DataBuffer);
+ }
+
+ SHELL_FREE_NON_NULL(FoundVarName);
+
+ if (Status == EFI_DEVICE_ERROR) {
+ ShellStatus = SHELL_DEVICE_ERROR;
+ } else if (Status == EFI_SECURITY_VIOLATION) {
+ ShellStatus = SHELL_SECURITY_VIOLATION;
+ } else if (EFI_ERROR(Status)) {
+ ShellStatus = SHELL_NOT_READY;
+ }
+
+ return (ShellStatus);
+}
+
+/**
+ Function to display or delete variables. This will set up and call into the recursive function.
+
+ @param[in] Name The variable name of the EFI variable (or NULL).
+ @param[in] Guid The GUID of the variable set (or NULL).
+ @param[in] Type The operation type.
+ @param[in] FileHandle The file to save or load variables.
+
+ @retval SHELL_SUCCESS The operation was successful.
+ @retval SHELL_OUT_OF_RESOURCES A memorty allocation failed.
+ @retval SHELL_ABORTED The abort message was received.
+ @retval SHELL_DEVICE_ERROR UEFI Variable Services returned an error.
+ @retval SHELL_NOT_FOUND the Name/Guid pair could not be found.
+**/
+SHELL_STATUS
+EFIAPI
+ProcessVariables (
+ IN CONST CHAR16 *Name OPTIONAL,
+ IN CONST EFI_GUID *Guid OPTIONAL,
+ IN DMP_STORE_TYPE Type,
+ IN SHELL_FILE_HANDLE FileHandle OPTIONAL
+ )
+{
+ SHELL_STATUS ShellStatus;
+ BOOLEAN Found;
+ EFI_GUID FoundVarGuid;
+
+ Found = FALSE;
+ ShellStatus = SHELL_SUCCESS;
+ ZeroMem (&FoundVarGuid, sizeof(EFI_GUID));
+
+ if (Type == DmpStoreLoad) {
+ ShellStatus = LoadVariablesFromFile (FileHandle, Name, Guid, &Found);
+ } else {
+ ShellStatus = CascadeProcessVariables(Name, Guid, Type, FileHandle, NULL, FoundVarGuid, &Found);
+ }
+
+ if (!Found) {
+ if (ShellStatus == SHELL_OUT_OF_RESOURCES) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle, L"dmpstore");
+ return (ShellStatus);
+ } else if (Name != NULL && Guid == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_N), gShellDebug1HiiHandle, L"dmpstore", Name);
+ } else if (Name != NULL && Guid != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_GN), gShellDebug1HiiHandle, L"dmpstore", Guid, Name);
+ } else if (Name == NULL && Guid == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND), gShellDebug1HiiHandle, L"dmpstore");
+ } else if (Name == NULL && Guid != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_NO_VAR_FOUND_G), gShellDebug1HiiHandle, L"dmpstore", Guid);
+ }
+ return (SHELL_NOT_FOUND);
+ }
+ return (ShellStatus);
+}
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-d", TypeFlag},
+ {L"-l", TypeValue},
+ {L"-s", TypeValue},
+ {L"-all", TypeFlag},
+ {L"-guid", TypeValue},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'dmpstore' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDmpStore (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ CONST CHAR16 *GuidStr;
+ CONST CHAR16 *File;
+ EFI_GUID *Guid;
+ EFI_GUID GuidData;
+ CONST CHAR16 *Name;
+ DMP_STORE_TYPE Type;
+ SHELL_FILE_HANDLE FileHandle;
+ EFI_FILE_INFO *FileInfo;
+
+ ShellStatus = SHELL_SUCCESS;
+ Package = NULL;
+ FileHandle = NULL;
+ File = NULL;
+ Type = DmpStoreDisplay;
+
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"dmpstore", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetCount(Package) > 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"dmpstore");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetFlag(Package, L"-all") && ShellCommandLineGetFlag(Package, L"-guid")) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDebug1HiiHandle, L"dmpstore", L"-all", L"-guid");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetFlag(Package, L"-s") && ShellCommandLineGetFlag(Package, L"-l")) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDebug1HiiHandle, L"dmpstore", L"-l", L"-s");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if ((ShellCommandLineGetFlag(Package, L"-s") || ShellCommandLineGetFlag(Package, L"-l")) && ShellCommandLineGetFlag(Package, L"-d")) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDebug1HiiHandle, L"dmpstore", L"-l or -s", L"-d");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // Determine the GUID to search for based on -all and -guid parameters
+ //
+ if (!ShellCommandLineGetFlag(Package, L"-all")) {
+ GuidStr = ShellCommandLineGetValue(Package, L"-guid");
+ if (GuidStr != NULL) {
+ Status = ConvertStringToGuid(GuidStr, &GuidData);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"dmpstore", GuidStr);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ Guid = &GuidData;
+ } else {
+ Guid = &gEfiGlobalVariableGuid;
+ }
+ } else {
+ Guid = NULL;
+ }
+
+ //
+ // Get the Name of the variable to find
+ //
+ Name = ShellCommandLineGetRawValue(Package, 1);
+
+ if (ShellStatus == SHELL_SUCCESS) {
+ if (ShellCommandLineGetFlag(Package, L"-s")) {
+ Type = DmpStoreSave;
+ File = ShellCommandLineGetValue(Package, L"-s");
+ if (File == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"dmpstore", L"-s");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Status = ShellOpenFileByName (File, &FileHandle, EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ, 0);
+ if (!EFI_ERROR (Status)) {
+ //
+ // Delete existing file, but do not delete existing directory
+ //
+ FileInfo = ShellGetFileInfo (FileHandle);
+ if (FileInfo == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", File);
+ Status = EFI_DEVICE_ERROR;
+ } else {
+ if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_IS_DIRECTORY), gShellDebug1HiiHandle, L"dmpstore", File);
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ Status = ShellDeleteFile (&FileHandle);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_DELETE_FAIL), gShellDebug1HiiHandle, L"dmpstore", File);
+ }
+ }
+ FreePool (FileInfo);
+ }
+ } else if (Status == EFI_NOT_FOUND) {
+ //
+ // Good when file doesn't exist
+ //
+ Status = EFI_SUCCESS;
+ } else {
+ //
+ // Otherwise it's bad.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", File);
+ }
+
+ if (!EFI_ERROR (Status)) {
+ Status = ShellOpenFileByName (File, &FileHandle, EFI_FILE_MODE_CREATE | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_READ, 0);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", File);
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ }
+ } else if (ShellCommandLineGetFlag(Package, L"-l")) {
+ Type = DmpStoreLoad;
+ File = ShellCommandLineGetValue(Package, L"-l");
+ if (File == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"dmpstore", L"-l");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Status = ShellOpenFileByName (File, &FileHandle, EFI_FILE_MODE_READ, 0);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", File);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ FileInfo = ShellGetFileInfo (FileHandle);
+ if (FileInfo == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"dmpstore", File);
+ ShellStatus = SHELL_DEVICE_ERROR;
+ } else {
+ if ((FileInfo->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_IS_DIRECTORY), gShellDebug1HiiHandle, L"dmpstore", File);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ FreePool (FileInfo);
+ }
+ }
+ }
+ } else if (ShellCommandLineGetFlag(Package, L"-d")) {
+ Type = DmpStoreDelete;
+ }
+ }
+
+ if (ShellStatus == SHELL_SUCCESS) {
+ if (Type == DmpStoreSave) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_SAVE), gShellDebug1HiiHandle, File);
+ } else if (Type == DmpStoreLoad) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DMPSTORE_LOAD), gShellDebug1HiiHandle, File);
+ }
+ ShellStatus = ProcessVariables (Name, Guid, Type, FileHandle);
+ if ((Type == DmpStoreLoad) || (Type == DmpStoreSave)) {
+ ShellCloseFile (&FileHandle);
+ }
+ }
+ }
+ }
+
+ if (Package != NULL) {
+ ShellCommandLineFreeVarList (Package);
+ }
+ return ShellStatus;
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Edit.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Edit.c
new file mode 100644
index 0000000000..986b7e7b88
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Edit.c
@@ -0,0 +1,162 @@
+/** @file
+ Main file for Edit shell Debug1 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDebug1CommandsLib.h"
+#include "TextEditor.h"
+
+/**
+ Function for 'edit' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunEdit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *Buffer;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ LIST_ENTRY *Package;
+ CONST CHAR16 *Cwd;
+ CHAR16 *Nfs;
+ CHAR16 *Spot;
+ CONST CHAR16 *TempParam;
+// SHELL_FILE_HANDLE TempHandle;
+
+ Buffer = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ Nfs = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"edit", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetCount(Package) > 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"edit");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Cwd = gEfiShellProtocol->GetCurDir(NULL);
+ if (Cwd == NULL) {
+ Cwd = ShellGetEnvironmentVariable(L"path");
+ if (Cwd != NULL) {
+ Nfs = StrnCatGrow(&Nfs, NULL, Cwd+3, 0);
+ if (Nfs != NULL) {
+ Spot = StrStr(Nfs, L";");
+ if (Spot != NULL) {
+ *Spot = CHAR_NULL;
+ }
+ Spot = StrStr(Nfs, L"\\");
+ if (Spot != NULL) {
+ Spot[1] = CHAR_NULL;
+ }
+ gEfiShellProtocol->SetCurDir(NULL, Nfs);
+ FreePool(Nfs);
+ }
+ }
+ }
+
+ Status = MainEditorInit ();
+
+ if (EFI_ERROR (Status)) {
+ gST->ConOut->ClearScreen (gST->ConOut);
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_MAIN_INIT_FAILED), gShellDebug1HiiHandle);
+ } else {
+ MainEditorBackup ();
+
+ //
+ // if editor launched with file named
+ //
+ if (ShellCommandLineGetCount(Package) == 2) {
+ TempParam = ShellCommandLineGetRawValue(Package, 1);
+ ASSERT(TempParam != NULL);
+ FileBufferSetFileName (TempParam);
+// if (EFI_ERROR(ShellFileExists(MainEditor.FileBuffer->FileName))) {
+// Status = ShellOpenFileByName(MainEditor.FileBuffer->FileName, &TempHandle, EFI_FILE_MODE_CREATE|EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0);
+// if (!EFI_ERROR(Status)) {
+// ShellCloseFile(&TempHandle);
+// }
+// }
+ }
+
+ Status = FileBufferRead (MainEditor.FileBuffer->FileName, FALSE);
+ if (!EFI_ERROR (Status)) {
+ MainEditorRefresh ();
+
+ Status = MainEditorKeyInput ();
+ }
+
+ if (Status != EFI_OUT_OF_RESOURCES) {
+ //
+ // back up the status string
+ //
+ Buffer = CatSPrint (NULL, L"%s", StatusBarGetString());
+ }
+
+ MainEditorCleanup ();
+
+ //
+ // print editor exit code on screen
+ //
+ if (Status == EFI_SUCCESS) {
+ } else if (Status == EFI_OUT_OF_RESOURCES) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_GEN_OUT_MEM), gShellDebug1HiiHandle, L"edit");
+ } else {
+ if (Buffer != NULL) {
+ if (StrCmp (Buffer, L"") != 0) {
+ //
+ // print out the status string
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_MAIN_BUFFER), gShellDebug1HiiHandle, Buffer);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_MAIN_UNKNOWN_EDITOR_ERR), gShellDebug1HiiHandle);
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_MAIN_UNKNOWN_EDITOR_ERR), gShellDebug1HiiHandle);
+ }
+ }
+
+ if (Status != EFI_OUT_OF_RESOURCES) {
+ SHELL_FREE_NON_NULL (Buffer);
+ }
+ }
+ }
+ ShellCommandLineFreeVarList (Package);
+ }
+ return ShellStatus;
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.c
new file mode 100644
index 0000000000..efe0df0253
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.c
@@ -0,0 +1,3370 @@
+/** @file
+ Implements filebuffer interface functions.
+
+ Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "TextEditor.h"
+#include <Guid/FileSystemInfo.h>
+#include <Library/FileHandleLib.h>
+
+EFI_EDITOR_FILE_BUFFER FileBuffer;
+EFI_EDITOR_FILE_BUFFER FileBufferBackupVar;
+
+//
+// for basic initialization of FileBuffer
+//
+EFI_EDITOR_FILE_BUFFER FileBufferConst = {
+ NULL,
+ FileTypeUnicode,
+ NULL,
+ NULL,
+ 0,
+ {
+ 0,
+ 0
+ },
+ {
+ 0,
+ 0
+ },
+ {
+ 0,
+ 0
+ },
+ {
+ 0,
+ 0
+ },
+ FALSE,
+ TRUE,
+ FALSE,
+ NULL
+};
+
+//
+// the whole edit area needs to be refreshed
+//
+BOOLEAN FileBufferNeedRefresh;
+
+//
+// only the current line in edit area needs to be refresh
+//
+BOOLEAN FileBufferOnlyLineNeedRefresh;
+
+BOOLEAN FileBufferMouseNeedRefresh;
+
+extern BOOLEAN EditorMouseAction;
+
+/**
+ Initialization function for FileBuffer.
+
+ @param EFI_SUCCESS The initialization was successful.
+ @param EFI_LOAD_ERROR A default name could not be created.
+ @param EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferInit (
+ VOID
+ )
+{
+ //
+ // basically initialize the FileBuffer
+ //
+ CopyMem (&FileBuffer , &FileBufferConst, sizeof (EFI_EDITOR_FILE_BUFFER));
+ CopyMem (&FileBufferBackupVar, &FileBufferConst, sizeof (EFI_EDITOR_FILE_BUFFER));
+
+ //
+ // set default FileName
+ //
+ FileBuffer.FileName = EditGetDefaultFileName (L"txt");
+ if (FileBuffer.FileName == NULL) {
+ return EFI_LOAD_ERROR;
+ }
+
+ FileBuffer.ListHead = AllocateZeroPool (sizeof (LIST_ENTRY));
+ if (FileBuffer.ListHead == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ InitializeListHead (FileBuffer.ListHead);
+
+ FileBuffer.DisplayPosition.Row = 2;
+ FileBuffer.DisplayPosition.Column = 1;
+ FileBuffer.LowVisibleRange.Row = 2;
+ FileBuffer.LowVisibleRange.Column = 1;
+
+ FileBufferNeedRefresh = FALSE;
+ FileBufferMouseNeedRefresh = FALSE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Backup function for FileBuffer. Only backup the following items:
+ Mouse/Cursor position
+ File Name, Type, ReadOnly, Modified
+ Insert Mode
+
+ This is for making the file buffer refresh as few as possible.
+
+ @retval EFI_SUCCESS The backup operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferBackup (
+ VOID
+ )
+{
+ FileBufferBackupVar.MousePosition = FileBuffer.MousePosition;
+
+ SHELL_FREE_NON_NULL (FileBufferBackupVar.FileName);
+ FileBufferBackupVar.FileName = NULL;
+ FileBufferBackupVar.FileName = StrnCatGrow (&FileBufferBackupVar.FileName, NULL, FileBuffer.FileName, 0);
+
+ FileBufferBackupVar.ModeInsert = FileBuffer.ModeInsert;
+ FileBufferBackupVar.FileType = FileBuffer.FileType;
+
+ FileBufferBackupVar.FilePosition = FileBuffer.FilePosition;
+ FileBufferBackupVar.LowVisibleRange = FileBuffer.LowVisibleRange;
+
+ FileBufferBackupVar.FileModified = FileBuffer.FileModified;
+ FileBufferBackupVar.ReadOnly = FileBuffer.ReadOnly;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Advance to the next Count lines
+
+ @param[in] Count The line number to advance by.
+ @param[in] CurrentLine The pointer to the current line structure.
+ @param[in] LineList The pointer to the linked list of lines.
+
+ @retval NULL There was an error.
+ @return The line structure after the advance.
+**/
+EFI_EDITOR_LINE *
+EFIAPI
+InternalEditorMiscLineAdvance (
+ IN CONST UINTN Count,
+ IN CONST EFI_EDITOR_LINE *CurrentLine,
+ IN CONST LIST_ENTRY *LineList
+ )
+
+{
+ UINTN Index;
+ CONST EFI_EDITOR_LINE *Line;
+
+ if (CurrentLine == NULL || LineList == NULL) {
+ return NULL;
+ }
+
+ for (Line = CurrentLine, Index = 0; Index < Count; Index++) {
+ //
+ // if already last line
+ //
+ if (Line->Link.ForwardLink == LineList) {
+ return NULL;
+ }
+
+ Line = CR (Line->Link.ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+ }
+
+ return ((EFI_EDITOR_LINE *)Line);
+}
+
+/**
+ Retreat to the previous Count lines.
+
+ @param[in] Count The line number to retreat by.
+ @param[in] CurrentLine The pointer to the current line structure.
+ @param[in] LineList The pointer to the linked list of lines.
+
+ @retval NULL There was an error.
+ @return The line structure after the retreat.
+**/
+EFI_EDITOR_LINE *
+EFIAPI
+InternalEditorMiscLineRetreat (
+ IN CONST UINTN Count,
+ IN CONST EFI_EDITOR_LINE *CurrentLine,
+ IN CONST LIST_ENTRY *LineList
+ )
+
+{
+ UINTN Index;
+ CONST EFI_EDITOR_LINE *Line;
+
+ if (CurrentLine == NULL || LineList == NULL) {
+ return NULL;
+ }
+
+ for (Line = CurrentLine, Index = 0; Index < Count; Index++) {
+ //
+ // already the first line
+ //
+ if (Line->Link.BackLink == LineList) {
+ return NULL;
+ }
+
+ Line = CR (Line->Link.BackLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+ }
+
+ return ((EFI_EDITOR_LINE *)Line);
+}
+
+/**
+ Advance/Retreat lines
+
+ @param[in] Count line number to advance/retreat
+ >0 : advance
+ <0 : retreat
+
+ @retval NULL An error occured.
+ @return The line after advance/retreat.
+**/
+EFI_EDITOR_LINE *
+MoveLine (
+ IN CONST INTN Count
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN AbsCount;
+
+ //
+ // if < 0, then retreat
+ // if > 0, the advance
+ //
+ if (Count <= 0) {
+ AbsCount = (UINTN)ABS(Count);
+ Line = InternalEditorMiscLineRetreat (AbsCount,MainEditor.FileBuffer->CurrentLine,MainEditor.FileBuffer->ListHead);
+ } else {
+ Line = InternalEditorMiscLineAdvance ((UINTN)Count,MainEditor.FileBuffer->CurrentLine,MainEditor.FileBuffer->ListHead);
+ }
+
+ return Line;
+}
+
+/**
+ Function to update the 'screen' to display the mouse position.
+
+ @retval EFI_SUCCESS The backup operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferRestoreMousePosition (
+ VOID
+ )
+{
+ EFI_EDITOR_COLOR_UNION Orig;
+ EFI_EDITOR_COLOR_UNION New;
+ UINTN FRow;
+ UINTN FColumn;
+ BOOLEAN HasCharacter;
+ EFI_EDITOR_LINE *CurrentLine;
+ EFI_EDITOR_LINE *Line;
+ CHAR16 Value;
+
+ //
+ // variable initialization
+ //
+ Line = NULL;
+
+ if (MainEditor.MouseSupported) {
+
+ if (FileBufferMouseNeedRefresh) {
+
+ FileBufferMouseNeedRefresh = FALSE;
+
+ //
+ // if mouse position not moved and only mouse action
+ // so do not need to refresh mouse position
+ //
+ if ((FileBuffer.MousePosition.Row == FileBufferBackupVar.MousePosition.Row &&
+ FileBuffer.MousePosition.Column == FileBufferBackupVar.MousePosition.Column)
+ && EditorMouseAction) {
+ return EFI_SUCCESS;
+ }
+ //
+ // backup the old screen attributes
+ //
+ Orig = MainEditor.ColorAttributes;
+ New.Data = 0;
+ New.Colors.Foreground = Orig.Colors.Background & 0xF;
+ New.Colors.Background = Orig.Colors.Foreground & 0x7;
+
+ //
+ // clear the old mouse position
+ //
+ FRow = FileBuffer.LowVisibleRange.Row + FileBufferBackupVar.MousePosition.Row - 2;
+
+ FColumn = FileBuffer.LowVisibleRange.Column + FileBufferBackupVar.MousePosition.Column - 1;
+
+ HasCharacter = TRUE;
+ if (FRow > FileBuffer.NumLines) {
+ HasCharacter = FALSE;
+ } else {
+ CurrentLine = FileBuffer.CurrentLine;
+ Line = MoveLine (FRow - FileBuffer.FilePosition.Row);
+
+ if (Line == NULL || FColumn > Line->Size) {
+ HasCharacter = FALSE;
+ }
+
+ FileBuffer.CurrentLine = CurrentLine;
+ }
+
+ ShellPrintEx (
+ (INT32)FileBufferBackupVar.MousePosition.Column - 1,
+ (INT32)FileBufferBackupVar.MousePosition.Row - 1,
+ L" "
+ );
+
+ if (HasCharacter) {
+ Value = (Line->Buffer[FColumn - 1]);
+ ShellPrintEx (
+ (INT32)FileBufferBackupVar.MousePosition.Column - 1,
+ (INT32)FileBufferBackupVar.MousePosition.Row - 1,
+ L"%c",
+ Value
+ );
+ }
+ //
+ // set the new mouse position
+ //
+ gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F);
+
+ //
+ // clear the old mouse position
+ //
+ FRow = FileBuffer.LowVisibleRange.Row + FileBuffer.MousePosition.Row - 2;
+ FColumn = FileBuffer.LowVisibleRange.Column + FileBuffer.MousePosition.Column - 1;
+
+ HasCharacter = TRUE;
+ if (FRow > FileBuffer.NumLines) {
+ HasCharacter = FALSE;
+ } else {
+ CurrentLine = FileBuffer.CurrentLine;
+ Line = MoveLine (FRow - FileBuffer.FilePosition.Row);
+
+ if (Line == NULL || FColumn > Line->Size) {
+ HasCharacter = FALSE;
+ }
+
+ FileBuffer.CurrentLine = CurrentLine;
+ }
+
+ ShellPrintEx (
+ (INT32)FileBuffer.MousePosition.Column - 1,
+ (INT32)FileBuffer.MousePosition.Row - 1,
+ L" "
+ );
+
+ if (HasCharacter) {
+ Value = Line->Buffer[FColumn - 1];
+ ShellPrintEx (
+ (INT32)FileBuffer.MousePosition.Column - 1,
+ (INT32)FileBuffer.MousePosition.Row - 1,
+ L"%c",
+ Value
+ );
+ }
+ //
+ // end of HasCharacter
+ //
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
+ }
+ //
+ // end of MouseNeedRefresh
+ //
+ }
+ //
+ // end of MouseSupported
+ //
+ return EFI_SUCCESS;
+}
+
+/**
+ Free all the lines in FileBuffer
+ Fields affected:
+ Lines
+ CurrentLine
+ NumLines
+ ListHead
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferFreeLines (
+ VOID
+ )
+{
+ LIST_ENTRY *Link;
+ EFI_EDITOR_LINE *Line;
+
+ //
+ // free all the lines
+ //
+ if (FileBuffer.Lines != NULL) {
+
+ Line = FileBuffer.Lines;
+ Link = &(Line->Link);
+ do {
+ Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+ Link = Link->ForwardLink;
+
+ //
+ // free line's buffer and line itself
+ //
+ LineFree (Line);
+ } while (Link != FileBuffer.ListHead);
+ }
+ //
+ // clean the line list related structure
+ //
+ FileBuffer.Lines = NULL;
+ FileBuffer.CurrentLine = NULL;
+ FileBuffer.NumLines = 0;
+
+ FileBuffer.ListHead->ForwardLink = FileBuffer.ListHead;
+ FileBuffer.ListHead->BackLink = FileBuffer.ListHead;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Cleanup function for FileBuffer.
+
+ @retval EFI_SUCCESS The cleanup was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferCleanup (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ SHELL_FREE_NON_NULL (FileBuffer.FileName);
+
+ //
+ // free all the lines
+ //
+ Status = FileBufferFreeLines ();
+
+ SHELL_FREE_NON_NULL (FileBuffer.ListHead);
+ FileBuffer.ListHead = NULL;
+
+ SHELL_FREE_NON_NULL (FileBufferBackupVar.FileName);
+ return Status;
+
+}
+
+/**
+ Print a line specified by Line on a row specified by Row of the screen.
+
+ @param[in] Line The line to print.
+ @param[in] Row The row on the screen to print onto (begin from 1).
+
+ @retval EFI_SUCCESS The printing was successful.
+**/
+EFI_STATUS
+FileBufferPrintLine (
+ IN CONST EFI_EDITOR_LINE *Line,
+ IN CONST UINTN Row
+ )
+{
+
+ CHAR16 *Buffer;
+ UINTN Limit;
+ CHAR16 *PrintLine;
+ CHAR16 *PrintLine2;
+ UINTN BufLen;
+
+ //
+ // print start from correct character
+ //
+ Buffer = Line->Buffer + FileBuffer.LowVisibleRange.Column - 1;
+
+ Limit = Line->Size - FileBuffer.LowVisibleRange.Column + 1;
+ if (Limit > Line->Size) {
+ Limit = 0;
+ }
+
+ BufLen = (MainEditor.ScreenSize.Column + 1) * sizeof (CHAR16);
+ PrintLine = AllocatePool (BufLen);
+ if (PrintLine != NULL) {
+ StrnCpyS (PrintLine, BufLen/sizeof(CHAR16), Buffer, MIN(Limit, MainEditor.ScreenSize.Column));
+ for (; Limit < MainEditor.ScreenSize.Column; Limit++) {
+ PrintLine[Limit] = L' ';
+ }
+
+ PrintLine[MainEditor.ScreenSize.Column] = CHAR_NULL;
+
+ PrintLine2 = AllocatePool (BufLen * 2);
+ if (PrintLine2 != NULL) {
+ ShellCopySearchAndReplace(PrintLine, PrintLine2, BufLen * 2, L"%", L"^%", FALSE, FALSE);
+
+ ShellPrintEx (
+ 0,
+ (INT32)Row - 1,
+ L"%s",
+ PrintLine2
+ );
+ FreePool (PrintLine2);
+ }
+ FreePool (PrintLine);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set the cursor position according to FileBuffer.DisplayPosition.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferRestorePosition (
+ VOID
+ )
+{
+ //
+ // set cursor position
+ //
+ return (gST->ConOut->SetCursorPosition (
+ gST->ConOut,
+ FileBuffer.DisplayPosition.Column - 1,
+ FileBuffer.DisplayPosition.Row - 1
+ ));
+}
+
+/**
+ Refresh the screen with whats in the buffer.
+
+ @retval EFI_SUCCESS The refresh was successful.
+ @retval EFI_LOAD_ERROR There was an error finding what to write.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferRefresh (
+ VOID
+ )
+{
+ LIST_ENTRY *Link;
+ EFI_EDITOR_LINE *Line;
+ UINTN Row;
+
+ //
+ // if it's the first time after editor launch, so should refresh
+ //
+ if (!EditorFirst) {
+ //
+ // no definite required refresh
+ // and file position displayed on screen has not been changed
+ //
+ if (!FileBufferNeedRefresh &&
+ !FileBufferOnlyLineNeedRefresh &&
+ FileBufferBackupVar.LowVisibleRange.Row == FileBuffer.LowVisibleRange.Row &&
+ FileBufferBackupVar.LowVisibleRange.Column == FileBuffer.LowVisibleRange.Column
+ ) {
+
+ FileBufferRestoreMousePosition ();
+ FileBufferRestorePosition ();
+
+ return EFI_SUCCESS;
+ }
+ }
+
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);
+
+ //
+ // only need to refresh current line
+ //
+ if (FileBufferOnlyLineNeedRefresh &&
+ FileBufferBackupVar.LowVisibleRange.Row == FileBuffer.LowVisibleRange.Row &&
+ FileBufferBackupVar.LowVisibleRange.Column == FileBuffer.LowVisibleRange.Column
+ ) {
+
+ EditorClearLine (FileBuffer.DisplayPosition.Row, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row);
+ FileBufferPrintLine (
+ FileBuffer.CurrentLine,
+ FileBuffer.DisplayPosition.Row
+ );
+ } else {
+ //
+ // the whole edit area need refresh
+ //
+
+ //
+ // no line
+ //
+ if (FileBuffer.Lines == NULL) {
+ FileBufferRestoreMousePosition ();
+ FileBufferRestorePosition ();
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+
+ return EFI_SUCCESS;
+ }
+ //
+ // get the first line that will be displayed
+ //
+ Line = MoveLine (FileBuffer.LowVisibleRange.Row - FileBuffer.FilePosition.Row);
+ if (Line == NULL) {
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+
+ return EFI_LOAD_ERROR;
+ }
+
+ Link = &(Line->Link);
+ Row = 2;
+ do {
+ Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+
+ //
+ // print line at row
+ //
+ FileBufferPrintLine (Line, Row);
+
+ Link = Link->ForwardLink;
+ Row++;
+ } while (Link != FileBuffer.ListHead && Row <= (MainEditor.ScreenSize.Row - 1));
+ //
+ // while not file end and not screen full
+ //
+ while (Row <= (MainEditor.ScreenSize.Row - 1)) {
+ EditorClearLine (Row, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row);
+ Row++;
+ }
+ }
+
+ FileBufferRestoreMousePosition ();
+ FileBufferRestorePosition ();
+
+ FileBufferNeedRefresh = FALSE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+ return EFI_SUCCESS;
+}
+
+/**
+ Create a new line and append it to the line list.
+ Fields affected:
+ NumLines
+ Lines
+
+ @retval NULL The create line failed.
+ @return The line created.
+**/
+EFI_EDITOR_LINE *
+EFIAPI
+FileBufferCreateLine (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+
+ //
+ // allocate a line structure
+ //
+ Line = AllocateZeroPool (sizeof (EFI_EDITOR_LINE));
+ if (Line == NULL) {
+ return NULL;
+ }
+ //
+ // initialize the structure
+ //
+ Line->Signature = LINE_LIST_SIGNATURE;
+ Line->Size = 0;
+ Line->TotalSize = 0;
+ Line->Type = NewLineTypeDefault;
+
+ //
+ // initial buffer of the line is "\0"
+ //
+ ASSERT(CHAR_NULL == CHAR_NULL);
+ Line->Buffer = CatSPrint (NULL, L"\0");
+ if (Line->Buffer == NULL) {
+ return NULL;
+ }
+
+ FileBuffer.NumLines++;
+
+ //
+ // insert the line into line list
+ //
+ InsertTailList (FileBuffer.ListHead, &Line->Link);
+
+ if (FileBuffer.Lines == NULL) {
+ FileBuffer.Lines = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+ }
+
+ return Line;
+}
+
+/**
+ Set FileName field in FileBuffer.
+
+ @param Str The file name to set.
+
+ @retval EFI_SUCCESS The filename was successfully set.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_INVALID_PARAMETER Str is not a valid filename.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferSetFileName (
+ IN CONST CHAR16 *Str
+ )
+{
+ //
+ // Verify the parameters
+ //
+ if (!IsValidFileName(Str)) {
+ return (EFI_INVALID_PARAMETER);
+ }
+ //
+ // free the old file name
+ //
+ SHELL_FREE_NON_NULL (FileBuffer.FileName);
+
+ //
+ // Allocate and set the new name
+ //
+ FileBuffer.FileName = CatSPrint (NULL, L"%s", Str);
+ if (FileBuffer.FileName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+/**
+ Free the existing file lines and reset the modified flag.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferFree (
+ VOID
+ )
+{
+ //
+ // free all the lines
+ //
+ FileBufferFreeLines ();
+ FileBuffer.FileModified = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Read a file from disk into the FileBuffer.
+
+ @param[in] FileName The filename to read.
+ @param[in] Recover TRUE if is for recover mode, no information printouts.
+
+ @retval EFI_SUCCESS The load was successful.
+ @retval EFI_LOAD_ERROR The load failed.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_INVALID_PARAMETER FileName is a directory.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferRead (
+ IN CONST CHAR16 *FileName,
+ IN CONST BOOLEAN Recover
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ EE_NEWLINE_TYPE Type;
+ UINTN LoopVar1;
+ UINTN LoopVar2;
+ UINTN LineSize;
+ VOID *Buffer;
+ CHAR16 *UnicodeBuffer;
+ UINT8 *AsciiBuffer;
+ UINTN FileSize;
+ SHELL_FILE_HANDLE FileHandle;
+ BOOLEAN CreateFile;
+ EFI_STATUS Status;
+ UINTN LineSizeBackup;
+ EFI_FILE_INFO *Info;
+
+ Line = NULL;
+ LoopVar1 = 0;
+ FileSize = 0;
+ UnicodeBuffer = NULL;
+ Type = NewLineTypeDefault;
+ FileHandle = NULL;
+ CreateFile = FALSE;
+
+ //
+ // in this function, when you return error ( except EFI_OUT_OF_RESOURCES )
+ // you should set status string via StatusBarSetStatusString(L"blah")
+ // since this function maybe called before the editorhandleinput loop
+ // so any error will cause editor return
+ // so if you want to print the error status
+ // you should set the status string
+ //
+
+ //
+ // try to open the file
+ //
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0);
+
+ if (!EFI_ERROR(Status)) {
+ CreateFile = FALSE;
+ if (FileHandle == NULL) {
+ StatusBarSetStatusString (L"Disk Error");
+ return EFI_LOAD_ERROR;
+ }
+
+ Info = ShellGetFileInfo(FileHandle);
+
+ if (Info->Attribute & EFI_FILE_DIRECTORY) {
+ StatusBarSetStatusString (L"Directory Can Not Be Edited");
+ FreePool (Info);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Info->Attribute & EFI_FILE_READ_ONLY) {
+ FileBuffer.ReadOnly = TRUE;
+ } else {
+ FileBuffer.ReadOnly = FALSE;
+ }
+ //
+ // get file size
+ //
+ FileSize = (UINTN) Info->FileSize;
+
+ FreePool (Info);
+ } else if (Status == EFI_NOT_FOUND) {
+ //
+ // file not exists. add create and try again
+ //
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_WRITE_PROTECTED ||
+ Status == EFI_ACCESS_DENIED ||
+ Status == EFI_NO_MEDIA ||
+ Status == EFI_MEDIA_CHANGED
+ ) {
+ StatusBarSetStatusString (L"Access Denied");
+ } else if (Status == EFI_DEVICE_ERROR || Status == EFI_VOLUME_CORRUPTED || Status == EFI_VOLUME_FULL) {
+ StatusBarSetStatusString (L"Disk Error");
+ } else {
+ StatusBarSetStatusString (L"Invalid File Name or Current-working-directory");
+ }
+
+ return Status;
+ } else {
+ //
+ // it worked. now delete it and move on with the name (now validated)
+ //
+ Status = ShellDeleteFile (&FileHandle);
+ if (Status == EFI_WARN_DELETE_FAILURE) {
+ Status = EFI_ACCESS_DENIED;
+ }
+ FileHandle = NULL;
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Access Denied");
+ return Status;
+ }
+ }
+ //
+ // file doesn't exist, so set CreateFile to TRUE
+ //
+ CreateFile = TRUE;
+ FileBuffer.ReadOnly = FALSE;
+
+ //
+ // all the check ends
+ // so now begin to set file name, free lines
+ //
+ if (StrCmp (FileName, FileBuffer.FileName) != 0) {
+ FileBufferSetFileName (FileName);
+ }
+ //
+ // free the old lines
+ //
+ FileBufferFree ();
+
+ }
+ //
+ // the file exists
+ //
+ if (!CreateFile) {
+ //
+ // allocate buffer to read file
+ //
+ Buffer = AllocateZeroPool (FileSize);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // read file into Buffer
+ //
+ Status = ShellReadFile (FileHandle, &FileSize, Buffer);
+ ShellCloseFile(&FileHandle);
+ FileHandle = NULL;
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Read File Failed");
+ SHELL_FREE_NON_NULL (Buffer);
+ return EFI_LOAD_ERROR;
+ }
+ //
+ // nothing in this file
+ //
+ if (FileSize == 0) {
+ SHELL_FREE_NON_NULL (Buffer);
+ //
+ // since has no head, so only can be an ASCII file
+ //
+ FileBuffer.FileType = FileTypeAscii;
+
+ goto Done;
+ }
+
+ AsciiBuffer = Buffer;
+
+ if (FileSize < 2) {
+ //
+ // size < Unicode file header, so only can be ASCII file
+ //
+ FileBuffer.FileType = FileTypeAscii;
+ } else {
+ //
+ // Unicode file
+ //
+ if (*(UINT16 *) Buffer == EFI_UNICODE_BYTE_ORDER_MARK) {
+ //
+ // Unicode file's size should be even
+ //
+ if ((FileSize % 2) != 0) {
+ StatusBarSetStatusString (L"File Format Wrong");
+ SHELL_FREE_NON_NULL (Buffer);
+ return EFI_LOAD_ERROR;
+ }
+
+ FileSize /= 2;
+
+ FileBuffer.FileType = FileTypeUnicode;
+ UnicodeBuffer = Buffer;
+
+ //
+ // pass this 0xff and 0xfe
+ //
+ UnicodeBuffer++;
+ FileSize--;
+ } else {
+ FileBuffer.FileType = FileTypeAscii;
+ }
+ //
+ // end of AsciiBuffer ==
+ //
+ }
+ //
+ // end of FileSize < 2
+ // all the check ends
+ // so now begin to set file name, free lines
+ //
+ if (StrCmp (FileName, FileBuffer.FileName) != 0) {
+ FileBufferSetFileName (FileName);
+ }
+
+ //
+ // free the old lines
+ //
+ FileBufferFree ();
+
+ //
+ // parse file content line by line
+ //
+ for (LoopVar1 = 0; LoopVar1 < FileSize; LoopVar1++) {
+ Type = NewLineTypeUnknown;
+
+ for (LineSize = LoopVar1; LineSize < FileSize; LineSize++) {
+ if (FileBuffer.FileType == FileTypeAscii) {
+ if (AsciiBuffer[LineSize] == CHAR_CARRIAGE_RETURN) {
+ Type = NewLineTypeCarriageReturn;
+
+ //
+ // has LF following
+ //
+ if (LineSize < FileSize - 1) {
+ if (AsciiBuffer[LineSize + 1] == CHAR_LINEFEED) {
+ Type = NewLineTypeCarriageReturnLineFeed;
+ }
+ }
+
+ break;
+ } else if (AsciiBuffer[LineSize] == CHAR_LINEFEED) {
+ Type = NewLineTypeLineFeed;
+
+ //
+ // has CR following
+ //
+ if (LineSize < FileSize - 1) {
+ if (AsciiBuffer[LineSize + 1] == CHAR_CARRIAGE_RETURN) {
+ Type = NewLineTypeLineFeedCarriageReturn;
+ }
+ }
+
+ break;
+ }
+ } else {
+ if (UnicodeBuffer[LineSize] == CHAR_CARRIAGE_RETURN) {
+ Type = NewLineTypeCarriageReturn;
+
+ //
+ // has LF following
+ //
+ if (LineSize < FileSize - 1) {
+ if (UnicodeBuffer[LineSize + 1] == CHAR_LINEFEED) {
+ Type = NewLineTypeCarriageReturnLineFeed;
+ }
+ }
+
+ break;
+ } else if (UnicodeBuffer[LineSize] == CHAR_LINEFEED) {
+ Type = NewLineTypeLineFeed;
+
+ //
+ // has CR following
+ //
+ if (LineSize < FileSize - 1) {
+ if (UnicodeBuffer[LineSize + 1] == CHAR_CARRIAGE_RETURN) {
+ Type = NewLineTypeLineFeedCarriageReturn;
+ }
+ }
+
+ break;
+ }
+ }
+ //
+ // endif == ASCII
+ //
+ }
+ //
+ // end of for LineSize
+ //
+ // if the type is wrong, then exit
+ //
+ if (Type == NewLineTypeUnknown) {
+ //
+ // Now if Type is NewLineTypeUnknown, it should be file end
+ //
+ Type = NewLineTypeDefault;
+ }
+
+ LineSizeBackup = LineSize;
+
+ //
+ // create a new line
+ //
+ Line = FileBufferCreateLine ();
+ if (Line == NULL) {
+ SHELL_FREE_NON_NULL (Buffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // calculate file length
+ //
+ LineSize -= LoopVar1;
+
+ //
+ // Unicode and one CHAR_NULL
+ //
+ SHELL_FREE_NON_NULL (Line->Buffer);
+ Line->Buffer = AllocateZeroPool (LineSize * 2 + 2);
+
+ if (Line->Buffer == NULL) {
+ RemoveEntryList (&Line->Link);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // copy this line to Line->Buffer
+ //
+ for (LoopVar2 = 0; LoopVar2 < LineSize; LoopVar2++) {
+ if (FileBuffer.FileType == FileTypeAscii) {
+ Line->Buffer[LoopVar2] = (CHAR16) AsciiBuffer[LoopVar1];
+ } else {
+ Line->Buffer[LoopVar2] = UnicodeBuffer[LoopVar1];
+ }
+
+ LoopVar1++;
+ }
+ //
+ // LoopVar1 now points to where CHAR_CARRIAGE_RETURN or CHAR_LINEFEED;
+ //
+ Line->Buffer[LineSize] = 0;
+
+ Line->Size = LineSize;
+ Line->TotalSize = LineSize;
+ Line->Type = Type;
+
+ if (Type == NewLineTypeCarriageReturnLineFeed || Type == NewLineTypeLineFeedCarriageReturn) {
+ LoopVar1++;
+ }
+
+ //
+ // last character is a return, SO create a new line
+ //
+ if (((Type == NewLineTypeCarriageReturnLineFeed || Type == NewLineTypeLineFeedCarriageReturn) && LineSizeBackup == FileSize - 2) ||
+ ((Type == NewLineTypeLineFeed || Type == NewLineTypeCarriageReturn) && LineSizeBackup == FileSize - 1)
+ ) {
+ Line = FileBufferCreateLine ();
+ if (Line == NULL) {
+ SHELL_FREE_NON_NULL (Buffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+ //
+ // end of if
+ //
+ }
+ //
+ // end of LoopVar1
+ //
+ SHELL_FREE_NON_NULL (Buffer);
+
+ }
+ //
+ // end of if CreateFile
+ //
+Done:
+
+ FileBuffer.DisplayPosition.Row = 2;
+ FileBuffer.DisplayPosition.Column = 1;
+ FileBuffer.LowVisibleRange.Row = 1;
+ FileBuffer.LowVisibleRange.Column = 1;
+ FileBuffer.FilePosition.Row = 1;
+ FileBuffer.FilePosition.Column = 1;
+ FileBuffer.MousePosition.Row = 2;
+ FileBuffer.MousePosition.Column = 1;
+
+ if (!Recover) {
+ UnicodeBuffer = CatSPrint (NULL, L"%d Lines Read", FileBuffer.NumLines);
+ if (UnicodeBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StatusBarSetStatusString (UnicodeBuffer);
+ FreePool (UnicodeBuffer);
+ }
+/*
+ //
+ // check whether we have fs?: in filename
+ //
+ LoopVar1 = 0;
+ FSMappingPtr = NULL;
+ while (FileName[LoopVar1] != 0) {
+ if (FileName[LoopVar1] == L':') {
+ FSMappingPtr = &FileName[LoopVar1];
+ break;
+ }
+
+ LoopVar1++;
+ }
+
+ if (FSMappingPtr == NULL) {
+ CurDir = ShellGetCurrentDir (NULL);
+ } else {
+ LoopVar1 = 0;
+ LoopVar2 = 0;
+ while (FileName[LoopVar1] != 0) {
+ if (FileName[LoopVar1] == L':') {
+ break;
+ }
+
+ FSMapping[LoopVar2++] = FileName[LoopVar1];
+
+ LoopVar1++;
+ }
+
+ FSMapping[LoopVar2] = 0;
+ CurDir = ShellGetCurrentDir (FSMapping);
+ }
+
+ if (CurDir != NULL) {
+ for (LoopVar1 = 0; LoopVar1 < StrLen (CurDir) && CurDir[LoopVar1] != ':'; LoopVar1++);
+
+ CurDir[LoopVar1] = 0;
+ DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) ShellGetMap (CurDir);
+ FreePool (CurDir);
+ } else {
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = LibDevicePathToInterface (
+ &gEfiSimpleFileSystemProtocolGuid,
+ DevicePath,
+ (VOID **) &Vol
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = Vol->OpenVolume (Vol, &RootFs);
+ if (EFI_ERROR (Status)) {
+ return EFI_LOAD_ERROR;
+ }
+ //
+ // Get volume information of file system
+ //
+ Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + 100;
+ VolumeInfo = (EFI_FILE_SYSTEM_INFO *) AllocateZeroPool (Size);
+ Status = RootFs->GetInfo (RootFs, &gEfiFileSystemInfoGuid, &Size, VolumeInfo);
+ if (EFI_ERROR (Status)) {
+ RootFs->Close (RootFs);
+ return EFI_LOAD_ERROR;
+ }
+
+ if (VolumeInfo->ReadOnly) {
+ StatusBarSetStatusString (L"WARNING: Volume Read Only");
+ }
+
+ FreePool (VolumeInfo);
+ RootFs->Close (RootFs);
+ }
+//
+*/
+ //
+ // has line
+ //
+ if (FileBuffer.Lines != 0) {
+ FileBuffer.CurrentLine = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+ } else {
+ //
+ // create a dummy line
+ //
+ Line = FileBufferCreateLine ();
+ if (Line == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ FileBuffer.CurrentLine = Line;
+ }
+
+ FileBuffer.FileModified = FALSE;
+ FileBufferNeedRefresh = TRUE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+ FileBufferMouseNeedRefresh = TRUE;
+
+
+ return EFI_SUCCESS;
+}
+
+/**
+ According to FileBuffer.NewLineType & FileBuffer.FileType,
+ get the return buffer and size.
+
+ @param[in] Type The type of line.
+ @param[out] Buffer The buffer to fill.
+ @param[out] Size The amount of the buffer used on return.
+**/
+VOID
+EFIAPI
+GetNewLine (
+ IN CONST EE_NEWLINE_TYPE Type,
+ OUT CHAR8 *Buffer,
+ OUT UINT8 *Size
+ )
+{
+ UINT8 NewLineSize;
+
+ //
+ // give new line buffer,
+ // and will judge unicode or ascii
+ //
+ NewLineSize = 0;
+
+ //
+ // not legal new line type
+ //
+ if (Type != NewLineTypeLineFeed && Type != NewLineTypeCarriageReturn && Type != NewLineTypeCarriageReturnLineFeed && Type != NewLineTypeLineFeedCarriageReturn) {
+ *Size = 0;
+ return ;
+ }
+ //
+ // use_cr: give 0x0d
+ //
+ if (Type == NewLineTypeCarriageReturn) {
+ if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
+ Buffer[0] = 0x0d;
+ Buffer[1] = 0;
+ NewLineSize = 2;
+ } else {
+ Buffer[0] = 0x0d;
+ NewLineSize = 1;
+ }
+
+ *Size = NewLineSize;
+ return ;
+ }
+ //
+ // use_lf: give 0x0a
+ //
+ if (Type == NewLineTypeLineFeed) {
+ if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
+ Buffer[0] = 0x0a;
+ Buffer[1] = 0;
+ NewLineSize = 2;
+ } else {
+ Buffer[0] = 0x0a;
+ NewLineSize = 1;
+ }
+
+ *Size = NewLineSize;
+ return ;
+ }
+ //
+ // use_crlf: give 0x0d 0x0a
+ //
+ if (Type == NewLineTypeCarriageReturnLineFeed) {
+ if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
+ Buffer[0] = 0x0d;
+ Buffer[1] = 0;
+ Buffer[2] = 0x0a;
+ Buffer[3] = 0;
+
+ NewLineSize = 4;
+ } else {
+ Buffer[0] = 0x0d;
+ Buffer[1] = 0x0a;
+ NewLineSize = 2;
+ }
+
+ *Size = NewLineSize;
+ return ;
+ }
+ //
+ // use_lfcr: give 0x0a 0x0d
+ //
+ if (Type == NewLineTypeLineFeedCarriageReturn) {
+ if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
+ Buffer[0] = 0x0a;
+ Buffer[1] = 0;
+ Buffer[2] = 0x0d;
+ Buffer[3] = 0;
+
+ NewLineSize = 4;
+ } else {
+ Buffer[0] = 0x0a;
+ Buffer[1] = 0x0d;
+ NewLineSize = 2;
+ }
+
+ *Size = NewLineSize;
+ return ;
+ }
+
+}
+
+/**
+ Change a Unicode string to an ASCII string.
+
+ @param[in] UStr The Unicode string.
+ @param[in] Length The maximum size of AStr.
+ @param[out] AStr ASCII string to pass out.
+
+ @return The actuall length.
+**/
+UINTN
+EFIAPI
+UnicodeToAscii (
+ IN CONST CHAR16 *UStr,
+ IN CONST UINTN Length,
+ OUT CHAR8 *AStr
+ )
+{
+ UINTN Index;
+
+ //
+ // just buffer copy, not character copy
+ //
+ for (Index = 0; Index < Length; Index++) {
+ *AStr++ = (CHAR8) *UStr++;
+ }
+
+ return Index;
+}
+
+/**
+ Save lines in FileBuffer to disk
+
+ @param[in] FileName The file name for writing.
+
+ @retval EFI_SUCCESS Data was written.
+ @retval EFI_LOAD_ERROR
+ @retval EFI_OUT_OF_RESOURCES There were not enough resources to write the file.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferSave (
+ IN CONST CHAR16 *FileName
+ )
+{
+ SHELL_FILE_HANDLE FileHandle;
+ LIST_ENTRY *Link;
+ EFI_EDITOR_LINE *Line;
+ CHAR16 *Str;
+
+ EFI_STATUS Status;
+ UINTN Length;
+ UINTN NumLines;
+ CHAR8 NewLineBuffer[4];
+ UINT8 NewLineSize;
+
+ EFI_FILE_INFO *Info;
+
+ UINT64 Attribute;
+
+ EE_NEWLINE_TYPE Type;
+
+ UINTN TotalSize;
+ //
+ // 2M
+ //
+ CHAR8 *Cache;
+ UINTN LeftSize;
+ UINTN Size;
+ CHAR8 *Ptr;
+
+ Length = 0;
+ //
+ // 2M
+ //
+ TotalSize = 0x200000;
+
+ Attribute = 0;
+
+
+
+ //
+ // if is the old file
+ //
+ if (FileBuffer.FileName != NULL && StrCmp (FileName, FileBuffer.FileName) == 0) {
+ //
+ // file has not been modified
+ //
+ if (!FileBuffer.FileModified) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // if file is read-only, set error
+ //
+ if (FileBuffer.ReadOnly) {
+ StatusBarSetStatusString (L"Read Only File Can Not Be Saved");
+ return EFI_SUCCESS;
+ }
+ }
+
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0);
+
+ if (!EFI_ERROR (Status)) {
+ Info = ShellGetFileInfo(FileHandle);
+
+ if (Info != NULL && Info->Attribute & EFI_FILE_DIRECTORY) {
+ StatusBarSetStatusString (L"Directory Can Not Be Saved");
+ ShellCloseFile(FileHandle);
+ FreePool(Info);
+ return EFI_LOAD_ERROR;
+ }
+
+ if (Info != NULL) {
+ Attribute = Info->Attribute & ~EFI_FILE_READ_ONLY;
+ FreePool(Info);
+ }
+
+ //
+ // if file exits, so delete it
+ //
+ Status = ShellDeleteFile (&FileHandle);
+ if (EFI_ERROR (Status) || Status == EFI_WARN_DELETE_FAILURE) {
+ StatusBarSetStatusString (L"Write File Failed");
+ return EFI_LOAD_ERROR;
+ }
+ }
+
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, Attribute);
+
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Create File Failed");
+ return EFI_LOAD_ERROR;
+ }
+
+ //
+ // if file is Unicode file, write Unicode header to it.
+ //
+ if (FileBuffer.FileType == FileTypeUnicode) {
+ Length = 2;
+ Status = ShellWriteFile (FileHandle, &Length, (VOID*)&gUnicodeFileTag);
+ if (EFI_ERROR (Status)) {
+ ShellDeleteFile (&FileHandle);
+ return EFI_LOAD_ERROR;
+ }
+ }
+
+ Cache = AllocateZeroPool (TotalSize);
+ if (Cache == NULL) {
+ ShellDeleteFile (&FileHandle);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // write all the lines back to disk
+ //
+ NumLines = 0;
+ Type = NewLineTypeCarriageReturnLineFeed;
+
+ Ptr = Cache;
+ LeftSize = TotalSize;
+
+ for (Link = FileBuffer.ListHead->ForwardLink; Link != FileBuffer.ListHead; Link = Link->ForwardLink) {
+ Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+
+ if (Line->Type != NewLineTypeDefault) {
+ Type = Line->Type;
+ }
+ //
+ // newline character is at most 4 bytes ( two Unicode characters )
+ //
+ Length = 4;
+ if (Line->Buffer != NULL && Line->Size != 0) {
+ if (FileBuffer.FileType == FileTypeAscii) {
+ Length += Line->Size;
+ } else {
+ Length += (Line->Size * 2);
+ }
+ //
+ // end if FileTypeAscii
+ //
+ }
+
+ //
+ // no cache room left, so write cache to disk
+ //
+ if (LeftSize < Length) {
+ Size = TotalSize - LeftSize;
+ Status = ShellWriteFile (FileHandle, &Size, Cache);
+ if (EFI_ERROR (Status)) {
+ ShellDeleteFile (&FileHandle);
+ FreePool (Cache);
+ return EFI_LOAD_ERROR;
+ }
+ Ptr = Cache;
+ LeftSize = TotalSize;
+ }
+
+ if (Line->Buffer != NULL && Line->Size != 0) {
+ if (FileBuffer.FileType == FileTypeAscii) {
+ UnicodeToAscii (Line->Buffer, Line->Size, Ptr);
+ Length = Line->Size;
+ } else {
+ Length = (Line->Size * 2);
+ CopyMem (Ptr, (CHAR8 *) Line->Buffer, Length);
+ }
+ //
+ // end if FileTypeAscii
+ //
+ Ptr += Length;
+ LeftSize -= Length;
+
+ }
+ //
+ // end of if Line -> Buffer != NULL && Line -> Size != 0
+ //
+ // if not the last line , write return buffer to disk
+ //
+ if (Link->ForwardLink != FileBuffer.ListHead) {
+ GetNewLine (Type, NewLineBuffer, &NewLineSize);
+ CopyMem (Ptr, (CHAR8 *) NewLineBuffer, NewLineSize);
+
+ Ptr += NewLineSize;
+ LeftSize -= NewLineSize;
+ }
+
+ NumLines++;
+ }
+
+ if (TotalSize != LeftSize) {
+ Size = TotalSize - LeftSize;
+ Status = ShellWriteFile (FileHandle, &Size, Cache);
+ if (EFI_ERROR (Status)) {
+ ShellDeleteFile (&FileHandle);
+ FreePool (Cache);
+ return EFI_LOAD_ERROR;
+ }
+ }
+
+ FreePool (Cache);
+
+ ShellCloseFile(&FileHandle);
+
+ FileBuffer.FileModified = FALSE;
+
+ //
+ // set status string
+ //
+ Str = CatSPrint (NULL, L"%d Lines Wrote", NumLines);
+ if (Str == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StatusBarSetStatusString (Str);
+ SHELL_FREE_NON_NULL (Str);
+
+ //
+ // now everything is ready , you can set the new file name to filebuffer
+ //
+ if (FileName != NULL && FileBuffer.FileName != NULL && StrCmp (FileName, FileBuffer.FileName) != 0) {
+ //
+ // not the same
+ //
+ FileBufferSetFileName (FileName);
+ if (FileBuffer.FileName == NULL) {
+ ShellDeleteFile (&FileHandle);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ FileBuffer.ReadOnly = FALSE;
+ return EFI_SUCCESS;
+}
+
+/**
+ Scroll cursor to left 1 character position.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferScrollLeft (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+
+ Line = FileBuffer.CurrentLine;
+
+ FRow = FileBuffer.FilePosition.Row;
+ FCol = FileBuffer.FilePosition.Column;
+
+ //
+ // if already at start of this line, so move to the end of previous line
+ //
+ if (FCol <= 1) {
+ //
+ // has previous line
+ //
+ if (Line->Link.BackLink != FileBuffer.ListHead) {
+ FRow--;
+ Line = CR (Line->Link.BackLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+ FCol = Line->Size + 1;
+ } else {
+ return EFI_SUCCESS;
+ }
+ } else {
+ //
+ // if not at start of this line, just move to previous column
+ //
+ FCol--;
+ }
+
+ FileBufferMovePosition (FRow, FCol);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Delete a char in line
+
+ @param[in, out] Line The line to delete in.
+ @param[in] Pos Position to delete the char at ( start from 0 ).
+**/
+VOID
+EFIAPI
+LineDeleteAt (
+ IN OUT EFI_EDITOR_LINE *Line,
+ IN UINTN Pos
+ )
+{
+ UINTN Index;
+
+ //
+ // move the latter characters front
+ //
+ for (Index = Pos - 1; Index < Line->Size; Index++) {
+ Line->Buffer[Index] = Line->Buffer[Index + 1];
+ }
+
+ Line->Size--;
+}
+
+/**
+ Concatenate Src into Dest.
+
+ @param[in, out] Dest Destination string
+ @param[in] Src Src String.
+**/
+VOID
+EFIAPI
+LineCat (
+ IN OUT EFI_EDITOR_LINE *Dest,
+ IN EFI_EDITOR_LINE *Src
+ )
+{
+ CHAR16 *Str;
+ UINTN Size;
+
+ Size = Dest->Size;
+
+ Dest->Buffer[Size] = 0;
+
+ //
+ // concatenate the two strings
+ //
+ Str = CatSPrint (NULL, L"%s%s", Dest->Buffer, Src->Buffer);
+ if (Str == NULL) {
+ Dest->Buffer = NULL;
+ return ;
+ }
+
+ Dest->Size = Size + Src->Size;
+ Dest->TotalSize = Dest->Size;
+
+ FreePool (Dest->Buffer);
+ FreePool (Src->Buffer);
+
+ //
+ // put str to dest->buffer
+ //
+ Dest->Buffer = Str;
+}
+
+/**
+ Delete the previous character.
+
+ @retval EFI_SUCCESS The delete was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferDoBackspace (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ EFI_EDITOR_LINE *End;
+ LIST_ENTRY *Link;
+ UINTN FileColumn;
+
+ FileColumn = FileBuffer.FilePosition.Column;
+
+ Line = FileBuffer.CurrentLine;
+
+ //
+ // the first column
+ //
+ if (FileColumn == 1) {
+ //
+ // the first row
+ //
+ if (FileBuffer.FilePosition.Row == 1) {
+ return EFI_SUCCESS;
+ }
+
+ FileBufferScrollLeft ();
+
+ Line = FileBuffer.CurrentLine;
+ Link = Line->Link.ForwardLink;
+ End = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+
+ //
+ // concatenate this line with previous line
+ //
+ LineCat (Line, End);
+ if (Line->Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // remove End from line list
+ //
+ RemoveEntryList (&End->Link);
+ FreePool (End);
+
+ FileBuffer.NumLines--;
+
+ FileBufferNeedRefresh = TRUE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+
+ } else {
+ //
+ // just delete the previous character
+ //
+ LineDeleteAt (Line, FileColumn - 1);
+ FileBufferScrollLeft ();
+ FileBufferOnlyLineNeedRefresh = TRUE;
+ }
+
+ if (!FileBuffer.FileModified) {
+ FileBuffer.FileModified = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Add a return into line at current position.
+
+ @retval EFI_SUCCESS The insetrion of the character was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferDoReturn (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ EFI_EDITOR_LINE *NewLine;
+ UINTN FileColumn;
+ UINTN Index;
+ CHAR16 *Buffer;
+ UINTN Row;
+ UINTN Col;
+
+ FileBufferNeedRefresh = TRUE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+
+ Line = FileBuffer.CurrentLine;
+
+ FileColumn = FileBuffer.FilePosition.Column;
+
+ NewLine = AllocateZeroPool (sizeof (EFI_EDITOR_LINE));
+ if (NewLine == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewLine->Signature = LINE_LIST_SIGNATURE;
+ NewLine->Size = Line->Size - FileColumn + 1;
+ NewLine->TotalSize = NewLine->Size;
+ NewLine->Buffer = CatSPrint (NULL, L"\0");
+ if (NewLine->Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ NewLine->Type = NewLineTypeDefault;
+
+ if (NewLine->Size > 0) {
+ //
+ // UNICODE + CHAR_NULL
+ //
+ Buffer = AllocateZeroPool (2 * (NewLine->Size + 1));
+ if (Buffer == NULL) {
+ FreePool (NewLine->Buffer);
+ FreePool (NewLine);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ FreePool (NewLine->Buffer);
+
+ NewLine->Buffer = Buffer;
+
+ for (Index = 0; Index < NewLine->Size; Index++) {
+ NewLine->Buffer[Index] = Line->Buffer[Index + FileColumn - 1];
+ }
+
+ NewLine->Buffer[NewLine->Size] = CHAR_NULL;
+
+ Line->Buffer[FileColumn - 1] = CHAR_NULL;
+ Line->Size = FileColumn - 1;
+ }
+ //
+ // increase NumLines
+ //
+ FileBuffer.NumLines++;
+
+ //
+ // insert it into the correct position of line list
+ //
+ NewLine->Link.BackLink = &(Line->Link);
+ NewLine->Link.ForwardLink = Line->Link.ForwardLink;
+ Line->Link.ForwardLink->BackLink = &(NewLine->Link);
+ Line->Link.ForwardLink = &(NewLine->Link);
+
+ //
+ // move cursor to the start of next line
+ //
+ Row = FileBuffer.FilePosition.Row + 1;
+ Col = 1;
+
+ FileBufferMovePosition (Row, Col);
+
+ //
+ // set file is modified
+ //
+ if (!FileBuffer.FileModified) {
+ FileBuffer.FileModified = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Delete current character from current line. This is the effect caused
+ by the 'del' key.
+
+ @retval EFI_SUCCESS
+**/
+EFI_STATUS
+EFIAPI
+FileBufferDoDelete (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ EFI_EDITOR_LINE *Next;
+ LIST_ENTRY *Link;
+ UINTN FileColumn;
+
+ Line = FileBuffer.CurrentLine;
+ FileColumn = FileBuffer.FilePosition.Column;
+
+ //
+ // the last column
+ //
+ if (FileColumn >= Line->Size + 1) {
+ //
+ // the last line
+ //
+ if (Line->Link.ForwardLink == FileBuffer.ListHead) {
+ return EFI_SUCCESS;
+ }
+ //
+ // since last character,
+ // so will add the next line to this line
+ //
+ Link = Line->Link.ForwardLink;
+ Next = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+ LineCat (Line, Next);
+ if (Line->Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ RemoveEntryList (&Next->Link);
+ FreePool (Next);
+
+ FileBuffer.NumLines--;
+
+ FileBufferNeedRefresh = TRUE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+
+ } else {
+ //
+ // just delete current character
+ //
+ LineDeleteAt (Line, FileColumn);
+ FileBufferOnlyLineNeedRefresh = TRUE;
+ }
+
+ if (!FileBuffer.FileModified) {
+ FileBuffer.FileModified = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Scroll cursor to right 1 character.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferScrollRight (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+
+ Line = FileBuffer.CurrentLine;
+ if (Line->Buffer == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ FRow = FileBuffer.FilePosition.Row;
+ FCol = FileBuffer.FilePosition.Column;
+
+ //
+ // if already at end of this line, scroll it to the start of next line
+ //
+ if (FCol > Line->Size) {
+ //
+ // has next line
+ //
+ if (Line->Link.ForwardLink != FileBuffer.ListHead) {
+ FRow++;
+ FCol = 1;
+ } else {
+ return EFI_SUCCESS;
+ }
+ } else {
+ //
+ // if not at end of this line, just move to next column
+ //
+ FCol++;
+ }
+
+ FileBufferMovePosition (FRow, FCol);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Insert a char into line
+
+
+ @param[in] Line The line to insert into.
+ @param[in] Char The char to insert.
+ @param[in] Pos The position to insert the char at ( start from 0 ).
+ @param[in] StrSize The current string size ( include CHAR_NULL ),unit is Unicode character.
+
+ @return The new string size ( include CHAR_NULL ) ( unit is Unicode character ).
+**/
+UINTN
+EFIAPI
+LineStrInsert (
+ IN EFI_EDITOR_LINE *Line,
+ IN CHAR16 Char,
+ IN UINTN Pos,
+ IN UINTN StrSize
+ )
+{
+ UINTN Index;
+ CHAR16 *TempStringPtr;
+ CHAR16 *Str;
+
+ Index = (StrSize) * 2;
+
+ Str = Line->Buffer;
+
+ //
+ // do not have free space
+ //
+ if (Line->TotalSize <= Line->Size) {
+ Str = ReallocatePool (Index, Index + 16, Str);
+ if (Str == NULL) {
+ return 0;
+ }
+
+ Line->TotalSize += 8;
+ }
+ //
+ // move the later part of the string one character right
+ //
+ TempStringPtr = Str;
+ for (Index = StrSize; Index > Pos; Index--) {
+ TempStringPtr[Index] = TempStringPtr[Index - 1];
+ }
+ //
+ // insert char into it.
+ //
+ TempStringPtr[Index] = Char;
+
+ Line->Buffer = Str;
+ Line->Size++;
+
+ return StrSize + 1;
+}
+
+/**
+ Add a character to the current line.
+
+ @param[in] Char The Character to input.
+
+ @retval EFI_SUCCESS The input was succesful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferAddChar (
+ IN CHAR16 Char
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN FilePos;
+
+ Line = FileBuffer.CurrentLine;
+
+ //
+ // only needs to refresh current line
+ //
+ FileBufferOnlyLineNeedRefresh = TRUE;
+
+ //
+ // when is insert mode, or cursor is at end of this line,
+ // so insert this character
+ // or replace the character.
+ //
+ FilePos = FileBuffer.FilePosition.Column - 1;
+ if (FileBuffer.ModeInsert || FilePos + 1 > Line->Size) {
+ LineStrInsert (Line, Char, FilePos, Line->Size + 1);
+ } else {
+ Line->Buffer[FilePos] = Char;
+ }
+ //
+ // move cursor to right
+ //
+ FileBufferScrollRight ();
+
+ if (!FileBuffer.FileModified) {
+ FileBuffer.FileModified = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Handles inputs from characters (ASCII key + Backspace + return)
+
+ @param[in] Char The input character.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR There was an error.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferDoCharInput (
+ IN CONST CHAR16 Char
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ switch (Char) {
+ case CHAR_NULL:
+ break;
+
+ case CHAR_BACKSPACE:
+ Status = FileBufferDoBackspace ();
+ break;
+
+ case CHAR_TAB:
+ //
+ // Tabs are ignored
+ //
+ break;
+
+ case CHAR_LINEFEED:
+ case CHAR_CARRIAGE_RETURN:
+ Status = FileBufferDoReturn ();
+ break;
+
+ default:
+ //
+ // DEAL WITH ASCII CHAR, filter out thing like ctrl+f
+ //
+ if (Char > 127 || Char < 32) {
+ Status = StatusBarSetStatusString (L"Unknown Command");
+ } else {
+ Status = FileBufferAddChar (Char);
+ }
+
+ break;
+
+ }
+
+ return Status;
+}
+
+/**
+ Scroll cursor to the next line.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferScrollDown (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+
+ Line = FileBuffer.CurrentLine;
+ if (Line->Buffer == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ FRow = FileBuffer.FilePosition.Row;
+ FCol = FileBuffer.FilePosition.Column;
+
+ //
+ // has next line
+ //
+ if (Line->Link.ForwardLink != FileBuffer.ListHead) {
+ FRow++;
+ Line = CR (Line->Link.ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+
+ //
+ // if the next line is not that long, so move to end of next line
+ //
+ if (FCol > Line->Size) {
+ FCol = Line->Size + 1;
+ }
+
+ } else {
+ return EFI_SUCCESS;
+ }
+
+ FileBufferMovePosition (FRow, FCol);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Scroll the cursor to previous line.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferScrollUp (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+
+ Line = FileBuffer.CurrentLine;
+
+ FRow = FileBuffer.FilePosition.Row;
+ FCol = FileBuffer.FilePosition.Column;
+
+ //
+ // has previous line
+ //
+ if (Line->Link.BackLink != FileBuffer.ListHead) {
+ FRow--;
+ Line = CR (Line->Link.BackLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+
+ //
+ // if previous line is not that long, so move to the end of previous line
+ //
+ if (FCol > Line->Size) {
+ FCol = Line->Size + 1;
+ }
+
+ } else {
+ return EFI_SUCCESS;
+ }
+
+ FileBufferMovePosition (FRow, FCol);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Scroll cursor to next page.
+
+ @retval EFI_SUCCESS The operation wa successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferPageDown (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+ UINTN Gap;
+
+ Line = FileBuffer.CurrentLine;
+
+ FRow = FileBuffer.FilePosition.Row;
+ FCol = FileBuffer.FilePosition.Column;
+
+ //
+ // has next page
+ //
+ if (FileBuffer.NumLines >= FRow + (MainEditor.ScreenSize.Row - 2)) {
+ Gap = (MainEditor.ScreenSize.Row - 2);
+ } else {
+ //
+ // MOVE CURSOR TO LAST LINE
+ //
+ Gap = FileBuffer.NumLines - FRow;
+ }
+ //
+ // get correct line
+ //
+ Line = MoveLine (Gap);
+
+ //
+ // if that line, is not that long, so move to the end of that line
+ //
+ if (Line != NULL && FCol > Line->Size) {
+ FCol = Line->Size + 1;
+ }
+
+ FRow += Gap;
+
+ FileBufferMovePosition (FRow, FCol);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Scroll cursor to previous screen.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferPageUp (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+ UINTN Gap;
+ INTN Retreat;
+
+ Line = FileBuffer.CurrentLine;
+
+ FRow = FileBuffer.FilePosition.Row;
+ FCol = FileBuffer.FilePosition.Column;
+
+ //
+ // has previous page
+ //
+ if (FRow > (MainEditor.ScreenSize.Row - 2)) {
+ Gap = (MainEditor.ScreenSize.Row - 2);
+ } else {
+ //
+ // the first line of file will displayed on the first line of screen
+ //
+ Gap = FRow - 1;
+ }
+
+ Retreat = Gap;
+ Retreat = -Retreat;
+
+ //
+ // get correct line
+ //
+ Line = MoveLine (Retreat);
+
+ //
+ // if that line is not that long, so move to the end of that line
+ //
+ if (Line != NULL && FCol > Line->Size) {
+ FCol = Line->Size + 1;
+ }
+
+ FRow -= Gap;
+
+ FileBufferMovePosition (FRow, FCol);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Scroll cursor to end of the current line.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferEnd (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+
+ Line = FileBuffer.CurrentLine;
+
+ FRow = FileBuffer.FilePosition.Row;
+
+ //
+ // goto the last column of the line
+ //
+ FCol = Line->Size + 1;
+
+ FileBufferMovePosition (FRow, FCol);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Dispatch input to different handler
+ @param[in] Key The input key. One of:
+ ASCII KEY
+ Backspace/Delete
+ Return
+ Direction key: up/down/left/right/pgup/pgdn
+ Home/End
+ INS
+
+ @retval EFI_SUCCESS The dispatch was done successfully.
+ @retval EFI_LOAD_ERROR The dispatch was not successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferHandleInput (
+ IN CONST EFI_INPUT_KEY *Key
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ switch (Key->ScanCode) {
+ //
+ // ordinary key input
+ //
+ case SCAN_NULL:
+ if (!FileBuffer.ReadOnly) {
+ Status = FileBufferDoCharInput (Key->UnicodeChar);
+ } else {
+ Status = StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
+ }
+
+ break;
+
+ //
+ // up arrow
+ //
+ case SCAN_UP:
+ Status = FileBufferScrollUp ();
+ break;
+
+ //
+ // down arrow
+ //
+ case SCAN_DOWN:
+ Status = FileBufferScrollDown ();
+ break;
+
+ //
+ // right arrow
+ //
+ case SCAN_RIGHT:
+ Status = FileBufferScrollRight ();
+ break;
+
+ //
+ // left arrow
+ //
+ case SCAN_LEFT:
+ Status = FileBufferScrollLeft ();
+ break;
+
+ //
+ // page up
+ //
+ case SCAN_PAGE_UP:
+ Status = FileBufferPageUp ();
+ break;
+
+ //
+ // page down
+ //
+ case SCAN_PAGE_DOWN:
+ Status = FileBufferPageDown ();
+ break;
+
+ //
+ // delete
+ //
+ case SCAN_DELETE:
+ if (!FileBuffer.ReadOnly) {
+ Status = FileBufferDoDelete ();
+ } else {
+ Status = StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
+ }
+
+ break;
+
+ //
+ // home
+ //
+ case SCAN_HOME:
+ FileBufferMovePosition (FileBuffer.FilePosition.Row, 1);
+ Status = EFI_SUCCESS;
+ break;
+
+ //
+ // end
+ //
+ case SCAN_END:
+ Status = FileBufferEnd ();
+ break;
+
+ //
+ // insert
+ //
+ case SCAN_INSERT:
+ FileBuffer.ModeInsert = (BOOLEAN)!FileBuffer.ModeInsert;
+ Status = EFI_SUCCESS;
+ break;
+
+ default:
+ Status = StatusBarSetStatusString (L"Unknown Command");
+ break;
+ }
+
+ return Status;
+}
+
+/**
+ Check user specified FileRow is above current screen.
+
+ @param[in] FileRow The row of file position ( start from 1 ).
+
+ @retval TRUE It is above the current screen.
+ @retval FALSE It is not above the current screen.
+**/
+BOOLEAN
+EFIAPI
+AboveCurrentScreen (
+ IN UINTN FileRow
+ )
+{
+ //
+ // if is to the above of the screen
+ //
+ if (FileRow < FileBuffer.LowVisibleRange.Row) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Check user specified FileRow is under current screen.
+
+ @param[in] FileRow The row of file position ( start from 1 ).
+
+ @retval TRUE It is under the current screen.
+ @retval FALSE It is not under the current screen.
+**/
+BOOLEAN
+EFIAPI
+UnderCurrentScreen (
+ IN UINTN FileRow
+ )
+{
+ //
+ // if is to the under of the screen
+ //
+ if (FileRow > FileBuffer.LowVisibleRange.Row + (MainEditor.ScreenSize.Row - 2) - 1) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Check user specified FileCol is left to current screen.
+
+ @param[in] FileCol The column of file position ( start from 1 ).
+
+ @retval TRUE It is to the left.
+ @retval FALSE It is not to the left.
+**/
+BOOLEAN
+EFIAPI
+LeftCurrentScreen (
+ IN UINTN FileCol
+ )
+{
+ //
+ // if is to the left of the screen
+ //
+ if (FileCol < FileBuffer.LowVisibleRange.Column) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Check user specified FileCol is right to current screen.
+
+ @param[in] FileCol The column of file position ( start from 1 ).
+
+ @retval TRUE It is to the right.
+ @retval FALSE It is not to the right.
+**/
+BOOLEAN
+EFIAPI
+RightCurrentScreen (
+ IN UINTN FileCol
+ )
+{
+ //
+ // if is to the right of the screen
+ //
+ if (FileCol > FileBuffer.LowVisibleRange.Column + MainEditor.ScreenSize.Column - 1) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Advance/Retreat lines and set CurrentLine in FileBuffer to it
+
+ @param[in] Count The line number to advance/retreat
+ >0 : advance
+ <0: retreat
+
+ @retval NULL An error occured.
+ @return The line after advance/retreat.
+**/
+EFI_EDITOR_LINE *
+EFIAPI
+MoveCurrentLine (
+ IN INTN Count
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ UINTN AbsCount;
+
+ if (Count <= 0) {
+ AbsCount = (UINTN)ABS(Count);
+ Line = InternalEditorMiscLineRetreat (AbsCount,MainEditor.FileBuffer->CurrentLine,MainEditor.FileBuffer->ListHead);
+ } else {
+ Line = InternalEditorMiscLineAdvance ((UINTN)Count,MainEditor.FileBuffer->CurrentLine,MainEditor.FileBuffer->ListHead);
+ }
+
+ if (Line == NULL) {
+ return NULL;
+ }
+
+ MainEditor.FileBuffer->CurrentLine = Line;
+
+ return Line;
+}
+
+/**
+ According to cursor's file position, adjust screen display
+
+ @param[in] NewFilePosRow The row of file position ( start from 1 ).
+ @param[in] NewFilePosCol The column of file position ( start from 1 ).
+**/
+VOID
+EFIAPI
+FileBufferMovePosition (
+ IN CONST UINTN NewFilePosRow,
+ IN CONST UINTN NewFilePosCol
+ )
+{
+ INTN RowGap;
+ INTN ColGap;
+ UINTN Abs;
+ BOOLEAN Above;
+ BOOLEAN Under;
+ BOOLEAN Right;
+ BOOLEAN Left;
+
+ //
+ // CALCULATE gap between current file position and new file position
+ //
+ RowGap = NewFilePosRow - FileBuffer.FilePosition.Row;
+ ColGap = NewFilePosCol - FileBuffer.FilePosition.Column;
+
+ Under = UnderCurrentScreen (NewFilePosRow);
+ Above = AboveCurrentScreen (NewFilePosRow);
+ //
+ // if is below current screen
+ //
+ if (Under) {
+ //
+ // display row will be unchanged
+ //
+ FileBuffer.FilePosition.Row = NewFilePosRow;
+ } else {
+ if (Above) {
+ //
+ // has enough above line, so display row unchanged
+ // not has enough above lines, so the first line is at the
+ // first display line
+ //
+ if (NewFilePosRow < (FileBuffer.DisplayPosition.Row - 1)) {
+ FileBuffer.DisplayPosition.Row = NewFilePosRow + 1;
+ }
+
+ FileBuffer.FilePosition.Row = NewFilePosRow;
+ } else {
+ //
+ // in current screen
+ //
+ FileBuffer.FilePosition.Row = NewFilePosRow;
+ if (RowGap < 0) {
+ Abs = (UINTN)ABS(RowGap);
+ FileBuffer.DisplayPosition.Row -= Abs;
+ } else {
+ FileBuffer.DisplayPosition.Row += RowGap;
+ }
+ }
+ }
+
+ FileBuffer.LowVisibleRange.Row = FileBuffer.FilePosition.Row - (FileBuffer.DisplayPosition.Row - 2);
+
+ Right = RightCurrentScreen (NewFilePosCol);
+ Left = LeftCurrentScreen (NewFilePosCol);
+
+ //
+ // if right to current screen
+ //
+ if (Right) {
+ //
+ // display column will be changed to end
+ //
+ FileBuffer.DisplayPosition.Column = MainEditor.ScreenSize.Column;
+ FileBuffer.FilePosition.Column = NewFilePosCol;
+ } else {
+ if (Left) {
+ //
+ // has enough left characters , so display row unchanged
+ // not has enough left characters,
+ // so the first character is at the first display column
+ //
+ if (NewFilePosCol < (FileBuffer.DisplayPosition.Column)) {
+ FileBuffer.DisplayPosition.Column = NewFilePosCol;
+ }
+
+ FileBuffer.FilePosition.Column = NewFilePosCol;
+ } else {
+ //
+ // in current screen
+ //
+ FileBuffer.FilePosition.Column = NewFilePosCol;
+ if (ColGap < 0) {
+ Abs = (UINTN)(-ColGap);
+ FileBuffer.DisplayPosition.Column -= Abs;
+ } else {
+ FileBuffer.DisplayPosition.Column += ColGap;
+ }
+ }
+ }
+
+ FileBuffer.LowVisibleRange.Column = FileBuffer.FilePosition.Column - (FileBuffer.DisplayPosition.Column - 1);
+
+ //
+ // let CurrentLine point to correct line;
+ //
+ FileBuffer.CurrentLine = MoveCurrentLine (RowGap);
+
+}
+
+/**
+ Cut current line out and return a pointer to it.
+
+ @param[out] CutLine Upon a successful return pointer to the pointer to
+ the allocated cut line.
+
+ @retval EFI_SUCCESS The cut was successful.
+ @retval EFI_NOT_FOUND There was no selection to cut.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferCutLine (
+ OUT EFI_EDITOR_LINE **CutLine
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ EFI_EDITOR_LINE *NewLine;
+ UINTN Row;
+ UINTN Col;
+
+ if (FileBuffer.ReadOnly) {
+ StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
+ return EFI_SUCCESS;
+ }
+
+ Line = FileBuffer.CurrentLine;
+
+ //
+ // if is the last dummy line, SO CAN not cut
+ //
+ if (StrCmp (Line->Buffer, L"\0") == 0 && Line->Link.ForwardLink == FileBuffer.ListHead
+ //
+ // last line
+ //
+ ) {
+ //
+ // LAST LINE AND NOTHING ON THIS LINE, SO CUT NOTHING
+ //
+ StatusBarSetStatusString (L"Nothing to Cut");
+ return EFI_NOT_FOUND;
+ }
+ //
+ // if is the last line, so create a dummy line
+ //
+ if (Line->Link.ForwardLink == FileBuffer.ListHead) {
+ //
+ // last line
+ // create a new line
+ //
+ NewLine = FileBufferCreateLine ();
+ if (NewLine == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ FileBuffer.NumLines--;
+ Row = FileBuffer.FilePosition.Row;
+ Col = 1;
+ //
+ // move home
+ //
+ FileBuffer.CurrentLine = CR (
+ FileBuffer.CurrentLine->Link.ForwardLink,
+ EFI_EDITOR_LINE,
+ Link,
+ LINE_LIST_SIGNATURE
+ );
+
+ RemoveEntryList (&Line->Link);
+
+ FileBuffer.Lines = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+
+ FileBufferMovePosition (Row, Col);
+
+ FileBuffer.FileModified = TRUE;
+ FileBufferNeedRefresh = TRUE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+
+ *CutLine = Line;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Paste a line into line list.
+
+ @retval EFI_SUCCESS The paste was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferPasteLine (
+ VOID
+ )
+{
+ EFI_EDITOR_LINE *Line;
+ EFI_EDITOR_LINE *NewLine;
+ UINTN Row;
+ UINTN Col;
+
+ //
+ // if nothing is on clip board
+ // then do nothing
+ //
+ if (MainEditor.CutLine == NULL) {
+ return EFI_SUCCESS;
+ }
+ //
+ // read only file can not be pasted on
+ //
+ if (FileBuffer.ReadOnly) {
+ StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
+ return EFI_SUCCESS;
+ }
+
+ NewLine = LineDup (MainEditor.CutLine);
+ if (NewLine == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // insert it above current line
+ //
+ Line = FileBuffer.CurrentLine;
+ NewLine->Link.BackLink = Line->Link.BackLink;
+ NewLine->Link.ForwardLink = &Line->Link;
+
+ Line->Link.BackLink->ForwardLink = &NewLine->Link;
+ Line->Link.BackLink = &NewLine->Link;
+
+ FileBuffer.NumLines++;
+ FileBuffer.CurrentLine = NewLine;
+
+ FileBuffer.Lines = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+
+ Col = 1;
+ //
+ // move home
+ //
+ Row = FileBuffer.FilePosition.Row;
+
+ FileBufferMovePosition (Row, Col);
+
+ //
+ // after paste, set some value so that refresh knows to do something
+ //
+ FileBuffer.FileModified = TRUE;
+ FileBufferNeedRefresh = TRUE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Search string from current position on in file
+
+ @param[in] Str The search string.
+ @param[in] Offset The offset from current position.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_NOT_FOUND The string Str was not found.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferSearch (
+ IN CONST CHAR16 *Str,
+ IN CONST UINTN Offset
+ )
+{
+ CHAR16 *Current;
+ UINTN Position;
+ UINTN Row;
+ UINTN Column;
+ EFI_EDITOR_LINE *Line;
+ CHAR16 *CharPos;
+ LIST_ENTRY *Link;
+ BOOLEAN Found;
+
+ Column = 0;
+ Position = 0;
+
+ //
+ // search if in current line
+ //
+ Current = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1 + Offset;
+
+ if (Current >= (FileBuffer.CurrentLine->Buffer + FileBuffer.CurrentLine->Size)) {
+ //
+ // the end
+ //
+ Current = FileBuffer.CurrentLine->Buffer + FileBuffer.CurrentLine->Size;
+ }
+
+ Found = FALSE;
+
+ CharPos = StrStr (Current, Str);
+ if (CharPos != NULL) {
+ Position = CharPos - Current + 1;
+ Found = TRUE;
+ }
+
+ //
+ // found
+ //
+ if (Found) {
+ Column = (Position - 1) + FileBuffer.FilePosition.Column + Offset;
+ Row = FileBuffer.FilePosition.Row;
+ } else {
+ //
+ // not found so find through next lines
+ //
+ Link = FileBuffer.CurrentLine->Link.ForwardLink;
+
+ Row = FileBuffer.FilePosition.Row + 1;
+ while (Link != FileBuffer.ListHead) {
+ Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+// Position = StrStr (Line->Buffer, Str);
+ CharPos = StrStr (Line->Buffer, Str);
+ if (CharPos != NULL) {
+ Position = CharPos - Line->Buffer + 1;
+ Found = TRUE;
+ }
+
+ if (Found) {
+ //
+ // found
+ //
+ Column = Position;
+ break;
+ }
+
+ Row++;
+ Link = Link->ForwardLink;
+ }
+
+ if (Link == FileBuffer.ListHead) {
+ Found = FALSE;
+ } else {
+ Found = TRUE;
+ }
+ }
+
+ if (!Found) {
+ return EFI_NOT_FOUND;
+ }
+
+ FileBufferMovePosition (Row, Column);
+
+ //
+ // call refresh to fresh edit area,
+ // because the outer may loop to find multiply occurrence of this string
+ //
+ FileBufferRefresh ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Replace SearchLen characters from current position on with Replace.
+
+ This will modify the current buffer at the current position.
+
+ @param[in] Replace The string to replace.
+ @param[in] SearchLen Search string's length.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferReplace (
+ IN CONST CHAR16 *Replace,
+ IN CONST UINTN SearchLen
+ )
+{
+ UINTN ReplaceLen;
+ UINTN Index;
+ CHAR16 *Buffer;
+ UINTN NewSize;
+ UINTN OldSize;
+ UINTN Gap;
+
+ ReplaceLen = StrLen (Replace);
+
+ OldSize = FileBuffer.CurrentLine->Size + 1;
+ //
+ // include CHAR_NULL
+ //
+ NewSize = OldSize + (ReplaceLen - SearchLen);
+
+ if (ReplaceLen > SearchLen) {
+ //
+ // do not have the enough space
+ //
+ if (FileBuffer.CurrentLine->TotalSize + 1 <= NewSize) {
+ FileBuffer.CurrentLine->Buffer = ReallocatePool (
+ 2 * OldSize,
+ 2 * NewSize,
+ FileBuffer.CurrentLine->Buffer
+ );
+ FileBuffer.CurrentLine->TotalSize = NewSize - 1;
+ }
+
+ if (FileBuffer.CurrentLine->Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // the end CHAR_NULL character;
+ //
+ Buffer = FileBuffer.CurrentLine->Buffer + (NewSize - 1);
+ Gap = ReplaceLen - SearchLen;
+
+ //
+ // keep the latter part
+ //
+ for (Index = 0; Index < (FileBuffer.CurrentLine->Size - FileBuffer.FilePosition.Column - SearchLen + 2); Index++) {
+ *Buffer = *(Buffer - Gap);
+ Buffer--;
+ }
+ //
+ // set replace into it
+ //
+ Buffer = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1;
+ for (Index = 0; Index < ReplaceLen; Index++) {
+ Buffer[Index] = Replace[Index];
+ }
+ }
+
+ if (ReplaceLen < SearchLen) {
+ Buffer = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1;
+
+ for (Index = 0; Index < ReplaceLen; Index++) {
+ Buffer[Index] = Replace[Index];
+ }
+
+ Buffer += ReplaceLen;
+ Gap = SearchLen - ReplaceLen;
+
+ //
+ // set replace into it
+ //
+ for (Index = 0; Index < (FileBuffer.CurrentLine->Size - FileBuffer.FilePosition.Column - ReplaceLen + 2); Index++) {
+ *Buffer = *(Buffer + Gap);
+ Buffer++;
+ }
+ }
+
+ if (ReplaceLen == SearchLen) {
+ Buffer = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1;
+ for (Index = 0; Index < ReplaceLen; Index++) {
+ Buffer[Index] = Replace[Index];
+ }
+ }
+
+ FileBuffer.CurrentLine->Size += (ReplaceLen - SearchLen);
+
+ FileBufferOnlyLineNeedRefresh = TRUE;
+
+ FileBuffer.FileModified = TRUE;
+
+ MainTitleBarRefresh (MainEditor.FileBuffer->FileName, MainEditor.FileBuffer->FileType, MainEditor.FileBuffer->ReadOnly, MainEditor.FileBuffer->FileModified, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row, 0, 0);
+ FileBufferRestorePosition ();
+ FileBufferRefresh ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Move the mouse cursor position.
+
+ @param[in] TextX The new x-coordinate.
+ @param[in] TextY The new y-coordinate.
+**/
+VOID
+EFIAPI
+FileBufferAdjustMousePosition (
+ IN CONST INT32 TextX,
+ IN CONST INT32 TextY
+ )
+{
+ UINTN CoordinateX;
+ UINTN CoordinateY;
+ UINTN AbsX;
+ UINTN AbsY;
+
+ //
+ // TextX and TextY is mouse movement data returned by mouse driver
+ // This function will change it to MousePosition
+ //
+ //
+ // get absolute value
+ //
+
+ AbsX = ABS(TextX);
+ AbsY = ABS(TextY);
+
+ CoordinateX = FileBuffer.MousePosition.Column;
+ CoordinateY = FileBuffer.MousePosition.Row;
+
+ if (TextX >= 0) {
+ CoordinateX += TextX;
+ } else {
+ if (CoordinateX >= AbsX) {
+ CoordinateX -= AbsX;
+ } else {
+ CoordinateX = 0;
+ }
+ }
+
+ if (TextY >= 0) {
+ CoordinateY += TextY;
+ } else {
+ if (CoordinateY >= AbsY) {
+ CoordinateY -= AbsY;
+ } else {
+ CoordinateY = 0;
+ }
+ }
+ //
+ // check whether new mouse column position is beyond screen
+ // if not, adjust it
+ //
+ if (CoordinateX >= 1 && CoordinateX <= MainEditor.ScreenSize.Column) {
+ FileBuffer.MousePosition.Column = CoordinateX;
+ } else if (CoordinateX < 1) {
+ FileBuffer.MousePosition.Column = 1;
+ } else if (CoordinateX > MainEditor.ScreenSize.Column) {
+ FileBuffer.MousePosition.Column = MainEditor.ScreenSize.Column;
+ }
+ //
+ // check whether new mouse row position is beyond screen
+ // if not, adjust it
+ //
+ if (CoordinateY >= 2 && CoordinateY <= (MainEditor.ScreenSize.Row - 1)) {
+ FileBuffer.MousePosition.Row = CoordinateY;
+ } else if (CoordinateY < 2) {
+ FileBuffer.MousePosition.Row = 2;
+ } else if (CoordinateY > (MainEditor.ScreenSize.Row - 1)) {
+ FileBuffer.MousePosition.Row = (MainEditor.ScreenSize.Row - 1);
+ }
+
+}
+
+/**
+ Search and replace operation.
+
+ @param[in] SearchStr The string to search for.
+ @param[in] ReplaceStr The string to replace with.
+ @param[in] Offset The column to start at.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferReplaceAll (
+ IN CHAR16 *SearchStr,
+ IN CHAR16 *ReplaceStr,
+ IN UINTN Offset
+ )
+{
+ CHAR16 *Buffer;
+ UINTN Position;
+ UINTN Column;
+ UINTN ReplaceLen;
+ UINTN SearchLen;
+ UINTN Index;
+ UINTN NewSize;
+ UINTN OldSize;
+ UINTN Gap;
+ EFI_EDITOR_LINE *Line;
+ LIST_ENTRY *Link;
+ CHAR16 *CharPos;
+
+ SearchLen = StrLen (SearchStr);
+ ReplaceLen = StrLen (ReplaceStr);
+
+ Column = FileBuffer.FilePosition.Column + Offset - 1;
+
+ if (Column > FileBuffer.CurrentLine->Size) {
+ Column = FileBuffer.CurrentLine->Size;
+ }
+
+ Link = &(FileBuffer.CurrentLine->Link);
+
+ while (Link != FileBuffer.ListHead) {
+ Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+ CharPos = StrStr (Line->Buffer + Column, SearchStr);
+ if (CharPos != NULL) {
+ Position = CharPos - Line->Buffer;// + Column;
+ //
+ // found
+ //
+ if (ReplaceLen > SearchLen) {
+ OldSize = Line->Size + 1;
+ //
+ // include CHAR_NULL
+ //
+ NewSize = OldSize + (ReplaceLen - SearchLen);
+
+ //
+ // do not have the enough space
+ //
+ if (Line->TotalSize + 1 <= NewSize) {
+ Line->Buffer = ReallocatePool (
+ 2 * OldSize,
+ 2 * NewSize,
+ Line->Buffer
+ );
+ Line->TotalSize = NewSize - 1;
+ }
+
+ if (Line->Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // the end CHAR_NULL character;
+ //
+ Buffer = Line->Buffer + (NewSize - 1);
+ Gap = ReplaceLen - SearchLen;
+
+ //
+ // keep the latter part
+ //
+ for (Index = 0; Index < (Line->Size - Position - SearchLen + 1); Index++) {
+ *Buffer = *(Buffer - Gap);
+ Buffer--;
+ }
+
+ } else if (ReplaceLen < SearchLen){
+ Buffer = Line->Buffer + Position + ReplaceLen;
+ Gap = SearchLen - ReplaceLen;
+
+ for (Index = 0; Index < (Line->Size - Position - ReplaceLen + 1); Index++) {
+ *Buffer = *(Buffer + Gap);
+ Buffer++;
+ }
+ } else {
+ ASSERT(ReplaceLen == SearchLen);
+ }
+ //
+ // set replace into it
+ //
+ Buffer = Line->Buffer + Position;
+ for (Index = 0; Index < ReplaceLen; Index++) {
+ Buffer[Index] = ReplaceStr[Index];
+ }
+
+ Line->Size += (ReplaceLen - SearchLen);
+ Column += ReplaceLen;
+ } else {
+ //
+ // not found
+ //
+ Column = 0;
+ Link = Link->ForwardLink;
+ }
+ }
+ //
+ // call refresh to fresh edit area
+ //
+ FileBuffer.FileModified = TRUE;
+ FileBufferNeedRefresh = TRUE;
+ FileBufferRefresh ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set the modified state to TRUE.
+**/
+VOID
+EFIAPI
+FileBufferSetModified (
+ VOID
+ )
+{
+ FileBuffer.FileModified = TRUE;
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.h
new file mode 100644
index 0000000000..9d4a08d7a3
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/FileBuffer.h
@@ -0,0 +1,263 @@
+/** @file
+ Declares filebuffer interface functions.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LIB_FILE_BUFFER_H_
+#define _LIB_FILE_BUFFER_H_
+
+#include "TextEditorTypes.h"
+
+/**
+ Initialization function for FileBuffer.
+
+ @param EFI_SUCCESS The initialization was successful.
+ @param EFI_LOAD_ERROR A default name could not be created.
+ @param EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferInit (
+ VOID
+ );
+
+/**
+ Cleanup function for FileBuffer.
+
+ @retval EFI_SUCCESS The cleanup was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferCleanup (
+ VOID
+ );
+
+/**
+ Refresh the screen with whats in the buffer.
+
+ @retval EFI_SUCCESS The refresh was successful.
+ @retval EFI_LOAD_ERROR There was an error finding what to write.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferRefresh (
+ VOID
+ );
+
+/**
+ Dispatch input to different handler
+ @param[in] Key The input key. One of:
+ ASCII KEY
+ Backspace/Delete
+ Return
+ Direction key: up/down/left/right/pgup/pgdn
+ Home/End
+ INS
+
+ @retval EFI_SUCCESS The dispatch was done successfully.
+ @retval EFI_LOAD_ERROR The dispatch was not successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferHandleInput (
+ IN CONST EFI_INPUT_KEY * Key
+ );
+
+/**
+ Backup function for FileBuffer. Only backup the following items:
+ Mouse/Cursor position
+ File Name, Type, ReadOnly, Modified
+ Insert Mode
+
+ This is for making the file buffer refresh as few as possible.
+
+ @retval EFI_SUCCESS The backup operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferBackup (
+ VOID
+ );
+
+/**
+ Set the cursor position according to FileBuffer.DisplayPosition.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferRestorePosition (
+ VOID
+ );
+
+/**
+ Set FileName field in FileBuffer.
+
+ @param Str The file name to set.
+
+ @retval EFI_SUCCESS The filename was successfully set.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_INVALID_PARAMETER Str is not a valid filename.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferSetFileName (
+ IN CONST CHAR16 *Str
+ );
+
+/**
+ Read a file from disk into the FileBuffer.
+
+ @param[in] FileName The filename to read.
+ @param[in] Recover TRUE if is for recover mode, no information printouts.
+
+ @retval EFI_SUCCESS The load was successful.
+ @retval EFI_LOAD_ERROR The load failed.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_INVALID_PARAMETER FileName is a directory.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferRead (
+ IN CONST CHAR16 *FileName,
+ IN CONST BOOLEAN Recover
+ );
+
+/**
+ Save lines in FileBuffer to disk
+
+ @param[in] FileName The file name for writing.
+
+ @retval EFI_SUCCESS Data was written.
+ @retval EFI_LOAD_ERROR
+ @retval EFI_OUT_OF_RESOURCES There were not enough resources to write the file.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferSave (
+ CONST CHAR16 *FileName
+ );
+
+/**
+ According to cursor's file position, adjust screen display
+
+ @param[in] NewFilePosRow The row of file position ( start from 1 ).
+ @param[in] NewFilePosCol The column of file position ( start from 1 ).
+**/
+VOID
+EFIAPI
+FileBufferMovePosition (
+ IN CONST UINTN NewFilePosRow,
+ IN CONST UINTN NewFilePosCol
+ );
+
+/**
+ Cut current line out and return a pointer to it.
+
+ @param[out] CutLine Upon a successful return pointer to the pointer to
+ the allocated cut line.
+
+ @retval EFI_SUCCESS The cut was successful.
+ @retval EFI_NOT_FOUND There was no selection to cut.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferCutLine (
+ OUT EFI_EDITOR_LINE **CutLine
+ );
+
+/**
+ Paste a line into line list.
+
+ @retval EFI_SUCCESS The paste was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferPasteLine (
+ VOID
+ );
+
+/**
+ Search string from current position on in file
+
+ @param[in] Str The search string.
+ @param[in] Offset The offset from current position.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_NOT_FOUND The string Str was not found.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferSearch (
+ IN CONST CHAR16 *Str,
+ IN CONST UINTN Offset
+ );
+
+/**
+ Replace SearchLen characters from current position on with Replace.
+
+ This will modify the current buffer at the current position.
+
+ @param[in] Replace The string to replace.
+ @param[in] SearchLen Search string's length.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferReplace (
+ IN CONST CHAR16 *Replace,
+ IN CONST UINTN SearchLen
+ );
+
+/**
+ Search and replace operation.
+
+ @param[in] SearchStr The string to search for.
+ @param[in] ReplaceStr The string to replace with.
+ @param[in] Offset The column to start at.
+**/
+EFI_STATUS
+EFIAPI
+FileBufferReplaceAll (
+ IN CHAR16 *SearchStr,
+ IN CHAR16 *ReplaceStr,
+ IN UINTN Offset
+ );
+
+/**
+ Move the mouse cursor position.
+
+ @param[in] TextX The new x-coordinate.
+ @param[in] TextY The new y-coordinate.
+**/
+VOID
+EFIAPI
+FileBufferAdjustMousePosition (
+ IN CONST INT32 TextX,
+ IN CONST INT32 TextY
+ );
+
+/**
+ Set the modified state to TRUE.
+**/
+VOID
+EFIAPI
+FileBufferSetModified (
+ VOID
+ );
+
+#endif
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c
new file mode 100644
index 0000000000..4eb7d9eee3
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.c
@@ -0,0 +1,1936 @@
+/** @file
+ Implements editor interface functions.
+
+ Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "TextEditor.h"
+#include "EditStatusBar.h"
+#include "EditInputBar.h"
+#include "EditMenuBar.h"
+
+//
+// the first time editor launch
+//
+BOOLEAN EditorFirst;
+
+//
+// it's time editor should exit
+//
+BOOLEAN EditorExit;
+
+BOOLEAN EditorMouseAction;
+
+extern EFI_EDITOR_FILE_BUFFER FileBuffer;
+
+extern BOOLEAN FileBufferNeedRefresh;
+
+extern BOOLEAN FileBufferOnlyLineNeedRefresh;
+
+extern BOOLEAN FileBufferMouseNeedRefresh;
+
+extern EFI_EDITOR_FILE_BUFFER FileBufferBackupVar;
+
+EFI_EDITOR_GLOBAL_EDITOR MainEditor;
+
+
+/**
+ Load a file from disk to editor
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+MainCommandOpenFile (
+ VOID
+ );
+
+/**
+ Switch a file from ASCII to UNICODE or vise-versa.
+
+ @retval EFI_SUCCESS The switch was ok or a warning was presented.
+**/
+EFI_STATUS
+MainCommandSwitchFileType (
+ VOID
+ );
+
+/**
+ move cursor to specified lines
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+MainCommandGotoLine (
+ VOID
+ );
+
+/**
+ Save current file to disk, you can save to current file name or
+ save to another file name.
+
+ @retval EFI_SUCCESS The file was saved correctly.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A file access error occured.
+**/
+EFI_STATUS
+MainCommandSaveFile (
+ VOID
+ );
+
+/**
+ Show help information for the editor.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+MainCommandDisplayHelp (
+ VOID
+ );
+
+/**
+ exit editor
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+MainCommandExit (
+ VOID
+ );
+
+/**
+ search string in file buffer
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+MainCommandSearch (
+ VOID
+ );
+
+/**
+ search string in file buffer, and replace it with another str
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+MainCommandSearchReplace (
+ VOID
+ );
+
+/**
+ cut current line to clipboard
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+MainCommandCutLine (
+ VOID
+ );
+
+/**
+ paste line to file buffer.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+MainCommandPasteLine (
+ VOID
+ );
+
+/**
+ Help info that will be displayed.
+**/
+EFI_STRING_ID MainMenuHelpInfo[] = {
+ STRING_TOKEN(STR_EDIT_HELP_TITLE),
+ STRING_TOKEN(STR_EDIT_HELP_BLANK),
+ STRING_TOKEN(STR_EDIT_HELP_LIST_TITLE),
+ STRING_TOKEN(STR_EDIT_HELP_DIV),
+ STRING_TOKEN(STR_EDIT_HELP_GO_TO_LINE),
+ STRING_TOKEN(STR_EDIT_HELP_SAVE_FILE),
+ STRING_TOKEN(STR_EDIT_HELP_EXIT),
+ STRING_TOKEN(STR_EDIT_HELP_SEARCH),
+ STRING_TOKEN(STR_EDIT_HELP_SEARCH_REPLACE),
+ STRING_TOKEN(STR_EDIT_HELP_CUT_LINE),
+ STRING_TOKEN(STR_EDIT_HELP_PASTE_LINE),
+ STRING_TOKEN(STR_EDIT_HELP_OPEN_FILE),
+ STRING_TOKEN(STR_EDIT_HELP_FILE_TYPE),
+ STRING_TOKEN(STR_EDIT_HELP_BLANK),
+ STRING_TOKEN(STR_EDIT_HELP_EXIT_HELP),
+ STRING_TOKEN(STR_EDIT_HELP_BLANK),
+ STRING_TOKEN(STR_EDIT_HELP_BLANK),
+ STRING_TOKEN(STR_EDIT_HELP_BLANK),
+ STRING_TOKEN(STR_EDIT_HELP_BLANK),
+ STRING_TOKEN(STR_EDIT_HELP_BLANK),
+ STRING_TOKEN(STR_EDIT_HELP_BLANK),
+ STRING_TOKEN(STR_EDIT_HELP_BLANK),
+ STRING_TOKEN(STR_EDIT_HELP_DIV),
+0
+};
+
+MENU_ITEM_FUNCTION MainControlBasedMenuFunctions[] = {
+ NULL,
+ NULL, /* Ctrl - A */
+ NULL, /* Ctrl - B */
+ NULL, /* Ctrl - C */
+ NULL, /* Ctrl - D */
+ MainCommandDisplayHelp, /* Ctrl - E */
+ MainCommandSearch, /* Ctrl - F */
+ MainCommandGotoLine, /* Ctrl - G */
+ NULL, /* Ctrl - H */
+ NULL, /* Ctrl - I */
+ NULL, /* Ctrl - J */
+ MainCommandCutLine, /* Ctrl - K */
+ NULL, /* Ctrl - L */
+ NULL, /* Ctrl - M */
+ NULL, /* Ctrl - N */
+ MainCommandOpenFile, /* Ctrl - O */
+ NULL, /* Ctrl - P */
+ MainCommandExit, /* Ctrl - Q */
+ MainCommandSearchReplace, /* Ctrl - R */
+ MainCommandSaveFile, /* Ctrl - S */
+ MainCommandSwitchFileType, /* Ctrl - T */
+ MainCommandPasteLine, /* Ctrl - U */
+ NULL, /* Ctrl - V */
+ NULL, /* Ctrl - W */
+ NULL, /* Ctrl - X */
+ NULL, /* Ctrl - Y */
+ NULL, /* Ctrl - Z */
+};
+
+EDITOR_MENU_ITEM MainMenuItems[] = {
+ {
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_GO_TO_LINE),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F1),
+ MainCommandGotoLine
+ },
+ {
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_SAVE_FILE),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F2),
+ MainCommandSaveFile
+ },
+ {
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_EXIT),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F3),
+ MainCommandExit
+ },
+
+ {
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_SEARCH),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F4),
+ MainCommandSearch
+ },
+ {
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_SEARCH_REPLACE),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F5),
+ MainCommandSearchReplace
+ },
+ {
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_CUT_LINE),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F6),
+ MainCommandCutLine
+ },
+ {
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_PASTE_LINE),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F7),
+ MainCommandPasteLine
+ },
+
+ {
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_OPEN_FILE),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F8),
+ MainCommandOpenFile
+ },
+ {
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_FILE_TYPE),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F9),
+ MainCommandSwitchFileType
+ },
+ {
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_FILE_TYPE),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F11),
+ MainCommandSwitchFileType
+ },
+
+ {
+ 0,
+ 0,
+ NULL
+ }
+};
+
+
+/**
+ Load a file from disk to editor
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+MainCommandOpenFile (
+ VOID
+ )
+{
+ BOOLEAN Done;
+ EFI_STATUS Status;
+
+ //
+ // This command will open a file from current working directory.
+ // Read-only file can also be opened. But it can not be modified.
+ // Below is the scenario of Open File command:
+ // 1.IF currently opened file has not been modIFied, directly go to step .
+ // IF currently opened file has been modified,
+ // an Input Bar will be prompted as :
+ // "File Modified. Save ( Yes/No/Cancel) ?"
+ // IF user press 'y' or 'Y', currently opened file will be saved.
+ // IF user press 'n' or 'N', currently opened file will
+ // not be saved.
+ // IF user press 'c' or 'C' or ESC, Open File command ends and
+ // currently opened file is still opened.
+ //
+ // 2. An Input Bar will be prompted as : "File Name to Open: "
+ // IF user press ESC, Open File command ends and
+ // currently opened file is still opened.
+ // Any other inputs with a Return will
+ // cause currently opened file close.
+ //
+ // 3. IF user input file name is an existing file , this file will be read
+ // and opened.
+ // IF user input file name is a new file, this file will be created
+ // and opened. This file's type ( UNICODE or ASCII ) is the same
+ // with the old file.
+ // if current file is modified, so you need to choose
+ // whether to save it first.
+ //
+ if (MainEditor.FileBuffer->FileModified) {
+
+ Status = InputBarSetPrompt (L"File modified. Save (Yes/No/Cancel) ? ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // the answer is just one character
+ //
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // loop for user's answer
+ // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'
+ //
+ Done = FALSE;
+ while (!Done) {
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh();
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString()[0]) {
+ case L'y':
+ case L'Y':
+ //
+ // want to save this file first
+ //
+ Status = FileBufferSave (MainEditor.FileBuffer->FileName);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ MainTitleBarRefresh (MainEditor.FileBuffer->FileName, MainEditor.FileBuffer->FileType, MainEditor.FileBuffer->ReadOnly, MainEditor.FileBuffer->FileModified, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row, 0, 0);
+ FileBufferRestorePosition ();
+ Done = TRUE;
+ break;
+
+ case L'n':
+ case L'N':
+ //
+ // the file won't be saved
+ //
+ Done = TRUE;
+ break;
+
+ case L'c':
+ case L'C':
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ //
+ // TO get the open file name
+ //
+ Status = InputBarSetPrompt (L"File Name to Open: ");
+ if (EFI_ERROR (Status)) {
+ FileBufferRead (MainEditor.FileBuffer->FileName, TRUE);
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (100);
+ if (EFI_ERROR (Status)) {
+ FileBufferRead (MainEditor.FileBuffer->FileName, TRUE);
+ return Status;
+ }
+
+ while (1) {
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh();
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+ //
+ // The input string length should > 0
+ //
+ if (StrLen (InputBarGetString()) > 0) {
+ //
+ // CHECK if filename is valid
+ //
+ if (!IsValidFileName (InputBarGetString())) {
+ FileBufferRead (MainEditor.FileBuffer->FileName, TRUE);
+ StatusBarSetStatusString (L"Invalid File Name");
+ return EFI_SUCCESS;
+ }
+
+ break;
+ }
+ }
+ //
+ // read from disk
+ //
+ Status = FileBufferRead (InputBarGetString(), FALSE);
+
+ if (EFI_ERROR (Status)) {
+ FileBufferRead (MainEditor.FileBuffer->FileName, TRUE);
+ return EFI_LOAD_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Switch a file from ASCII to UNICODE or vise-versa.
+
+ @retval EFI_SUCCESS The switch was ok or a warning was presented.
+**/
+EFI_STATUS
+MainCommandSwitchFileType (
+ VOID
+ )
+{
+ //
+ // Below is the scenario of File Type command:
+ // After File Type is executed, file type will be changed to another type
+ // if file is read-only, can not be modified
+ //
+ if (MainEditor.FileBuffer->ReadOnly) {
+ StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
+ return EFI_SUCCESS;
+ }
+
+ if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
+ MainEditor.FileBuffer->FileType = FileTypeAscii;
+ } else {
+ MainEditor.FileBuffer->FileType = FileTypeUnicode;
+ }
+
+ MainEditor.FileBuffer->FileModified = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ cut current line to clipboard
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+MainCommandCutLine (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_EDITOR_LINE *Line;
+
+ //
+ // This command will cut current line ( where cursor is on ) to clip board.
+ // And cursor will move to the beginning of next line.
+ // Below is the scenario of Cut Line command:
+ // 1. IF cursor is on valid line, current line will be cut to clip board.
+ // IF cursor is not on valid line, an Status String will be prompted :
+ // "Nothing to Cut".
+ //
+ Line = NULL;
+ Status = FileBufferCutLine (&Line);
+ if (Status == EFI_NOT_FOUND) {
+ return EFI_SUCCESS;
+ }
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ MainEditor.CutLine = Line;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ paste line to file buffer.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+MainCommandPasteLine (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Below is the scenario of Paste Line command:
+ // 1. IF nothing is on clipboard, a Status String will be prompted :
+ // "No Line to Paste" and Paste Line command ends.
+ // IF something is on clipboard, insert it above current line.
+ // nothing on clipboard
+ //
+ if (MainEditor.CutLine == NULL) {
+ StatusBarSetStatusString (L"No Line to Paste");
+ return EFI_SUCCESS;
+ }
+
+ Status = FileBufferPasteLine ();
+
+ return Status;
+}
+
+
+/**
+ search string in file buffer
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+MainCommandSearch (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *Buffer;
+ BOOLEAN Done;
+ UINTN Offset;
+
+ //
+ // Below is the scenario of Search command:
+ // 1. An Input Bar will be prompted : "Enter Search String:".
+ // IF user press ESC, Search command ends.
+ // IF user just press Enter, Search command ends.
+ // IF user inputs the search string, do Step 2.
+ //
+ // 2. IF input search string is found, cursor will move to the first
+ // occurrence and do Step 3.
+ // IF input search string is not found, a Status String
+ // "Search String Not Found" will be prompted and Search command ends.
+ //
+ // 3. An Input Bar will be prompted: "Find Next (Yes/No/Cancel ) ?".
+ // IF user press ESC, Search command ends.
+ // IF user press 'y' or 'Y', do Step 2.
+ // IF user press 'n' or 'N', Search command ends.
+ // IF user press 'c' or 'C', Search command ends.
+ //
+ Status = InputBarSetPrompt (L"Enter Search String: ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (40);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh();
+
+ //
+ // ESC
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+ //
+ // just enter pressed
+ //
+ if (StrLen (InputBarGetString()) == 0) {
+ return EFI_SUCCESS;
+ }
+
+ Buffer = CatSPrint (NULL, L"%s", InputBarGetString());
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // the first time , search from current position
+ //
+ Offset = 0;
+ do {
+ //
+ // since search may be continued to search multiple times
+ // so we need to backup editor each time
+ //
+ MainEditorBackup ();
+
+ Status = FileBufferSearch (Buffer, Offset);
+
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ }
+ //
+ // Find next
+ //
+ Status = InputBarSetPrompt (L"Find Next (Yes/No) ?");
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return Status;
+ }
+
+ Done = FALSE;
+ while (!Done) {
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh();
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ FreePool (Buffer);
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString()[0]) {
+ case L'y':
+ case L'Y':
+ Done = TRUE;
+ break;
+
+ case L'n':
+ case L'N':
+ FreePool (Buffer);
+ return EFI_SUCCESS;
+
+ }
+ //
+ // end of which
+ //
+ }
+ //
+ // end of while !Done
+ // for search second, third time, search from current position + strlen
+ //
+ Offset = StrLen (Buffer);
+
+ } while (1);
+ //
+ // end of do
+ //
+ FreePool (Buffer);
+ StatusBarSetStatusString (L"Search String Not Found");
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Search string in file buffer, and replace it with another str.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+MainCommandSearchReplace (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *Search;
+ CHAR16 *Replace;
+ BOOLEAN Done;
+ BOOLEAN First;
+ BOOLEAN ReplaceOption;
+ UINTN SearchLen;
+ UINTN ReplaceLen;
+ BOOLEAN ReplaceAll;
+
+ ReplaceOption = FALSE;
+
+ //
+ // Below is the scenario of Search/Replace command:
+ // 1. An Input Bar is prompted : "Enter Search String:".
+ // IF user press ESC, Search/Replace command ends.
+ // IF user just press Enter, Search/Replace command ends.
+ // IF user inputs the search string S, do Step 2.
+ //
+ // 2. An Input Bar is prompted: "Replace With:".
+ // IF user press ESC, Search/Replace command ends.
+ // IF user inputs the replace string R, do Step 3.
+ //
+ // 3. IF input search string is not found, an Status String
+ // "Search String Not Found" will be prompted
+ // and Search/Replace command ends
+ // IF input search string is found, do Step 4.
+ //
+ // 4. An Input Bar will be prompted: "Replace ( Yes/No/All/Cancel )?"
+ // IF user press 'y' or 'Y', S will be replaced with R and do Step 5
+ // IF user press 'n' or 'N', S will not be replaced and do Step 5.
+ // IF user press 'a' or 'A', all the S from file current position on
+ // will be replaced with R and Search/Replace command ends.
+ // IF user press 'c' or 'C' or ESC, Search/Replace command ends.
+ //
+ // 5. An Input Bar will be prompted: "Find Next (Yes/No/Cancel) ?".
+ // IF user press ESC, Search/Replace command ends.
+ // IF user press 'y' or 'Y', do Step 3.
+ // IF user press 'n' or 'N', Search/Replace command ends.
+ // IF user press 'c' or 'C', Search/Replace command ends.
+ // input search string
+ //
+ Status = InputBarSetPrompt (L"Enter Search String: ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (40);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh();
+
+ //
+ // ESC
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+ //
+ // if just pressed enter
+ //
+ if (StrLen (InputBarGetString()) == 0) {
+ return EFI_SUCCESS;
+ }
+
+ Search = CatSPrint (NULL, L"%s", InputBarGetString());
+ if (Search == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ SearchLen = StrLen (Search);
+
+ //
+ // input replace string
+ //
+ Status = InputBarSetPrompt (L"Replace With: ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (40);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh();
+
+ //
+ // ESC
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ Replace = CatSPrint (NULL, L"%s", InputBarGetString());
+ if (Replace == NULL) {
+ FreePool (Search);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ReplaceLen = StrLen (Replace);
+
+ First = TRUE;
+ ReplaceAll = FALSE;
+ do {
+ //
+ // since search may be continued to search multiple times
+ // so we need to backup editor each time
+ //
+ MainEditorBackup ();
+
+ if (First) {
+ Status = FileBufferSearch (Search, 0);
+ } else {
+ //
+ // if just replace, so skip this replace string
+ // if replace string is an empty string, so skip to next character
+ //
+ if (ReplaceOption) {
+ Status = FileBufferSearch (Search, (ReplaceLen == 0) ? 1 : ReplaceLen);
+ } else {
+ Status = FileBufferSearch (Search, SearchLen);
+ }
+ }
+
+ if (Status == EFI_NOT_FOUND) {
+ break;
+ }
+ //
+ // replace or not?
+ //
+ Status = InputBarSetPrompt (L"Replace (Yes/No/All/Cancel) ?");
+
+ if (EFI_ERROR (Status)) {
+ FreePool (Search);
+ FreePool (Replace);
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ FreePool (Search);
+ FreePool (Replace);
+ return Status;
+ }
+
+ Done = FALSE;
+ while (!Done) {
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh();
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ FreePool (Search);
+ FreePool (Replace);
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString()[0]) {
+ case L'y':
+ case L'Y':
+ Done = TRUE;
+ ReplaceOption = TRUE;
+ break;
+
+ case L'n':
+ case L'N':
+ Done = TRUE;
+ ReplaceOption = FALSE;
+ break;
+
+ case L'a':
+ case L'A':
+ Done = TRUE;
+ ReplaceOption = TRUE;
+ ReplaceAll = TRUE;
+ break;
+
+ case L'c':
+ case L'C':
+ FreePool (Search);
+ FreePool (Replace);
+ return EFI_SUCCESS;
+
+ }
+ //
+ // end of which
+ //
+ }
+ //
+ // end of while !Done
+ // Decide to Replace
+ //
+ if (ReplaceOption) {
+ //
+ // file is read-only
+ //
+ if (MainEditor.FileBuffer->ReadOnly) {
+ StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
+ return EFI_SUCCESS;
+ }
+ //
+ // replace all
+ //
+ if (ReplaceAll) {
+ Status = FileBufferReplaceAll (Search, Replace, 0);
+ FreePool (Search);
+ FreePool (Replace);
+ return Status;
+ }
+ //
+ // replace
+ //
+ Status = FileBufferReplace (Replace, SearchLen);
+ if (EFI_ERROR (Status)) {
+ FreePool (Search);
+ FreePool (Replace);
+ return Status;
+ }
+ }
+ //
+ // Find next
+ //
+ Status = InputBarSetPrompt (L"Find Next (Yes/No) ?");
+ if (EFI_ERROR (Status)) {
+ FreePool (Search);
+ FreePool (Replace);
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ FreePool (Search);
+ FreePool (Replace);
+ return Status;
+ }
+
+ Done = FALSE;
+ while (!Done) {
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh();
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ FreePool (Search);
+ FreePool (Replace);
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString()[0]) {
+ case L'y':
+ case L'Y':
+ Done = TRUE;
+ break;
+
+ case L'n':
+ case L'N':
+ FreePool (Search);
+ FreePool (Replace);
+ return EFI_SUCCESS;
+
+ }
+ //
+ // end of which
+ //
+ }
+ //
+ // end of while !Done
+ //
+ First = FALSE;
+
+ } while (1);
+ //
+ // end of do
+ //
+ FreePool (Search);
+ FreePool (Replace);
+
+ StatusBarSetStatusString (L"Search String Not Found");
+
+ return EFI_SUCCESS;
+}
+
+/**
+ exit editor
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+MainCommandExit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Below is the scenario of Exit command:
+ // 1. IF currently opened file is not modified, exit the editor and
+ // Exit command ends.
+ // IF currently opened file is modified, do Step 2
+ //
+ // 2. An Input Bar will be prompted:
+ // "File modified. Save ( Yes/No/Cancel )?"
+ // IF user press 'y' or 'Y', currently opened file will be saved
+ // and Editor exits
+ // IF user press 'n' or 'N', currently opened file will not be saved
+ // and Editor exits.
+ // IF user press 'c' or 'C' or ESC, Exit command ends.
+ // if file has been modified, so will prompt user whether to save the changes
+ //
+ if (MainEditor.FileBuffer->FileModified) {
+
+ Status = InputBarSetPrompt (L"File modified. Save (Yes/No/Cancel) ? ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ while (1) {
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh();
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString()[0]) {
+ case L'y':
+ case L'Y':
+ //
+ // write file back to disk
+ //
+ Status = FileBufferSave (MainEditor.FileBuffer->FileName);
+ if (!EFI_ERROR (Status)) {
+ EditorExit = TRUE;
+ }
+
+ return Status;
+
+ case L'n':
+ case L'N':
+ EditorExit = TRUE;
+ return EFI_SUCCESS;
+
+ case L'c':
+ case L'C':
+ return EFI_SUCCESS;
+
+ }
+ }
+ }
+
+ EditorExit = TRUE;
+ return EFI_SUCCESS;
+
+}
+
+/**
+ move cursor to specified lines
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+MainCommandGotoLine (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN Row;
+
+ //
+ // Below is the scenario of Go To Line command:
+ // 1. An Input Bar will be prompted : "Go To Line:".
+ // IF user press ESC, Go To Line command ends.
+ // IF user just press Enter, cursor remains unchanged.
+ // IF user inputs line number, do Step 2.
+ //
+ // 2. IF input line number is valid, move cursor to the beginning
+ // of specified line and Go To Line command ends.
+ // IF input line number is invalid, a Status String will be prompted:
+ // "No Such Line" and Go To Line command ends.
+ //
+ Status = InputBarSetPrompt (L"Go To Line: ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // line number's digit <= 6
+ //
+ Status = InputBarSetStringSize (6);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh();
+
+ //
+ // press ESC
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+ //
+ // if JUST press enter
+ //
+ if (StrLen (InputBarGetString()) == 0) {
+ return EFI_SUCCESS;
+ }
+
+ Row = ShellStrToUintn (InputBarGetString());
+
+ //
+ // invalid line number
+ //
+ if (Row > MainEditor.FileBuffer->NumLines || Row <= 0) {
+ StatusBarSetStatusString (L"No Such Line");
+ return EFI_SUCCESS;
+ }
+ //
+ // move cursor to that line's start
+ //
+ FileBufferMovePosition (Row, 1);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Save current file to disk, you can save to current file name or
+ save to another file name.
+
+ @retval EFI_SUCCESS The file was saved correctly.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A file access error occured.
+**/
+EFI_STATUS
+MainCommandSaveFile (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *FileName;
+ BOOLEAN OldFile;
+ CHAR16 *Str;
+ SHELL_FILE_HANDLE FileHandle;
+ EFI_FILE_INFO *Info;
+
+ //
+ // This command will save currently opened file to disk.
+ // You can choose save to another file name or just save to
+ // current file name.
+ // Below is the scenario of Save File command:
+ // ( Suppose the old file name is A )
+ // 1. An Input Bar will be prompted: "File To Save: [ old file name]"
+ // IF user press ESC, Save File command ends .
+ // IF user press Enter, input file name will be A.
+ // IF user inputs a new file name B, input file name will be B.
+ //
+ // 2. IF input file name is A, go to do Step 3.
+ // IF input file name is B, go to do Step 4.
+ //
+ // 3. IF A is read only, Status Bar will show "Access Denied" and
+ // Save File commands ends.
+ // IF A is not read only, save file buffer to disk and remove modified
+ // flag in Title Bar , then Save File command ends.
+ //
+ // 4. IF B does not exist, create this file and save file buffer to it.
+ // Go to do Step 7.
+ // IF B exits, do Step 5.
+ //
+ // 5.An Input Bar will be prompted:
+ // "File Exists. Overwrite ( Yes/No/Cancel )?"
+ // IF user press 'y' or 'Y', do Step 6.
+ // IF user press 'n' or 'N', Save File commands ends.
+ // IF user press 'c' or 'C' or ESC, Save File commands ends.
+ //
+ // 6. IF B is a read-only file, Status Bar will show "Access Denied" and
+ // Save File commands ends.
+ // IF B can be read and write, save file buffer to B.
+ //
+ // 7. Update File Name field in Title Bar to B and remove the modified
+ // flag in Title Bar.
+ //
+ Str = CatSPrint (NULL, L"File to Save: [%s]", MainEditor.FileBuffer->FileName);
+ if (Str == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (StrLen (Str) >= 50) {
+ //
+ // replace the long file name with "..."
+ //
+ Str[46] = L'.';
+ Str[47] = L'.';
+ Str[48] = L'.';
+ Str[49] = L']';
+ Str[50] = CHAR_NULL;
+ }
+
+ Status = InputBarSetPrompt (Str);
+ FreePool(Str);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+
+ Status = InputBarSetStringSize (100);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // get new file name
+ //
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh();
+
+ //
+ // if user pressed ESC
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // if just enter pressed, so think save to current file name
+ //
+ if (StrLen (InputBarGetString()) == 0) {
+ FileName = CatSPrint (NULL, L"%s", MainEditor.FileBuffer->FileName);
+ } else {
+ FileName = CatSPrint (NULL, L"%s", InputBarGetString());
+ }
+
+ if (FileName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (!IsValidFileName (FileName)) {
+ StatusBarSetStatusString (L"Invalid File Name");
+ FreePool (FileName);
+ return EFI_SUCCESS;
+ }
+
+ OldFile = FALSE;
+
+ //
+ // save to the old file
+ //
+ if (StringNoCaseCompare (&FileName, &MainEditor.FileBuffer->FileName) == 0) {
+ OldFile = TRUE;
+ }
+
+ if (OldFile) {
+ //
+ // if the file is read only, so can not write back to it.
+ //
+ if (MainEditor.FileBuffer->ReadOnly == TRUE) {
+ StatusBarSetStatusString (L"Access Denied");
+ FreePool (FileName);
+ return EFI_SUCCESS;
+ }
+ } else {
+ //
+ // if the file exists
+ //
+ if (ShellFileExists(FileName) != EFI_NOT_FOUND) {
+ //
+ // check for read only
+ //
+ Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_READ, 0);
+ if (EFI_ERROR(Status)) {
+ StatusBarSetStatusString (L"Open Failed");
+ FreePool (FileName);
+ return EFI_SUCCESS;
+ }
+
+ Info = ShellGetFileInfo(FileHandle);
+ if (Info == NULL) {
+ StatusBarSetStatusString (L"Access Denied");
+ FreePool (FileName);
+ return (EFI_SUCCESS);
+ }
+
+ if (Info->Attribute & EFI_FILE_READ_ONLY) {
+ StatusBarSetStatusString (L"Access Denied - Read Only");
+ FreePool (Info);
+ FreePool (FileName);
+ return (EFI_SUCCESS);
+ }
+ FreePool (Info);
+
+ //
+ // ask user whether to overwrite this file
+ //
+ Status = InputBarSetPrompt (L"File exists. Overwrite (Yes/No/Cancel) ? ");
+ if (EFI_ERROR (Status)) {
+ SHELL_FREE_NON_NULL (FileName);
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ SHELL_FREE_NON_NULL (FileName);
+ return Status;
+ }
+
+ while (TRUE) {
+ Status = InputBarRefresh (MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column);
+ StatusBarSetRefresh();
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ SHELL_FREE_NON_NULL (FileName);
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString()[0]) {
+ case L'y':
+ case L'Y':
+ break;
+
+ case L'n':
+ case L'N':
+ case L'c':
+ case L'C':
+ SHELL_FREE_NON_NULL (FileName);
+ return EFI_SUCCESS;
+ } // end switch
+ } // while (!done)
+ } // file does exist
+ } // if old file name same
+
+ //
+ // save file to disk with specified name
+ //
+ FileBufferSetModified();
+ Status = FileBufferSave (FileName);
+ SHELL_FREE_NON_NULL (FileName);
+
+ return Status;
+}
+
+/**
+ Show help information for the editor.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+MainCommandDisplayHelp (
+ VOID
+ )
+{
+ INT32 CurrentLine;
+ CHAR16 *InfoString;
+ EFI_INPUT_KEY Key;
+
+ //
+ // print helpInfo
+ //
+ for (CurrentLine = 0; 0 != MainMenuHelpInfo[CurrentLine]; CurrentLine++) {
+ InfoString = HiiGetString(gShellDebug1HiiHandle, MainMenuHelpInfo[CurrentLine], NULL);
+ ShellPrintEx (0, CurrentLine+1, L"%E%s%N", InfoString);
+ }
+
+ //
+ // scan for ctrl+w
+ //
+ do {
+ gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ } while(SCAN_CONTROL_W != Key.UnicodeChar);
+
+ //
+ // update screen with file buffer's info
+ //
+ FileBufferRestorePosition ();
+ FileBufferNeedRefresh = TRUE;
+ FileBufferOnlyLineNeedRefresh = FALSE;
+ FileBufferRefresh ();
+
+ return EFI_SUCCESS;
+}
+
+EFI_EDITOR_COLOR_ATTRIBUTES OriginalColors;
+INTN OriginalMode;
+
+
+//
+// basic initialization for MainEditor
+//
+EFI_EDITOR_GLOBAL_EDITOR MainEditorConst = {
+ &FileBuffer,
+ {
+ {0, 0}
+ },
+ {
+ 0,
+ 0
+ },
+ NULL,
+ FALSE,
+ NULL
+};
+
+/**
+ The initialization function for MainEditor.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+EFIAPI
+MainEditorInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+ UINTN Index;
+
+ //
+ // basic initialization
+ //
+ CopyMem (&MainEditor, &MainEditorConst, sizeof (MainEditor));
+
+ //
+ // set screen attributes
+ //
+ MainEditor.ColorAttributes.Colors.Foreground = gST->ConOut->Mode->Attribute & 0x000000ff;
+
+ MainEditor.ColorAttributes.Colors.Background = (UINT8) (gST->ConOut->Mode->Attribute >> 4);
+ OriginalColors = MainEditor.ColorAttributes.Colors;
+
+ OriginalMode = gST->ConOut->Mode->Mode;
+
+ //
+ // query screen size
+ //
+ gST->ConOut->QueryMode (
+ gST->ConOut,
+ gST->ConOut->Mode->Mode,
+ &(MainEditor.ScreenSize.Column),
+ &(MainEditor.ScreenSize.Row)
+ );
+
+ //
+ // Find mouse in System Table ConsoleInHandle
+ //
+ Status = gBS->HandleProtocol (
+ gST->ConIn,
+ &gEfiSimplePointerProtocolGuid,
+ (VOID**)&MainEditor.MouseInterface
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // If there is no Simple Pointer Protocol on System Table
+ //
+ HandleBuffer = NULL;
+ MainEditor.MouseInterface = NULL;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSimplePointerProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (!EFI_ERROR (Status) && HandleCount > 0) {
+ //
+ // Try to find the first available mouse device
+ //
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiSimplePointerProtocolGuid,
+ (VOID**)&MainEditor.MouseInterface
+ );
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ }
+ }
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+ }
+
+ if (!EFI_ERROR (Status) && MainEditor.MouseInterface != NULL) {
+ MainEditor.MouseAccumulatorX = 0;
+ MainEditor.MouseAccumulatorY = 0;
+ MainEditor.MouseSupported = TRUE;
+ }
+
+ //
+ // below will call the five components' init function
+ //
+ Status = MainTitleBarInit (L"UEFI EDIT");
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_TITLEBAR), gShellDebug1HiiHandle);
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = ControlHotKeyInit (MainControlBasedMenuFunctions);
+ Status = MenuBarInit (MainMenuItems);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_MAINMENU), gShellDebug1HiiHandle);
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = StatusBarInit ();
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_STATUSBAR), gShellDebug1HiiHandle);
+ return EFI_LOAD_ERROR;
+ }
+
+ InputBarInit ();
+
+ Status = FileBufferInit ();
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_FILEBUFFER), gShellDebug1HiiHandle);
+ return EFI_LOAD_ERROR;
+ }
+ //
+ // clear whole screen and enable cursor
+ //
+ gST->ConOut->ClearScreen (gST->ConOut);
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+
+ //
+ // initialize EditorFirst and EditorExit
+ //
+ EditorFirst = TRUE;
+ EditorExit = FALSE;
+ EditorMouseAction = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ The cleanup function for MainEditor.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+EFIAPI
+MainEditorCleanup (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // call the five components' cleanup function
+ // if error, do not exit
+ // just print some warning
+ //
+ MainTitleBarCleanup();
+ StatusBarCleanup();
+ InputBarCleanup();
+ MenuBarCleanup ();
+
+ Status = FileBufferCleanup ();
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBEDITOR_FILEBUFFER_CLEANUP), gShellDebug1HiiHandle);
+ }
+ //
+ // restore old mode
+ //
+ if (OriginalMode != gST->ConOut->Mode->Mode) {
+ gST->ConOut->SetMode (gST->ConOut, OriginalMode);
+ }
+ //
+ // restore old screen color
+ //
+ gST->ConOut->SetAttribute (
+ gST->ConOut,
+ EFI_TEXT_ATTR (OriginalColors.Foreground, OriginalColors.Background)
+ );
+
+ gST->ConOut->ClearScreen (gST->ConOut);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Refresh the main editor component.
+**/
+VOID
+EFIAPI
+MainEditorRefresh (
+ VOID
+ )
+{
+ //
+ // The Stall value is from experience. NOT from spec. avoids 'flicker'
+ //
+ gBS->Stall (50);
+
+ //
+ // call the components refresh function
+ //
+ if (EditorFirst
+ || StrCmp (FileBufferBackupVar.FileName, FileBuffer.FileName) != 0
+ || FileBufferBackupVar.FileType != FileBuffer.FileType
+ || FileBufferBackupVar.FileModified != FileBuffer.FileModified
+ || FileBufferBackupVar.ReadOnly != FileBuffer.ReadOnly) {
+
+ MainTitleBarRefresh (MainEditor.FileBuffer->FileName, MainEditor.FileBuffer->FileType, MainEditor.FileBuffer->ReadOnly, MainEditor.FileBuffer->FileModified, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row, 0, 0);
+ FileBufferRestorePosition ();
+ }
+
+ if (EditorFirst
+ || FileBufferBackupVar.FilePosition.Row != FileBuffer.FilePosition.Row
+ || FileBufferBackupVar.FilePosition.Column != FileBuffer.FilePosition.Column
+ || FileBufferBackupVar.ModeInsert != FileBuffer.ModeInsert
+ || StatusBarGetRefresh()) {
+
+ StatusBarRefresh (EditorFirst, MainEditor.ScreenSize.Row, MainEditor.ScreenSize.Column, MainEditor.FileBuffer->FilePosition.Row, MainEditor.FileBuffer->FilePosition.Column, MainEditor.FileBuffer->ModeInsert);
+ FileBufferRestorePosition ();
+ }
+
+ if (EditorFirst) {
+ FileBufferRestorePosition ();
+ }
+
+ FileBufferRefresh ();
+
+ //
+ // EditorFirst is now set to FALSE
+ //
+ EditorFirst = FALSE;
+}
+
+/**
+ Get's the resultant location of the cursor based on the relative movement of the Mouse.
+
+ @param[in] GuidX The relative mouse movement.
+
+ @return The X location of the mouse.
+**/
+INT32
+EFIAPI
+GetTextX (
+ IN INT32 GuidX
+ )
+{
+ INT32 Gap;
+
+ MainEditor.MouseAccumulatorX += GuidX;
+ Gap = (MainEditor.MouseAccumulatorX * (INT32) MainEditor.ScreenSize.Column) / (INT32) (50 * (INT32) MainEditor.MouseInterface->Mode->ResolutionX);
+ MainEditor.MouseAccumulatorX = (MainEditor.MouseAccumulatorX * (INT32) MainEditor.ScreenSize.Column) % (INT32) (50 * (INT32) MainEditor.MouseInterface->Mode->ResolutionX);
+ MainEditor.MouseAccumulatorX = MainEditor.MouseAccumulatorX / (INT32) MainEditor.ScreenSize.Column;
+ return Gap;
+}
+
+/**
+ Get's the resultant location of the cursor based on the relative movement of the Mouse.
+
+ @param[in] GuidY The relative mouse movement.
+
+ @return The Y location of the mouse.
+**/
+INT32
+EFIAPI
+GetTextY (
+ IN INT32 GuidY
+ )
+{
+ INT32 Gap;
+
+ MainEditor.MouseAccumulatorY += GuidY;
+ Gap = (MainEditor.MouseAccumulatorY * (INT32) MainEditor.ScreenSize.Row) / (INT32) (50 * (INT32) MainEditor.MouseInterface->Mode->ResolutionY);
+ MainEditor.MouseAccumulatorY = (MainEditor.MouseAccumulatorY * (INT32) MainEditor.ScreenSize.Row) % (INT32) (50 * (INT32) MainEditor.MouseInterface->Mode->ResolutionY);
+ MainEditor.MouseAccumulatorY = MainEditor.MouseAccumulatorY / (INT32) MainEditor.ScreenSize.Row;
+
+ return Gap;
+}
+
+/**
+ Support mouse movement. Move the cursor.
+
+ @param[in] MouseState The current mouse state.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_NOT_FOUND There was no mouse support found.
+**/
+EFI_STATUS
+EFIAPI
+MainEditorHandleMouseInput (
+ IN EFI_SIMPLE_POINTER_STATE MouseState
+ )
+{
+
+ INT32 TextX;
+ INT32 TextY;
+ UINTN FRow;
+ UINTN FCol;
+
+ LIST_ENTRY *Link;
+ EFI_EDITOR_LINE *Line;
+
+ UINTN Index;
+ BOOLEAN Action;
+
+ //
+ // mouse action means:
+ // mouse movement
+ // mouse left button
+ //
+ Action = FALSE;
+
+ //
+ // have mouse movement
+ //
+ if (MouseState.RelativeMovementX || MouseState.RelativeMovementY) {
+ //
+ // handle
+ //
+ TextX = GetTextX (MouseState.RelativeMovementX);
+ TextY = GetTextY (MouseState.RelativeMovementY);
+
+ FileBufferAdjustMousePosition (TextX, TextY);
+
+ Action = TRUE;
+
+ }
+
+ //
+ // if left button pushed down
+ //
+ if (MouseState.LeftButton) {
+
+ FCol = MainEditor.FileBuffer->MousePosition.Column - 1 + 1;
+
+ FRow = MainEditor.FileBuffer->FilePosition.Row +
+ MainEditor.FileBuffer->MousePosition.Row -
+ MainEditor.FileBuffer->DisplayPosition.Row;
+
+ //
+ // beyond the file line length
+ //
+ if (MainEditor.FileBuffer->NumLines < FRow) {
+ FRow = MainEditor.FileBuffer->NumLines;
+ }
+
+ Link = MainEditor.FileBuffer->ListHead->ForwardLink;
+ for (Index = 0; Index < FRow - 1; Index++) {
+ Link = Link->ForwardLink;
+ }
+
+ Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
+
+ //
+ // beyond the line's column length
+ //
+ if (FCol > Line->Size + 1) {
+ FCol = Line->Size + 1;
+ }
+
+ FileBufferMovePosition (FRow, FCol);
+
+ MainEditor.FileBuffer->MousePosition.Row = MainEditor.FileBuffer->DisplayPosition.Row;
+
+ MainEditor.FileBuffer->MousePosition.Column = MainEditor.FileBuffer->DisplayPosition.Column;
+
+ Action = TRUE;
+ }
+ //
+ // mouse has action
+ //
+ if (Action) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // no mouse action
+ //
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Handle user key input. This routes to other functions for the actions.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+MainEditorKeyInput (
+ VOID
+ )
+{
+ EFI_INPUT_KEY Key;
+ EFI_STATUS Status;
+ EFI_SIMPLE_POINTER_STATE MouseState;
+
+ do {
+
+ Status = EFI_SUCCESS;
+ EditorMouseAction = FALSE;
+
+ //
+ // backup some key elements, so that can aVOID some refresh work
+ //
+ MainEditorBackup ();
+
+ //
+ // change priority of checking mouse/keyboard activity dynamically
+ // so prevent starvation of keyboard.
+ // if last time, mouse moves then this time check keyboard
+ //
+ if (MainEditor.MouseSupported) {
+ Status = MainEditor.MouseInterface->GetState (
+ MainEditor.MouseInterface,
+ &MouseState
+ );
+ if (!EFI_ERROR (Status)) {
+
+ Status = MainEditorHandleMouseInput (MouseState);
+
+ if (!EFI_ERROR (Status)) {
+ EditorMouseAction = TRUE;
+ FileBufferMouseNeedRefresh = TRUE;
+ } else if (Status == EFI_LOAD_ERROR) {
+ StatusBarSetStatusString (L"Invalid Mouse Movement ");
+ }
+ }
+ }
+
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ if (!EFI_ERROR (Status)) {
+ //
+ // dispatch to different components' key handling function
+ // so not everywhere has to set this variable
+ //
+ FileBufferMouseNeedRefresh = TRUE;
+ //
+ // clear previous status string
+ //
+ StatusBarSetRefresh();
+
+ //
+ // dispatch to different components' key handling function
+ //
+ if (EFI_NOT_FOUND != MenuBarDispatchControlHotKey(&Key)) {
+ Status = EFI_SUCCESS;
+ } else if ((Key.ScanCode == SCAN_NULL) || ((Key.ScanCode >= SCAN_UP) && (Key.ScanCode <= SCAN_PAGE_DOWN))) {
+ Status = FileBufferHandleInput (&Key);
+ } else if ((Key.ScanCode >= SCAN_F1) && (Key.ScanCode <= SCAN_F12)) {
+ Status = MenuBarDispatchFunctionKey (&Key);
+ } else {
+ StatusBarSetStatusString (L"Unknown Command");
+ FileBufferMouseNeedRefresh = FALSE;
+ }
+
+ if (Status != EFI_SUCCESS && Status != EFI_OUT_OF_RESOURCES) {
+ //
+ // not already has some error status
+ //
+ if (StatusBarGetString() != NULL && StrCmp (L"", StatusBarGetString()) == 0) {
+ StatusBarSetStatusString (L"Disk Error. Try Again");
+ }
+ }
+
+ }
+ //
+ // after handling, refresh editor
+ //
+ MainEditorRefresh ();
+
+ } while (Status != EFI_OUT_OF_RESOURCES && !EditorExit);
+
+ return Status;
+}
+
+/**
+ Set clipboard
+
+ @param[in] Line A pointer to the line to be set to clipboard
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+MainEditorSetCutLine (
+ EFI_EDITOR_LINE *Line
+ )
+{
+ if (Line == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ if (MainEditor.CutLine != NULL) {
+ //
+ // free the old clipboard
+ //
+ LineFree (MainEditor.CutLine);
+ }
+ //
+ // duplicate the line to clipboard
+ //
+ MainEditor.CutLine = LineDup (Line);
+ if (MainEditor.CutLine == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Backup function for MainEditor
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+MainEditorBackup (
+ VOID
+ )
+{
+ FileBufferBackup ();
+
+ return EFI_SUCCESS;
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.h
new file mode 100644
index 0000000000..c45859deda
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/MainTextEditor.h
@@ -0,0 +1,77 @@
+/** @file
+ Declares editor interface functions.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LIB_EDITOR_H_
+#define _LIB_EDITOR_H_
+
+#include "TextEditorTypes.h"
+
+/**
+ The initialization function for MainEditor.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+EFIAPI
+MainEditorInit (
+ VOID
+ );
+
+/**
+ The cleanup function for MainEditor.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+EFIAPI
+MainEditorCleanup (
+ VOID
+ );
+
+/**
+ Refresh the main editor component.
+**/
+VOID
+EFIAPI
+MainEditorRefresh (
+ VOID
+ );
+
+/**
+ Handle user key input. This routes to other functions for the actions.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+MainEditorKeyInput (
+ VOID
+ );
+
+/**
+ Backup function for MainEditor
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+MainEditorBackup (
+ VOID
+ );
+
+#endif
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.c
new file mode 100644
index 0000000000..ade78b8f90
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.c
@@ -0,0 +1,92 @@
+/** @file
+ Implementation of various string and line routines.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "TextEditor.h"
+#include "Misc.h"
+
+/**
+ Duplicate a EFI_EDITOR_LINE structure.
+
+ @param Src The line structure to copy from.
+
+ @retval NULL A memory allocation failed.
+ @return a pointer to the newly allcoated line.
+**/
+EFI_EDITOR_LINE *
+EFIAPI
+LineDup (
+ IN EFI_EDITOR_LINE *Src
+ )
+{
+ EFI_EDITOR_LINE *Dest;
+
+ //
+ // allocate for the line structure
+ //
+ Dest = AllocateZeroPool (sizeof (EFI_EDITOR_LINE));
+ if (Dest == NULL) {
+ return NULL;
+ }
+ //
+ // allocate and set the line buffer
+ //
+ Dest->Buffer = CatSPrint (NULL, L"%s", Src->Buffer);
+ if (Dest->Buffer == NULL) {
+ FreePool (Dest);
+ return NULL;
+ }
+
+ //
+ // set the other structure members
+ //
+ Dest->Signature = LINE_LIST_SIGNATURE;
+ Dest->Size = Src->Size;
+ Dest->TotalSize = Dest->Size;
+ Dest->Type = Src->Type;
+ Dest->Link = Src->Link;
+
+ return Dest;
+}
+
+/**
+ Free a EFI_EDITOR_LINE structure.
+
+ @param Src The line structure to free.
+**/
+VOID
+EFIAPI
+LineFree (
+ IN EFI_EDITOR_LINE *Src
+ )
+{
+ if (Src == NULL) {
+ return ;
+ }
+ //
+ // free the line buffer and then the line structure itself
+ //
+ SHELL_FREE_NON_NULL (Src->Buffer);
+ SHELL_FREE_NON_NULL (Src);
+
+}
+
+
+
+
+
+
+
+
+
+
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.h
new file mode 100644
index 0000000000..583de3b42c
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/Misc.h
@@ -0,0 +1,52 @@
+/** @file
+ Declares generic editor helper functions.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LIB_MISC_H_
+#define _LIB_MISC_H_
+
+#include "TextEditorTypes.h"
+
+
+
+/**
+ Free a EFI_EDITOR_LINE structure.
+
+ @param Src The line structure to free.
+**/
+VOID
+EFIAPI
+LineFree (
+ IN EFI_EDITOR_LINE *Src
+ );
+
+/**
+ Duplicate a EFI_EDITOR_LINE structure.
+
+ @param Src The line structure to copy from.
+
+ @retval NULL A memory allocation failed.
+ @return a pointer to the newly allcoated line.
+**/
+EFI_EDITOR_LINE *
+EFIAPI
+LineDup (
+ IN EFI_EDITOR_LINE *Src
+ );
+
+
+
+
+
+
+#endif
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditStrings.uni b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditStrings.uni
new file mode 100644
index 0000000000..f799148135
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditStrings.uni
@@ -0,0 +1,75 @@
+// /**
+//
+// Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved.<BR>
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// Abstract:
+//
+// Additional string definitions for UEFI Shell 2.0 Debug1 profile Edit command
+//
+//
+// **/
+
+/=#
+
+#langdef en-US "english"
+
+#string STR_EDIT_LIBEDITOR_TITLEBAR #language en-US "%EMainEditor init failed on TitleBar init\r\n%N"
+#string STR_EDIT_LIBEDITOR_MAINMENU #language en-US "%EMainEditor init was not successful on MainMenu init\r\n%N"
+#string STR_EDIT_LIBEDITOR_STATUSBAR #language en-US "%EMainEditor init was not successful on StatusBar init\r\n%N"
+#string STR_EDIT_LIBEDITOR_INPUTBAR #language en-US "%EMainEditor init was not successful on InputBar init\r\n%N"
+#string STR_EDIT_LIBEDITOR_FILEBUFFER #language en-US "%EMainEditor init was not successful on FileBuffer init\r\n%N"
+#string STR_EDIT_LIBEDITOR_TITLEBAR_CLEANUP #language en-US "TitleBar cleanup was not successful\r\n"
+#string STR_EDIT_LIBEDITOR_MENUBAR_CLEANUP #language en-US "MenuBar cleanup was not successful\r\n"
+#string STR_EDIT_LIBEDITOR_STATUSBAR_CLEANUP #language en-US "StatusBar cleanup was not successful\r\n"
+#string STR_EDIT_LIBEDITOR_INPUTBAR_CLEANUP #language en-US "InputBar cleanup was not successful\r\n"
+#string STR_EDIT_LIBEDITOR_FILEBUFFER_CLEANUP #language en-US "FileBuffer cleanup was not successful\r\n"
+#string STR_EDIT_LIBEDITOR_MAINEDITOR_INIT #language en-US "%EMainEditor init was not succesful on TitleBar init\r\n%N"
+#string STR_EDIT_LIBINPUTBAR_MAININPUTBAR #language en-US "%s"
+#string STR_EDIT_LIBMENUBAR_OPEN_FILE #language en-US "Open File"
+#string STR_EDIT_LIBMENUBAR_SAVE_FILE #language en-US "Save File"
+#string STR_EDIT_LIBMENUBAR_EXIT #language en-US "Exit"
+#string STR_EDIT_LIBMENUBAR_CUT_LINE #language en-US "Cut Line"
+#string STR_EDIT_LIBMENUBAR_PASTE_LINE #language en-US "Paste Line"
+#string STR_EDIT_LIBMENUBAR_GO_TO_LINE #language en-US "Go To Line"
+#string STR_EDIT_LIBMENUBAR_SEARCH #language en-US "Search"
+#string STR_EDIT_LIBMENUBAR_SEARCH_REPLACE #language en-US "Search/Replace"
+#string STR_EDIT_LIBMENUBAR_FILE_TYPE #language en-US "File Type"
+#string STR_EDIT_LIBMENUBAR_F1 #language en-US "F1"
+#string STR_EDIT_LIBMENUBAR_F2 #language en-US "F2"
+#string STR_EDIT_LIBMENUBAR_F3 #language en-US "F3"
+#string STR_EDIT_LIBMENUBAR_F4 #language en-US "F4"
+#string STR_EDIT_LIBMENUBAR_F5 #language en-US "F5"
+#string STR_EDIT_LIBMENUBAR_F6 #language en-US "F6"
+#string STR_EDIT_LIBMENUBAR_F7 #language en-US "F7"
+#string STR_EDIT_LIBMENUBAR_F8 #language en-US "F8"
+#string STR_EDIT_LIBMENUBAR_F9 #language en-US "F9"
+#string STR_EDIT_LIBMENUBAR_F10 #language en-US "F10"
+#string STR_EDIT_LIBMENUBAR_F11 #language en-US "F11"
+#string STR_EDIT_LIBMENUBAR_F12 #language en-US "F12"
+#string STR_EDIT_LIBMENUBAR_CTRL_E #language en-US "Ctrl+E"
+#string STR_EDIT_LIBMENUBAR_CTRL_W #language en-US "Ctrl+W"
+#string STR_EDIT_HELP_TITLE #language en-US "Help \n"
+#string STR_EDIT_HELP_BLANK #language en-US " \n"
+#string STR_EDIT_HELP_LIST_TITLE #language en-US "Control Key Function Key Command \n"
+#string STR_EDIT_HELP_DIV #language en-US "----------- ------------ ----------------- \n"
+#string STR_EDIT_HELP_GO_TO_LINE #language en-US "Ctrl-G F1 Go To Line \n"
+#string STR_EDIT_HELP_SAVE_FILE #language en-US "Ctrl-S F2 Save File \n"
+#string STR_EDIT_HELP_EXIT #language en-US "Ctrl-Q F3 Exit \n"
+#string STR_EDIT_HELP_SEARCH #language en-US "Ctrl-F F4 Search \n"
+#string STR_EDIT_HELP_SEARCH_REPLACE #language en-US "Ctrl-R F5 Search/Replace \n"
+#string STR_EDIT_HELP_CUT_LINE #language en-US "Ctrl-K F6 Cut Line \n"
+#string STR_EDIT_HELP_PASTE_LINE #language en-US "Ctrl-U F7 Paste Line \n"
+#string STR_EDIT_HELP_OPEN_FILE #language en-US "Ctrl-O F8 Open File \n"
+#string STR_EDIT_HELP_FILE_TYPE #language en-US "Ctrl-T F9 File Type \n"
+#string STR_EDIT_HELP_EXIT_HELP #language en-US "Use Ctrl-W to exit this help \n"
+#string STR_EDIT_MAIN_INVALID_FILE_NAME #language en-US "%Hedit%N: Invalid File Name\r\n"
+#string STR_EDIT_MAIN_INIT_FAILED #language en-US "%Hedit%N: Initialization was not successful\r\n"
+#string STR_EDIT_MAIN_BUFFER #language en-US "%Hedit%N: %s\r\n"
+#string STR_EDIT_MAIN_UNKNOWN_EDITOR_ERR #language en-US "%Hedit%N: Unknown Editor Error\r\n"
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditor.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditor.h
new file mode 100644
index 0000000000..774f01a291
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditor.h
@@ -0,0 +1,32 @@
+/** @file
+ Main include file for Edit shell Debug1 function.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _EFI_EDIT_H_
+#define _EFI_EDIT_H_
+
+#include "TextEditorTypes.h"
+
+#include "MainTextEditor.h"
+#include "FileBuffer.h"
+#include "EditTitleBar.h"
+#include "EditStatusBar.h"
+#include "EditInputBar.h"
+#include "EditMenuBar.h"
+#include "Misc.h"
+
+extern EFI_EDITOR_GLOBAL_EDITOR MainEditor;
+extern BOOLEAN EditorFirst;
+extern BOOLEAN EditorExit;
+
+#endif // _EFI_EDIT_H_
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditorTypes.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditorTypes.h
new file mode 100644
index 0000000000..dfd56dd9a6
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Edit/TextEditorTypes.h
@@ -0,0 +1,102 @@
+/** @file
+ Declares editor types.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _EDITOR_TYPE_H_
+#define _EDITOR_TYPE_H_
+
+#include "UefiShellDebug1CommandsLib.h"
+#include "EditTitleBar.h"
+#include "EditMenuBar.h"
+
+#define MIN_POOL_SIZE 125
+#define MAX_STRING_LENGTH 127
+
+typedef struct {
+ UINTN Row;
+ UINTN Column;
+} EFI_EDITOR_POSITION;
+
+typedef
+EFI_STATUS
+(*EFI_MENU_ITEM_FUNCTION) (
+ VOID
+ );
+
+typedef enum {
+ NewLineTypeDefault,
+ NewLineTypeLineFeed,
+ NewLineTypeCarriageReturn,
+ NewLineTypeCarriageReturnLineFeed,
+ NewLineTypeLineFeedCarriageReturn,
+ NewLineTypeUnknown
+} EE_NEWLINE_TYPE;
+
+#define LINE_LIST_SIGNATURE SIGNATURE_32 ('e', 'e', 'l', 'l')
+typedef struct _EFI_EDITOR_LINE {
+ UINTN Signature;
+ CHAR16 *Buffer;
+ UINTN Size; // unit is Unicode
+ UINTN TotalSize; // unit is Unicode, exclude CHAR_NULL
+ EE_NEWLINE_TYPE Type;
+ LIST_ENTRY Link;
+} EFI_EDITOR_LINE;
+
+typedef struct {
+ UINT32 Foreground : 4;
+ UINT32 Background : 4;
+} EFI_EDITOR_COLOR_ATTRIBUTES;
+
+typedef union {
+ EFI_EDITOR_COLOR_ATTRIBUTES Colors;
+ UINTN Data;
+} EFI_EDITOR_COLOR_UNION;
+
+typedef struct {
+ UINTN Columns;
+ UINTN Rows;
+} EFI_EDITOR_TEXT_MODE;
+
+typedef struct {
+ CHAR16 *FileName; // file name current edited in editor
+ EDIT_FILE_TYPE FileType; // Unicode file or ASCII file
+ LIST_ENTRY *ListHead; // list head of lines
+ EFI_EDITOR_LINE *Lines; // lines of current file
+ UINTN NumLines; // total line numbers
+ EFI_EDITOR_POSITION DisplayPosition; // cursor position in screen
+ EFI_EDITOR_POSITION FilePosition; // cursor position in file
+ EFI_EDITOR_POSITION MousePosition; // mouse position in screen
+ // file position of first byte displayed on screen
+ //
+ EFI_EDITOR_POSITION LowVisibleRange;
+
+ BOOLEAN FileModified; // file is modified or not
+ BOOLEAN ModeInsert; // input mode INS or OVR
+ BOOLEAN ReadOnly; // file is read-only or not
+ EFI_EDITOR_LINE *CurrentLine; // current line cursor is at
+} EFI_EDITOR_FILE_BUFFER;
+
+typedef struct {
+ EFI_EDITOR_FILE_BUFFER *FileBuffer;
+
+ EFI_EDITOR_COLOR_UNION ColorAttributes;
+ EFI_EDITOR_POSITION ScreenSize; // row number and column number
+ EFI_EDITOR_LINE *CutLine; // clip board
+ BOOLEAN MouseSupported;
+ EFI_SIMPLE_POINTER_PROTOCOL *MouseInterface;
+ INT32 MouseAccumulatorX;
+ INT32 MouseAccumulatorY;
+
+} EFI_EDITOR_GLOBAL_EDITOR;
+
+#endif
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditInputBar.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditInputBar.c
new file mode 100644
index 0000000000..5c43ffcd9d
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditInputBar.c
@@ -0,0 +1,323 @@
+/** @file
+ Implements inputbar interface functions.
+
+ Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "EditInputBar.h"
+#include "UefiShellDebug1CommandsLib.h"
+
+CHAR16 *mPrompt; // Input bar mPrompt string.
+CHAR16 *mReturnString; // The returned string.
+UINTN StringSize; // Size of mReturnString space size.
+
+/**
+ Initialize the input bar.
+**/
+VOID
+EFIAPI
+InputBarInit (
+ VOID
+ )
+{
+ mPrompt = NULL;
+ mReturnString = NULL;
+ StringSize = 0;
+}
+
+/**
+ Cleanup function for input bar.
+**/
+VOID
+EFIAPI
+InputBarCleanup (
+ VOID
+ )
+{
+ //
+ // free input bar's prompt and input string
+ //
+ SHELL_FREE_NON_NULL (mPrompt);
+ SHELL_FREE_NON_NULL (mReturnString);
+ mPrompt = NULL;
+ mReturnString = NULL;
+}
+
+/**
+ Display the prompt.
+ Do the requesting of input.
+
+ @param[in] LastColumn The last printable column.
+ @param[in] LastRow The last printable row.
+**/
+VOID
+EFIAPI
+InputBarPrintInput (
+ IN UINTN LastColumn,
+ IN UINTN LastRow
+ )
+{
+ UINTN Limit;
+ UINTN Size;
+ CHAR16 *Buffer;
+ UINTN Index;
+ UINTN mPromptLen;
+
+ mPromptLen = StrLen (mPrompt);
+ Limit = LastColumn - mPromptLen - 1;
+ Size = StrLen (mReturnString);
+
+ //
+ // check whether the mPrompt length and input length will
+ // exceed limit
+ //
+ if (Size <= Limit) {
+ Buffer = mReturnString;
+ } else {
+ Buffer = mReturnString + Size - Limit;
+ }
+
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);
+
+ ShellPrintEx (((INT32)mPromptLen), ((INT32)LastRow) - 1, L"%s", Buffer);
+ Size = StrLen (Buffer);
+
+ //
+ // print " " after mPrompt
+ //
+ for (Index = Size; Index < Limit; Index++) {
+ ShellPrintEx ((INT32)(mPromptLen + Size), ((INT32)LastRow) - 1, L" ");
+ }
+
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+ gST->ConOut->SetCursorPosition (gST->ConOut, Size + mPromptLen, LastRow - 1);
+}
+
+typedef struct {
+ UINT32 Foreground : 4;
+ UINT32 Background : 3;
+} INPUT_BAR_COLOR_ATTRIBUTES;
+
+typedef union {
+ INPUT_BAR_COLOR_ATTRIBUTES Colors;
+ UINTN Data;
+} INPUT_BAR_COLOR_UNION;
+
+
+/**
+ The refresh function for InputBar, it will wait for user input
+
+ @param[in] LastRow The last printable row.
+ @param[in] LastColumn The last printable column.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+InputBarRefresh (
+ UINTN LastRow,
+ UINTN LastColumn
+ )
+{
+ INPUT_BAR_COLOR_UNION Orig;
+ INPUT_BAR_COLOR_UNION New;
+ EFI_INPUT_KEY Key;
+ UINTN Size;
+ EFI_STATUS Status;
+ BOOLEAN NoDisplay;
+ UINTN EventIndex;
+ UINTN CursorRow;
+ UINTN CursorCol;
+
+ //
+ // variable initialization
+ //
+ Size = 0;
+ Status = EFI_SUCCESS;
+
+ //
+ // back up the old screen attributes
+ //
+ CursorCol = gST->ConOut->Mode->CursorColumn;
+ CursorRow = gST->ConOut->Mode->CursorRow;
+ Orig.Data = gST->ConOut->Mode->Attribute;
+ New.Data = 0;
+ New.Colors.Foreground = Orig.Colors.Background & 0xF;
+ New.Colors.Background = Orig.Colors.Foreground & 0x7;
+
+ gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F);
+
+ //
+ // clear input bar
+ //
+ EditorClearLine (LastRow , LastColumn, LastRow);
+
+ gST->ConOut->SetCursorPosition (gST->ConOut, 0, LastRow - 1);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_EDIT_LIBINPUTBAR_MAININPUTBAR), gShellDebug1HiiHandle, mPrompt);
+
+ //
+ // this is a selection mPrompt, cursor will stay in edit area
+ // actually this is for search , search/replace
+ //
+ if (StrStr (mPrompt, L"Yes/No")) {
+ NoDisplay = TRUE;
+ gST->ConOut->SetCursorPosition (gST->ConOut, CursorCol, CursorRow);
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
+ } else {
+ NoDisplay = FALSE;
+ }
+ //
+ // wait for user input
+ //
+ for (;;) {
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ //
+ // pressed ESC
+ //
+ if (Key.ScanCode == SCAN_ESC) {
+ Size = 0;
+ Status = EFI_NOT_READY;
+ break;
+ }
+ //
+ // return pressed
+ //
+ if (Key.UnicodeChar == CHAR_LINEFEED || Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+ break;
+ } else if (Key.UnicodeChar == CHAR_BACKSPACE) {
+ //
+ // backspace
+ //
+ if (Size > 0) {
+ Size--;
+ mReturnString[Size] = CHAR_NULL;
+ if (!NoDisplay) {
+
+ InputBarPrintInput (LastColumn, LastRow);
+
+ }
+ }
+ } else if (Key.UnicodeChar <= 127 && Key.UnicodeChar >= 32) {
+ //
+ // VALID ASCII char pressed
+ //
+ mReturnString[Size] = Key.UnicodeChar;
+
+ //
+ // should be less than specified length
+ //
+ if (Size >= StringSize) {
+ continue;
+ }
+
+ Size++;
+
+ mReturnString[Size] = CHAR_NULL;
+
+ if (!NoDisplay) {
+
+ InputBarPrintInput (LastColumn, LastRow);
+
+ } else {
+ //
+ // if just choose yes/no
+ //
+ break;
+ }
+
+ }
+ }
+
+ mReturnString[Size] = CHAR_NULL;
+
+
+ //
+ // restore screen attributes
+ //
+ gST->ConOut->SetCursorPosition (gST->ConOut, CursorCol, CursorRow);
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
+
+ return Status;
+}
+
+/**
+ SetPrompt and wait for input.
+
+ @param[in] Str The prompt string.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+InputBarSetPrompt (
+ IN CONST CHAR16 *Str
+ )
+{
+ //
+ // FREE the old mPrompt string
+ //
+ SHELL_FREE_NON_NULL (mPrompt);
+
+ mPrompt = CatSPrint (NULL, L"%s ", Str);
+ if (mPrompt == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set the size of the string in characters.
+
+ @param[in] Size The max number of characters to accept.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+InputBarSetStringSize (
+ UINTN Size
+ )
+{
+ //
+ // free the old ReturnStirng
+ //
+ SHELL_FREE_NON_NULL (mReturnString);
+
+ StringSize = Size;
+ mReturnString = AllocateZeroPool ((StringSize + 1) * sizeof(mReturnString[0]));
+ if (mReturnString == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Function to retrieve the input from the user.
+
+ @retval NULL No input has been received.
+ @return The string that was input.
+**/
+CONST CHAR16*
+EFIAPI
+InputBarGetString (
+ VOID
+ )
+{
+ return (mReturnString);
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditInputBar.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditInputBar.h
new file mode 100644
index 0000000000..c8557a83f1
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditInputBar.h
@@ -0,0 +1,91 @@
+/** @file
+ Declares imputbar interface functions.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LIB_INPUT_BAR_H_
+#define _LIB_INPUT_BAR_H_
+
+/**
+ Initialize the input bar.
+**/
+VOID
+EFIAPI
+InputBarInit (
+ VOID
+ );
+
+/**
+ Cleanup function for input bar.
+**/
+VOID
+EFIAPI
+InputBarCleanup (
+ VOID
+ );
+
+/**
+ The refresh function for InputBar, it will wait for user input
+
+ @param[in] LastRow The last printable row.
+ @param[in] LastColumn The last printable column.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+InputBarRefresh (
+ UINTN LastRow,
+ UINTN LastColumn
+ );
+
+/**
+ SetPrompt and wait for input.
+
+ @param[in] Str The prompt string.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+InputBarSetPrompt (
+ IN CONST CHAR16 *Str
+ );
+
+/**
+ Set the size of the string in characters.
+
+ @param[in] Size The max number of characters to accept.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+InputBarSetStringSize (
+ UINTN Size
+ );
+
+/**
+ Function to retrieve the input from the user.
+
+ @retval NULL No input has been received.
+ @return The string that was input.
+**/
+CONST CHAR16*
+EFIAPI
+InputBarGetString (
+ VOID
+ );
+
+#endif
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditMenuBar.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditMenuBar.c
new file mode 100644
index 0000000000..b721850300
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditMenuBar.c
@@ -0,0 +1,196 @@
+/** @file
+ implements menubar interface functions.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "EditMenuBar.h"
+#include "UefiShellDebug1CommandsLib.h"
+#include "EditStatusBar.h"
+
+EDITOR_MENU_ITEM *MenuItems;
+MENU_ITEM_FUNCTION *ControlBasedMenuFunctions;
+UINTN NumItems;
+
+/**
+ Cleanup function for a menu bar. frees all allocated memory.
+**/
+VOID
+EFIAPI
+MenuBarCleanup (
+ VOID
+ )
+{
+ SHELL_FREE_NON_NULL(MenuItems);
+}
+
+/**
+ Initialize the menu bar with the specified items.
+
+ @param[in] Items The items to display and their functions.
+
+ @retval EFI_SUCCESS The initialization was correct.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+MenuBarInit (
+ IN CONST EDITOR_MENU_ITEM *Items
+ )
+{
+ CONST EDITOR_MENU_ITEM *ItemsWalker;
+
+ for (NumItems = 0, ItemsWalker = Items ; ItemsWalker != NULL && ItemsWalker->Function != NULL ; ItemsWalker++,NumItems++);
+
+ MenuItems = AllocateZeroPool((NumItems+1) * sizeof(EDITOR_MENU_ITEM));
+ if (MenuItems == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CopyMem(MenuItems, Items, (NumItems+1) * sizeof(EDITOR_MENU_ITEM));
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialize the control hot-key with the specified items.
+
+ @param[in] Items The hot-key functions.
+
+ @retval EFI_SUCCESS The initialization was correct.
+**/
+EFI_STATUS
+EFIAPI
+ControlHotKeyInit (
+ IN MENU_ITEM_FUNCTION *Items
+ )
+{
+ ControlBasedMenuFunctions = Items;
+ return EFI_SUCCESS;
+}
+/**
+ Refresh function for the menu bar.
+
+ @param[in] LastRow The last printable row.
+ @param[in] LastCol The last printable column.
+
+ @retval EFI_SUCCESS The refresh was successful.
+**/
+EFI_STATUS
+EFIAPI
+MenuBarRefresh (
+ IN CONST UINTN LastRow,
+ IN CONST UINTN LastCol
+ )
+{
+ EDITOR_MENU_ITEM *Item;
+ UINTN Col;
+ UINTN Row;
+ UINTN Width;
+ CHAR16 *NameString;
+ CHAR16 *FunctionKeyString;
+
+ //
+ // variable initialization
+ //
+ Col = 1;
+ Row = (LastRow - 2);
+
+ //
+ // clear menu bar rows
+ //
+ EditorClearLine (LastRow - 2, LastCol, LastRow);
+ EditorClearLine (LastRow - 1, LastCol, LastRow);
+ EditorClearLine (LastRow , LastCol, LastRow);
+
+
+ //
+ // print out the menu items
+ //
+ for (Item = MenuItems; Item != NULL && Item->Function != NULL; Item++) {
+
+
+ NameString = HiiGetString(gShellDebug1HiiHandle, Item->NameToken, NULL);
+
+
+ Width = MAX ((StrLen (NameString) + 6), 20);
+ if (((Col + Width) > LastCol)) {
+ Row++;
+ Col = 1;
+ }
+
+ FunctionKeyString = HiiGetString(gShellDebug1HiiHandle, Item->FunctionKeyToken, NULL);
+
+ ShellPrintEx ((INT32)(Col) - 1, (INT32)(Row) - 1, L"%E%s%N %H%s%N ", FunctionKeyString, NameString);
+
+ FreePool (NameString);
+ FreePool (FunctionKeyString);
+ Col += Width;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Function to dispatch the correct function based on a function key (F1...)
+
+ @param[in] Key The pressed key.
+
+ @retval EFI_NOT_FOUND The key was not a valid function key
+ (an error was sent to the status bar).
+ @return The return value from the called dispatch function.
+**/
+EFI_STATUS
+EFIAPI
+MenuBarDispatchFunctionKey (
+ IN CONST EFI_INPUT_KEY *Key
+ )
+{
+ UINTN Index;
+
+ Index = Key->ScanCode - SCAN_F1;
+
+ //
+ // check whether in range
+ //
+ if (Index > (NumItems - 1)) {
+ StatusBarSetStatusString (L"Unknown Command");
+ return EFI_SUCCESS;
+ }
+
+ return (MenuItems[Index].Function ());
+}
+
+/**
+ Function to dispatch the correct function based on a control-based key (ctrl+o...)
+
+ @param[in] Key The pressed key.
+
+ @retval EFI_NOT_FOUND The key was not a valid control-based key
+ (an error was sent to the status bar).
+ @return EFI_SUCCESS.
+**/
+EFI_STATUS
+EFIAPI
+MenuBarDispatchControlHotKey (
+ IN CONST EFI_INPUT_KEY *Key
+ )
+{
+
+ if ((SCAN_CONTROL_Z < Key->UnicodeChar)
+ ||(NULL == ControlBasedMenuFunctions[Key->UnicodeChar]))
+ {
+ return EFI_NOT_FOUND;
+ }
+
+ ControlBasedMenuFunctions[Key->UnicodeChar]();
+ return EFI_SUCCESS;
+}
+
+
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditMenuBar.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditMenuBar.h
new file mode 100644
index 0000000000..8cd846f28b
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditMenuBar.h
@@ -0,0 +1,125 @@
+/** @file
+ Declares menubar interface functions.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LIB_MENU_BAR_H_
+#define _LIB_MENU_BAR_H_
+
+#define SCAN_CONTROL_E 5
+#define SCAN_CONTROL_F 6
+#define SCAN_CONTROL_G 7
+#define SCAN_CONTROL_K 11
+#define SCAN_CONTROL_O 15
+#define SCAN_CONTROL_Q 17
+#define SCAN_CONTROL_R 18
+#define SCAN_CONTROL_S 19
+#define SCAN_CONTROL_T 20
+#define SCAN_CONTROL_U 21
+#define SCAN_CONTROL_W 23
+#define SCAN_CONTROL_Z 26
+
+
+typedef
+EFI_STATUS
+(*MENU_ITEM_FUNCTION) (
+ VOID
+ );
+
+typedef struct _EDITOR_MENU_ITEM {
+ EFI_STRING_ID NameToken;
+ CHAR16 FunctionKeyToken;
+ MENU_ITEM_FUNCTION Function;
+} EDITOR_MENU_ITEM;
+
+/**
+ Initializa the menu bar with the specified items.
+
+ @param[in] Items The items to display and their functions.
+
+ @retval EFI_SUCCESS The initialization was correct.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+MenuBarInit (
+ IN CONST EDITOR_MENU_ITEM *Items
+ );
+
+/**
+ Initialize the control hot-key with the specified items.
+
+ @param[in] Items The hot-key functions.
+
+ @retval EFI_SUCCESS The initialization was correct.
+**/
+EFI_STATUS
+EFIAPI
+ControlHotKeyInit (
+ IN MENU_ITEM_FUNCTION *Items
+ );
+
+/**
+ Cleanup function for a menu bar. frees all allocated memory.
+**/
+VOID
+EFIAPI
+MenuBarCleanup (
+ VOID
+ );
+
+/**
+ Refresh function for the menu bar.
+
+ @param[in] LastRow The last printable row.
+ @param[in] LastCol The last printable column.
+
+ @retval EFI_SUCCESS The refresh was successful.
+**/
+EFI_STATUS
+EFIAPI
+MenuBarRefresh (
+ IN CONST UINTN LastRow,
+ IN CONST UINTN LastCol
+ );
+
+/**
+ Function to dispatch the correct function based on a function key (F1...)
+
+ @param[in] Key The pressed key.
+
+ @retval EFI_NOT_FOUND The key was not a valid function key
+ (an error was sent to the status bar).
+ @return The return value from the called dispatch function.
+**/
+EFI_STATUS
+EFIAPI
+MenuBarDispatchFunctionKey (
+ IN CONST EFI_INPUT_KEY *Key
+ );
+
+/**
+ Function to dispatch the correct function based on a control-based key (ctrl+o...)
+
+ @param[in] Key The pressed key.
+
+ @retval EFI_NOT_FOUND The key was not a valid control-based key
+ (an error was sent to the status bar).
+ @return EFI_SUCCESS.
+**/
+EFI_STATUS
+EFIAPI
+MenuBarDispatchControlHotKey (
+ IN CONST EFI_INPUT_KEY *Key
+ );
+
+#endif
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditStatusBar.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditStatusBar.c
new file mode 100644
index 0000000000..fbf48b7e2b
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditStatusBar.c
@@ -0,0 +1,237 @@
+/** @file
+ Implements statusbar interface functions.
+
+ Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "EditStatusBar.h"
+#include "UefiShellDebug1CommandsLib.h"
+
+CHAR16 *StatusString;
+BOOLEAN StatusBarNeedRefresh;
+BOOLEAN StatusStringChanged;
+
+/**
+ Initialization function for Status Bar.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @sa StatusBarSetStatusString
+**/
+EFI_STATUS
+EFIAPI
+StatusBarInit (
+ VOID
+ )
+{
+ //
+ // initialize the statusbar
+ //
+ StatusString = NULL;
+ StatusBarNeedRefresh = TRUE;
+ StatusStringChanged = FALSE;
+
+ //
+ // status string set to ""
+ //
+ return (StatusBarSetStatusString (L""));
+}
+
+/**
+ Cleanup function for the status bar.
+**/
+VOID
+EFIAPI
+StatusBarCleanup (
+ VOID
+ )
+{
+ //
+ // free the status string and backvar's status string
+ //
+ SHELL_FREE_NON_NULL (StatusString);
+}
+
+typedef struct {
+ UINT32 Foreground : 4;
+ UINT32 Background : 3;
+} STATUS_BAR_COLOR_ATTRIBUTES;
+
+typedef union {
+ STATUS_BAR_COLOR_ATTRIBUTES Colors;
+ UINTN Data;
+} STATUS_BAR_COLOR_UNION;
+
+/**
+ Cause the status bar to refresh it's printing on the screen.
+
+ @param[in] EditorFirst TRUE to indicate the first launch of the editor.
+ FALSE otherwise.
+ @param[in] LastRow LastPrintable row.
+ @param[in] LastCol Last printable column.
+ @param[in] FileRow Row in the file.
+ @param[in] FileCol Column in the file.
+ @param[in] InsertMode TRUE to indicate InsertMode. FALSE otherwise.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+StatusBarRefresh (
+ IN BOOLEAN EditorFirst,
+ IN UINTN LastRow,
+ IN UINTN LastCol,
+ IN UINTN FileRow,
+ IN UINTN FileCol,
+ IN BOOLEAN InsertMode
+ )
+{
+ STATUS_BAR_COLOR_UNION Orig;
+ STATUS_BAR_COLOR_UNION New;
+
+ if (!StatusStringChanged && StatusBarNeedRefresh) {
+ StatusBarSetStatusString (L"\0");
+ }
+ //
+ // when it's called first time after editor launch, so refresh is mandatory
+ //
+ if (!StatusBarNeedRefresh && !StatusStringChanged) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // back up the screen attributes
+ //
+ Orig.Data = gST->ConOut->Mode->Attribute;
+ New.Data = 0;
+ New.Colors.Foreground = Orig.Colors.Background & 0xF;
+ New.Colors.Background = Orig.Colors.Foreground & 0x7;
+
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);
+ gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F);
+
+ //
+ // clear status bar
+ //
+ EditorClearLine (LastRow, LastCol, LastRow);
+
+ //
+ // print row, column fields
+ //
+ if (FileRow != (UINTN)(-1) && FileCol != (UINTN)(-1)) {
+ ShellPrintEx (
+ 0,
+ (INT32)(LastRow) - 1,
+ L" %d,%d %s",
+ FileRow,
+ FileCol,
+ StatusString
+ );
+ } else {
+ ShellPrintEx (
+ 0,
+ (INT32)(LastRow) - 1,
+ L" %s",
+ StatusString
+ );
+ }
+
+ //
+ // print insert mode field
+ //
+ if (InsertMode) {
+ ShellPrintEx ((INT32)(LastCol) - 21, (INT32)(LastRow) - 1, L"|%s| Help: Ctrl-E", L"INS");
+ } else {
+ ShellPrintEx ((INT32)(LastCol) - 21, (INT32)(LastRow) - 1, L"|%s| Help: Ctrl-E", L"OVR");
+ }
+ //
+ // restore the old screen attributes
+ //
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
+
+ //
+ // restore position in edit area
+ //
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+
+ StatusBarNeedRefresh = FALSE;
+ StatusStringChanged = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set the status string text part.
+
+ @param[in] Str The string to use.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+StatusBarSetStatusString (
+ IN CHAR16 *Str
+ )
+{
+ StatusStringChanged = TRUE;
+
+ //
+ // free the old status string
+ //
+ SHELL_FREE_NON_NULL (StatusString);
+ StatusString = CatSPrint (NULL, L"%s", Str);
+ if (StatusString == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Function to retrieve the current status string.
+
+ @return The string that is used.
+**/
+CONST CHAR16*
+EFIAPI
+StatusBarGetString (
+ VOID
+ )
+{
+ return (StatusString);
+}
+
+/**
+ Function to set the need refresh boolean to TRUE.
+**/
+VOID
+EFIAPI
+StatusBarSetRefresh(
+ VOID
+ )
+{
+ StatusBarNeedRefresh = TRUE;
+}
+
+/**
+ Function to get the need refresh boolean to TRUE.
+
+ @retval TRUE The status bar needs to be refreshed.
+**/
+BOOLEAN
+EFIAPI
+StatusBarGetRefresh(
+ VOID
+ )
+{
+ return (StatusBarNeedRefresh);
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditStatusBar.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditStatusBar.h
new file mode 100644
index 0000000000..debf83a9ec
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditStatusBar.h
@@ -0,0 +1,109 @@
+/** @file
+ Declares statusbar interface functions.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LIB_STATUS_BAR_H_
+#define _LIB_STATUS_BAR_H_
+
+/**
+ Initialization function for Status Bar.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @sa StatusBarSetStatusString
+**/
+EFI_STATUS
+EFIAPI
+StatusBarInit (
+ VOID
+ );
+
+/**
+ Cleanup function for the status bar.
+**/
+VOID
+EFIAPI
+StatusBarCleanup (
+ VOID
+ );
+
+/**
+ Cause the status bar to refresh it's printing on the screen.
+
+ @param[in] EditorFirst TRUE to indicate the first launch of the editor.
+ FALSE otherwise.
+ @param[in] LastRow LastPrintable row.
+ @param[in] LastCol Last printable column.
+ @param[in] FileRow Row in the file.
+ @param[in] FileCol Column in the file.
+ @param[in] InsertMode TRUE to indicate InsertMode. FALSE otherwise.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+StatusBarRefresh (
+ IN BOOLEAN EditorFirst,
+ IN UINTN LastRow,
+ IN UINTN LastCol,
+ IN UINTN FileRow,
+ IN UINTN FileCol,
+ IN BOOLEAN InsertMode
+ );
+
+/**
+ Set the status string text part.
+
+ @param[in] Str The string to use.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+StatusBarSetStatusString (
+ IN CHAR16 *Str
+ );
+
+/**
+ Function to retrieve the current status string.
+
+ @return The string that is used.
+**/
+CONST CHAR16*
+EFIAPI
+StatusBarGetString (
+ VOID
+ );
+
+/**
+ Function to set the need refresh boolean to TRUE.
+**/
+VOID
+EFIAPI
+StatusBarSetRefresh(
+ VOID
+ );
+
+/**
+ Function to get the need refresh boolean to TRUE.
+
+ @retval TRUE The status bar needs to be refreshed.
+**/
+BOOLEAN
+EFIAPI
+StatusBarGetRefresh(
+ VOID
+ );
+
+#endif
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditTitleBar.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditTitleBar.c
new file mode 100644
index 0000000000..a0d7cad1e5
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditTitleBar.c
@@ -0,0 +1,210 @@
+/** @file
+ Implements titlebar interface functions.
+
+ (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "EditTitleBar.h"
+#include "UefiShellDebug1CommandsLib.h"
+
+CHAR16 *Title = NULL;
+
+/**
+ Initialize a title bar.
+
+ @param[in] Prompt The prompt to print in the title bar.
+
+ @retval EFI_SUCCESS The initialization was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+MainTitleBarInit (
+ CONST CHAR16 *Prompt
+ )
+{
+ SHELL_FREE_NON_NULL (Title);
+ if (Prompt == NULL) {
+ Title = CatSPrint (NULL, L"");
+ } else {
+ //
+ // set Title
+ //
+ Title = CatSPrint (NULL, L"%s", Prompt);
+ }
+ if (Title == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Clean up the memory used.
+**/
+VOID
+EFIAPI
+MainTitleBarCleanup (
+ VOID
+ )
+{
+ SHELL_FREE_NON_NULL (Title);
+ Title = NULL;
+}
+
+typedef struct {
+ UINT32 Foreground : 4;
+ UINT32 Background : 4;
+} TITLE_BAR_COLOR_ATTRIBUTES;
+
+typedef union {
+ TITLE_BAR_COLOR_ATTRIBUTES Colors;
+ UINTN Data;
+} TITLE_BAR_COLOR_UNION;
+
+/**
+ Refresh function for MainTitleBar
+
+ @param[in] FileName The open file's name (or NULL).
+ @param[in] FileType The type fo the file.
+ @param[in] ReadOnly TRUE if the file is read only. FALSE otherwise.
+ @param[in] Modified TRUE if the file was modified. FALSE otherwise.
+ @param[in] LastCol The last printable column.
+ @param[in] LastRow The last printable row.
+ @param[in] Offset The offset into the file. (only for mem/disk)
+ @param[in] Size The file's size. (only for mem/disk)
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+MainTitleBarRefresh (
+ IN CONST CHAR16 *FileName OPTIONAL,
+ IN CONST EDIT_FILE_TYPE FileType,
+ IN CONST BOOLEAN ReadOnly,
+ IN CONST BOOLEAN Modified,
+ IN CONST UINTN LastCol,
+ IN CONST UINTN LastRow,
+ IN CONST UINTN Offset,
+ IN CONST UINTN Size
+ )
+{
+ TITLE_BAR_COLOR_UNION Orig;
+ TITLE_BAR_COLOR_UNION New;
+ CONST CHAR16 *FileNameTmp;
+ INTN TempInteger;
+
+
+ //
+ // backup the old screen attributes
+ //
+ Orig.Data = gST->ConOut->Mode->Attribute;
+ New.Data = 0;
+ New.Colors.Foreground = Orig.Colors.Background & 0xF;
+ New.Colors.Background = Orig.Colors.Foreground & 0x7;
+
+ gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F);
+
+ //
+ // clear the title line
+ //
+ EditorClearLine (1, LastCol, LastRow);
+
+ if (Title != NULL) {
+ //
+ // print the new title bar prefix
+ //
+ ShellPrintEx (
+ 0,
+ 0,
+ L"%s ",
+ Title
+ );
+ }
+ if (FileName == NULL) {
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
+ return EFI_SUCCESS;
+ }
+ //
+ // First Extract the FileName from fullpath
+ //
+ FileNameTmp = FileName;
+ for (TempInteger = StrLen (FileNameTmp) - 1; TempInteger >= 0; TempInteger--) {
+ if (FileNameTmp[TempInteger] == L'\\') {
+ break;
+ }
+ }
+
+ FileNameTmp = FileNameTmp + TempInteger + 1;
+
+ //
+ // the space for file name is 20 characters
+ //
+ if (StrLen (FileNameTmp) <= 20) {
+ ShellPrintEx (-1,-1, L"%s ", FileNameTmp);
+ for (TempInteger = StrLen (FileNameTmp); TempInteger < 20; TempInteger++) {
+ ShellPrintEx (-1,-1, L" ");
+ }
+
+ } else {
+ for (TempInteger = 0; TempInteger < 17; TempInteger++) {
+ ShellPrintEx (-1,-1, L"%c", FileNameTmp[TempInteger]);
+ }
+ //
+ // print "..."
+ //
+ ShellPrintEx (-1,-1, L"... ");
+ }
+ //
+ // print file type field
+ //
+ switch (FileType){
+ case FileTypeAscii:
+ case FileTypeUnicode:
+ if (FileType == FileTypeAscii){
+ ShellPrintEx (-1,-1, L" ASCII ");
+ } else {
+ ShellPrintEx (-1,-1, L" UNICODE ");
+ }
+ //
+ // print read-only field for text files
+ //
+ if (ReadOnly) {
+ ShellPrintEx (-1,-1, L"ReadOnly ");
+ } else {
+ ShellPrintEx (-1,-1, L" ");
+ }
+ break;
+ case FileTypeDiskBuffer:
+ case FileTypeMemBuffer:
+ //
+ // Print the offset.
+ //
+ ShellPrintEx (-1,-1, L"Offset %X | Size %X", Offset, Size);
+ case FileTypeFileBuffer:
+ break;
+ default:
+ break;
+ }
+ //
+ // print modified field
+ //
+ if (Modified) {
+ ShellPrintEx (-1,-1, L"Modified");
+ }
+ //
+ // restore the old attribute
+ //
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
+
+ return EFI_SUCCESS;
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditTitleBar.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditTitleBar.h
new file mode 100644
index 0000000000..d8f420fb80
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EditTitleBar.h
@@ -0,0 +1,77 @@
+/** @file
+ Declares titlebar interface functions.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LIB_TITLE_BAR_H_
+#define _LIB_TITLE_BAR_H_
+
+/**
+ Initialize a title bar.
+
+ @param[in] Prompt The prompt to print in the title bar.
+
+ @retval EFI_SUCCESS The initialization was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+MainTitleBarInit (
+ CONST CHAR16 *Prompt
+ );
+
+/**
+ Clean up the memory used.
+**/
+VOID
+EFIAPI
+MainTitleBarCleanup (
+ VOID
+ );
+
+typedef enum {
+ FileTypeNone,
+ FileTypeAscii,
+ FileTypeUnicode,
+ FileTypeDiskBuffer,
+ FileTypeMemBuffer,
+ FileTypeFileBuffer
+} EDIT_FILE_TYPE;
+
+/**
+ Refresh function for MainTitleBar
+
+ @param[in] FileName The open file's name (or NULL).
+ @param[in] FileType The type fo the file.
+ @param[in] ReadOnly TRUE if the file is read only. FALSE otherwise.
+ @param[in] Modified TRUE if the file was modified. FALSE otherwise.
+ @param[in] LastCol The last printable column.
+ @param[in] LastRow The last printable row.
+ @param[in] Offset The offset into the file. (only for mem/disk)
+ @param[in] Size The file's size. (only for mem/disk)
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+MainTitleBarRefresh (
+ IN CONST CHAR16 *FileName OPTIONAL,
+ IN CONST EDIT_FILE_TYPE FileType,
+ IN CONST BOOLEAN ReadOnly,
+ IN CONST BOOLEAN Modified,
+ IN CONST UINTN LastCol,
+ IN CONST UINTN LastRow,
+ IN CONST UINTN Offset,
+ IN CONST UINTN Size
+ );
+
+#endif
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EfiCompress.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EfiCompress.c
new file mode 100644
index 0000000000..d94acf4e4b
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EfiCompress.c
@@ -0,0 +1,164 @@
+/** @file
+ Main file for EfiCompress shell Debug1 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDebug1CommandsLib.h"
+#include "Compress.h"
+
+/**
+ Function for 'compress' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunEfiCompress (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ SHELL_FILE_HANDLE InShellFileHandle;
+ SHELL_FILE_HANDLE OutShellFileHandle;
+ UINT64 OutSize;
+ UINTN OutSize2;
+ VOID *OutBuffer;
+ UINT64 InSize;
+ UINTN InSize2;
+ VOID *InBuffer;
+ CHAR16 *InFileName;
+ CONST CHAR16 *OutFileName;
+ CONST CHAR16 *TempParam;
+
+ InFileName = NULL;
+ OutFileName = NULL;
+ OutSize = 0;
+ ShellStatus = SHELL_SUCCESS;
+ Status = EFI_SUCCESS;
+ OutBuffer = NULL;
+ InShellFileHandle = NULL;
+ OutShellFileHandle = NULL;
+ InBuffer = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"eficompress", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetCount(Package) > 3) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"eficompress");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetCount(Package) < 3) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"eficompress");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ TempParam = ShellCommandLineGetRawValue(Package, 1);
+ ASSERT(TempParam != NULL);
+ InFileName = ShellFindFilePath(TempParam);
+ OutFileName = ShellCommandLineGetRawValue(Package, 2);
+ if (InFileName == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_FIND_FAIL), gShellDebug1HiiHandle, L"eficompress", TempParam);
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ if (ShellIsDirectory(InFileName) == EFI_SUCCESS){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_NOT_DIR), gShellDebug1HiiHandle, L"eficompress", InFileName);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ if (ShellIsDirectory(OutFileName) == EFI_SUCCESS){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_NOT_DIR), gShellDebug1HiiHandle, L"eficompress", OutFileName);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ if (ShellStatus == SHELL_SUCCESS) {
+ Status = ShellOpenFileByName(InFileName, &InShellFileHandle, EFI_FILE_MODE_READ, 0);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"eficompress", ShellCommandLineGetRawValue(Package, 1));
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ Status = ShellOpenFileByName(OutFileName, &OutShellFileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"eficompress", ShellCommandLineGetRawValue(Package, 2));
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ }
+ if (ShellStatus == SHELL_SUCCESS) {
+ Status = gEfiShellProtocol->GetFileSize(InShellFileHandle, &InSize);
+ ASSERT_EFI_ERROR(Status);
+ InBuffer = AllocateZeroPool((UINTN)InSize);
+ if (InBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ InSize2 = (UINTN) InSize;
+ Status = gEfiShellProtocol->ReadFile (InShellFileHandle, &InSize2, InBuffer);
+ InSize = InSize2;
+ ASSERT_EFI_ERROR (Status);
+ Status = Compress (InBuffer, InSize, OutBuffer, &OutSize);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ OutBuffer = AllocateZeroPool ((UINTN) OutSize);
+ if (OutBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ Status = Compress (InBuffer, InSize, OutBuffer, &OutSize);
+ }
+ }
+ }
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_EFI_COMPRESS_FAIL), gShellDebug1HiiHandle, Status);
+ ShellStatus = ((Status == EFI_OUT_OF_RESOURCES) ? SHELL_OUT_OF_RESOURCES : SHELL_DEVICE_ERROR);
+ } else {
+ OutSize2 = (UINTN)OutSize;
+ Status = gEfiShellProtocol->WriteFile(OutShellFileHandle, &OutSize2, OutBuffer);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_WRITE_FAIL), gShellDebug1HiiHandle, L"eficompress", OutFileName);
+ ShellStatus = SHELL_DEVICE_ERROR;
+ }
+ }
+ }
+ }
+ }
+
+ ShellCommandLineFreeVarList (Package);
+ }
+ if (InShellFileHandle != NULL) {
+ gEfiShellProtocol->CloseFile(InShellFileHandle);
+ }
+ if (OutShellFileHandle != NULL) {
+ gEfiShellProtocol->CloseFile(OutShellFileHandle);
+ }
+ SHELL_FREE_NON_NULL(InFileName);
+ SHELL_FREE_NON_NULL(InBuffer);
+ SHELL_FREE_NON_NULL(OutBuffer);
+
+ return (ShellStatus);
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EfiDecompress.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EfiDecompress.c
new file mode 100644
index 0000000000..28c37ee769
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/EfiDecompress.c
@@ -0,0 +1,186 @@
+/** @file
+ Main file for EfiDecompress shell Debug1 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDebug1CommandsLib.h"
+#include <Protocol/Decompress.h>
+
+
+/**
+ Function for 'decompress' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunEfiDecompress (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ SHELL_FILE_HANDLE InFileHandle;
+ SHELL_FILE_HANDLE OutFileHandle;
+ UINT32 OutSize;
+ UINTN OutSizeTemp;
+ VOID *OutBuffer;
+ UINTN InSize;
+ VOID *InBuffer;
+ CHAR16 *InFileName;
+ CONST CHAR16 *OutFileName;
+ UINT64 Temp64Bit;
+ UINT32 ScratchSize;
+ VOID *ScratchBuffer;
+ EFI_DECOMPRESS_PROTOCOL *Decompress;
+ CONST CHAR16 *TempParam;
+
+ InFileName = NULL;
+ OutFileName = NULL;
+ OutSize = 0;
+ ScratchSize = 0;
+ ShellStatus = SHELL_SUCCESS;
+ Status = EFI_SUCCESS;
+ OutBuffer = NULL;
+ InBuffer = NULL;
+ ScratchBuffer = NULL;
+ InFileHandle = NULL;
+ OutFileHandle = NULL;
+ Decompress = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"efidecompress", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetCount(Package) > 3) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"efidecompress");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetCount(Package) < 3) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"efidecompress");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ TempParam = ShellCommandLineGetRawValue(Package, 1);
+ ASSERT(TempParam != NULL);
+ InFileName = ShellFindFilePath(TempParam);
+ OutFileName = ShellCommandLineGetRawValue(Package, 2);
+ if (InFileName == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_FIND_FAIL), gShellDebug1HiiHandle, L"efidecompress", TempParam);
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ if (ShellIsDirectory(InFileName) == EFI_SUCCESS){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_NOT_DIR), gShellDebug1HiiHandle, L"efidecompress", InFileName);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ if (ShellIsDirectory(OutFileName) == EFI_SUCCESS){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_NOT_DIR), gShellDebug1HiiHandle, L"efidecompress", OutFileName);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ if (ShellStatus == SHELL_SUCCESS) {
+ Status = ShellOpenFileByName(InFileName, &InFileHandle, EFI_FILE_MODE_READ, 0);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"efidecompress", ShellCommandLineGetRawValue(Package, 1));
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ }
+
+ if (ShellStatus == SHELL_SUCCESS) {
+ Status = FileHandleGetSize(InFileHandle, &Temp64Bit);
+ ASSERT(Temp64Bit <= (UINT32)(-1));
+ InSize = (UINTN)Temp64Bit;
+ ASSERT_EFI_ERROR(Status);
+ InBuffer = AllocateZeroPool(InSize);
+ if (InBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ Status = gEfiShellProtocol->ReadFile (InFileHandle, &InSize, InBuffer);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID**) &Decompress);
+ ASSERT_EFI_ERROR (Status);
+
+ Status = Decompress->GetInfo (Decompress, InBuffer, (UINT32) InSize, &OutSize, &ScratchSize);
+ }
+
+ if (EFI_ERROR(Status) || OutSize == 0) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_EFI_DECOMPRESS_NOPE), gShellDebug1HiiHandle, InFileName);
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ Status = ShellOpenFileByName(OutFileName, &OutFileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_OPEN_FAIL), gShellDebug1HiiHandle, ShellCommandLineGetRawValue(Package, 2), Status);
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ OutBuffer = AllocateZeroPool(OutSize);
+ ScratchBuffer = AllocateZeroPool(ScratchSize);
+ if (OutBuffer == NULL || ScratchBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ Status = Decompress->Decompress (Decompress, InBuffer, (UINT32) InSize, OutBuffer, OutSize, ScratchBuffer, ScratchSize);
+ }
+ }
+ }
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_EFI_DECOMPRESS_FAIL), gShellDebug1HiiHandle, Status);
+ ShellStatus = ((Status == EFI_OUT_OF_RESOURCES) ? SHELL_OUT_OF_RESOURCES : SHELL_DEVICE_ERROR);
+ } else {
+ OutSizeTemp = OutSize;
+ Status = gEfiShellProtocol->WriteFile (OutFileHandle, &OutSizeTemp, OutBuffer);
+ OutSize = (UINT32) OutSizeTemp;
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_FILE_WRITE_FAIL), gShellDebug1HiiHandle, L"efidecompress", OutFileName, Status);
+ ShellStatus = SHELL_DEVICE_ERROR;
+ }
+ }
+ }
+ }
+ }
+
+ ShellCommandLineFreeVarList (Package);
+ }
+ if (InFileHandle != NULL) {
+ gEfiShellProtocol->CloseFile(InFileHandle);
+ }
+ if (OutFileHandle != NULL) {
+ gEfiShellProtocol->CloseFile(OutFileHandle);
+ }
+
+ SHELL_FREE_NON_NULL(InFileName);
+ SHELL_FREE_NON_NULL(InBuffer);
+ SHELL_FREE_NON_NULL(OutBuffer);
+ SHELL_FREE_NON_NULL(ScratchBuffer);
+
+ return (ShellStatus);
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.c
new file mode 100644
index 0000000000..777c2e0199
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.c
@@ -0,0 +1,2484 @@
+/** @file
+ Defines HBufferImage - the view of the file that is visible at any point,
+ as well as the event handlers for editing the file
+
+ Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HexEditor.h"
+
+extern EFI_HANDLE HImageHandleBackup;
+
+extern HEFI_EDITOR_FILE_IMAGE HFileImage;
+extern HEFI_EDITOR_DISK_IMAGE HDiskImage;
+extern HEFI_EDITOR_MEM_IMAGE HMemImage;
+
+extern HEFI_EDITOR_FILE_IMAGE HFileImageBackupVar;
+extern HEFI_EDITOR_DISK_IMAGE HDiskImageBackupVar;
+extern HEFI_EDITOR_MEM_IMAGE HMemImageBackupVar;
+
+extern BOOLEAN HEditorMouseAction;
+
+extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;
+extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditorBackupVar;
+
+HEFI_EDITOR_BUFFER_IMAGE HBufferImage;
+HEFI_EDITOR_BUFFER_IMAGE HBufferImageBackupVar;
+
+//
+// for basic initialization of HBufferImage
+//
+HEFI_EDITOR_BUFFER_IMAGE HBufferImageConst = {
+ NULL,
+ NULL,
+ 0,
+ NULL,
+ {
+ 0,
+ 0
+ },
+ {
+ 0,
+ 0
+ },
+ {
+ 0,
+ 0
+ },
+ 0,
+ TRUE,
+ FALSE,
+ FileTypeNone,
+ NULL,
+ NULL,
+ NULL
+};
+
+//
+// the whole edit area needs to be refreshed
+//
+BOOLEAN HBufferImageNeedRefresh;
+
+//
+// only the current line in edit area needs to be refresh
+//
+BOOLEAN HBufferImageOnlyLineNeedRefresh;
+
+BOOLEAN HBufferImageMouseNeedRefresh;
+
+/**
+ Initialization function for HBufferImage
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HBufferImageInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // basically initialize the HBufferImage
+ //
+ CopyMem (&HBufferImage, &HBufferImageConst, sizeof (HBufferImage));
+
+ //
+ // INIT listhead
+ //
+ HBufferImage.ListHead = AllocateZeroPool (sizeof (LIST_ENTRY));
+ if (HBufferImage.ListHead == NULL) {
+ return EFI_LOAD_ERROR;
+ }
+
+ InitializeListHead (HBufferImage.ListHead);
+
+ HBufferImage.DisplayPosition.Row = 2;
+ HBufferImage.DisplayPosition.Column = 10;
+ HBufferImage.MousePosition.Row = 2;
+ HBufferImage.MousePosition.Column = 10;
+
+ HBufferImage.FileImage = &HFileImage;
+ HBufferImage.DiskImage = &HDiskImage;
+ HBufferImage.MemImage = &HMemImage;
+
+ HBufferImageNeedRefresh = FALSE;
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+ HBufferImageMouseNeedRefresh = FALSE;
+
+ HBufferImageBackupVar.FileImage = &HFileImageBackupVar;
+ HBufferImageBackupVar.DiskImage = &HDiskImageBackupVar;
+ HBufferImageBackupVar.MemImage = &HMemImageBackupVar;
+
+ Status = HFileImageInit ();
+ if (EFI_ERROR (Status)) {
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = HDiskImageInit ();
+ if (EFI_ERROR (Status)) {
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = HMemImageInit ();
+ if (EFI_ERROR (Status)) {
+ return EFI_LOAD_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Backup function for HBufferImage. Only a few fields need to be backup.
+ This is for making the file buffer refresh as few as possible.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HBufferImageBackup (
+ VOID
+ )
+{
+ HBufferImageBackupVar.MousePosition = HBufferImage.MousePosition;
+
+ HBufferImageBackupVar.BufferPosition = HBufferImage.BufferPosition;
+
+ HBufferImageBackupVar.Modified = HBufferImage.Modified;
+
+ HBufferImageBackupVar.BufferType = HBufferImage.BufferType;
+ HBufferImageBackupVar.LowVisibleRow = HBufferImage.LowVisibleRow;
+ HBufferImageBackupVar.HighBits = HBufferImage.HighBits;
+
+ //
+ // three kinds of buffer supported
+ // file buffer
+ // disk buffer
+ // memory buffer
+ //
+ switch (HBufferImage.BufferType) {
+ case FileTypeFileBuffer:
+ HFileImageBackup ();
+ break;
+
+ case FileTypeDiskBuffer:
+ HDiskImageBackup ();
+ break;
+
+ case FileTypeMemBuffer:
+ HMemImageBackup ();
+ break;
+
+ default:
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Free all the lines in HBufferImage.
+ Fields affected:
+ Lines
+ CurrentLine
+ NumLines
+ ListHead
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HBufferImageFreeLines (
+ VOID
+ )
+{
+ HFreeLines (HBufferImage.ListHead, HBufferImage.Lines);
+
+ HBufferImage.Lines = NULL;
+ HBufferImage.CurrentLine = NULL;
+ HBufferImage.NumLines = 0;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Cleanup function for HBufferImage
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HBufferImageCleanup (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // free all the lines
+ //
+ Status = HBufferImageFreeLines ();
+
+ SHELL_FREE_NON_NULL (HBufferImage.ListHead);
+ HBufferImage.ListHead = NULL;
+
+ HFileImageCleanup ();
+ HDiskImageCleanup ();
+
+ return Status;
+
+}
+
+/**
+ Print Line on Row
+
+ @param[in] Line The lline to print.
+ @param[in] Row The row on screen ( begin from 1 ).
+ @param[in] FRow The FRow.
+ @param[in] Orig The original color.
+ @param[in] New The color to print with.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HBufferImagePrintLine (
+ IN HEFI_EDITOR_LINE *Line,
+ IN UINTN Row,
+ IN UINTN FRow,
+ IN HEFI_EDITOR_COLOR_UNION Orig,
+ IN HEFI_EDITOR_COLOR_UNION New
+
+ )
+{
+
+ UINTN Index;
+ UINTN Pos;
+ BOOLEAN Selected;
+ BOOLEAN BeNewColor;
+ UINTN RowStart;
+ UINTN RowEnd;
+ UINTN ColStart;
+ UINTN ColEnd;
+
+ //
+ // variable initialization
+ //
+ ColStart = 0;
+ ColEnd = 0;
+ Selected = FALSE;
+
+ //
+ // print the selected area in opposite color
+ //
+ if (HMainEditor.SelectStart != 0 && HMainEditor.SelectEnd != 0) {
+ RowStart = (HMainEditor.SelectStart - 1) / 0x10 + 1;
+ RowEnd = (HMainEditor.SelectEnd - 1) / 0x10 + 1;
+
+ ColStart = (HMainEditor.SelectStart - 1) % 0x10 + 1;
+ ColEnd = (HMainEditor.SelectEnd - 1) % 0x10 + 1;
+
+ if (FRow >= RowStart && FRow <= RowEnd) {
+ Selected = TRUE;
+ }
+
+ if (FRow > RowStart) {
+ ColStart = 1;
+ }
+
+ if (FRow < RowEnd) {
+ ColEnd = 0x10;
+ }
+
+ }
+
+ if (!HEditorMouseAction) {
+ ShellPrintEx (
+ 0,
+ (INT32)Row - 1,
+ L"%8X ",
+ ((INT32)Row - 2 + HBufferImage.LowVisibleRow - 1) * 0x10
+ );
+
+ }
+
+ for (Index = 0; Index < 0x08 && Index < Line->Size; Index++) {
+
+ BeNewColor = FALSE;
+
+ if (Selected) {
+ if (Index + 1 >= ColStart && Index + 1 <= ColEnd) {
+ BeNewColor = TRUE;
+ }
+ }
+
+ if (BeNewColor) {
+ gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F);
+ } else {
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F);
+ }
+
+ Pos = 10 + (Index * 3);
+ if (Line->Buffer[Index] < 0x10) {
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"0");
+ Pos++;
+ }
+
+ if (Index < 0x07) {
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]);
+ } else {
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]);
+ }
+
+ }
+
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F);
+ while (Index < 0x08) {
+ Pos = 10 + (Index * 3);
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
+ Index++;
+ }
+
+ while (Index < 0x10 && Index < Line->Size) {
+
+ BeNewColor = FALSE;
+
+ if (Selected) {
+ if (Index + 1 >= ColStart && Index + 1 <= ColEnd) {
+ BeNewColor = TRUE;
+ }
+ }
+
+ if (BeNewColor) {
+ gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F);
+ } else {
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F);
+ }
+
+ Pos = 10 + (Index * 3) + 1;
+ if (Line->Buffer[Index] < 0x10) {
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"0");
+ Pos++;
+ }
+
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%x ", Line->Buffer[Index]);
+ Index++;
+ }
+
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F);
+ while (Index < 0x10) {
+ Pos = 10 + (Index * 3) + 1;
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
+ Index++;
+ }
+ //
+ // restore the original color
+ //
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data & 0x7F);
+
+ //
+ // PRINT the buffer content
+ //
+ if (!HEditorMouseAction) {
+ for (Index = 0; Index < 0x10 && Index < Line->Size; Index++) {
+ Pos = ASCII_POSITION + Index;
+
+ //
+ // learned from shelle.h -- IsValidChar
+ //
+ if (Line->Buffer[Index] >= L' ') {
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%c", (CHAR16) Line->Buffer[Index]);
+ } else {
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L"%c", '.');
+ }
+ }
+
+ while (Index < 0x10) {
+ Pos = ASCII_POSITION + Index;
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
+ Index++;
+ }
+ }
+ //
+ // restore the abundant blank in hex edit area to original color
+ //
+ if (Selected) {
+ if (ColEnd <= 7) {
+ Pos = 10 + (ColEnd - 1) * 3 + 2;
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
+ } else if (ColEnd == 8) {
+ Pos = 10 + (ColEnd - 1) * 3 + 2;
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
+ } else {
+ Pos = 10 + (ColEnd - 1) * 3 + 3;
+ ShellPrintEx ((INT32)Pos - 1, (INT32)Row - 1, L" ");
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Function to decide if a column number is stored in the high bits.
+
+ @param[in] Column The column to examine.
+ @param[out] FCol The actual column number.
+
+ @retval TRUE The actual column was in high bits and is now in FCol.
+ @retval FALSE There was not a column number in the high bits.
+**/
+BOOLEAN
+HBufferImageIsAtHighBits (
+ IN UINTN Column,
+ OUT UINTN *FCol
+ )
+{
+ Column -= 10;
+
+ //
+ // NOW AFTER THE SUB, Column start from 0
+ // 23 AND 24 ARE BOTH BLANK
+ //
+ if (Column == 24) {
+ *FCol = 0;
+ return FALSE;
+ }
+
+ if (Column > 24) {
+ Column--;
+ }
+
+ *FCol = (Column / 3) + 1;
+
+ if (Column % 3 == 0) {
+ return TRUE;
+ }
+
+ if ((Column % 3 == 2)) {
+ *FCol = 0;
+ }
+
+ return FALSE;
+}
+
+/**
+ Decide if a point is in the already selected area.
+
+ @param[in] MouseRow The row of the point to test.
+ @param[in] MouseCol The col of the point to test.
+
+ @retval TRUE The point is in the selected area.
+ @retval FALSE The point is not in the selected area.
+**/
+BOOLEAN
+HBufferImageIsInSelectedArea (
+ IN UINTN MouseRow,
+ IN UINTN MouseCol
+ )
+{
+ UINTN FRow;
+ UINTN RowStart;
+ UINTN RowEnd;
+ UINTN ColStart;
+ UINTN ColEnd;
+ UINTN MouseColStart;
+ UINTN MouseColEnd;
+
+ //
+ // judge mouse position whether is in selected area
+ //
+ //
+ // not select
+ //
+ if (HMainEditor.SelectStart == 0 || HMainEditor.SelectEnd == 0) {
+ return FALSE;
+ }
+ //
+ // calculate the select area
+ //
+ RowStart = (HMainEditor.SelectStart - 1) / 0x10 + 1;
+ RowEnd = (HMainEditor.SelectEnd - 1) / 0x10 + 1;
+
+ ColStart = (HMainEditor.SelectStart - 1) % 0x10 + 1;
+ ColEnd = (HMainEditor.SelectEnd - 1) % 0x10 + 1;
+
+ FRow = HBufferImage.LowVisibleRow + MouseRow - 2;
+ if (FRow < RowStart || FRow > RowEnd) {
+ return FALSE;
+ }
+
+ if (FRow > RowStart) {
+ ColStart = 1;
+ }
+
+ if (FRow < RowEnd) {
+ ColEnd = 0x10;
+ }
+
+ MouseColStart = 10 + (ColStart - 1) * 3;
+ if (ColStart > 8) {
+ MouseColStart++;
+ }
+
+ MouseColEnd = 10 + (ColEnd - 1) * 3 + 1;
+ if (ColEnd > 8) {
+ MouseColEnd++;
+ }
+
+ if (MouseCol < MouseColStart || MouseCol > MouseColEnd) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ Set mouse position according to HBufferImage.MousePosition.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HBufferImageRestoreMousePosition (
+ VOID
+ )
+{
+ HEFI_EDITOR_COLOR_UNION Orig;
+ HEFI_EDITOR_COLOR_UNION New;
+ UINTN FRow;
+ UINTN FColumn;
+ BOOLEAN HasCharacter;
+ HEFI_EDITOR_LINE *CurrentLine;
+ HEFI_EDITOR_LINE *Line;
+ UINT8 Value;
+ BOOLEAN HighBits;
+
+ Line = NULL;
+ if (HMainEditor.MouseSupported) {
+
+ if (HBufferImageMouseNeedRefresh) {
+
+ HBufferImageMouseNeedRefresh = FALSE;
+
+ //
+ // if mouse position not moved and only mouse action
+ // so do not need to refresh mouse position
+ //
+ if ((
+ HBufferImage.MousePosition.Row == HBufferImageBackupVar.MousePosition.Row &&
+ HBufferImage.MousePosition.Column == HBufferImageBackupVar.MousePosition.Column
+ ) &&
+ HEditorMouseAction
+ ) {
+ return EFI_SUCCESS;
+ }
+ //
+ // backup the old screen attributes
+ //
+ Orig = HMainEditor.ColorAttributes;
+ New.Data = 0;
+ New.Colors.Foreground = Orig.Colors.Background & 0xF;
+ New.Colors.Background = Orig.Colors.Foreground & 0x7;
+
+ //
+ // if in selected area,
+ // so do not need to refresh mouse
+ //
+ if (!HBufferImageIsInSelectedArea (
+ HBufferImageBackupVar.MousePosition.Row,
+ HBufferImageBackupVar.MousePosition.Column
+ )) {
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
+ } else {
+ gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F);
+ }
+ //
+ // clear the old mouse position
+ //
+ FRow = HBufferImage.LowVisibleRow + HBufferImageBackupVar.MousePosition.Row - 2;
+
+ HighBits = HBufferImageIsAtHighBits (
+ HBufferImageBackupVar.MousePosition.Column,
+ &FColumn
+ );
+
+ HasCharacter = TRUE;
+ if (FRow > HBufferImage.NumLines || FColumn == 0) {
+ HasCharacter = FALSE;
+ } else {
+ CurrentLine = HBufferImage.CurrentLine;
+ Line = HMoveLine (FRow - HBufferImage.BufferPosition.Row);
+
+ if (Line == NULL || FColumn > Line->Size) {
+ HasCharacter = FALSE;
+ }
+
+ HBufferImage.CurrentLine = CurrentLine;
+ }
+
+ ShellPrintEx (
+ (INT32)HBufferImageBackupVar.MousePosition.Column - 1,
+ (INT32)HBufferImageBackupVar.MousePosition.Row - 1,
+ L" "
+ );
+
+ if (HasCharacter) {
+ if (HighBits) {
+ Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf0);
+ Value = (UINT8) (Value >> 4);
+ } else {
+ Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf);
+ }
+
+ ShellPrintEx (
+ (INT32)HBufferImageBackupVar.MousePosition.Column - 1,
+ (INT32)HBufferImageBackupVar.MousePosition.Row - 1,
+ L"%x",
+ Value
+ );
+ }
+
+ if (!HBufferImageIsInSelectedArea (
+ HBufferImage.MousePosition.Row,
+ HBufferImage.MousePosition.Column
+ )) {
+ gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F);
+ } else {
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
+ }
+ //
+ // clear the old mouse position
+ //
+ FRow = HBufferImage.LowVisibleRow + HBufferImage.MousePosition.Row - 2;
+
+ HighBits = HBufferImageIsAtHighBits (
+ HBufferImage.MousePosition.Column,
+ &FColumn
+ );
+
+ HasCharacter = TRUE;
+ if (FRow > HBufferImage.NumLines || FColumn == 0) {
+ HasCharacter = FALSE;
+ } else {
+ CurrentLine = HBufferImage.CurrentLine;
+ Line = HMoveLine (FRow - HBufferImage.BufferPosition.Row);
+
+ if (Line == NULL || FColumn > Line->Size) {
+ HasCharacter = FALSE;
+ }
+
+ HBufferImage.CurrentLine = CurrentLine;
+ }
+
+ ShellPrintEx (
+ (INT32)HBufferImage.MousePosition.Column - 1,
+ (INT32)HBufferImage.MousePosition.Row - 1,
+ L" "
+ );
+
+ if (HasCharacter) {
+ if (HighBits) {
+ Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf0);
+ Value = (UINT8) (Value >> 4);
+ } else {
+ Value = (UINT8) (Line->Buffer[FColumn - 1] & 0xf);
+ }
+
+ ShellPrintEx (
+ (INT32)HBufferImage.MousePosition.Column - 1,
+ (INT32)HBufferImage.MousePosition.Row - 1,
+ L"%x",
+ Value
+ );
+ }
+ //
+ // end of HasCharacter
+ //
+ gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
+ }
+ //
+ // end of MouseNeedRefresh
+ //
+ }
+ //
+ // end of MouseSupported
+ //
+ return EFI_SUCCESS;
+}
+
+/**
+ Set cursor position according to HBufferImage.DisplayPosition.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HBufferImageRestorePosition (
+ VOID
+ )
+{
+ //
+ // set cursor position
+ //
+ gST->ConOut->SetCursorPosition (
+ gST->ConOut,
+ HBufferImage.DisplayPosition.Column - 1,
+ HBufferImage.DisplayPosition.Row - 1
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Refresh function for HBufferImage.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A Load error occured.
+
+**/
+EFI_STATUS
+HBufferImageRefresh (
+ VOID
+ )
+{
+ LIST_ENTRY *Link;
+ HEFI_EDITOR_LINE *Line;
+ UINTN Row;
+ HEFI_EDITOR_COLOR_UNION Orig;
+ HEFI_EDITOR_COLOR_UNION New;
+
+ UINTN StartRow;
+ UINTN EndRow;
+ UINTN FStartRow;
+ UINTN Tmp;
+
+ Orig = HMainEditor.ColorAttributes;
+ New.Data = 0;
+ New.Colors.Foreground = Orig.Colors.Background;
+ New.Colors.Background = Orig.Colors.Foreground;
+
+ //
+ // if it's the first time after editor launch, so should refresh
+ //
+ if (HEditorFirst == FALSE) {
+ //
+ // no definite required refresh
+ // and file position displayed on screen has not been changed
+ //
+ if (!HBufferImageNeedRefresh &&
+ !HBufferImageOnlyLineNeedRefresh &&
+ HBufferImageBackupVar.LowVisibleRow == HBufferImage.LowVisibleRow
+ ) {
+ HBufferImageRestoreMousePosition ();
+ HBufferImageRestorePosition ();
+ return EFI_SUCCESS;
+ }
+ }
+
+ gST->ConOut->EnableCursor (gST->ConOut, FALSE);
+
+ //
+ // only need to refresh current line
+ //
+ if (HBufferImageOnlyLineNeedRefresh && HBufferImageBackupVar.LowVisibleRow == HBufferImage.LowVisibleRow) {
+
+ HBufferImagePrintLine (
+ HBufferImage.CurrentLine,
+ HBufferImage.DisplayPosition.Row,
+ HBufferImage.BufferPosition.Row,
+ Orig,
+ New
+ );
+ } else {
+ //
+ // the whole edit area need refresh
+ //
+ if (HEditorMouseAction && HMainEditor.SelectStart != 0 && HMainEditor.SelectEnd != 0) {
+ if (HMainEditor.SelectStart != HMainEditorBackupVar.SelectStart) {
+ if (HMainEditor.SelectStart >= HMainEditorBackupVar.SelectStart && HMainEditorBackupVar.SelectStart != 0) {
+ StartRow = (HMainEditorBackupVar.SelectStart - 1) / 0x10 + 1;
+ } else {
+ StartRow = (HMainEditor.SelectStart - 1) / 0x10 + 1;
+ }
+ } else {
+ StartRow = (HMainEditor.SelectStart - 1) / 0x10 + 1;
+ }
+
+ if (HMainEditor.SelectEnd <= HMainEditorBackupVar.SelectEnd) {
+ EndRow = (HMainEditorBackupVar.SelectEnd - 1) / 0x10 + 1;
+ } else {
+ EndRow = (HMainEditor.SelectEnd - 1) / 0x10 + 1;
+ }
+ //
+ // swap
+ //
+ if (StartRow > EndRow) {
+ Tmp = StartRow;
+ StartRow = EndRow;
+ EndRow = Tmp;
+ }
+
+ FStartRow = StartRow;
+
+ StartRow = 2 + StartRow - HBufferImage.LowVisibleRow;
+ EndRow = 2 + EndRow - HBufferImage.LowVisibleRow;
+
+ } else {
+ //
+ // not mouse selection actions
+ //
+ FStartRow = HBufferImage.LowVisibleRow;
+ StartRow = 2;
+ EndRow = (HMainEditor.ScreenSize.Row - 1);
+ }
+ //
+ // no line
+ //
+ if (HBufferImage.Lines == NULL) {
+ HBufferImageRestoreMousePosition ();
+ HBufferImageRestorePosition ();
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+ return EFI_SUCCESS;
+ }
+ //
+ // get the first line that will be displayed
+ //
+ Line = HMoveLine (FStartRow - HBufferImage.BufferPosition.Row);
+ if (Line == NULL) {
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+ return EFI_LOAD_ERROR;
+ }
+
+ Link = &(Line->Link);
+ Row = StartRow;
+ do {
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+
+ //
+ // print line at row
+ //
+ HBufferImagePrintLine (
+ Line,
+ Row,
+ HBufferImage.LowVisibleRow + Row - 2,
+ Orig,
+ New
+ );
+
+ Link = Link->ForwardLink;
+ Row++;
+ } while (Link != HBufferImage.ListHead && Row <= EndRow);
+
+ while (Row <= EndRow) {
+ EditorClearLine (Row, HMainEditor.ScreenSize.Column, HMainEditor.ScreenSize.Row);
+ Row++;
+ }
+ //
+ // while not file end and not screen full
+ //
+ }
+
+ HBufferImageRestoreMousePosition ();
+ HBufferImageRestorePosition ();
+
+ HBufferImageNeedRefresh = FALSE;
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read an image into a buffer friom a source.
+
+ @param[in] FileName Pointer to the file name. OPTIONAL and ignored if not FileTypeFileBuffer.
+ @param[in] DiskName Pointer to the disk name. OPTIONAL and ignored if not FileTypeDiskBuffer.
+ @param[in] DiskOffset Offset into the disk. OPTIONAL and ignored if not FileTypeDiskBuffer.
+ @param[in] DiskSize Size of the disk buffer. OPTIONAL and ignored if not FileTypeDiskBuffer.
+ @param[in] MemOffset Offset into the Memory. OPTIONAL and ignored if not FileTypeMemBuffer.
+ @param[in] MemSize Size of the Memory buffer. OPTIONAL and ignored if not FileTypeMemBuffer.
+ @param[in] BufferType The type of buffer to save. IGNORED.
+ @param[in] Recover TRUE for recovermode, FALSE otherwise.
+
+ @return EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+HBufferImageRead (
+ IN CONST CHAR16 *FileName,
+ IN CONST CHAR16 *DiskName,
+ IN UINTN DiskOffset,
+ IN UINTN DiskSize,
+ IN UINTN MemOffset,
+ IN UINTN MemSize,
+ IN EDIT_FILE_TYPE BufferType,
+ IN BOOLEAN Recover
+ )
+{
+ EFI_STATUS Status;
+ EDIT_FILE_TYPE BufferTypeBackup;
+
+ //
+ // variable initialization
+ //
+ Status = EFI_SUCCESS;
+ HBufferImage.BufferType = BufferType;
+
+ //
+ // three types of buffer supported
+ // file buffer
+ // disk buffer
+ // memory buffer
+ //
+ BufferTypeBackup = HBufferImage.BufferType;
+
+ switch (BufferType) {
+ case FileTypeFileBuffer:
+ Status = HFileImageRead (FileName, Recover);
+ break;
+
+ case FileTypeDiskBuffer:
+ Status = HDiskImageRead (DiskName, DiskOffset, DiskSize, Recover);
+ break;
+
+ case FileTypeMemBuffer:
+ Status = HMemImageRead (MemOffset, MemSize, Recover);
+ break;
+
+ default:
+ Status = EFI_NOT_FOUND;
+ break;
+ }
+
+ if (EFI_ERROR (Status)) {
+ HBufferImage.BufferType = BufferTypeBackup;
+ }
+
+ return Status;
+}
+
+/**
+ Save the current image.
+
+ @param[in] FileName Pointer to the file name. OPTIONAL and ignored if not FileTypeFileBuffer.
+ @param[in] DiskName Pointer to the disk name. OPTIONAL and ignored if not FileTypeDiskBuffer.
+ @param[in] DiskOffset Offset into the disk. OPTIONAL and ignored if not FileTypeDiskBuffer.
+ @param[in] DiskSize Size of the disk buffer. OPTIONAL and ignored if not FileTypeDiskBuffer.
+ @param[in] MemOffset Offset into the Memory. OPTIONAL and ignored if not FileTypeMemBuffer.
+ @param[in] MemSize Size of the Memory buffer. OPTIONAL and ignored if not FileTypeMemBuffer.
+ @param[in] BufferType The type of buffer to save. IGNORED.
+
+ @return EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HBufferImageSave (
+ IN CHAR16 *FileName,
+ IN CHAR16 *DiskName,
+ IN UINTN DiskOffset,
+ IN UINTN DiskSize,
+ IN UINTN MemOffset,
+ IN UINTN MemSize,
+ IN EDIT_FILE_TYPE BufferType
+ )
+{
+ EFI_STATUS Status;
+ EDIT_FILE_TYPE BufferTypeBackup;
+
+ //
+ // variable initialization
+ //
+ Status = EFI_SUCCESS;
+ BufferTypeBackup = HBufferImage.BufferType;
+
+ switch (HBufferImage.BufferType) {
+ //
+ // file buffer
+ //
+ case FileTypeFileBuffer:
+ Status = HFileImageSave (FileName);
+ break;
+
+ //
+ // disk buffer
+ //
+ case FileTypeDiskBuffer:
+ Status = HDiskImageSave (DiskName, DiskOffset, DiskSize);
+ break;
+
+ //
+ // memory buffer
+ //
+ case FileTypeMemBuffer:
+ Status = HMemImageSave (MemOffset, MemSize);
+ break;
+
+ default:
+ Status = EFI_NOT_FOUND;
+ break;
+ }
+
+ if (EFI_ERROR (Status)) {
+ HBufferImage.BufferType = BufferTypeBackup;
+ }
+
+ return Status;
+}
+
+/**
+ Create a new line and append it to the line list.
+ Fields affected:
+ NumLines
+ Lines
+
+ @retval NULL create line failed.
+ @return the line created.
+
+**/
+HEFI_EDITOR_LINE *
+HBufferImageCreateLine (
+ VOID
+ )
+{
+ HEFI_EDITOR_LINE *Line;
+
+ //
+ // allocate for line structure
+ //
+ Line = AllocateZeroPool (sizeof (HEFI_EDITOR_LINE));
+ if (Line == NULL) {
+ return NULL;
+ }
+
+ Line->Signature = EFI_EDITOR_LINE_LIST;
+ Line->Size = 0;
+
+ HBufferImage.NumLines++;
+
+ //
+ // insert to line list
+ //
+ InsertTailList (HBufferImage.ListHead, &Line->Link);
+
+ if (HBufferImage.Lines == NULL) {
+ HBufferImage.Lines = CR (
+ HBufferImage.ListHead->ForwardLink,
+ HEFI_EDITOR_LINE,
+ Link,
+ EFI_EDITOR_LINE_LIST
+ );
+ }
+
+ return Line;
+}
+
+/**
+ Free the current image.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HBufferImageFree (
+ VOID
+ )
+{
+ //
+ // free all lines
+ //
+ HBufferImageFreeLines ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ change char to int value based on Hex.
+
+ @param[in] Char The input char.
+
+ @return The character's index value.
+ @retval -1 The operation failed.
+**/
+INTN
+EFIAPI
+HBufferImageCharToHex (
+ IN CHAR16 Char
+ )
+{
+ //
+ // change the character to hex
+ //
+ if (Char >= L'0' && Char <= L'9') {
+ return (INTN) (Char - L'0');
+ }
+
+ if (Char >= L'a' && Char <= L'f') {
+ return (INTN) (Char - L'a' + 10);
+ }
+
+ if (Char >= L'A' && Char <= L'F') {
+ return (INTN) (Char - L'A' + 10);
+ }
+
+ return -1;
+}
+
+/**
+ Add character.
+
+ @param[in] Char -- input char.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+HBufferImageAddChar (
+ IN CHAR16 Char
+ )
+{
+ HEFI_EDITOR_LINE *Line;
+ HEFI_EDITOR_LINE *NewLine;
+ INTN Value;
+ UINT8 Old;
+ UINTN FRow;
+ UINTN FCol;
+ BOOLEAN High;
+
+ Value = HBufferImageCharToHex (Char);
+
+ //
+ // invalid input
+ //
+ if (Value == -1) {
+ return EFI_SUCCESS;
+ }
+
+ Line = HBufferImage.CurrentLine;
+ FRow = HBufferImage.BufferPosition.Row;
+ FCol = HBufferImage.BufferPosition.Column;
+ High = HBufferImage.HighBits;
+
+ //
+ // only needs to refresh current line
+ //
+ HBufferImageOnlyLineNeedRefresh = TRUE;
+
+ //
+ // not a full line and beyond the last character
+ //
+ if (FCol > Line->Size) {
+ //
+ // cursor always at high 4 bits
+ // and always put input to the low 4 bits
+ //
+ Line->Buffer[Line->Size] = (UINT8) Value;
+ Line->Size++;
+ High = FALSE;
+ } else {
+
+ Old = Line->Buffer[FCol - 1];
+
+ //
+ // always put the input to the low 4 bits
+ //
+ Old = (UINT8) (Old & 0x0f);
+ Old = (UINT8) (Old << 4);
+ Old = (UINT8) (Value + Old);
+ Line->Buffer[FCol - 1] = Old;
+
+ //
+ // at the low 4 bits of the last character of a full line
+ // so if no next line, need to create a new line
+ //
+ if (!High && FCol == 0x10) {
+
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+ HBufferImageNeedRefresh = TRUE;
+
+ if (Line->Link.ForwardLink == HBufferImage.ListHead) {
+ //
+ // last line
+ //
+ // create a new line
+ //
+ NewLine = HBufferImageCreateLine ();
+ if (NewLine == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // end of NULL
+ //
+ }
+ //
+ // end of == ListHead
+ //
+ }
+ //
+ // end of == 0x10
+ //
+ // if already at end of this line, scroll it to the start of next line
+ //
+ if (FCol == 0x10 && !High) {
+ //
+ // definitely has next line
+ //
+ FRow++;
+ FCol = 1;
+ High = TRUE;
+ } else {
+ //
+ // if not at end of this line, just move to next column
+ //
+ if (!High) {
+ FCol++;
+ }
+
+ if (High) {
+ High = FALSE;
+ } else {
+ High = TRUE;
+ }
+
+ }
+ //
+ // end of ==FALSE
+ //
+ }
+ //
+ // move cursor to right
+ //
+ HBufferImageMovePosition (FRow, FCol, High);
+
+ if (!HBufferImage.Modified) {
+ HBufferImage.Modified = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Delete the previous character.
+
+ @retval EFI_SUCCESS The operationw as successful.
+**/
+EFI_STATUS
+EFIAPI
+HBufferImageDoBackspace (
+ VOID
+ )
+{
+ HEFI_EDITOR_LINE *Line;
+
+ UINTN FileColumn;
+ UINTN FPos;
+ BOOLEAN LastLine;
+
+ //
+ // variable initialization
+ //
+ LastLine = FALSE;
+
+ //
+ // already the first character
+ //
+ if (HBufferImage.BufferPosition.Row == 1 && HBufferImage.BufferPosition.Column == 1) {
+ return EFI_SUCCESS;
+ }
+
+ FPos = (HBufferImage.BufferPosition.Row - 1) * 0x10 + HBufferImage.BufferPosition.Column - 1;
+
+ FileColumn = HBufferImage.BufferPosition.Column;
+
+ Line = HBufferImage.CurrentLine;
+ LastLine = FALSE;
+ if (Line->Link.ForwardLink == HBufferImage.ListHead && FileColumn > 1) {
+ LastLine = TRUE;
+ }
+
+ HBufferImageDeleteCharacterFromBuffer (FPos - 1, 1, NULL);
+
+ //
+ // if is the last line
+ // then only this line need to be refreshed
+ //
+ if (LastLine) {
+ HBufferImageNeedRefresh = FALSE;
+ HBufferImageOnlyLineNeedRefresh = TRUE;
+ } else {
+ HBufferImageNeedRefresh = TRUE;
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+ }
+
+ if (!HBufferImage.Modified) {
+ HBufferImage.Modified = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ ASCII key + Backspace + return.
+
+ @param[in] Char The input char.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+HBufferImageDoCharInput (
+ IN CHAR16 Char
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ switch (Char) {
+ case 0:
+ break;
+
+ case 0x08:
+ Status = HBufferImageDoBackspace ();
+ break;
+
+ case 0x09:
+ case 0x0a:
+ case 0x0d:
+ //
+ // Tabs, Returns are thought as nothing
+ //
+ break;
+
+ default:
+ //
+ // DEAL WITH ASCII CHAR, filter out thing like ctrl+f
+ //
+ if (Char > 127 || Char < 32) {
+ Status = StatusBarSetStatusString (L"Unknown Command");
+ } else {
+ Status = HBufferImageAddChar (Char);
+ }
+
+ break;
+ }
+
+ return Status;
+}
+
+/**
+ Check user specified FileRow is above current screen.
+
+ @param[in] FileRow Row of file position ( start from 1 ).
+
+ @retval TRUE It is above the current screen.
+ @retval FALSE It is not above the current screen.
+
+**/
+BOOLEAN
+HAboveCurrentScreen (
+ IN UINTN FileRow
+ )
+{
+ if (FileRow < HBufferImage.LowVisibleRow) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ Check user specified FileRow is under current screen.
+
+ @param[in] FileRow Row of file position ( start from 1 ).
+
+ @retval TRUE It is under the current screen.
+ @retval FALSE It is not under the current screen.
+
+**/
+BOOLEAN
+HUnderCurrentScreen (
+ IN UINTN FileRow
+ )
+{
+ if (FileRow > HBufferImage.LowVisibleRow + (HMainEditor.ScreenSize.Row - 2) - 1) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/**
+ According to cursor's file position, adjust screen display.
+
+ @param[in] NewFilePosRow Row of file position ( start from 1 ).
+ @param[in] NewFilePosCol Column of file position ( start from 1 ).
+ @param[in] HighBits Cursor will on high4 bits or low4 bits.
+**/
+VOID
+HBufferImageMovePosition (
+ IN UINTN NewFilePosRow,
+ IN UINTN NewFilePosCol,
+ IN BOOLEAN HighBits
+ )
+{
+ INTN RowGap;
+ UINTN Abs;
+ BOOLEAN Above;
+ BOOLEAN Under;
+ UINTN NewDisplayCol;
+
+ //
+ // CALCULATE gap between current file position and new file position
+ //
+ RowGap = NewFilePosRow - HBufferImage.BufferPosition.Row;
+
+ Under = HUnderCurrentScreen (NewFilePosRow);
+ Above = HAboveCurrentScreen (NewFilePosRow);
+
+ HBufferImage.HighBits = HighBits;
+
+ //
+ // if is below current screen
+ //
+ if (Under) {
+ //
+ // display row will be unchanged
+ //
+ HBufferImage.BufferPosition.Row = NewFilePosRow;
+ } else {
+ if (Above) {
+ //
+ // has enough above line, so display row unchanged
+ // not has enough above lines, so the first line is
+ // at the first display line
+ //
+ if (NewFilePosRow < (HBufferImage.DisplayPosition.Row - 2 + 1)) {
+ HBufferImage.DisplayPosition.Row = NewFilePosRow + 2 - 1;
+ }
+
+ HBufferImage.BufferPosition.Row = NewFilePosRow;
+ } else {
+ //
+ // in current screen
+ //
+ HBufferImage.BufferPosition.Row = NewFilePosRow;
+ if (RowGap <= 0) {
+ Abs = (UINTN)ABS(RowGap);
+ HBufferImage.DisplayPosition.Row -= Abs;
+ } else {
+ HBufferImage.DisplayPosition.Row += RowGap;
+ }
+
+ }
+ }
+
+ HBufferImage.LowVisibleRow = HBufferImage.BufferPosition.Row - (HBufferImage.DisplayPosition.Row - 2);
+
+ //
+ // always in current screen
+ //
+ HBufferImage.BufferPosition.Column = NewFilePosCol;
+
+ NewDisplayCol = 10 + (NewFilePosCol - 1) * 3;
+ if (NewFilePosCol > 0x8) {
+ NewDisplayCol++;
+ }
+
+ if (!HighBits) {
+ NewDisplayCol++;
+ }
+
+ HBufferImage.DisplayPosition.Column = NewDisplayCol;
+
+ //
+ // let CurrentLine point to correct line;
+ //
+ HBufferImage.CurrentLine = HMoveCurrentLine (RowGap);
+
+}
+
+/**
+ Scroll cursor to right.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HBufferImageScrollRight (
+ VOID
+ )
+{
+ HEFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+
+ //
+ // scroll right will always move to the high4 bits of the next character
+ //
+ HBufferImageNeedRefresh = FALSE;
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+
+ Line = HBufferImage.CurrentLine;
+
+ FRow = HBufferImage.BufferPosition.Row;
+ FCol = HBufferImage.BufferPosition.Column;
+
+ //
+ // this line is not full and no next line
+ //
+ if (FCol > Line->Size) {
+ return EFI_SUCCESS;
+ }
+ //
+ // if already at end of this line, scroll it to the start of next line
+ //
+ if (FCol == 0x10) {
+ //
+ // has next line
+ //
+ if (Line->Link.ForwardLink != HBufferImage.ListHead) {
+ FRow++;
+ FCol = 1;
+
+ } else {
+ return EFI_SUCCESS;
+ }
+ } else {
+ //
+ // if not at end of this line, just move to next column
+ //
+ FCol++;
+
+ }
+
+ HBufferImageMovePosition (FRow, FCol, TRUE);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Scroll cursor to left.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HBufferImageScrollLeft (
+ VOID
+ )
+{
+
+ HEFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+
+ HBufferImageNeedRefresh = FALSE;
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+
+ Line = HBufferImage.CurrentLine;
+
+ FRow = HBufferImage.BufferPosition.Row;
+ FCol = HBufferImage.BufferPosition.Column;
+
+ //
+ // if already at start of this line, so move to the end of previous line
+ //
+ if (FCol <= 1) {
+ //
+ // has previous line
+ //
+ if (Line->Link.BackLink != HBufferImage.ListHead) {
+ FRow--;
+ Line = CR (Line->Link.BackLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+ FCol = Line->Size;
+ } else {
+ return EFI_SUCCESS;
+ }
+ } else {
+ //
+ // if not at start of this line, just move to previous column
+ //
+ FCol--;
+ }
+
+ HBufferImageMovePosition (FRow, FCol, TRUE);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Scroll cursor to the next line
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HBufferImageScrollDown (
+ VOID
+ )
+{
+ HEFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+ BOOLEAN HighBits;
+
+ Line = HBufferImage.CurrentLine;
+
+ FRow = HBufferImage.BufferPosition.Row;
+ FCol = HBufferImage.BufferPosition.Column;
+ HighBits = HBufferImage.HighBits;
+
+ //
+ // has next line
+ //
+ if (Line->Link.ForwardLink != HBufferImage.ListHead) {
+ FRow++;
+ Line = CR (Line->Link.ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+
+ //
+ // if the next line is not that long, so move to end of next line
+ //
+ if (FCol > Line->Size) {
+ FCol = Line->Size + 1;
+ HighBits = TRUE;
+ }
+
+ } else {
+ return EFI_SUCCESS;
+ }
+
+ HBufferImageMovePosition (FRow, FCol, HighBits);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Scroll cursor to previous line
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HBufferImageScrollUp (
+ VOID
+ )
+{
+ HEFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+
+ Line = HBufferImage.CurrentLine;
+
+ FRow = HBufferImage.BufferPosition.Row;
+ FCol = HBufferImage.BufferPosition.Column;
+
+ //
+ // has previous line
+ //
+ if (Line->Link.BackLink != HBufferImage.ListHead) {
+ FRow--;
+
+ } else {
+ return EFI_SUCCESS;
+ }
+
+ HBufferImageMovePosition (FRow, FCol, HBufferImage.HighBits);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Scroll cursor to next page
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HBufferImagePageDown (
+ VOID
+ )
+{
+ HEFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+ UINTN Gap;
+ BOOLEAN HighBits;
+
+ Line = HBufferImage.CurrentLine;
+
+ FRow = HBufferImage.BufferPosition.Row;
+ FCol = HBufferImage.BufferPosition.Column;
+ HighBits = HBufferImage.HighBits;
+
+ //
+ // has next page
+ //
+ if (HBufferImage.NumLines >= FRow + (HMainEditor.ScreenSize.Row - 2)) {
+ Gap = (HMainEditor.ScreenSize.Row - 2);
+ } else {
+ //
+ // MOVE CURSOR TO LAST LINE
+ //
+ Gap = HBufferImage.NumLines - FRow;
+ }
+ //
+ // get correct line
+ //
+ Line = HMoveLine (Gap);
+
+ //
+ // if that line, is not that long, so move to the end of that line
+ //
+ if (Line != NULL && FCol > Line->Size) {
+ FCol = Line->Size + 1;
+ HighBits = TRUE;
+ }
+
+ FRow += Gap;
+
+ HBufferImageMovePosition (FRow, FCol, HighBits);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Scroll cursor to previous page
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HBufferImagePageUp (
+ VOID
+ )
+{
+ UINTN FRow;
+ UINTN FCol;
+ UINTN Gap;
+ INTN Retreat;
+
+ FRow = HBufferImage.BufferPosition.Row;
+ FCol = HBufferImage.BufferPosition.Column;
+
+ //
+ // has previous page
+ //
+ if (FRow > (HMainEditor.ScreenSize.Row - 2)) {
+ Gap = (HMainEditor.ScreenSize.Row - 2);
+ } else {
+ //
+ // the first line of file will displayed on the first line of screen
+ //
+ Gap = FRow - 1;
+ }
+
+ Retreat = Gap;
+ Retreat = -Retreat;
+
+ FRow -= Gap;
+
+ HBufferImageMovePosition (FRow, FCol, HBufferImage.HighBits);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Scroll cursor to start of line
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HBufferImageHome (
+ VOID
+ )
+{
+ UINTN FRow;
+ UINTN FCol;
+ BOOLEAN HighBits;
+
+ //
+ // curosr will at the high bit
+ //
+ FRow = HBufferImage.BufferPosition.Row;
+ FCol = 1;
+ HighBits = TRUE;
+
+ //
+ // move cursor position
+ //
+ HBufferImageMovePosition (FRow, FCol, HighBits);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Scroll cursor to end of line.
+
+ @retval EFI_SUCCESS Teh operation was successful.
+**/
+EFI_STATUS
+HBufferImageEnd (
+ VOID
+ )
+{
+ HEFI_EDITOR_LINE *Line;
+ UINTN FRow;
+ UINTN FCol;
+ BOOLEAN HighBits;
+
+ //
+ // need refresh mouse
+ //
+ HBufferImageMouseNeedRefresh = TRUE;
+
+ Line = HBufferImage.CurrentLine;
+
+ FRow = HBufferImage.BufferPosition.Row;
+
+ if (Line->Size == 0x10) {
+ FCol = Line->Size;
+ HighBits = FALSE;
+ } else {
+ FCol = Line->Size + 1;
+ HighBits = TRUE;
+ }
+ //
+ // move cursor position
+ //
+ HBufferImageMovePosition (FRow, FCol, HighBits);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get the size of the open buffer.
+
+ @retval The size in bytes.
+**/
+UINTN
+HBufferImageGetTotalSize (
+ VOID
+ )
+{
+ UINTN Size;
+
+ HEFI_EDITOR_LINE *Line;
+
+ //
+ // calculate the total size of whole line list's buffer
+ //
+ if (HBufferImage.Lines == NULL) {
+ return 0;
+ }
+
+ Line = CR (
+ HBufferImage.ListHead->BackLink,
+ HEFI_EDITOR_LINE,
+ Link,
+ EFI_EDITOR_LINE_LIST
+ );
+ //
+ // one line at most 0x10
+ //
+ Size = 0x10 * (HBufferImage.NumLines - 1) + Line->Size;
+
+ return Size;
+}
+
+/**
+ Delete character from buffer.
+
+ @param[in] Pos Position, Pos starting from 0.
+ @param[in] Count The Count of characters to delete.
+ @param[out] DeleteBuffer The DeleteBuffer.
+
+ @retval EFI_SUCCESS Success
+**/
+EFI_STATUS
+HBufferImageDeleteCharacterFromBuffer (
+ IN UINTN Pos,
+ IN UINTN Count,
+ OUT UINT8 *DeleteBuffer
+ )
+{
+ UINTN Index;
+
+ VOID *Buffer;
+ UINT8 *BufferPtr;
+ UINTN Size;
+
+ HEFI_EDITOR_LINE *Line;
+ LIST_ENTRY *Link;
+
+ UINTN OldFCol;
+ UINTN OldFRow;
+ UINTN OldPos;
+
+ UINTN NewPos;
+
+ EFI_STATUS Status;
+
+ Size = HBufferImageGetTotalSize ();
+
+ if (Size < Count) {
+ return EFI_LOAD_ERROR;
+ }
+
+ if (Size == 0) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // relocate all the HBufferImage fields
+ //
+ OldFRow = HBufferImage.BufferPosition.Row;
+ OldFCol = HBufferImage.BufferPosition.Column;
+ OldPos = (OldFRow - 1) * 0x10 + OldFCol - 1;
+
+ if (Pos > 0) {
+ //
+ // has character before it,
+ // so locate according to block's previous character
+ //
+ NewPos = Pos - 1;
+
+ } else {
+ //
+ // has no character before it,
+ // so locate according to block's next character
+ //
+ NewPos = 0;
+ }
+
+ HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);
+
+ Buffer = AllocateZeroPool (Size);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ HBufferImageListToBuffer (Buffer, Size);
+
+ BufferPtr = (UINT8 *) Buffer;
+
+ //
+ // pass deleted buffer out
+ //
+ if (DeleteBuffer != NULL) {
+ for (Index = 0; Index < Count; Index++) {
+ DeleteBuffer[Index] = BufferPtr[Pos + Index];
+ }
+ }
+ //
+ // delete the part from Pos
+ //
+ for (Index = Pos; Index < Size - Count; Index++) {
+ BufferPtr[Index] = BufferPtr[Index + Count];
+ }
+
+ Size -= Count;
+
+ HBufferImageFreeLines ();
+
+ Status = HBufferImageBufferToList (Buffer, Size);
+ FreePool (Buffer);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Link = HMainEditor.BufferImage->ListHead->ForwardLink;
+ for (Index = 0; Index < NewPos / 0x10; Index++) {
+ Link = Link->ForwardLink;
+ }
+
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+ HBufferImage.CurrentLine = Line;
+
+ //
+ // if current cursor position if inside select area
+ // then move it to the block's NEXT character
+ //
+ if (OldPos >= Pos && OldPos < (Pos + Count)) {
+ NewPos = Pos;
+ } else {
+ if (OldPos < Pos) {
+ NewPos = OldPos;
+ } else {
+ NewPos = OldPos - Count;
+ }
+ }
+
+ HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Add character to buffer, add before pos.
+
+ @param[in] Pos Position, Pos starting from 0.
+ @param[in] Count Count of characters to add.
+ @param[in] AddBuffer Add buffer.
+
+ @retval EFI_SUCCESS Success.
+**/
+EFI_STATUS
+HBufferImageAddCharacterToBuffer (
+ IN UINTN Pos,
+ IN UINTN Count,
+ IN UINT8 *AddBuffer
+ )
+{
+ INTN Index;
+
+ VOID *Buffer;
+ UINT8 *BufferPtr;
+ UINTN Size;
+
+ HEFI_EDITOR_LINE *Line;
+
+ LIST_ENTRY *Link;
+
+ UINTN OldFCol;
+ UINTN OldFRow;
+ UINTN OldPos;
+
+ UINTN NewPos;
+
+ Size = HBufferImageGetTotalSize ();
+
+ //
+ // relocate all the HBufferImage fields
+ //
+ OldFRow = HBufferImage.BufferPosition.Row;
+ OldFCol = HBufferImage.BufferPosition.Column;
+ OldPos = (OldFRow - 1) * 0x10 + OldFCol - 1;
+
+ //
+ // move cursor before Pos
+ //
+ if (Pos > 0) {
+ NewPos = Pos - 1;
+ } else {
+ NewPos = 0;
+ }
+
+ HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);
+
+ Buffer = AllocateZeroPool (Size + Count);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ HBufferImageListToBuffer (Buffer, Size);
+
+ BufferPtr = (UINT8 *) Buffer;
+
+ //
+ // get a place to add
+ //
+ for (Index = (INTN) (Size + Count - 1); Index >= (INTN) Pos; Index--) {
+ BufferPtr[Index] = BufferPtr[Index - Count];
+ }
+ //
+ // add the buffer
+ //
+ for (Index = (INTN) 0; Index < (INTN) Count; Index++) {
+ BufferPtr[Index + Pos] = AddBuffer[Index];
+ }
+
+ Size += Count;
+
+ HBufferImageFreeLines ();
+
+ HBufferImageBufferToList (Buffer, Size);
+
+ FreePool (Buffer);
+
+ Link = HMainEditor.BufferImage->ListHead->ForwardLink;
+ for (Index = 0; Index < (INTN) NewPos / 0x10; Index++) {
+ Link = Link->ForwardLink;
+ }
+
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+ HBufferImage.CurrentLine = Line;
+
+ if (OldPos >= Pos) {
+ NewPos = OldPos + Count;
+ } else {
+ NewPos = OldPos;
+ }
+
+ HBufferImageMovePosition (NewPos / 0x10 + 1, NewPos % 0x10 + 1, TRUE);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Delete current character from line.
+
+ @retval EFI_SUCCESS The operationw as successful.
+**/
+EFI_STATUS
+EFIAPI
+HBufferImageDoDelete (
+ VOID
+ )
+{
+
+ HEFI_EDITOR_LINE *Line;
+
+ BOOLEAN LastLine;
+ UINTN FileColumn;
+ UINTN FPos;
+
+ FPos = (HBufferImage.BufferPosition.Row - 1) * 0x10 + HBufferImage.BufferPosition.Column - 1;
+
+ FileColumn = HBufferImage.BufferPosition.Column;
+
+ Line = HBufferImage.CurrentLine;
+
+ //
+ // if beyond the last character
+ //
+ if (FileColumn > Line->Size) {
+ return EFI_SUCCESS;
+ }
+
+ LastLine = FALSE;
+ if (Line->Link.ForwardLink == HBufferImage.ListHead) {
+ LastLine = TRUE;
+ }
+
+ HBufferImageDeleteCharacterFromBuffer (FPos, 1, NULL);
+
+ //
+ // if is the last line
+ // then only this line need to be refreshed
+ //
+ if (LastLine) {
+ HBufferImageNeedRefresh = FALSE;
+ HBufferImageOnlyLineNeedRefresh = TRUE;
+ } else {
+ HBufferImageNeedRefresh = TRUE;
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+ }
+
+ if (!HBufferImage.Modified) {
+ HBufferImage.Modified = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Change the raw buffer to a list of lines for the UI.
+
+ @param[in] Buffer The pointer to the buffer to fill.
+ @param[in] Bytes The size of the buffer in bytes.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+HBufferImageBufferToList (
+ IN VOID *Buffer,
+ IN UINTN Bytes
+ )
+{
+ UINTN TempI;
+ UINTN TempJ;
+ UINTN Left;
+ HEFI_EDITOR_LINE *Line;
+ UINT8 *BufferPtr;
+
+ TempI = 0;
+ Left = 0;
+ BufferPtr = (UINT8 *) Buffer;
+
+ //
+ // parse file content line by line
+ //
+ while (TempI < Bytes) {
+ if (Bytes - TempI >= 0x10) {
+ Left = 0x10;
+ } else {
+ Left = Bytes - TempI;
+ }
+
+ //
+ // allocate a new line
+ //
+ Line = HBufferImageCreateLine ();
+ if (Line == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Line->Size = Left;
+
+ for (TempJ = 0; TempJ < Left; TempJ++) {
+ Line->Buffer[TempJ] = BufferPtr[TempI];
+ TempI++;
+ }
+
+ }
+
+ //
+ // last line is a full line, SO create a new line
+ //
+ if (Left == 0x10 || Bytes == 0) {
+ Line = HBufferImageCreateLine ();
+ if (Line == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Change the list of lines from the UI to a raw buffer.
+
+ @param[in] Buffer The pointer to the buffer to fill.
+ @param[in] Bytes The size of the buffer in bytes.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+HBufferImageListToBuffer (
+ IN VOID *Buffer,
+ IN UINTN Bytes
+ )
+{
+ UINTN Count;
+ UINTN Index;
+ HEFI_EDITOR_LINE *Line;
+ LIST_ENTRY *Link;
+ UINT8 *BufferPtr;
+
+ //
+ // change the line list to a large buffer
+ //
+ if (HBufferImage.Lines == NULL) {
+ return EFI_SUCCESS;
+ }
+
+ Link = &HBufferImage.Lines->Link;
+ Count = 0;
+ BufferPtr = (UINT8 *) Buffer;
+
+ //
+ // deal line by line
+ //
+ while (Link != HBufferImage.ListHead) {
+
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+
+ //@todo shouldn't this be an error???
+ if (Count + Line->Size > Bytes) {
+ return EFI_SUCCESS;
+ }
+
+ for (Index = 0; Index < Line->Size; Index++) {
+ BufferPtr[Index] = Line->Buffer[Index];
+ }
+
+ Count += Line->Size;
+ BufferPtr += Line->Size;
+
+ Link = Link->ForwardLink;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Move the mouse in the image buffer.
+
+ @param[in] TextX The x-coordinate.
+ @param[in] TextY The y-coordinate.
+**/
+VOID
+EFIAPI
+HBufferImageAdjustMousePosition (
+ IN INT32 TextX,
+ IN INT32 TextY
+ )
+{
+ UINTN TempX;
+ UINTN TempY;
+ UINTN AbsX;
+ UINTN AbsY;
+
+ //
+ // TextX and TextY is mouse movement data returned by mouse driver
+ // This function will change it to MousePosition
+ //
+ //
+ // get absolute TempX value
+ //
+ if (TextX >= 0) {
+ AbsX = TextX;
+ } else {
+ AbsX = -TextX;
+ }
+ //
+ // get absolute TempY value
+ //
+ if (TextY >= 0) {
+ AbsY = TextY;
+ } else {
+ AbsY = -TextY;
+ }
+
+ TempX = HBufferImage.MousePosition.Column;
+ TempY = HBufferImage.MousePosition.Row;
+
+ if (TextX >= 0) {
+ TempX += TextX;
+ } else {
+ if (TempX >= AbsX) {
+ TempX -= AbsX;
+ } else {
+ TempX = 0;
+ }
+ }
+
+ if (TextY >= 0) {
+ TempY += TextY;
+ } else {
+ if (TempY >= AbsY) {
+ TempY -= AbsY;
+ } else {
+ TempY = 0;
+ }
+ }
+ //
+ // check whether new mouse column position is beyond screen
+ // if not, adjust it
+ //
+ if (TempX >= 10 && TempX <= (10 + 0x10 * 3 - 1)) {
+ HBufferImage.MousePosition.Column = TempX;
+ } else if (TempX < 10) {
+ HBufferImage.MousePosition.Column = 10;
+ } else if (TempX > (10 + 0x10 * 3 - 1)) {
+ HBufferImage.MousePosition.Column = 10 + 0x10 * 3 - 1;
+ }
+ //
+ // check whether new mouse row position is beyond screen
+ // if not, adjust it
+ //
+ if (TempY >= 2 && TempY <= (HMainEditor.ScreenSize.Row - 1)) {
+ HBufferImage.MousePosition.Row = TempY;
+ } else if (TempY < 2) {
+ HBufferImage.MousePosition.Row = 2;
+ } else if (TempY > (HMainEditor.ScreenSize.Row - 1)) {
+ HBufferImage.MousePosition.Row = (HMainEditor.ScreenSize.Row - 1);
+ }
+
+}
+
+/**
+ Dispatch input to different handler
+
+ @param[in] Key The input key:
+ the keys can be:
+ ASCII KEY
+ Backspace/Delete
+ Direction key: up/down/left/right/pgup/pgdn
+ Home/End
+ INS
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_OUT_OF_RESOURCES A Memory allocation failed.
+**/
+EFI_STATUS
+HBufferImageHandleInput (
+ IN EFI_INPUT_KEY *Key
+ )
+{
+ EFI_STATUS Status;
+
+ Status = EFI_SUCCESS;
+
+ switch (Key->ScanCode) {
+ //
+ // ordinary key
+ //
+ case SCAN_NULL:
+ Status = HBufferImageDoCharInput (Key->UnicodeChar);
+ break;
+
+ //
+ // up arrow
+ //
+ case SCAN_UP:
+ Status = HBufferImageScrollUp ();
+ break;
+
+ //
+ // down arrow
+ //
+ case SCAN_DOWN:
+ Status = HBufferImageScrollDown ();
+ break;
+
+ //
+ // right arrow
+ //
+ case SCAN_RIGHT:
+ Status = HBufferImageScrollRight ();
+ break;
+
+ //
+ // left arrow
+ //
+ case SCAN_LEFT:
+ Status = HBufferImageScrollLeft ();
+ break;
+
+ //
+ // page up
+ //
+ case SCAN_PAGE_UP:
+ Status = HBufferImagePageUp ();
+ break;
+
+ //
+ // page down
+ //
+ case SCAN_PAGE_DOWN:
+ Status = HBufferImagePageDown ();
+ break;
+
+ //
+ // delete
+ //
+ case SCAN_DELETE:
+ Status = HBufferImageDoDelete ();
+ break;
+
+ //
+ // home
+ //
+ case SCAN_HOME:
+ Status = HBufferImageHome ();
+ break;
+
+ //
+ // end
+ //
+ case SCAN_END:
+ Status = HBufferImageEnd ();
+ break;
+
+ default:
+ Status = StatusBarSetStatusString (L"Unknown Command");
+ break;
+ }
+
+ return Status;
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.h
new file mode 100644
index 0000000000..91369b5931
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/BufferImage.h
@@ -0,0 +1,277 @@
+/** @file
+ Defines BufferImage - the view of the file that is visible at any point,
+ as well as the event handlers for editing the file
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LIB_BUFFER_IMAGE_H_
+#define _LIB_BUFFER_IMAGE_H_
+
+#include "HexEditor.h"
+
+/**
+ Initialization function for HBufferImage
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HBufferImageInit (
+ VOID
+ );
+
+/**
+ Cleanup function for HBufferImage
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HBufferImageCleanup (
+ VOID
+ );
+
+/**
+ Refresh function for HBufferImage.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A Load error occured.
+
+**/
+EFI_STATUS
+HBufferImageRefresh (
+ VOID
+ );
+
+/**
+ Dispatch input to different handler
+
+ @param[in] Key The input key:
+ the keys can be:
+ ASCII KEY
+ Backspace/Delete
+ Direction key: up/down/left/right/pgup/pgdn
+ Home/End
+ INS
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_OUT_OF_RESOURCES A Memory allocation failed.
+**/
+EFI_STATUS
+HBufferImageHandleInput (
+ IN EFI_INPUT_KEY *Key
+ );
+
+/**
+ Backup function for HBufferImage. Only a few fields need to be backup.
+ This is for making the file buffer refresh as few as possible.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HBufferImageBackup (
+ VOID
+ );
+
+/**
+ Read an image into a buffer friom a source.
+
+ @param[in] FileName Pointer to the file name. OPTIONAL and ignored if not FileTypeFileBuffer.
+ @param[in] DiskName Pointer to the disk name. OPTIONAL and ignored if not FileTypeDiskBuffer.
+ @param[in] DiskOffset Offset into the disk. OPTIONAL and ignored if not FileTypeDiskBuffer.
+ @param[in] DiskSize Size of the disk buffer. OPTIONAL and ignored if not FileTypeDiskBuffer.
+ @param[in] MemOffset Offset into the Memory. OPTIONAL and ignored if not FileTypeMemBuffer.
+ @param[in] MemSize Size of the Memory buffer. OPTIONAL and ignored if not FileTypeMemBuffer.
+ @param[in] BufferType The type of buffer to save. IGNORED.
+ @param[in] Recover TRUE for recovermode, FALSE otherwise.
+
+ @return EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+HBufferImageRead (
+ IN CONST CHAR16 *FileName,
+ IN CONST CHAR16 *DiskName,
+ IN UINTN DiskOffset,
+ IN UINTN DiskSize,
+ IN UINTN MemOffset,
+ IN UINTN MemSize,
+ IN EDIT_FILE_TYPE BufferType,
+ IN BOOLEAN Recover
+ );
+
+/**
+ Save the current image.
+
+ @param[in] FileName Pointer to the file name. OPTIONAL and ignored if not FileTypeFileBuffer.
+ @param[in] DiskName Pointer to the disk name. OPTIONAL and ignored if not FileTypeDiskBuffer.
+ @param[in] DiskOffset Offset into the disk. OPTIONAL and ignored if not FileTypeDiskBuffer.
+ @param[in] DiskSize Size of the disk buffer. OPTIONAL and ignored if not FileTypeDiskBuffer.
+ @param[in] MemOffset Offset into the Memory. OPTIONAL and ignored if not FileTypeMemBuffer.
+ @param[in] MemSize Size of the Memory buffer. OPTIONAL and ignored if not FileTypeMemBuffer.
+ @param[in] BufferType The type of buffer to save. IGNORED.
+
+ @return EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HBufferImageSave (
+ IN CHAR16 *FileName,
+ IN CHAR16 *DiskName,
+ IN UINTN DiskOffset,
+ IN UINTN DiskSize,
+ IN UINTN MemOffset,
+ IN UINTN MemSize,
+ IN EDIT_FILE_TYPE BufferType
+ );
+
+/**
+ According to cursor's file position, adjust screen display.
+
+ @param[in] NewFilePosRow Row of file position ( start from 1 ).
+ @param[in] NewFilePosCol Column of file position ( start from 1 ).
+ @param[in] HighBits Cursor will on high4 bits or low4 bits.
+**/
+VOID
+HBufferImageMovePosition (
+ IN UINTN NewFilePosRow,
+ IN UINTN NewFilePosCol,
+ IN BOOLEAN HighBits
+ );
+
+
+/**
+ Create a new line and append it to the line list.
+ Fields affected:
+ NumLines
+ Lines
+
+ @retval NULL create line failed.
+ @return the line created.
+
+**/
+HEFI_EDITOR_LINE *
+HBufferImageCreateLine (
+ VOID
+ );
+
+/**
+ Free the current image.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HBufferImageFree (
+ VOID
+ );
+
+/**
+ Delete character from buffer.
+
+ @param[in] Pos Position, Pos starting from 0.
+ @param[in] Count The Count of characters to delete.
+ @param[out] DeleteBuffer The DeleteBuffer.
+
+ @retval EFI_SUCCESS Success
+**/
+EFI_STATUS
+HBufferImageDeleteCharacterFromBuffer (
+ IN UINTN Pos,
+ IN UINTN Count,
+ OUT UINT8 *DeleteBuffer
+ );
+
+/**
+ Add character to buffer, add before pos.
+
+ @param[in] Pos Position, Pos starting from 0.
+ @param[in] Count Count of characters to add.
+ @param[in] AddBuffer Add buffer.
+
+ @retval EFI_SUCCESS Success.
+**/
+EFI_STATUS
+HBufferImageAddCharacterToBuffer (
+ IN UINTN Pos,
+ IN UINTN Count,
+ IN UINT8 *AddBuffer
+ );
+
+/**
+ Change the raw buffer to a list of lines for the UI.
+
+ @param[in] Buffer The pointer to the buffer to fill.
+ @param[in] Bytes The size of the buffer in bytes.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+HBufferImageBufferToList (
+ IN VOID *Buffer,
+ IN UINTN Bytes
+ );
+
+/**
+ Change the list of lines from the UI to a raw buffer.
+
+ @param[in] Buffer The pointer to the buffer to fill.
+ @param[in] Bytes The size of the buffer in bytes.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+HBufferImageListToBuffer (
+ IN VOID *Buffer,
+ IN UINTN Bytes
+ );
+
+/**
+ Move the mouse in the image buffer.
+
+ @param[in] TextX The x-coordinate.
+ @param[in] TextY The y-coordinate.
+**/
+VOID
+EFIAPI
+HBufferImageAdjustMousePosition (
+ IN INT32 TextX,
+ IN INT32 TextY
+ );
+
+/**
+ Function to decide if a column number is stored in the high bits.
+
+ @param[in] Column The column to examine.
+ @param[out] FCol The actual column number.
+
+ @retval TRUE The actual column was in high bits and is now in FCol.
+ @retval FALSE There was not a column number in the high bits.
+**/
+BOOLEAN
+HBufferImageIsAtHighBits (
+ IN UINTN Column,
+ OUT UINTN *FCol
+ );
+
+/**
+ Get the size of the open buffer.
+
+ @retval The size in bytes.
+**/
+UINTN
+HBufferImageGetTotalSize (
+ VOID
+ );
+
+#endif
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.c
new file mode 100644
index 0000000000..4d5bfb391f
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.c
@@ -0,0 +1,112 @@
+/** @file
+ Functions to deal with Clip Board
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HexEditor.h"
+
+typedef struct {
+ UINT8 *Buffer;
+ UINTN Size;
+} HEFI_EDITOR_CLIPBOARD;
+
+HEFI_EDITOR_CLIPBOARD HClipBoard;
+
+//
+// for basic initialization of HClipBoard
+//
+HEFI_EDITOR_CLIPBOARD HClipBoardConst = {
+ NULL,
+ 0
+};
+
+/**
+ Initialization function for HDiskImage.
+
+ @param[in] EFI_SUCCESS The operation was successful.
+ @param[in] EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HClipBoardInit (
+ VOID
+ )
+{
+ //
+ // basiclly initialize the HDiskImage
+ //
+ CopyMem (&HClipBoard, &HClipBoardConst, sizeof (HClipBoard));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Initialization function for HDiskImage.
+
+ @param[in] EFI_SUCCESS The operation was successful.
+ @param[in] EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HClipBoardCleanup (
+ VOID
+ )
+{
+
+ SHELL_FREE_NON_NULL (HClipBoard.Buffer);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set a buffer into the clipboard.
+
+ @param[in] Buffer The buffer to add to the clipboard.
+ @param[in] Size The size of Buffer in bytes.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HClipBoardSet (
+ IN UINT8 *Buffer,
+ IN UINTN Size
+ )
+{
+ //
+ // free the old clipboard buffer
+ // and set new clipboard buffer
+ //
+ SHELL_FREE_NON_NULL (HClipBoard.Buffer);
+ HClipBoard.Buffer = Buffer;
+
+ HClipBoard.Size = Size;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get a buffer from the clipboard.
+
+ @param[out] Buffer The pointer to the buffer to add to the clipboard.
+
+ @return the size of the buffer.
+**/
+UINTN
+HClipBoardGet (
+ OUT UINT8 **Buffer
+ )
+{
+ //
+ // return the clipboard buffer
+ //
+ *Buffer = HClipBoard.Buffer;
+
+ return HClipBoard.Size;
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.h
new file mode 100644
index 0000000000..8066c29247
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Clipboard.h
@@ -0,0 +1,69 @@
+/** @file
+ Defines DiskImage - the view of the file that is visible at any point,
+ as well as the event handlers for editing the file
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LIB_CLIP_BOARD_H_
+#define _LIB_CLIP_BOARD_H_
+
+#include "HexEditor.h"
+
+/**
+ Initialization function for HDiskImage
+
+ @param[in] EFI_SUCCESS The operation was successful.
+ @param[in] EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HClipBoardInit (
+ VOID
+ );
+
+/**
+ Initialization function for HDiskImage.
+
+ @param[in] EFI_SUCCESS The operation was successful.
+ @param[in] EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HClipBoardCleanup (
+ VOID
+ );
+
+/**
+ Set a buffer into the clipboard.
+
+ @param[in] Buffer The buffer to add to the clipboard.
+ @param[in] Size The size of Buffer in bytes.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HClipBoardSet (
+ IN UINT8 *Buffer,
+ IN UINTN Size
+ );
+
+/**
+ Get a buffer from the clipboard.
+
+ @param[out] Buffer The pointer to the buffer to add to the clipboard.
+
+ @return the size of the buffer.
+**/
+UINTN
+HClipBoardGet (
+ OUT UINT8 **Buffer
+ );
+
+#endif
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.c
new file mode 100644
index 0000000000..a50b52f5f2
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.c
@@ -0,0 +1,420 @@
+/** @file
+ Functions to deal with Disk buffer.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HexEditor.h"
+#include <Protocol/BlockIo.h>
+
+extern EFI_HANDLE HImageHandleBackup;
+extern HEFI_EDITOR_BUFFER_IMAGE HBufferImage;
+
+extern BOOLEAN HBufferImageNeedRefresh;
+extern BOOLEAN HBufferImageOnlyLineNeedRefresh;
+extern BOOLEAN HBufferImageMouseNeedRefresh;
+
+extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;
+
+HEFI_EDITOR_DISK_IMAGE HDiskImage;
+HEFI_EDITOR_DISK_IMAGE HDiskImageBackupVar;
+
+//
+// for basic initialization of HDiskImage
+//
+HEFI_EDITOR_DISK_IMAGE HDiskImageConst = {
+ NULL,
+ 0,
+ 0,
+ 0
+};
+
+/**
+ Initialization function for HDiskImage.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HDiskImageInit (
+ VOID
+ )
+{
+ //
+ // basically initialize the HDiskImage
+ //
+ CopyMem (&HDiskImage, &HDiskImageConst, sizeof (HDiskImage));
+
+ CopyMem (&HDiskImageBackupVar, &HDiskImageConst, sizeof (HDiskImageBackupVar));
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Backup function for HDiskImage. Only a few fields need to be backup.
+ This is for making the Disk buffer refresh as few as possible.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES gST->ConOut of resources.
+**/
+EFI_STATUS
+HDiskImageBackup (
+ VOID
+ )
+{
+ //
+ // backup the disk name, offset and size
+ //
+ //
+ SHELL_FREE_NON_NULL (HDiskImageBackupVar.Name);
+
+ HDiskImageBackupVar.Name = CatSPrint(NULL, L"%s", HDiskImage.Name);
+ if (HDiskImageBackupVar.Name == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ HDiskImageBackupVar.Offset = HDiskImage.Offset;
+ HDiskImageBackupVar.Size = HDiskImage.Size;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Cleanup function for HDiskImage.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HDiskImageCleanup (
+ VOID
+ )
+{
+ SHELL_FREE_NON_NULL (HDiskImage.Name);
+ SHELL_FREE_NON_NULL (HDiskImageBackupVar.Name);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set FileName field in HFileImage.
+
+ @param[in] Str File name to set.
+ @param[in] Offset The offset.
+ @param[in] Size The size.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+HDiskImageSetDiskNameOffsetSize (
+ IN CONST CHAR16 *Str,
+ IN UINTN Offset,
+ IN UINTN Size
+ )
+{
+ UINTN Len;
+ UINTN Index;
+
+ //
+ // free the old file name
+ //
+ SHELL_FREE_NON_NULL (HDiskImage.Name);
+
+ Len = StrLen (Str);
+
+ HDiskImage.Name = AllocateZeroPool (2 * (Len + 1));
+ if (HDiskImage.Name == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Index = 0; Index < Len; Index++) {
+ HDiskImage.Name[Index] = Str[Index];
+ }
+
+ HDiskImage.Name[Len] = L'\0';
+
+ HDiskImage.Offset = Offset;
+ HDiskImage.Size = Size;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read a disk from disk into HBufferImage.
+
+ @param[in] DeviceName filename to read.
+ @param[in] Offset The offset.
+ @param[in] Size The size.
+ @param[in] Recover if is for recover, no information print.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.
+**/
+EFI_STATUS
+HDiskImageRead (
+ IN CONST CHAR16 *DeviceName,
+ IN UINTN Offset,
+ IN UINTN Size,
+ IN BOOLEAN Recover
+ )
+{
+ CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *DupDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *DupDevicePathForFree;
+ EFI_HANDLE Handle;
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+ EFI_STATUS Status;
+
+ VOID *Buffer;
+ CHAR16 *Str;
+ UINTN Bytes;
+
+ HEFI_EDITOR_LINE *Line;
+
+ HBufferImage.BufferType = FileTypeDiskBuffer;
+
+ DevicePath = gEfiShellProtocol->GetDevicePathFromMap(DeviceName);
+ if (DevicePath == NULL) {
+ StatusBarSetStatusString (L"Cannot Find Device");
+ return EFI_INVALID_PARAMETER;
+ }
+ DupDevicePath = DuplicateDevicePath(DevicePath);
+ DupDevicePathForFree = DupDevicePath;
+ //
+ // get blkio interface
+ //
+ Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid,&DupDevicePath,&Handle);
+ FreePool(DupDevicePathForFree);
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Read Disk Failed");
+ return Status;
+ }
+ Status = gBS->OpenProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID**)&BlkIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Read Disk Failed");
+ return Status;
+ }
+ //
+ // if Offset exceeds LastBlock,
+ // return error
+ //
+ if (Offset > BlkIo->Media->LastBlock || Offset + Size > BlkIo->Media->LastBlock) {
+ StatusBarSetStatusString (L"Invalid Offset + Size");
+ return EFI_LOAD_ERROR;
+ }
+
+ Bytes = BlkIo->Media->BlockSize * Size;
+ Buffer = AllocateZeroPool (Bytes);
+
+ if (Buffer == NULL) {
+ StatusBarSetStatusString (L"Read Disk Failed");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // read from disk
+ //
+ Status = BlkIo->ReadBlocks (
+ BlkIo,
+ BlkIo->Media->MediaId,
+ Offset,
+ Bytes,
+ Buffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ StatusBarSetStatusString (L"Read Disk Failed");
+ return EFI_LOAD_ERROR;
+ }
+
+ HBufferImageFree ();
+
+ //
+ // convert buffer to line list
+ //
+ Status = HBufferImageBufferToList (Buffer, Bytes);
+ FreePool (Buffer);
+
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Read Disk Failed");
+ return Status;
+ }
+
+ Status = HDiskImageSetDiskNameOffsetSize (DeviceName, Offset, Size);
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Read Disk Failed");
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // initialize some variables
+ //
+ HDiskImage.BlockSize = BlkIo->Media->BlockSize;
+
+ HBufferImage.DisplayPosition.Row = 2;
+ HBufferImage.DisplayPosition.Column = 10;
+
+ HBufferImage.MousePosition.Row = 2;
+ HBufferImage.MousePosition.Column = 10;
+
+ HBufferImage.LowVisibleRow = 1;
+ HBufferImage.HighBits = TRUE;
+
+ HBufferImage.BufferPosition.Row = 1;
+ HBufferImage.BufferPosition.Column = 1;
+
+ if (!Recover) {
+ Str = CatSPrint(NULL, L"%d Lines Read", HBufferImage.NumLines);
+ if (Str == NULL) {
+ StatusBarSetStatusString (L"Read Disk Failed");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StatusBarSetStatusString (Str);
+ SHELL_FREE_NON_NULL (Str);
+
+ HMainEditor.SelectStart = 0;
+ HMainEditor.SelectEnd = 0;
+
+ }
+
+ //
+ // has line
+ //
+ if (HBufferImage.Lines != NULL) {
+ HBufferImage.CurrentLine = CR (
+ HBufferImage.ListHead->ForwardLink,
+ HEFI_EDITOR_LINE,
+ Link,
+ EFI_EDITOR_LINE_LIST
+ );
+ } else {
+ //
+ // create a dummy line
+ //
+ Line = HBufferImageCreateLine ();
+ if (Line == NULL) {
+ StatusBarSetStatusString (L"Read Disk Failed");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ HBufferImage.CurrentLine = Line;
+ }
+
+ HBufferImage.Modified = FALSE;
+ HBufferImageNeedRefresh = TRUE;
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+ HBufferImageMouseNeedRefresh = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Save lines in HBufferImage to disk.
+ NOT ALLOW TO WRITE TO ANOTHER DISK!!!!!!!!!
+
+ @param[in] DeviceName The device name.
+ @param[in] Offset The offset.
+ @param[in] Size The size.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.
+**/
+EFI_STATUS
+HDiskImageSave (
+ IN CHAR16 *DeviceName,
+ IN UINTN Offset,
+ IN UINTN Size
+ )
+{
+
+ CONST EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *DupDevicePath;
+ EFI_BLOCK_IO_PROTOCOL *BlkIo;
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ VOID *Buffer;
+ UINTN Bytes;
+
+ //
+ // if not modified, directly return
+ //
+ if (HBufferImage.Modified == FALSE) {
+ return EFI_SUCCESS;
+ }
+
+ HBufferImage.BufferType = FileTypeDiskBuffer;
+
+ DevicePath = gEfiShellProtocol->GetDevicePathFromMap(DeviceName);
+ if (DevicePath == NULL) {
+// StatusBarSetStatusString (L"Cannot Find Device");
+ return EFI_INVALID_PARAMETER;
+ }
+ DupDevicePath = DuplicateDevicePath(DevicePath);
+
+ //
+ // get blkio interface
+ //
+ Status = gBS->LocateDevicePath(&gEfiBlockIoProtocolGuid,&DupDevicePath,&Handle);
+ FreePool(DupDevicePath);
+ if (EFI_ERROR (Status)) {
+// StatusBarSetStatusString (L"Read Disk Failed");
+ return Status;
+ }
+ Status = gBS->OpenProtocol(Handle, &gEfiBlockIoProtocolGuid, (VOID**)&BlkIo, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR (Status)) {
+// StatusBarSetStatusString (L"Read Disk Failed");
+ return Status;
+ }
+
+ Bytes = BlkIo->Media->BlockSize * Size;
+ Buffer = AllocateZeroPool (Bytes);
+
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // concatenate the line list to a buffer
+ //
+ Status = HBufferImageListToBuffer (Buffer, Bytes);
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return Status;
+ }
+
+ //
+ // write the buffer to disk
+ //
+ Status = BlkIo->WriteBlocks (
+ BlkIo,
+ BlkIo->Media->MediaId,
+ Offset,
+ Bytes,
+ Buffer
+ );
+
+ FreePool (Buffer);
+
+ if (EFI_ERROR (Status)) {
+ return EFI_LOAD_ERROR;
+ }
+ //
+ // now not modified
+ //
+ HBufferImage.Modified = FALSE;
+
+ return EFI_SUCCESS;
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.h
new file mode 100644
index 0000000000..06fb53020a
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/DiskImage.h
@@ -0,0 +1,95 @@
+/** @file
+ Defines DiskImage - the view of the file that is visible at any point,
+ as well as the event handlers for editing the file
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LIB_DISK_IMAGE_H_
+#define _LIB_DISK_IMAGE_H_
+
+#include "HexEditor.h"
+
+/**
+ Initialization function for HDiskImage.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HDiskImageInit (
+ VOID
+ );
+
+/**
+ Cleanup function for HDiskImage.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HDiskImageCleanup (
+ VOID
+ );
+
+/**
+ Backup function for HDiskImage. Only a few fields need to be backup.
+ This is for making the Disk buffer refresh as few as possible.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES gST->ConOut of resources.
+**/
+EFI_STATUS
+HDiskImageBackup (
+ VOID
+ );
+
+/**
+ Read a disk from disk into HBufferImage.
+
+ @param[in] DeviceName filename to read.
+ @param[in] Offset The offset.
+ @param[in] Size The size.
+ @param[in] Recover if is for recover, no information print.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.
+**/
+EFI_STATUS
+HDiskImageRead (
+ IN CONST CHAR16 *DeviceName,
+ IN UINTN Offset,
+ IN UINTN Size,
+ IN BOOLEAN Recover
+ );
+
+/**
+ Save lines in HBufferImage to disk.
+ NOT ALLOW TO WRITE TO ANOTHER DISK!!!!!!!!!
+
+ @param[in] DeviceName The device name.
+ @param[in] Offset The offset.
+ @param[in] Size The size.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.
+**/
+EFI_STATUS
+HDiskImageSave (
+ IN CHAR16 *DeviceName,
+ IN UINTN Offset,
+ IN UINTN Size
+ );
+
+#endif
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.c
new file mode 100644
index 0000000000..2517a57f59
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.c
@@ -0,0 +1,403 @@
+/** @file
+ Functions to deal with file buffer.
+
+ Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HexEditor.h"
+
+extern EFI_HANDLE HImageHandleBackup;
+extern HEFI_EDITOR_BUFFER_IMAGE HBufferImage;
+
+extern BOOLEAN HBufferImageNeedRefresh;
+extern BOOLEAN HBufferImageOnlyLineNeedRefresh;
+extern BOOLEAN HBufferImageMouseNeedRefresh;
+
+extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;
+
+HEFI_EDITOR_FILE_IMAGE HFileImage;
+HEFI_EDITOR_FILE_IMAGE HFileImageBackupVar;
+
+//
+// for basic initialization of HFileImage
+//
+HEFI_EDITOR_BUFFER_IMAGE HFileImageConst = {
+ NULL,
+ 0,
+ FALSE
+};
+
+/**
+ Initialization function for HFileImage
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HFileImageInit (
+ VOID
+ )
+{
+ //
+ // basically initialize the HFileImage
+ //
+ CopyMem (&HFileImage, &HFileImageConst, sizeof (HFileImage));
+
+ CopyMem (
+ &HFileImageBackupVar,
+ &HFileImageConst,
+ sizeof (HFileImageBackupVar)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Backup function for HFileImage. Only a few fields need to be backup.
+ This is for making the file buffer refresh as few as possible.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+HFileImageBackup (
+ VOID
+ )
+{
+ SHELL_FREE_NON_NULL (HFileImageBackupVar.FileName);
+ HFileImageBackupVar.FileName = CatSPrint(NULL, L"%s", HFileImage.FileName);
+ if (HFileImageBackupVar.FileName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Cleanup function for HFileImage.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HFileImageCleanup (
+ VOID
+ )
+{
+
+ SHELL_FREE_NON_NULL (HFileImage.FileName);
+ SHELL_FREE_NON_NULL (HFileImageBackupVar.FileName);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set FileName field in HFileImage
+
+ @param[in] Str File name to set.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+HFileImageSetFileName (
+ IN CONST CHAR16 *Str
+ )
+{
+ UINTN Size;
+ UINTN Index;
+
+ //
+ // free the old file name
+ //
+ SHELL_FREE_NON_NULL (HFileImage.FileName);
+
+ Size = StrLen (Str);
+
+ HFileImage.FileName = AllocateZeroPool (2 * (Size + 1));
+ if (HFileImage.FileName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Index = 0; Index < Size; Index++) {
+ HFileImage.FileName[Index] = Str[Index];
+ }
+
+ HFileImage.FileName[Size] = L'\0';
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read a file from disk into HBufferImage.
+
+ @param[in] FileName filename to read.
+ @param[in] Recover if is for recover, no information print.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HFileImageRead (
+ IN CONST CHAR16 *FileName,
+ IN BOOLEAN Recover
+ )
+{
+ HEFI_EDITOR_LINE *Line;
+ UINT8 *Buffer;
+ CHAR16 *UnicodeBuffer;
+ EFI_STATUS Status;
+
+ //
+ // variable initialization
+ //
+ Line = NULL;
+
+ //
+ // in this function, when you return error ( except EFI_OUT_OF_RESOURCES )
+ // you should set status string
+ // since this function maybe called before the editorhandleinput loop
+ // so any error will cause editor return
+ // so if you want to print the error status
+ // you should set the status string
+ //
+ Status = ReadFileIntoBuffer (FileName, (VOID**)&Buffer, &HFileImage.Size, &HFileImage.ReadOnly);
+ //
+ // NULL pointer is only also a failure for a non-zero file size.
+ //
+ if ((EFI_ERROR(Status)) || (Buffer == NULL && HFileImage.Size != 0)) {
+ UnicodeBuffer = CatSPrint(NULL, L"Read error on file %s: %r", FileName, Status);
+ if (UnicodeBuffer == NULL) {
+ SHELL_FREE_NON_NULL(Buffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StatusBarSetStatusString (UnicodeBuffer);
+ FreePool (UnicodeBuffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ HFileImageSetFileName (FileName);
+
+ //
+ // free the old lines
+ //
+ HBufferImageFree ();
+
+ Status = HBufferImageBufferToList (Buffer, HFileImage.Size);
+ SHELL_FREE_NON_NULL (Buffer);
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Error parsing file.");
+ return Status;
+ }
+
+ HBufferImage.DisplayPosition.Row = 2;
+ HBufferImage.DisplayPosition.Column = 10;
+ HBufferImage.MousePosition.Row = 2;
+ HBufferImage.MousePosition.Column = 10;
+ HBufferImage.LowVisibleRow = 1;
+ HBufferImage.HighBits = TRUE;
+ HBufferImage.BufferPosition.Row = 1;
+ HBufferImage.BufferPosition.Column = 1;
+ HBufferImage.BufferType = FileTypeFileBuffer;
+
+ if (!Recover) {
+ UnicodeBuffer = CatSPrint(NULL, L"%d Lines Read", HBufferImage.NumLines);
+ if (UnicodeBuffer == NULL) {
+ SHELL_FREE_NON_NULL(Buffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StatusBarSetStatusString (UnicodeBuffer);
+ FreePool (UnicodeBuffer);
+
+ HMainEditor.SelectStart = 0;
+ HMainEditor.SelectEnd = 0;
+ }
+
+ //
+ // has line
+ //
+ if (HBufferImage.Lines != 0) {
+ HBufferImage.CurrentLine = CR (HBufferImage.ListHead->ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+ } else {
+ //
+ // create a dummy line
+ //
+ Line = HBufferImageCreateLine ();
+ if (Line == NULL) {
+ SHELL_FREE_NON_NULL(Buffer);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ HBufferImage.CurrentLine = Line;
+ }
+
+ HBufferImage.Modified = FALSE;
+ HBufferImageNeedRefresh = TRUE;
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+ HBufferImageMouseNeedRefresh = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Save lines in HBufferImage to disk.
+
+ @param[in] FileName The file name.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HFileImageSave (
+ IN CHAR16 *FileName
+ )
+{
+
+ LIST_ENTRY *Link;
+ HEFI_EDITOR_LINE *Line;
+ CHAR16 *Str;
+ EFI_STATUS Status;
+ UINTN NumLines;
+ SHELL_FILE_HANDLE FileHandle;
+ UINTN TotalSize;
+ UINT8 *Buffer;
+ UINT8 *Ptr;
+ EDIT_FILE_TYPE BufferTypeBackup;
+
+ BufferTypeBackup = HBufferImage.BufferType;
+ HBufferImage.BufferType = FileTypeFileBuffer;
+
+ //
+ // if is the old file
+ //
+ if (HFileImage.FileName != NULL && FileName != NULL && StrCmp (FileName, HFileImage.FileName) == 0) {
+ //
+ // check whether file exists on disk
+ //
+ if (ShellIsFile(FileName) == EFI_SUCCESS) {
+ //
+ // current file exists on disk
+ // so if not modified, then not save
+ //
+ if (HBufferImage.Modified == FALSE) {
+ return EFI_SUCCESS;
+ }
+ //
+ // if file is read-only, set error
+ //
+ if (HFileImage.ReadOnly == TRUE) {
+ StatusBarSetStatusString (L"Read Only File Can Not Be Saved");
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ if (ShellIsDirectory(FileName) == EFI_SUCCESS) {
+ StatusBarSetStatusString (L"Directory Can Not Be Saved");
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0);
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // the file exits, delete it
+ //
+ Status = ShellDeleteFile (&FileHandle);
+ if (EFI_ERROR (Status) || Status == EFI_WARN_DELETE_FAILURE) {
+ StatusBarSetStatusString (L"Write File Failed");
+ return EFI_LOAD_ERROR;
+ }
+ }
+
+ //
+ // write all the lines back to disk
+ //
+ NumLines = 0;
+ TotalSize = 0;
+ for (Link = HBufferImage.ListHead->ForwardLink; Link != HBufferImage.ListHead; Link = Link->ForwardLink) {
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+
+ if (Line->Size != 0) {
+ TotalSize += Line->Size;
+ }
+ //
+ // end of if Line -> Size != 0
+ //
+ NumLines++;
+ }
+ //
+ // end of for Link
+ //
+ Buffer = AllocateZeroPool (TotalSize);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Ptr = Buffer;
+ for (Link = HBufferImage.ListHead->ForwardLink; Link != HBufferImage.ListHead; Link = Link->ForwardLink) {
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+
+ if (Line->Size != 0) {
+ CopyMem (Ptr, Line->Buffer, Line->Size);
+ Ptr += Line->Size;
+ }
+ //
+ // end of if Line -> Size != 0
+ //
+ }
+
+
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
+
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Create File Failed");
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = ShellWriteFile (FileHandle, &TotalSize, Buffer);
+ FreePool (Buffer);
+ if (EFI_ERROR (Status)) {
+ ShellDeleteFile (&FileHandle);
+ return EFI_LOAD_ERROR;
+ }
+
+ ShellCloseFile(&FileHandle);
+
+ HBufferImage.Modified = FALSE;
+
+ //
+ // set status string
+ //
+ Str = CatSPrint(NULL, L"%d Lines Wrote", NumLines);
+ StatusBarSetStatusString (Str);
+ FreePool (Str);
+
+ //
+ // now everything is ready , you can set the new file name to filebuffer
+ //
+ if ((BufferTypeBackup != FileTypeFileBuffer && FileName != NULL) ||
+ (FileName != NULL && HFileImage.FileName != NULL && StringNoCaseCompare (&FileName, &HFileImage.FileName) != 0)){
+ //
+ // not the same
+ //
+ HFileImageSetFileName (FileName);
+ if (HFileImage.FileName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ }
+
+ HFileImage.ReadOnly = FALSE;
+
+ return EFI_SUCCESS;
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.h
new file mode 100644
index 0000000000..ed27ad03ae
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/FileImage.h
@@ -0,0 +1,83 @@
+/** @file
+ Defines FileImage - the view of the file that is visible at any point,
+ as well as the event handlers for editing the file
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LIB_FILE_IMAGE_H_
+#define _LIB_FILE_IMAGE_H_
+
+#include "HexEditor.h"
+
+/**
+ Initialization function for HFileImage
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HFileImageInit (
+ VOID
+ );
+
+/**
+ Cleanup function for HFileImage.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HFileImageCleanup (
+ VOID
+ );
+
+/**
+ Backup function for HFileImage. Only a few fields need to be backup.
+ This is for making the file buffer refresh as few as possible.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+HFileImageBackup (
+ VOID
+ );
+
+/**
+ Read a file from disk into HBufferImage.
+
+ @param[in] FileName filename to read.
+ @param[in] Recover if is for recover, no information print.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HFileImageRead (
+ IN CONST CHAR16 *FileName,
+ IN BOOLEAN Recover
+ );
+
+/**
+ Save lines in HBufferImage to disk.
+
+ @param[in] FileName The file name.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HFileImageSave (
+ IN CHAR16 *FileName
+ );
+
+#endif
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEdit.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEdit.c
new file mode 100644
index 0000000000..118aa7c3ed
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEdit.c
@@ -0,0 +1,277 @@
+/** @file
+ Main entry point of editor
+
+ (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDebug1CommandsLib.h"
+#include "HexEditor.h"
+
+//
+// Global Variables
+//
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-f", TypeFlag},
+ {L"-d", TypeFlag},
+ {L"-m", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'hexedit' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunHexEdit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *Buffer;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ LIST_ENTRY *Package;
+ CHAR16 *NewName;
+ CONST CHAR16 *Name;
+ UINTN Offset;
+ UINTN Size;
+ EDIT_FILE_TYPE WhatToDo;
+
+ Buffer = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ NewName = NULL;
+ Buffer = NULL;
+ Name = NULL;
+ Offset = 0;
+ Size = 0;
+ WhatToDo = FileTypeNone;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"hexedit", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // Check for -d
+ //
+ if (ShellCommandLineGetFlag(Package, L"-d")){
+ if (ShellCommandLineGetCount(Package) < 4) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"hexedit");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetCount(Package) > 4) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"hexedit");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ WhatToDo = FileTypeDiskBuffer;
+ Name = ShellCommandLineGetRawValue(Package, 1);
+ Offset = ShellStrToUintn(ShellCommandLineGetRawValue(Package, 2));
+ Size = ShellStrToUintn(ShellCommandLineGetRawValue(Package, 3));
+ }
+ if (Offset == (UINTN)-1 || Size == (UINTN)-1) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"hexedit", L"-d");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // check for -f
+ //
+ if (ShellCommandLineGetFlag(Package, L"-f") && (WhatToDo == FileTypeNone)){
+ if (ShellCommandLineGetCount(Package) < 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"hexedit");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetCount(Package) > 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"hexedit");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Name = ShellCommandLineGetRawValue(Package, 1);
+ if (Name == NULL || !IsValidFileName(Name)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"hexedit", Name);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ WhatToDo = FileTypeFileBuffer;
+ }
+ }
+ }
+
+ //
+ // check for -m
+ //
+ if (ShellCommandLineGetFlag(Package, L"-m") && (WhatToDo == FileTypeNone)){
+ if (ShellCommandLineGetCount(Package) < 3) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"hexedit");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetCount(Package) > 3) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"hexedit");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ WhatToDo = FileTypeMemBuffer;
+ Offset = ShellStrToUintn(ShellCommandLineGetRawValue(Package, 1));
+ Size = ShellStrToUintn(ShellCommandLineGetRawValue(Package, 2));
+ }
+ }
+ Name = ShellCommandLineGetRawValue(Package, 1);
+ if (WhatToDo == FileTypeNone && Name != NULL) {
+ if (ShellCommandLineGetCount(Package) > 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"hexedit");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (!IsValidFileName(Name)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"hexedit", Name);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ WhatToDo = FileTypeFileBuffer;
+ }
+ } else if (WhatToDo == FileTypeNone) {
+ if (gEfiShellProtocol->GetCurDir(NULL) == NULL) {
+ ShellStatus = SHELL_NOT_FOUND;
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellDebug1HiiHandle, L"hexedit");
+ } else {
+ NewName = EditGetDefaultFileName(L"bin");
+ Name = NewName;
+ WhatToDo = FileTypeFileBuffer;
+ }
+ }
+
+ if (ShellStatus == SHELL_SUCCESS && WhatToDo == FileTypeNone) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"hexedit");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (WhatToDo == FileTypeFileBuffer && ShellGetCurrentDir(NULL) == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellDebug1HiiHandle, L"hexedit");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+
+ if (ShellStatus == SHELL_SUCCESS) {
+ //
+ // Do the editor
+ //
+ Status = HMainEditorInit ();
+ if (EFI_ERROR (Status)) {
+ gST->ConOut->ClearScreen (gST->ConOut);
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_INIT_FAILED), gShellDebug1HiiHandle);
+ } else {
+ HMainEditorBackup ();
+ switch (WhatToDo) {
+ case FileTypeFileBuffer:
+ Status = HBufferImageRead (
+ Name==NULL?L"":Name,
+ NULL,
+ 0,
+ 0,
+ 0,
+ 0,
+ FileTypeFileBuffer,
+ FALSE
+ );
+ break;
+
+ case FileTypeDiskBuffer:
+ Status = HBufferImageRead (
+ NULL,
+ Name==NULL?L"":Name,
+ Offset,
+ Size,
+ 0,
+ 0,
+ FileTypeDiskBuffer,
+ FALSE
+ );
+ break;
+
+ case FileTypeMemBuffer:
+ Status = HBufferImageRead (
+ NULL,
+ NULL,
+ 0,
+ 0,
+ (UINT32) Offset,
+ Size,
+ FileTypeMemBuffer,
+ FALSE
+ );
+ break;
+
+ default:
+ Status = EFI_NOT_FOUND;
+ break;
+ }
+ if (!EFI_ERROR (Status)) {
+ HMainEditorRefresh ();
+ Status = HMainEditorKeyInput ();
+ }
+ if (Status != EFI_OUT_OF_RESOURCES) {
+ //
+ // back up the status string
+ //
+ Buffer = CatSPrint (NULL, L"%s\r\n", StatusBarGetString());
+ }
+ }
+
+ //
+ // cleanup
+ //
+ HMainEditorCleanup ();
+
+ if (EFI_ERROR (Status)) {
+ if (ShellStatus == SHELL_SUCCESS) {
+ ShellStatus = SHELL_UNSUPPORTED;
+ }
+ }
+
+ //
+ // print editor exit code on screen
+ //
+ if (Status == EFI_OUT_OF_RESOURCES) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle, L"hexedit");
+ } else if (EFI_ERROR(Status)){
+ if (Buffer != NULL) {
+ if (StrCmp (Buffer, L"") != 0) {
+ //
+ // print out the status string
+ //
+ ShellPrintEx(-1, -1, L"%s", Buffer);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_UNKNOWN_EDITOR), gShellDebug1HiiHandle);
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_UNKNOWN_EDITOR), gShellDebug1HiiHandle);
+ }
+ }
+ }
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ SHELL_FREE_NON_NULL (Buffer);
+ SHELL_FREE_NON_NULL (NewName);
+ return ShellStatus;
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditor.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditor.h
new file mode 100644
index 0000000000..d0a4bf4aae
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditor.h
@@ -0,0 +1,41 @@
+/** @file
+ Main include file for hex editor
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _EFI_SHELL_HEXEDIT_H_
+#define _EFI_SHELL_HEXEDIT_H_
+
+#include "UefiShellDebug1CommandsLib.h"
+#include "HexEditorTypes.h"
+
+#include "MainHexEditor.h"
+
+#include "BufferImage.h"
+#include "FileImage.h"
+#include "DiskImage.h"
+#include "MemImage.h"
+
+#include "EditTitleBar.h"
+#include "EditStatusBar.h"
+#include "EditInputBar.h"
+#include "EditMenuBar.h"
+
+#include "Misc.h"
+
+#include "Clipboard.h"
+
+extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;
+extern BOOLEAN HEditorFirst;
+extern BOOLEAN HEditorExit;
+
+#endif // _HEDITOR_H
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditorTypes.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditorTypes.h
new file mode 100644
index 0000000000..ddd6070c94
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexEditorTypes.h
@@ -0,0 +1,126 @@
+/** @file
+ data types that are used by editor
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _HEDITOR_TYPE_H_
+#define _HEDITOR_TYPE_H_
+
+#include "UefiShellDebug1CommandsLib.h"
+#include "EditTitleBar.h"
+
+#define EFI_EDITOR_LINE_LIST SIGNATURE_32 ('e', 'e', 'l', 'l')
+
+#define ASCII_POSITION ((0x10 * 3) + 12)
+
+
+typedef struct {
+ UINTN Row;
+ UINTN Column;
+} HEFI_EDITOR_POSITION;
+
+typedef
+EFI_STATUS
+(*HEFI_MENU_ITEM_FUNCTION) (
+ VOID
+ );
+
+typedef struct {
+ CHAR16 Name[50];
+ CHAR16 Key[3];
+ HEFI_MENU_ITEM_FUNCTION Function;
+} HMENU_ITEMS;
+
+typedef struct _HEFI_EDITOR_LINE {
+ UINTN Signature;
+ UINT8 Buffer[0x10];
+ UINTN Size; // unit is Unicode
+ LIST_ENTRY Link;
+} HEFI_EDITOR_LINE;
+
+typedef struct _HEFI_EDITOR_MENU_ITEM {
+ CHAR16 NameToken;
+ CHAR16 FunctionKeyToken;
+ HEFI_MENU_ITEM_FUNCTION Function;
+} HEFI_EDITOR_MENU_ITEM;
+
+typedef struct {
+ UINT32 Foreground : 4;
+ UINT32 Background : 4;
+} HEFI_EDITOR_COLOR_ATTRIBUTES;
+
+typedef union {
+ HEFI_EDITOR_COLOR_ATTRIBUTES Colors;
+ UINTN Data;
+} HEFI_EDITOR_COLOR_UNION;
+
+typedef struct {
+ UINTN Columns;
+ UINTN Rows;
+} HEFI_EDITOR_TEXT_MODE;
+
+
+typedef struct {
+ CHAR16 *Name;
+
+ UINTN BlockSize;
+ UINTN Size;
+ UINTN Offset;
+} HEFI_EDITOR_DISK_IMAGE;
+
+typedef struct {
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoFncs;
+
+ UINTN Offset;
+ UINTN Size;
+} HEFI_EDITOR_MEM_IMAGE;
+
+typedef struct {
+ CHAR16 *FileName;
+ UINTN Size; // file size
+ BOOLEAN ReadOnly; // file is read-only or not
+} HEFI_EDITOR_FILE_IMAGE;
+
+typedef struct {
+ LIST_ENTRY *ListHead; // list head of lines
+ HEFI_EDITOR_LINE *Lines; // lines of current file
+ UINTN NumLines; // number of lines
+ HEFI_EDITOR_LINE *CurrentLine; // current line cursor is at
+ HEFI_EDITOR_POSITION DisplayPosition; // cursor position in screen
+ HEFI_EDITOR_POSITION MousePosition; // mouse position in screen
+ HEFI_EDITOR_POSITION BufferPosition; // cursor position in buffer
+ UINTN LowVisibleRow; // the lowest visible row of file position
+ BOOLEAN HighBits; // cursor is at the high4 bits or low4 bits
+ BOOLEAN Modified; // BUFFER is modified or not
+ EDIT_FILE_TYPE BufferType;
+
+ HEFI_EDITOR_FILE_IMAGE *FileImage;
+ HEFI_EDITOR_DISK_IMAGE *DiskImage;
+ HEFI_EDITOR_MEM_IMAGE *MemImage;
+
+} HEFI_EDITOR_BUFFER_IMAGE;
+
+typedef struct {
+ HEFI_EDITOR_BUFFER_IMAGE *BufferImage;
+
+ HEFI_EDITOR_COLOR_UNION ColorAttributes;
+ HEFI_EDITOR_POSITION ScreenSize; // row number and column number
+ BOOLEAN MouseSupported;
+ EFI_SIMPLE_POINTER_PROTOCOL *MouseInterface;
+ INT32 MouseAccumulatorX;
+ INT32 MouseAccumulatorY;
+
+ UINTN SelectStart; // starting from 1
+ UINTN SelectEnd; // starting from 1
+} HEFI_EDITOR_GLOBAL_EDITOR;
+
+#endif
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexeditStrings.uni b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexeditStrings.uni
new file mode 100644
index 0000000000..d9591ca13d
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/HexeditStrings.uni
@@ -0,0 +1,76 @@
+// /**
+//
+// Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved.<BR>
+// (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// Abstract:
+//
+// Additional string definitions for UEFI Shell 2.0 Debug1 profile Edit command
+//
+//
+// **/
+
+/=#
+
+#langdef en-US "english"
+
+
+#string STR_HEXEDIT_USAGE #language en-US "\n\n %EHexEditor Usage%N\n"
+#string STR_HEXEDIT_FILENAME #language en-US " %H[-f] Filename%N Open File For Editing\n"
+#string STR_HEXEDIT_DISKNAME #language en-US " %H-d DiskName FirstBlockNo. BlockNumber%N Open Disk Block For Editing\n"
+#string STR_HEXEDIT_OFFSET_SIZE #language en-US " %H-m Offset Size%N Open Memory Region For Editing\n"
+#string STR_HEXEDIT_FILE_NAME #language en-US "%Hhexedit%N: Invalid File Name\n"
+#string STR_HEXEDIT_LIBEDITOR_MAINEDITOR_TITLE #language en-US "%EMainEditor init failed on TitleBar init\n%N"
+#string STR_HEXEDIT_LIBEDITOR_MAINEDITOR_MAINMENU #language en-US "%EMainEditor init failed on MainMenu init\n%N"
+#string STR_HEXEDIT_LIBEDITOR_MAINEDITOR_STATUS #language en-US "%EMainEditor init failed on StatusBar init\n%N"
+#string STR_HEXEDIT_LIBEDITOR_MAINEDITOR_INPUTBAR #language en-US "%EMainEditor init failed on InputBar init\n%N"
+#string STR_HEXEDIT_LIBEDITOR_MAINEDITOR_BUFFERIMAGE #language en-US "%EMainEditor init failed on BufferImage init\n%N"
+#string STR_HEXEDIT_LIBEDITOR_MAINEDITOR_CLIPBOARD #language en-US "%EMainEditor init failed on ClipBoard init\n%N"
+#string STR_HEXEDIT_LIBEDITOR_TITLEBAR_CLEAN #language en-US "TitleBar cleanup failed\n"
+#string STR_HEXEDIT_LIBEDITOR_MENUBAR_CLEAN #language en-US "MenuBar cleanup failed\n"
+#string STR_HEXEDIT_LIBEDITOR_STATUSBAR_CLEAN #language en-US "StatusBar cleanup failed\n"
+#string STR_HEXEDIT_LIBEDITOR_INPUTBAR_CLEAN #language en-US "InputBar cleanup failed\n"
+#string STR_HEXEDIT_LIBEDITOR_BUFFERIMAGE_CLEAN #language en-US "BufferImage cleanup failed\n"
+#string STR_HEXEDIT_LIBEDITOR_CLIPBOARD_CLEAN #language en-US "ClipBoard cleanup failed\n"
+#string STR_HEXEDIT_LIBINPUTBAR_MAININPUTBAR #language en-US "%s"
+#string STR_HEXEDIT_LIBMENUBAR_OPEN_FILE #language en-US "Open File"
+#string STR_HEXEDIT_LIBMENUBAR_OPEN_DISK #language en-US "Open Disk"
+#string STR_HEXEDIT_LIBMENUBAR_OPEN_MEMORY #language en-US "Open Memory"
+#string STR_HEXEDIT_LIBMENUBAR_SAVE_BUFFER #language en-US "Save Buffer"
+#string STR_HEXEDIT_LIBMENUBAR_SELECT_START #language en-US "Select Start"
+#string STR_HEXEDIT_LIBMENUBAR_SELECT_END #language en-US "Select End"
+#string STR_HEXEDIT_LIBMENUBAR_CUT #language en-US "Cut"
+#string STR_HEXEDIT_LIBMENUBAR_PASTE #language en-US "Paste"
+#string STR_HEXEDIT_LIBMENUBAR_GO_TO_OFFSET #language en-US "Go To Offset"
+#string STR_HEXEDIT_LIBTITLEBAR_MAINEDITOR #language en-US "%s"
+#string STR_HEXEDIT_LIBTITLEBAR_MAINEDITOR_C #language en-US "%c"
+#string STR_HEXEDIT_LIBTITLEBAR_MAINEDITOR_TWOVARS #language en-US "( %X ~ %X ) "
+#string STR_HEXEDIT_LIBTITLEBAR_FILE #language en-US " [FILE]"
+#string STR_HEXEDIT_LIBTITLEBAR_DISK #language en-US " [DISK]"
+#string STR_HEXEDIT_LIBTITLEBAR_MEM #language en-US " [MEM]"
+#string STR_HEXEDIT_HELP_TITLE #language en-US "Help \n"
+#string STR_HEXEDIT_HELP_BLANK #language en-US " \n"
+#string STR_HEXEDIT_HELP_LIST_TITLE #language en-US "Control Key Function Key Command \n"
+#string STR_HEXEDIT_HELP_DIV #language en-US "----------- ------------ ----------------- \n"
+#string STR_HEXEDIT_HELP_GO_TO_OFFSET #language en-US "Ctrl-G F1 Go To Offset \n"
+#string STR_HEXEDIT_HELP_SAVE_BUFFER #language en-US "Ctrl-S F2 Save Buffer \n"
+#string STR_HEXEDIT_HELP_EXIT #language en-US "Ctrl-Q F3 Exit \n"
+#string STR_HEXEDIT_HELP_SELECT_START #language en-US "Ctrl-T F4 Select Start \n"
+#string STR_HEXEDIT_HELP_SELECT_END #language en-US "Ctrl-D F5 Select End \n"
+#string STR_HEXEDIT_HELP_CUT #language en-US "Ctrl-X F6 Cut \n"
+#string STR_HEXEDIT_HELP_PASTE #language en-US "Ctrl-V F7 Paste \n"
+#string STR_HEXEDIT_HELP_OPEN_FILE #language en-US "Ctrl-O F8 Open File \n"
+#string STR_HEXEDIT_HELP_OPEN_DISK #language en-US "Ctrl-I F9 Open Disk \n"
+#string STR_HEXEDIT_HELP_OPEN_MEMORY #language en-US "Ctrl-M F10 Open Memory \n"
+#string STR_HEXEDIT_HELP_EXIT_HELP #language en-US "Use Ctrl-W to exit this help \n"
+#string STR_HEXEDIT_INIT_FAILED #language en-US "%Hhexedit%N: Initialization failed\n"
+#string STR_HEXEDIT_ONE_VAR #language en-US "%Hhexedit%N: %s\n"
+#string STR_HEXEDIT_UNKNOWN_EDITOR #language en-US "%Hhexedit%N: Unknown editor error\n"
+#string STR_HEXEDIT_NOREDIRECT #language en-US "%Hhexedit%N: Redirection is not allowed\n"
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.c
new file mode 100644
index 0000000000..4c346cc24e
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.c
@@ -0,0 +1,2318 @@
+/** @file
+ Defines the Main Editor data type -
+ - Global variables
+ - Instances of the other objects of the editor
+ - Main Interfaces
+
+ Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HexEditor.h"
+#include "EditStatusBar.h"
+#include "EditInputBar.h"
+
+HEFI_EDITOR_COLOR_ATTRIBUTES HOriginalColors;
+INTN HOriginalMode;
+
+//
+// the first time editor launch
+//
+BOOLEAN HEditorFirst;
+
+//
+// it's time editor should exit
+//
+BOOLEAN HEditorExit;
+
+BOOLEAN HEditorMouseAction;
+
+extern HEFI_EDITOR_BUFFER_IMAGE HBufferImage;
+extern HEFI_EDITOR_BUFFER_IMAGE HBufferImageBackupVar;
+
+extern BOOLEAN HBufferImageMouseNeedRefresh;
+extern BOOLEAN HBufferImageNeedRefresh;
+extern BOOLEAN HBufferImageOnlyLineNeedRefresh;
+
+HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;
+HEFI_EDITOR_GLOBAL_EDITOR HMainEditorBackupVar;
+
+//
+// basic initialization for MainEditor
+//
+HEFI_EDITOR_GLOBAL_EDITOR HMainEditorConst = {
+ &HBufferImage,
+ {
+ {0, 0}
+ },
+ {
+ 0,
+ 0
+ },
+ FALSE,
+ NULL,
+ 0,
+ 0,
+ 1,
+ 1
+};
+
+/**
+ Help info that will be displayed.
+**/
+EFI_STRING_ID HexMainMenuHelpInfo[] = {
+ STRING_TOKEN(STR_HEXEDIT_HELP_TITLE),
+ STRING_TOKEN(STR_HEXEDIT_HELP_BLANK),
+ STRING_TOKEN(STR_HEXEDIT_HELP_LIST_TITLE),
+ STRING_TOKEN(STR_HEXEDIT_HELP_DIV),
+ STRING_TOKEN(STR_HEXEDIT_HELP_GO_TO_OFFSET),
+ STRING_TOKEN(STR_HEXEDIT_HELP_SAVE_BUFFER),
+ STRING_TOKEN(STR_HEXEDIT_HELP_EXIT),
+ STRING_TOKEN(STR_HEXEDIT_HELP_SELECT_START),
+ STRING_TOKEN(STR_HEXEDIT_HELP_SELECT_END),
+ STRING_TOKEN(STR_HEXEDIT_HELP_CUT),
+ STRING_TOKEN(STR_HEXEDIT_HELP_PASTE),
+ STRING_TOKEN(STR_HEXEDIT_HELP_OPEN_FILE),
+ STRING_TOKEN(STR_HEXEDIT_HELP_OPEN_DISK),
+ STRING_TOKEN(STR_HEXEDIT_HELP_OPEN_MEMORY),
+ STRING_TOKEN(STR_HEXEDIT_HELP_BLANK),
+ STRING_TOKEN(STR_HEXEDIT_HELP_EXIT_HELP),
+ STRING_TOKEN(STR_HEXEDIT_HELP_BLANK),
+ STRING_TOKEN(STR_HEXEDIT_HELP_BLANK),
+ STRING_TOKEN(STR_HEXEDIT_HELP_BLANK),
+ STRING_TOKEN(STR_HEXEDIT_HELP_BLANK),
+ STRING_TOKEN(STR_HEXEDIT_HELP_BLANK),
+ STRING_TOKEN(STR_HEXEDIT_HELP_BLANK),
+ STRING_TOKEN(STR_HEXEDIT_HELP_DIV),
+ 0
+};
+
+
+/**
+ show help menu.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HMainCommandDisplayHelp (
+ VOID
+ )
+{
+ INT32 CurrentLine;
+ CHAR16 * InfoString;
+ EFI_INPUT_KEY Key;
+
+ CurrentLine = 0;
+ // print helpInfo
+ for (CurrentLine = 0; 0 != HexMainMenuHelpInfo[CurrentLine]; CurrentLine++) {
+ InfoString = HiiGetString(gShellDebug1HiiHandle, HexMainMenuHelpInfo[CurrentLine]
+, NULL);
+ ShellPrintEx (0,CurrentLine+1,L"%E%s%N",InfoString);
+ }
+
+ // scan for ctrl+w
+ do {
+ gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ } while(SCAN_CONTROL_W != Key.UnicodeChar);
+
+ // update screen with buffer's info
+ HBufferImageNeedRefresh = TRUE;
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+ HBufferImageRefresh ();
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Move cursor to specified lines.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HMainCommandGoToOffset (
+ VOID
+ )
+{
+ UINTN Size;
+ UINT64 Offset;
+ EFI_STATUS Status;
+ UINTN FRow;
+ UINTN FCol;
+
+ //
+ // variable initialization
+ //
+ Size = 0;
+ Offset = 0;
+ FRow = 0;
+ FCol = 0;
+
+ //
+ // get offset
+ //
+ Status = InputBarSetPrompt (L"Go To Offset: ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (8);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ while (1) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+
+ return EFI_SUCCESS;
+ }
+ //
+ // THE input string length should > 0
+ //
+ if (StrLen (InputBarGetString()) > 0) {
+ Status = ShellConvertStringToUint64 (InputBarGetString(), &Offset, TRUE, FALSE);
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Invalid Offset");
+ return EFI_SUCCESS;
+ }
+
+ break;
+ }
+ }
+
+ Size = HBufferImageGetTotalSize ();
+ if (Offset >= Size) {
+ StatusBarSetStatusString (L"Invalid Offset");
+ return EFI_SUCCESS;
+ }
+
+ FRow = (UINTN)DivU64x32(Offset , 0x10) + 1;
+ FCol = (UINTN)ModU64x32(Offset , 0x10) + 1;
+
+ HBufferImageMovePosition (FRow, FCol, TRUE);
+
+ HBufferImageNeedRefresh = TRUE;
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+ HBufferImageMouseNeedRefresh = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Save current opened buffer.
+ If is file buffer, you can save to current file name or
+ save to another file name.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation occured.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HMainCommandSaveBuffer (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Done;
+ CHAR16 *FileName;
+ BOOLEAN OldFile;
+ CHAR16 *Str;
+ EFI_FILE_INFO *Info;
+ SHELL_FILE_HANDLE ShellFileHandle;
+
+ if (HMainEditor.BufferImage->BufferType != FileTypeFileBuffer) {
+ if (!HMainEditor.BufferImage->Modified) {
+ return EFI_SUCCESS;
+ }
+
+ Status = InputBarSetPrompt (L"Dangerous to save disk/mem buffer. Save (Yes/No/Cancel) ? ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // the answer is just one character
+ //
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // loop for user's answer
+ // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'
+ //
+ while (1) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString()[0]) {
+ case L'y':
+ case L'Y':
+ //
+ // want to save this buffer first
+ //
+ Status = HBufferImageSave (
+ NULL,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ HMainEditor.BufferImage->BufferType
+ );
+
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"BufferSave: Problems Writing");
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+
+ case L'n':
+ case L'N':
+ //
+ // the file won't be saved
+ //
+ return EFI_SUCCESS;
+
+ case L'c':
+ case L'C':
+ return EFI_SUCCESS;
+ }
+ //
+ // end of switch
+ //
+ }
+ //
+ // ENDOF WHILE
+ //
+ }
+ //
+ // ENDOF != FILEBUFFER
+ //
+ // This command will save currently opened file to disk.
+ // You can choose save to another file name or just save to
+ // current file name.
+ // Below is the scenario of Save File command: (
+ // Suppose the old file name is A )
+ // 1. An Input Bar will be prompted: "File To Save: [ old file name]"
+ // IF user press ESC, Save File command ends .
+ // IF user press Enter, input file name will be A.
+ // IF user inputs a new file name B, input file name will be B.
+ //
+ // 2. IF input file name is A, go to do Step 3.
+ // IF input file name is B, go to do Step 4.
+ //
+ // 3. IF A is read only, Status Bar will show "Access Denied"
+ // and Save File commands ends.
+ // IF A is not read only, save file buffer to disk
+ // and remove Modified flag in Title Bar , then Save File command ends.
+ //
+ // 4. IF B does not exist, create this file and save file buffer to it.
+ // Go to do Step 7.
+ // IF B exits, do Step 5.
+ //
+ // 5. An Input Bar will be prompted:
+ // "File Exists. Overwrite ( Yes/No/Cancel ) ?"
+ // IF user press 'y' or 'Y', do Step 6.
+ // IF user press 'n' or 'N', Save File commands ends.
+ // IF user press 'c' or 'C' or ESC, Save File commands ends.
+ //
+ // 6. IF B is a read-only file, Status Bar will show "Access Denied"
+ // and Save File commands ends.
+ // IF B can be read and write, save file buffer to B.
+ //
+ // 7. Update File Name field in Title Bar to B
+ // and remove the Modified flag in Title Bar.
+ //
+ Str = CatSPrint(NULL,
+ L"File to Save: [%s]",
+ HMainEditor.BufferImage->FileImage->FileName
+ );
+ if (Str == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (StrLen (Str) >= 50) {
+ //
+ // replace the long file name with "..."
+ //
+ Str[46] = L'.';
+ Str[47] = L'.';
+ Str[48] = L'.';
+ Str[49] = L']';
+ Str[50] = L'\0';
+ }
+
+ Status = InputBarSetPrompt (Str);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (100);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // get new file name
+ //
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // if user pressed ESC
+ //
+ if (Status == EFI_NOT_READY) {
+ SHELL_FREE_NON_NULL (Str);
+ return EFI_SUCCESS;
+ }
+
+ SHELL_FREE_NON_NULL (Str);
+
+ //
+ // if just enter pressed, so think save to current file name
+ //
+ if (StrLen (InputBarGetString()) == 0) {
+ FileName = CatSPrint(NULL,
+ L"%s",
+ HMainEditor.BufferImage->FileImage->FileName
+ );
+ } else {
+ FileName = CatSPrint(NULL, L"%s", InputBarGetString());
+ }
+
+ if (FileName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ if (!IsValidFileName (FileName)) {
+ StatusBarSetStatusString (L"Invalid File Name");
+ SHELL_FREE_NON_NULL (FileName);
+ return EFI_SUCCESS;
+ }
+
+ OldFile = FALSE;
+
+ //
+ // save to the old file
+ //
+ if (StringNoCaseCompare (
+ &FileName,
+ &HMainEditor.BufferImage->FileImage->FileName
+ ) == 0) {
+ OldFile = TRUE;
+ }
+
+ if (OldFile) {
+ //
+ // if the file is read only, so can not write back to it.
+ //
+ if (HMainEditor.BufferImage->FileImage->ReadOnly) {
+ StatusBarSetStatusString (L"Access Denied");
+ SHELL_FREE_NON_NULL (FileName);
+ return EFI_SUCCESS;
+ }
+ } else {
+ Status = ShellOpenFileByName (FileName, &ShellFileHandle, EFI_FILE_MODE_READ, 0);
+
+ if (!EFI_ERROR (Status)) {
+
+ Info = ShellGetFileInfo(ShellFileHandle);
+
+ ShellCloseFile(&ShellFileHandle);
+ //
+ // check if read only
+ //
+ if (Info->Attribute & EFI_FILE_READ_ONLY) {
+ StatusBarSetStatusString (L"Access Denied");
+ SHELL_FREE_NON_NULL (FileName);
+ return EFI_SUCCESS;
+ }
+
+ SHELL_FREE_NON_NULL(Info);
+ //
+ // ask user whether to overwrite this file
+ //
+ Status = InputBarSetPrompt (L"File exists. Overwrite (Yes/No/Cancel) ? ");
+ if (EFI_ERROR (Status)) {
+ SHELL_FREE_NON_NULL (FileName);
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ SHELL_FREE_NON_NULL (FileName);
+ return Status;
+ }
+
+ Done = FALSE;
+ while (!Done) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ if (Status == EFI_NOT_READY) {
+ SHELL_FREE_NON_NULL (FileName);
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString()[0]) {
+ case L'y':
+ case L'Y':
+ Done = TRUE;
+ break;
+ case L'n':
+ case L'N':
+ SHELL_FREE_NON_NULL (FileName);
+ return EFI_SUCCESS;
+ case L'c':
+ case L'C':
+ SHELL_FREE_NON_NULL (FileName);
+ return EFI_SUCCESS;
+ } // switch
+ } // while
+ } // if opened existing file
+ } // if OldFile
+
+ //
+ // save file back to disk
+ //
+ Status = HBufferImageSave (
+ FileName,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ FileTypeFileBuffer
+ );
+ SHELL_FREE_NON_NULL (FileName);
+
+ if (EFI_ERROR (Status)) {
+ return EFI_LOAD_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Load a disk buffer editor.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation occured.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HMainCommandSelectStart (
+ VOID
+ )
+{
+ UINTN Start;
+
+ Start = (HMainEditor.BufferImage->BufferPosition.Row - 1) * 0x10 + HMainEditor.BufferImage->BufferPosition.Column;
+
+ //
+ // last line
+ //
+ if (HMainEditor.BufferImage->CurrentLine->Link.ForwardLink == HMainEditor.BufferImage->ListHead) {
+ if (HMainEditor.BufferImage->BufferPosition.Column > HMainEditor.BufferImage->CurrentLine->Size) {
+ StatusBarSetStatusString (L"Invalid Block Start");
+ return EFI_LOAD_ERROR;
+ }
+ }
+
+ if (HMainEditor.SelectEnd != 0 && Start > HMainEditor.SelectEnd) {
+ StatusBarSetStatusString (L"Invalid Block Start");
+ return EFI_LOAD_ERROR;
+ }
+
+ HMainEditor.SelectStart = Start;
+
+ HBufferImageNeedRefresh = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Load a disk buffer editor.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation occured.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HMainCommandSelectEnd (
+ VOID
+ )
+{
+ UINTN End;
+
+ End = (HMainEditor.BufferImage->BufferPosition.Row - 1) * 0x10 + HMainEditor.BufferImage->BufferPosition.Column;
+
+ //
+ // last line
+ //
+ if (HMainEditor.BufferImage->CurrentLine->Link.ForwardLink == HMainEditor.BufferImage->ListHead) {
+ if (HMainEditor.BufferImage->BufferPosition.Column > HMainEditor.BufferImage->CurrentLine->Size) {
+ StatusBarSetStatusString (L"Invalid Block End");
+ return EFI_LOAD_ERROR;
+ }
+ }
+
+ if (HMainEditor.SelectStart != 0 && End < HMainEditor.SelectStart) {
+ StatusBarSetStatusString (L"Invalid Block End");
+ return EFI_SUCCESS;
+ }
+
+ HMainEditor.SelectEnd = End;
+
+ HBufferImageNeedRefresh = TRUE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Cut current line to clipboard.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation occured.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HMainCommandCut (
+ VOID
+ )
+{
+ UINTN Index;
+ LIST_ENTRY *Link;
+ UINT8 *Buffer;
+ UINTN Count;
+
+ //
+ // not select, so not allowed to cut
+ //
+ if (HMainEditor.SelectStart == 0) {
+ StatusBarSetStatusString (L"No Block is Selected");
+ return EFI_SUCCESS;
+ }
+ //
+ // not select, so not allowed to cut
+ //
+ if (HMainEditor.SelectEnd == 0) {
+ StatusBarSetStatusString (L"No Block is Selected");
+ return EFI_SUCCESS;
+ }
+
+ Link = HMainEditor.BufferImage->ListHead->ForwardLink;
+ for (Index = 0; Index < (HMainEditor.SelectEnd - 1) / 0x10; Index++) {
+ Link = Link->ForwardLink;
+ }
+
+ Count = HMainEditor.SelectEnd - HMainEditor.SelectStart + 1;
+ Buffer = AllocateZeroPool (Count);
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // cut the selected area
+ //
+ HBufferImageDeleteCharacterFromBuffer (
+ HMainEditor.SelectStart - 1,
+ Count,
+ Buffer
+ );
+
+ //
+ // put to clipboard
+ //
+ HClipBoardSet (Buffer, Count);
+
+ HBufferImageNeedRefresh = TRUE;
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+
+ if (!HMainEditor.BufferImage->Modified) {
+ HMainEditor.BufferImage->Modified = TRUE;
+ }
+
+ //
+ // now no select area
+ //
+ HMainEditor.SelectStart = 0;
+ HMainEditor.SelectEnd = 0;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Paste line to file buffer.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation occured.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HMainCommandPaste (
+ VOID
+ )
+{
+
+ BOOLEAN OnlyLineRefresh;
+ HEFI_EDITOR_LINE *Line;
+ UINT8 *Buffer;
+ UINTN Count;
+ UINTN FPos;
+
+ Count = HClipBoardGet (&Buffer);
+ if (Count == 0 || Buffer == NULL) {
+ StatusBarSetStatusString (L"Nothing to Paste");
+ return EFI_SUCCESS;
+ }
+
+ Line = HMainEditor.BufferImage->CurrentLine;
+
+ OnlyLineRefresh = FALSE;
+ if (Line->Link.ForwardLink == HMainEditor.BufferImage->ListHead && Line->Size + Count < 0x10) {
+ //
+ // is at last line, and after paste will not exceed
+ // so only this line need to be refreshed
+ //
+ // if after add, the line is 0x10, then will append a new line
+ // so the whole page will need be refreshed
+ //
+ OnlyLineRefresh = TRUE;
+
+ }
+
+ FPos = 0x10 * (HMainEditor.BufferImage->BufferPosition.Row - 1) + HMainEditor.BufferImage->BufferPosition.Column - 1;
+
+ HBufferImageAddCharacterToBuffer (FPos, Count, Buffer);
+
+ if (OnlyLineRefresh) {
+ HBufferImageNeedRefresh = FALSE;
+ HBufferImageOnlyLineNeedRefresh = TRUE;
+ } else {
+ HBufferImageNeedRefresh = TRUE;
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+ }
+
+ if (!HMainEditor.BufferImage->Modified) {
+ HMainEditor.BufferImage->Modified = TRUE;
+ }
+
+ return EFI_SUCCESS;
+
+}
+
+/**
+ Exit editor.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation occured.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HMainCommandExit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Below is the scenario of Exit command:
+ // 1. IF currently opened file is not modified, exit the editor and
+ // Exit command ends.
+ // IF currently opened file is modified, do Step 2
+ //
+ // 2. An Input Bar will be prompted:
+ // "File modified. Save ( Yes/No/Cancel )?"
+ // IF user press 'y' or 'Y', currently opened file will be saved and
+ // Editor exits
+ // IF user press 'n' or 'N', currently opened file will not be saved
+ // and Editor exits.
+ // IF user press 'c' or 'C' or ESC, Exit command ends.
+ //
+ //
+ // if file has been modified, so will prompt user
+ // whether to save the changes
+ //
+ if (HMainEditor.BufferImage->Modified) {
+
+ Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ while (1) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString()[0]) {
+ case L'y':
+ case L'Y':
+ //
+ // write file back to disk
+ //
+ Status = HBufferImageSave (
+ HMainEditor.BufferImage->FileImage->FileName,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ HMainEditor.BufferImage->BufferType
+ );
+ if (!EFI_ERROR (Status)) {
+ HEditorExit = TRUE;
+ }
+
+ return Status;
+
+ case L'n':
+ case L'N':
+ HEditorExit = TRUE;
+ return EFI_SUCCESS;
+
+ case L'c':
+ case L'C':
+ return EFI_SUCCESS;
+
+ }
+ }
+ }
+
+ HEditorExit = TRUE;
+ return EFI_SUCCESS;
+
+}
+
+/**
+ Load a file from disk to editor.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation occured.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HMainCommandOpenFile (
+ VOID
+ )
+{
+ BOOLEAN Done;
+ EFI_STATUS Status;
+ EDIT_FILE_TYPE BufferType;
+
+ BufferType = HMainEditor.BufferImage->BufferType;
+
+ //
+ // This command will open a file from current working directory.
+ // Read-only file can also be opened. But it can not be modified.
+ // Below is the scenario of Open File command:
+ // 1. IF currently opened file has not been modified, directly go to step .
+ // IF currently opened file has been modified, an Input Bar will be
+ // prompted as :
+ // "File Modified. Save ( Yes/No/Cancel) ?"
+ // IF user press 'y' or 'Y', currently opened file will be saved.
+ // IF user press 'n' or 'N', currently opened file will
+ // not be saved.
+ // IF user press 'c' or 'C' or ESC, Open File command ends and
+ // currently opened file is still opened.
+ //
+ // 2. An Input Bar will be prompted as : "File Name to Open: "
+ // IF user press ESC, Open File command ends and
+ // currently opened file is still opened.
+ // Any other inputs with a Return will cause
+ // currently opened file close.
+ //
+ // 3. IF user input file name is an existing file ,
+ // this file will be read and opened.
+ // IF user input file name is a new file, this file will be created
+ // and opened. This file's type ( UNICODE or ASCII ) is the same with
+ // the old file.
+ //
+ //
+ // if current file is modified, so you need to choose whether to
+ // save it first.
+ //
+ if (HMainEditor.BufferImage->Modified) {
+
+ Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // the answer is just one character
+ //
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // loop for user's answer
+ // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'
+ //
+ Done = FALSE;
+ while (!Done) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString()[0]) {
+ case L'y':
+ case L'Y':
+ //
+ // want to save this buffer first
+ //
+ Status = HBufferImageSave (
+ HMainEditor.BufferImage->FileImage->FileName,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ HMainEditor.BufferImage->BufferType
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ MainTitleBarRefresh (
+ HMainEditor.BufferImage->BufferType == FileTypeFileBuffer?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Name:NULL,
+ HMainEditor.BufferImage->BufferType,
+ HMainEditor.BufferImage->FileImage->ReadOnly,
+ FALSE,
+ HMainEditor.ScreenSize.Column,
+ HMainEditor.ScreenSize.Row,
+ HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Offset:HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Offset:0,
+ HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Size :HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Size :0
+ );
+ Done = TRUE;
+ break;
+
+ case L'n':
+ case L'N':
+ //
+ // the file won't be saved
+ //
+ Done = TRUE;
+ break;
+
+ case L'c':
+ case L'C':
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ //
+ // TO get the open file name
+ //
+ Status = InputBarSetPrompt (L"File Name to Open: ");
+ if (EFI_ERROR (Status)) {
+ HBufferImageRead (
+ HMainEditor.BufferImage->FileImage->FileName,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ BufferType,
+ TRUE
+ );
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (100);
+ if (EFI_ERROR (Status)) {
+ Status = HBufferImageRead (
+ HMainEditor.BufferImage->FileImage->FileName,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ BufferType,
+ TRUE
+ );
+ return Status;
+ }
+
+ while (1) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ Status = HBufferImageRead (
+ HMainEditor.BufferImage->FileImage->FileName,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ BufferType,
+ TRUE
+ );
+
+ return Status;
+ }
+ //
+ // THE input string length should > 0
+ //
+ if (StrLen (InputBarGetString()) > 0) {
+ //
+ // CHECK if filename's valid
+ //
+ if (!IsValidFileName (InputBarGetString())) {
+ HBufferImageRead (
+ HMainEditor.BufferImage->FileImage->FileName,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ BufferType,
+ TRUE
+ );
+
+ StatusBarSetStatusString (L"Invalid File Name");
+ return EFI_SUCCESS;
+ }
+
+ break;
+ }
+ }
+ //
+ // read from disk
+ //
+ Status = HBufferImageRead (
+ InputBarGetString(),
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ FileTypeFileBuffer,
+ FALSE
+ );
+
+ if (EFI_ERROR (Status)) {
+ HBufferImageRead (
+ HMainEditor.BufferImage->FileImage->FileName,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ BufferType,
+ TRUE
+ );
+
+ return EFI_LOAD_ERROR;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Load a disk buffer editor.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation occured.
+ @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_NOT_FOUND The disk was not found.
+**/
+EFI_STATUS
+HMainCommandOpenDisk (
+ VOID
+ )
+{
+ UINT64 Size;
+ UINT64 Offset;
+ CHAR16 *DeviceName;
+ EFI_STATUS Status;
+ BOOLEAN Done;
+
+ EDIT_FILE_TYPE BufferType;
+
+ //
+ // variable initialization
+ //
+ Size = 0;
+ Offset = 0;
+ BufferType = HMainEditor.BufferImage->BufferType;
+
+ //
+ // if current file is modified, so you need to choose
+ // whether to save it first.
+ //
+ if (HMainEditor.BufferImage->Modified) {
+
+ Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // the answer is just one character
+ //
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // loop for user's answer
+ // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'
+ //
+ Done = FALSE;
+ while (!Done) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString()[0]) {
+ case L'y':
+ case L'Y':
+ //
+ // want to save this buffer first
+ //
+ Status = HBufferImageSave (
+ HMainEditor.BufferImage->FileImage->FileName,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ BufferType
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ MainTitleBarRefresh (
+ HMainEditor.BufferImage->BufferType == FileTypeFileBuffer?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Name:NULL,
+ HMainEditor.BufferImage->BufferType,
+ HMainEditor.BufferImage->FileImage->ReadOnly,
+ FALSE,
+ HMainEditor.ScreenSize.Column,
+ HMainEditor.ScreenSize.Row,
+ HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Offset:HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Offset:0,
+ HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Size :HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Size :0
+ );
+ Done = TRUE;
+ break;
+
+ case L'n':
+ case L'N':
+ //
+ // the file won't be saved
+ //
+ Done = TRUE;
+ break;
+
+ case L'c':
+ case L'C':
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ //
+ // get disk block device name
+ //
+ Status = InputBarSetPrompt (L"Block Device to Open: ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (100);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ while (1) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+
+ return EFI_SUCCESS;
+ }
+ //
+ // THE input string length should > 0
+ //
+ if (StrLen (InputBarGetString()) > 0) {
+ break;
+ }
+ }
+
+ DeviceName = CatSPrint(NULL, L"%s", InputBarGetString());
+ if (DeviceName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // get starting offset
+ //
+ Status = InputBarSetPrompt (L"First Block No.: ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (16);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ while (1) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+
+ return EFI_SUCCESS;
+ }
+ //
+ // THE input string length should > 0
+ //
+ if (StrLen (InputBarGetString()) > 0) {
+ Status = ShellConvertStringToUint64 (InputBarGetString(), &Offset, TRUE, FALSE);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ break;
+ }
+ }
+ //
+ // get Number of Blocks:
+ //
+ Status = InputBarSetPrompt (L"Number of Blocks: ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (8);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ while (1) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+
+ return EFI_SUCCESS;
+ }
+ //
+ // THE input string length should > 0
+ //
+ if (StrLen (InputBarGetString()) > 0) {
+ Status = ShellConvertStringToUint64 (InputBarGetString(), &Size, TRUE, FALSE);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if (Size == 0) {
+ continue;
+ }
+
+ break;
+ }
+ }
+
+ Status = HBufferImageRead (
+ NULL,
+ DeviceName,
+ (UINTN)Offset,
+ (UINTN)Size,
+ 0,
+ 0,
+ FileTypeDiskBuffer,
+ FALSE
+ );
+
+ if (EFI_ERROR (Status)) {
+
+ HBufferImageRead (
+ HMainEditor.BufferImage->FileImage->FileName,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ BufferType,
+ TRUE
+ );
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Load memory content to editor
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation occured.
+ @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_NOT_FOUND The disk was not found.
+**/
+EFI_STATUS
+HMainCommandOpenMemory (
+ VOID
+ )
+{
+ UINT64 Size;
+ UINT64 Offset;
+ EFI_STATUS Status;
+ BOOLEAN Done;
+ EDIT_FILE_TYPE BufferType;
+
+ //
+ // variable initialization
+ //
+ Size = 0;
+ Offset = 0;
+ BufferType = HMainEditor.BufferImage->BufferType;
+
+ //
+ // if current buffer is modified, so you need to choose
+ // whether to save it first.
+ //
+ if (HMainEditor.BufferImage->Modified) {
+
+ Status = InputBarSetPrompt (L"Buffer modified. Save (Yes/No/Cancel) ? ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // the answer is just one character
+ //
+ Status = InputBarSetStringSize (1);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // loop for user's answer
+ // valid answer is just 'y' 'Y', 'n' 'N', 'c' 'C'
+ //
+ Done = FALSE;
+ while (!Done) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+ return EFI_SUCCESS;
+ }
+
+ switch (InputBarGetString()[0]) {
+ case L'y':
+ case L'Y':
+ //
+ // want to save this buffer first
+ //
+ Status = HBufferImageSave (
+ HMainEditor.BufferImage->FileImage->FileName,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ BufferType
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ MainTitleBarRefresh (
+ HMainEditor.BufferImage->BufferType == FileTypeFileBuffer?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Name:NULL,
+ HMainEditor.BufferImage->BufferType,
+ HMainEditor.BufferImage->FileImage->ReadOnly,
+ FALSE,
+ HMainEditor.ScreenSize.Column,
+ HMainEditor.ScreenSize.Row,
+ HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Offset:HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Offset:0,
+ HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer?HMainEditor.BufferImage->DiskImage->Size :HMainEditor.BufferImage->BufferType == FileTypeMemBuffer?HMainEditor.BufferImage->MemImage->Size :0
+ );
+ Done = TRUE;
+ break;
+
+ case L'n':
+ case L'N':
+ //
+ // the file won't be saved
+ //
+ Done = TRUE;
+ break;
+
+ case L'c':
+ case L'C':
+ return EFI_SUCCESS;
+ }
+ }
+ }
+ //
+ // get starting offset
+ //
+ Status = InputBarSetPrompt (L"Starting Offset: ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (8);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ while (1) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+
+ return EFI_SUCCESS;
+ }
+ //
+ // THE input string length should > 0
+ //
+ if (StrLen (InputBarGetString()) > 0) {
+ Status = ShellConvertStringToUint64 (InputBarGetString(), &Offset, TRUE, FALSE);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ break;
+ }
+ }
+ //
+ // get Number of Blocks:
+ //
+ Status = InputBarSetPrompt (L"Buffer Size: ");
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = InputBarSetStringSize (8);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ while (1) {
+ Status = InputBarRefresh (HMainEditor.ScreenSize.Row, HMainEditor.ScreenSize.Column);
+
+ //
+ // ESC pressed
+ //
+ if (Status == EFI_NOT_READY) {
+
+ return EFI_SUCCESS;
+ }
+ //
+ // THE input string length should > 0
+ //
+ if (StrLen (InputBarGetString()) > 0) {
+ Status = ShellConvertStringToUint64 (InputBarGetString(), &Size, TRUE, FALSE);
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if (Size == 0) {
+ continue;
+ }
+
+ break;
+ }
+ }
+
+ if ((Offset + Size - 1)> 0xffffffff) {
+ StatusBarSetStatusString (L"Invalid parameter");
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = HBufferImageRead (
+ NULL,
+ NULL,
+ 0,
+ 0,
+ (UINTN)Offset,
+ (UINTN)Size,
+ FileTypeMemBuffer,
+ FALSE
+ );
+
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Read Device Error!");
+ HBufferImageRead (
+ HMainEditor.BufferImage->FileImage->FileName,
+ HMainEditor.BufferImage->DiskImage->Name,
+ HMainEditor.BufferImage->DiskImage->Offset,
+ HMainEditor.BufferImage->DiskImage->Size,
+ HMainEditor.BufferImage->MemImage->Offset,
+ HMainEditor.BufferImage->MemImage->Size,
+ BufferType,
+ TRUE
+ );
+ return EFI_NOT_FOUND;
+ }
+ return EFI_SUCCESS;
+
+}
+
+MENU_ITEM_FUNCTION HexMainControlBasedMenuFunctions[] = {
+ NULL,
+ NULL, /* Ctrl - A */
+ NULL, /* Ctrl - B */
+ NULL, /* Ctrl - C */
+ HMainCommandSelectEnd, /* Ctrl - D */
+ HMainCommandDisplayHelp, /* Ctrl - E */
+ NULL, /* Ctrl - F */
+ HMainCommandGoToOffset, /* Ctrl - G */
+ NULL, /* Ctrl - H */
+ HMainCommandOpenDisk, /* Ctrl - I */
+ NULL, /* Ctrl - J */
+ NULL, /* Ctrl - K */
+ NULL, /* Ctrl - L */
+ HMainCommandOpenMemory, /* Ctrl - M */
+ NULL, /* Ctrl - N */
+ HMainCommandOpenFile, /* Ctrl - O */
+ NULL, /* Ctrl - P */
+ HMainCommandExit, /* Ctrl - Q */
+ NULL, /* Ctrl - R */
+ HMainCommandSaveBuffer, /* Ctrl - S */
+ HMainCommandSelectStart, /* Ctrl - T */
+ NULL, /* Ctrl - U */
+ HMainCommandPaste, /* Ctrl - V */
+ NULL, /* Ctrl - W */
+ HMainCommandCut, /* Ctrl - X */
+ NULL, /* Ctrl - Y */
+ NULL, /* Ctrl - Z */
+};
+
+CONST EDITOR_MENU_ITEM HexEditorMenuItems[] = {
+ {
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_GO_TO_OFFSET),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F1),
+ HMainCommandGoToOffset
+ },
+ {
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_SAVE_BUFFER),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F2),
+ HMainCommandSaveBuffer
+ },
+ {
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_EXIT),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F3),
+ HMainCommandExit
+ },
+
+ {
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_SELECT_START),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F4),
+ HMainCommandSelectStart
+ },
+ {
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_SELECT_END),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F5),
+ HMainCommandSelectEnd
+ },
+ {
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_CUT),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F6),
+ HMainCommandCut
+ },
+ {
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_PASTE),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F7),
+ HMainCommandPaste
+ },
+
+ {
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_OPEN_FILE),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F8),
+ HMainCommandOpenFile
+ },
+ {
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_OPEN_DISK),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F9),
+ HMainCommandOpenDisk
+ },
+ {
+ STRING_TOKEN(STR_HEXEDIT_LIBMENUBAR_OPEN_MEMORY),
+ STRING_TOKEN(STR_EDIT_LIBMENUBAR_F10),
+ HMainCommandOpenMemory
+ },
+
+ {
+ 0,
+ 0,
+ NULL
+ }
+};
+
+/**
+ Init function for MainEditor
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HMainEditorInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleCount;
+ UINTN Index;
+
+ //
+ // basic initialization
+ //
+ CopyMem (&HMainEditor, &HMainEditorConst, sizeof (HMainEditor));
+
+ //
+ // set screen attributes
+ //
+ HMainEditor.ColorAttributes.Colors.Foreground = gST->ConOut->Mode->Attribute & 0x000000ff;
+
+ HMainEditor.ColorAttributes.Colors.Background = (UINT8) (gST->ConOut->Mode->Attribute >> 4);
+
+ HOriginalColors = HMainEditor.ColorAttributes.Colors;
+
+ HOriginalMode = gST->ConOut->Mode->Mode;
+
+ //
+ // query screen size
+ //
+ gST->ConOut->QueryMode (
+ gST->ConOut,
+ gST->ConOut->Mode->Mode,
+ &(HMainEditor.ScreenSize.Column),
+ &(HMainEditor.ScreenSize.Row)
+ );
+
+ //
+ // Find mouse in System Table ConsoleInHandle
+ //
+ Status = gBS->HandleProtocol (
+ gST->ConIn,
+ &gEfiSimplePointerProtocolGuid,
+ (VOID**)&HMainEditor.MouseInterface
+ );
+ if (EFI_ERROR (Status)) {
+ //
+ // If there is no Simple Pointer Protocol on System Table
+ //
+ HandleBuffer = NULL;
+ HMainEditor.MouseInterface = NULL;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiSimplePointerProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (!EFI_ERROR (Status) && HandleCount > 0) {
+ //
+ // Try to find the first available mouse device
+ //
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiSimplePointerProtocolGuid,
+ (VOID**)&HMainEditor.MouseInterface
+ );
+ if (!EFI_ERROR (Status)) {
+ break;
+ }
+ }
+ }
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+ }
+
+ if (!EFI_ERROR (Status) && HMainEditor.MouseInterface != NULL) {
+ HMainEditor.MouseAccumulatorX = 0;
+ HMainEditor.MouseAccumulatorY = 0;
+ HMainEditor.MouseSupported = TRUE;
+ }
+
+ //
+ // below will call the five components' init function
+ //
+ Status = MainTitleBarInit (L"UEFI HEXEDIT");
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_TITLE), gShellDebug1HiiHandle);
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = ControlHotKeyInit (HexMainControlBasedMenuFunctions);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_MAINMENU), gShellDebug1HiiHandle);
+ return EFI_LOAD_ERROR;
+ }
+ Status = MenuBarInit (HexEditorMenuItems);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_MAINMENU), gShellDebug1HiiHandle);
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = StatusBarInit ();
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_STATUS), gShellDebug1HiiHandle);
+ return EFI_LOAD_ERROR;
+ }
+
+ InputBarInit ();
+
+ Status = HBufferImageInit ();
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_BUFFERIMAGE), gShellDebug1HiiHandle);
+ return EFI_LOAD_ERROR;
+ }
+
+ Status = HClipBoardInit ();
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_MAINEDITOR_CLIPBOARD), gShellDebug1HiiHandle);
+ return EFI_LOAD_ERROR;
+ }
+ //
+ // clear whole screen and enable cursor
+ //
+ gST->ConOut->ClearScreen (gST->ConOut);
+ gST->ConOut->EnableCursor (gST->ConOut, TRUE);
+
+ //
+ // initialize EditorFirst and EditorExit
+ //
+ HEditorFirst = TRUE;
+ HEditorExit = FALSE;
+ HEditorMouseAction = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Cleanup function for MainEditor.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HMainEditorCleanup (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // call the five components' cleanup function
+ //
+ MainTitleBarCleanup ();
+
+ MenuBarCleanup ();
+
+ StatusBarCleanup ();
+
+ InputBarCleanup ();
+
+ Status = HBufferImageCleanup ();
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_BUFFERIMAGE_CLEAN), gShellDebug1HiiHandle);
+ }
+
+ Status = HClipBoardCleanup ();
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HEXEDIT_LIBEDITOR_CLIPBOARD_CLEAN), gShellDebug1HiiHandle);
+ }
+ //
+ // restore old mode
+ //
+ if (HOriginalMode != gST->ConOut->Mode->Mode) {
+ gST->ConOut->SetMode (gST->ConOut, HOriginalMode);
+ }
+
+ gST->ConOut->SetAttribute (
+ gST->ConOut,
+ EFI_TEXT_ATTR (HOriginalColors.Foreground, HOriginalColors.Background)
+ );
+ gST->ConOut->ClearScreen (gST->ConOut);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Refresh function for MainEditor.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HMainEditorRefresh (
+ VOID
+ )
+{
+ BOOLEAN NameChange;
+ BOOLEAN ReadChange;
+
+ NameChange = FALSE;
+ ReadChange = FALSE;
+
+ if (HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer) {
+ if (HMainEditor.BufferImage->DiskImage != NULL &&
+ HBufferImageBackupVar.DiskImage != NULL &&
+ (HMainEditor.BufferImage->DiskImage->Offset != HBufferImageBackupVar.DiskImage->Offset ||
+ HMainEditor.BufferImage->DiskImage->Size != HBufferImageBackupVar.DiskImage->Size) ){
+ NameChange = TRUE;
+ }
+ } else if (HMainEditor.BufferImage->BufferType == FileTypeMemBuffer) {
+ if (HMainEditor.BufferImage->MemImage != NULL &&
+ HBufferImageBackupVar.MemImage != NULL &&
+ (HMainEditor.BufferImage->MemImage->Offset != HBufferImageBackupVar.MemImage->Offset ||
+ HMainEditor.BufferImage->MemImage->Size != HBufferImageBackupVar.MemImage->Size) ){
+ NameChange = TRUE;
+ }
+ } else if (HMainEditor.BufferImage->BufferType == FileTypeFileBuffer) {
+ if ( HMainEditor.BufferImage->FileImage != NULL &&
+ HMainEditor.BufferImage->FileImage->FileName != NULL &&
+ HBufferImageBackupVar.FileImage != NULL &&
+ HBufferImageBackupVar.FileImage->FileName != NULL &&
+ StrCmp (HMainEditor.BufferImage->FileImage->FileName, HBufferImageBackupVar.FileImage->FileName) != 0 ) {
+ NameChange = TRUE;
+ }
+ }
+ if ( HMainEditor.BufferImage->FileImage != NULL &&
+ HBufferImageBackupVar.FileImage != NULL &&
+ HMainEditor.BufferImage->FileImage->ReadOnly != HBufferImageBackupVar.FileImage->ReadOnly ) {
+ ReadChange = TRUE;
+ }
+
+ //
+ // to aVOID screen flicker
+ // the stall value is from experience
+ //
+ gBS->Stall (50);
+
+ //
+ // call the components refresh function
+ //
+ if (HEditorFirst
+ || NameChange
+ || HMainEditor.BufferImage->BufferType != HBufferImageBackupVar.BufferType
+ || HBufferImageBackupVar.Modified != HMainEditor.BufferImage->Modified
+ || ReadChange ) {
+
+ MainTitleBarRefresh (
+ HMainEditor.BufferImage->BufferType == FileTypeFileBuffer&&HMainEditor.BufferImage->FileImage!=NULL?HMainEditor.BufferImage->FileImage->FileName:HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer&&HMainEditor.BufferImage->DiskImage!=NULL?HMainEditor.BufferImage->DiskImage->Name:NULL,
+ HMainEditor.BufferImage->BufferType,
+ (BOOLEAN)(HMainEditor.BufferImage->FileImage!=NULL?HMainEditor.BufferImage->FileImage->ReadOnly:FALSE),
+ HMainEditor.BufferImage->Modified,
+ HMainEditor.ScreenSize.Column,
+ HMainEditor.ScreenSize.Row,
+ HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer&&HMainEditor.BufferImage->DiskImage!=NULL?HMainEditor.BufferImage->DiskImage->Offset:HMainEditor.BufferImage->BufferType == FileTypeMemBuffer&&HMainEditor.BufferImage->MemImage!=NULL?HMainEditor.BufferImage->MemImage->Offset:0,
+ HMainEditor.BufferImage->BufferType == FileTypeDiskBuffer&&HMainEditor.BufferImage->DiskImage!=NULL?HMainEditor.BufferImage->DiskImage->Size :HMainEditor.BufferImage->BufferType == FileTypeMemBuffer&&HMainEditor.BufferImage->MemImage!=NULL?HMainEditor.BufferImage->MemImage->Size :0
+ );
+ HBufferImageRefresh ();
+ }
+ if (HEditorFirst
+ || HBufferImageBackupVar.DisplayPosition.Row != HMainEditor.BufferImage->DisplayPosition.Row
+ || HBufferImageBackupVar.DisplayPosition.Column != HMainEditor.BufferImage->DisplayPosition.Column
+ || StatusBarGetRefresh()) {
+
+ StatusBarRefresh (
+ HEditorFirst,
+ HMainEditor.ScreenSize.Row,
+ HMainEditor.ScreenSize.Column,
+ (UINTN)(-1),
+ (UINTN)(-1),
+ FALSE
+ );
+ HBufferImageRefresh ();
+ }
+
+ if (HEditorFirst) {
+ HBufferImageRefresh ();
+ }
+
+ //
+ // EditorFirst is now set to FALSE
+ //
+ HEditorFirst = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Handle the mouse input.
+
+ @param[in] MouseState The current mouse state.
+ @param[out] BeforeLeftButtonDown helps with selections.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation occured.
+ @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_NOT_FOUND The disk was not found.
+**/
+EFI_STATUS
+HMainEditorHandleMouseInput (
+ IN EFI_SIMPLE_POINTER_STATE MouseState,
+ OUT BOOLEAN *BeforeLeftButtonDown
+ )
+{
+
+ INT32 TextX;
+ INT32 TextY;
+ UINTN FRow;
+ UINTN FCol;
+ BOOLEAN HighBits;
+ LIST_ENTRY *Link;
+ HEFI_EDITOR_LINE *Line;
+ UINTN Index;
+ BOOLEAN Action;
+
+ Action = FALSE;
+
+ //
+ // have mouse movement
+ //
+ if (MouseState.RelativeMovementX || MouseState.RelativeMovementY) {
+ //
+ // handle
+ //
+ TextX = HGetTextX (MouseState.RelativeMovementX);
+ TextY = HGetTextY (MouseState.RelativeMovementY);
+
+ HBufferImageAdjustMousePosition (TextX, TextY);
+
+ Action = TRUE;
+
+ }
+
+ if (MouseState.LeftButton) {
+ HighBits = HBufferImageIsAtHighBits (
+ HMainEditor.BufferImage->MousePosition.Column,
+ &FCol
+ );
+
+ //
+ // not at an movable place
+ //
+ if (FCol == 0) {
+ //
+ // now just move mouse pointer to legal position
+ //
+ //
+ // move mouse position to legal position
+ //
+ HMainEditor.BufferImage->MousePosition.Column -= 10;
+ if (HMainEditor.BufferImage->MousePosition.Column > 24) {
+ HMainEditor.BufferImage->MousePosition.Column--;
+ FCol = HMainEditor.BufferImage->MousePosition.Column / 3 + 1 + 1;
+ } else {
+ if (HMainEditor.BufferImage->MousePosition.Column < 24) {
+ FCol = HMainEditor.BufferImage->MousePosition.Column / 3 + 1 + 1;
+ } else {
+ //
+ // == 24
+ //
+ FCol = 9;
+ }
+ }
+
+ HighBits = TRUE;
+
+ }
+
+ FRow = HMainEditor.BufferImage->BufferPosition.Row +
+ HMainEditor.BufferImage->MousePosition.Row -
+ HMainEditor.BufferImage->DisplayPosition.Row;
+
+ if (HMainEditor.BufferImage->NumLines < FRow) {
+ //
+ // dragging
+ //
+ //
+ // now just move mouse pointer to legal position
+ //
+ FRow = HMainEditor.BufferImage->NumLines;
+ HighBits = TRUE;
+ }
+
+ Link = HMainEditor.BufferImage->ListHead->ForwardLink;
+ for (Index = 0; Index < FRow - 1; Index++) {
+ Link = Link->ForwardLink;
+ }
+
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+
+ //
+ // dragging
+ //
+ //
+ // now just move mouse pointer to legal position
+ //
+ if (FCol > Line->Size) {
+ if (*BeforeLeftButtonDown) {
+ HighBits = FALSE;
+
+ if (Line->Size == 0) {
+ if (FRow > 1) {
+ FRow--;
+ FCol = 16;
+ } else {
+ FRow = 1;
+ FCol = 1;
+ }
+
+ } else {
+ FCol = Line->Size;
+ }
+ } else {
+ FCol = Line->Size + 1;
+ HighBits = TRUE;
+ }
+ }
+
+ HBufferImageMovePosition (FRow, FCol, HighBits);
+
+ HMainEditor.BufferImage->MousePosition.Row = HMainEditor.BufferImage->DisplayPosition.Row;
+
+ HMainEditor.BufferImage->MousePosition.Column = HMainEditor.BufferImage->DisplayPosition.Column;
+
+ *BeforeLeftButtonDown = TRUE;
+
+ Action = TRUE;
+ } else {
+ //
+ // else of if LButton
+ //
+ // release LButton
+ //
+ if (*BeforeLeftButtonDown) {
+ Action = TRUE;
+ }
+ //
+ // mouse up
+ //
+ *BeforeLeftButtonDown = FALSE;
+ }
+
+ if (Action) {
+ return EFI_SUCCESS;
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Handle user key input. will route it to other components handle function.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation occured.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HMainEditorKeyInput (
+ VOID
+ )
+{
+ EFI_INPUT_KEY Key;
+ EFI_STATUS Status;
+ EFI_SIMPLE_POINTER_STATE MouseState;
+ BOOLEAN LengthChange;
+ UINTN Size;
+ UINTN OldSize;
+ BOOLEAN BeforeMouseIsDown;
+ BOOLEAN MouseIsDown;
+ BOOLEAN FirstDown;
+ BOOLEAN MouseDrag;
+ UINTN FRow;
+ UINTN FCol;
+ UINTN SelectStartBackup;
+ UINTN SelectEndBackup;
+
+ //
+ // variable initialization
+ //
+ OldSize = 0;
+ FRow = 0;
+ FCol = 0;
+ LengthChange = FALSE;
+
+ MouseIsDown = FALSE;
+ FirstDown = FALSE;
+ MouseDrag = FALSE;
+
+ do {
+
+ Status = EFI_SUCCESS;
+
+ HEditorMouseAction = FALSE;
+
+ //
+ // backup some key elements, so that can aVOID some refresh work
+ //
+ HMainEditorBackup ();
+
+ //
+ // wait for user key input
+ //
+ //
+ // change priority of checking mouse/keyboard activity dynamically
+ // so prevent starvation of keyboard.
+ // if last time, mouse moves then this time check keyboard
+ //
+ if (HMainEditor.MouseSupported) {
+ Status = HMainEditor.MouseInterface->GetState (
+ HMainEditor.MouseInterface,
+ &MouseState
+ );
+ if (!EFI_ERROR (Status)) {
+
+ BeforeMouseIsDown = MouseIsDown;
+
+ Status = HMainEditorHandleMouseInput (MouseState, &MouseIsDown);
+
+ if (!EFI_ERROR (Status)) {
+ if (!BeforeMouseIsDown) {
+ //
+ // mouse down
+ //
+ if (MouseIsDown) {
+ FRow = HBufferImage.BufferPosition.Row;
+ FCol = HBufferImage.BufferPosition.Column;
+ SelectStartBackup = HMainEditor.SelectStart;
+ SelectEndBackup = HMainEditor.SelectEnd;
+
+ FirstDown = TRUE;
+ }
+ } else {
+
+ SelectStartBackup = HMainEditor.SelectStart;
+ SelectEndBackup = HMainEditor.SelectEnd;
+
+ //
+ // begin to drag
+ //
+ if (MouseIsDown) {
+ if (FirstDown) {
+ if (MouseState.RelativeMovementX || MouseState.RelativeMovementY) {
+ HMainEditor.SelectStart = 0;
+ HMainEditor.SelectEnd = 0;
+ HMainEditor.SelectStart = (FRow - 1) * 0x10 + FCol;
+
+ MouseDrag = TRUE;
+ FirstDown = FALSE;
+ }
+ } else {
+ if ((
+ (HBufferImage.BufferPosition.Row - 1) *
+ 0x10 +
+ HBufferImage.BufferPosition.Column
+ ) >= HMainEditor.SelectStart
+ ) {
+ HMainEditor.SelectEnd = (HBufferImage.BufferPosition.Row - 1) *
+ 0x10 +
+ HBufferImage.BufferPosition.Column;
+ } else {
+ HMainEditor.SelectEnd = 0;
+ }
+ }
+ //
+ // end of if RelativeX/Y
+ //
+ } else {
+ //
+ // mouse is up
+ //
+ if (MouseDrag) {
+ if (HBufferImageGetTotalSize () == 0) {
+ HMainEditor.SelectStart = 0;
+ HMainEditor.SelectEnd = 0;
+ FirstDown = FALSE;
+ MouseDrag = FALSE;
+ }
+
+ if ((
+ (HBufferImage.BufferPosition.Row - 1) *
+ 0x10 +
+ HBufferImage.BufferPosition.Column
+ ) >= HMainEditor.SelectStart
+ ) {
+ HMainEditor.SelectEnd = (HBufferImage.BufferPosition.Row - 1) *
+ 0x10 +
+ HBufferImage.BufferPosition.Column;
+ } else {
+ HMainEditor.SelectEnd = 0;
+ }
+
+ if (HMainEditor.SelectEnd == 0) {
+ HMainEditor.SelectStart = 0;
+ }
+ }
+
+ FirstDown = FALSE;
+ MouseDrag = FALSE;
+ }
+
+ if (SelectStartBackup != HMainEditor.SelectStart || SelectEndBackup != HMainEditor.SelectEnd) {
+ if ((SelectStartBackup - 1) / 0x10 != (HMainEditor.SelectStart - 1) / 0x10) {
+ HBufferImageNeedRefresh = TRUE;
+ } else {
+ if ((SelectEndBackup - 1) / 0x10 != (HMainEditor.SelectEnd - 1) / 0x10) {
+ HBufferImageNeedRefresh = TRUE;
+ } else {
+ HBufferImageOnlyLineNeedRefresh = TRUE;
+ }
+ }
+ }
+ }
+
+ HEditorMouseAction = TRUE;
+ HBufferImageMouseNeedRefresh = TRUE;
+
+ } else if (Status == EFI_LOAD_ERROR) {
+ StatusBarSetStatusString (L"Invalid Mouse Movement ");
+ }
+ }
+ }
+
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ if (!EFI_ERROR (Status)) {
+ //
+ // dispatch to different components' key handling function
+ // so not everywhere has to set this variable
+ //
+ HBufferImageMouseNeedRefresh = TRUE;
+
+ //
+ // clear previous status string
+ //
+ StatusBarSetRefresh();
+ if (EFI_SUCCESS == MenuBarDispatchControlHotKey(&Key)) {
+ Status = EFI_SUCCESS;
+ } else if (Key.ScanCode == SCAN_NULL) {
+ Status = HBufferImageHandleInput (&Key);
+ } else if (((Key.ScanCode >= SCAN_UP) && (Key.ScanCode <= SCAN_PAGE_DOWN))) {
+ Status = HBufferImageHandleInput (&Key);
+ } else if (((Key.ScanCode >= SCAN_F1) && Key.ScanCode <= (SCAN_F12))) {
+ Status = MenuBarDispatchFunctionKey (&Key);
+ } else {
+ StatusBarSetStatusString (L"Unknown Command");
+
+ HBufferImageMouseNeedRefresh = FALSE;
+ }
+
+ if (Status != EFI_SUCCESS && Status != EFI_OUT_OF_RESOURCES) {
+ //
+ // not already has some error status
+ //
+ if (StrCmp (L"", StatusBarGetString()) == 0) {
+ StatusBarSetStatusString (L"Disk Error. Try Again");
+ }
+ }
+ }
+ //
+ // decide if has to set length warning
+ //
+ if (HBufferImage.BufferType != HBufferImageBackupVar.BufferType) {
+ LengthChange = FALSE;
+ } else {
+ //
+ // still the old buffer
+ //
+ if (HBufferImage.BufferType != FileTypeFileBuffer) {
+ Size = HBufferImageGetTotalSize ();
+
+ switch (HBufferImage.BufferType) {
+ case FileTypeDiskBuffer:
+ OldSize = HBufferImage.DiskImage->Size * HBufferImage.DiskImage->BlockSize;
+ break;
+
+ case FileTypeMemBuffer:
+ OldSize = HBufferImage.MemImage->Size;
+ break;
+
+ default:
+ OldSize = 0;
+ break;
+ }
+
+ if (!LengthChange) {
+ if (OldSize != Size) {
+ StatusBarSetStatusString (L"Disk/Mem Buffer Length should not be changed");
+ }
+ }
+
+ if (OldSize != Size) {
+ LengthChange = TRUE;
+ } else {
+ LengthChange = FALSE;
+ }
+ }
+ }
+ //
+ // after handling, refresh editor
+ //
+ HMainEditorRefresh ();
+
+ } while (Status != EFI_OUT_OF_RESOURCES && !HEditorExit);
+
+ return Status;
+}
+
+/**
+ Backup function for MainEditor.
+**/
+VOID
+EFIAPI
+HMainEditorBackup (
+ VOID
+ )
+{
+ HMainEditorBackupVar.SelectStart = HMainEditor.SelectStart;
+ HMainEditorBackupVar.SelectEnd = HMainEditor.SelectEnd;
+ HBufferImageBackup ();
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.h
new file mode 100644
index 0000000000..ad9a7b4be8
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MainHexEditor.h
@@ -0,0 +1,76 @@
+/** @file
+ Defines the Main Editor data type -
+ - Global variables
+ - Instances of the other objects of the editor
+ - Main Interfaces
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LIB_EDITOR_H_
+#define _LIB_EDITOR_H_
+
+#include "HexEditor.h"
+
+/**
+ Init function for MainEditor
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HMainEditorInit (
+ VOID
+ );
+
+/**
+ Cleanup function for MainEditor.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HMainEditorCleanup (
+ VOID
+ );
+
+/**
+ Refresh function for MainEditor.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HMainEditorRefresh (
+ VOID
+ );
+
+/**
+ Handle user key input. will route it to other components handle function.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation occured.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HMainEditorKeyInput (
+ VOID
+ );
+
+/**
+ Backup function for MainEditor.
+**/
+VOID
+EFIAPI
+HMainEditorBackup (
+ VOID
+ );
+
+#endif
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.c
new file mode 100644
index 0000000000..300c67f0d4
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.c
@@ -0,0 +1,345 @@
+/** @file
+ Functions to deal with Mem buffer
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HexEditor.h"
+
+extern EFI_HANDLE HImageHandleBackup;
+
+extern HEFI_EDITOR_BUFFER_IMAGE HBufferImage;
+
+extern BOOLEAN HBufferImageNeedRefresh;
+extern BOOLEAN HBufferImageOnlyLineNeedRefresh;
+extern BOOLEAN HBufferImageMouseNeedRefresh;
+
+extern HEFI_EDITOR_GLOBAL_EDITOR HMainEditor;
+
+HEFI_EDITOR_MEM_IMAGE HMemImage;
+HEFI_EDITOR_MEM_IMAGE HMemImageBackupVar;
+
+EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL DummyPciRootBridgeIo;
+
+//
+// for basic initialization of HDiskImage
+//
+HEFI_EDITOR_MEM_IMAGE HMemImageConst = {
+ NULL,
+ 0,
+ 0
+};
+
+/**
+ Empty function. always returns the same.
+
+ @param[in] This Ignored.
+ @param[in] Width Ignored.
+ @param[in] Address Ignored.
+ @param[in] Count Ignored.
+ @param[in, out] Buffer Ignored.
+
+ @retval EFI_UNSUPPORTED.
+**/
+EFI_STATUS
+EFIAPI
+DummyMemRead (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Empty function. always returns the same.
+
+ @param[in] This Ignored.
+ @param[in] Width Ignored.
+ @param[in] Address Ignored.
+ @param[in] Count Ignored.
+ @param[in, out] Buffer Ignored.
+
+ @retval EFI_UNSUPPORTED.
+**/
+EFI_STATUS
+EFIAPI
+DummyMemWrite (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL * This,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH Width,
+ IN UINT64 Address,
+ IN UINTN Count,
+ IN OUT VOID *Buffer
+ )
+{
+ return EFI_UNSUPPORTED;
+}
+
+/**
+ Initialization function for HDiskImage.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HMemImageInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // basically initialize the HMemImage
+ //
+ CopyMem (&HMemImage, &HMemImageConst, sizeof (HMemImage));
+
+ Status = gBS->LocateProtocol (
+ &gEfiPciRootBridgeIoProtocolGuid,
+ NULL,
+ (VOID**)&HMemImage.IoFncs
+ );
+ if (Status == EFI_NOT_FOUND) {
+ //
+ // For NT32, no EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL is available
+ // Use Dummy PciRootBridgeIo for memory access
+ //
+ ZeroMem (&DummyPciRootBridgeIo, sizeof (EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL));
+ DummyPciRootBridgeIo.Mem.Read = DummyMemRead;
+ DummyPciRootBridgeIo.Mem.Write = DummyMemWrite;
+ HMemImage.IoFncs = &DummyPciRootBridgeIo;
+ Status = EFI_SUCCESS;
+ }
+ if (!EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_LOAD_ERROR;
+ }
+}
+
+/**
+ Backup function for HDiskImage. Only a few fields need to be backup.
+ This is for making the Disk buffer refresh as few as possible.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HMemImageBackup (
+ VOID
+ )
+{
+ HMemImageBackupVar.Offset = HMemImage.Offset;
+ HMemImageBackupVar.Size = HMemImage.Size;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Set FileName field in HFileImage.
+
+ @param[in] Offset The offset.
+ @param[in] Size The size.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+HMemImageSetMemOffsetSize (
+ IN UINTN Offset,
+ IN UINTN Size
+ )
+{
+
+ HMemImage.Offset = Offset;
+ HMemImage.Size = Size;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Read a disk from disk into HBufferImage.
+
+ @param[in] Offset The offset.
+ @param[in] Size The size.
+ @param[in] Recover if is for recover, no information print.
+
+ @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+HMemImageRead (
+ IN UINTN Offset,
+ IN UINTN Size,
+ IN BOOLEAN Recover
+ )
+{
+
+ EFI_STATUS Status;
+ void *Buffer;
+ CHAR16 *Str;
+ HEFI_EDITOR_LINE *Line;
+
+ HBufferImage.BufferType = FileTypeMemBuffer;
+
+ Buffer = AllocateZeroPool (Size);
+ if (Buffer == NULL) {
+ StatusBarSetStatusString (L"Read Memory Failed");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = HMemImage.IoFncs->Mem.Read (
+ HMemImage.IoFncs,
+ EfiPciWidthUint8,
+ Offset,
+ Size,
+ Buffer
+ );
+
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ StatusBarSetStatusString (L"Memory Specified Not Accessible");
+ return EFI_LOAD_ERROR;
+ }
+
+ HBufferImageFree ();
+
+ Status = HBufferImageBufferToList (Buffer, Size);
+ FreePool (Buffer);
+
+ if (EFI_ERROR (Status)) {
+ StatusBarSetStatusString (L"Read Memory Failed");
+ return Status;
+ }
+
+ Status = HMemImageSetMemOffsetSize (Offset, Size);
+
+ HBufferImage.DisplayPosition.Row = 2;
+ HBufferImage.DisplayPosition.Column = 10;
+
+ HBufferImage.MousePosition.Row = 2;
+ HBufferImage.MousePosition.Column = 10;
+
+ HBufferImage.LowVisibleRow = 1;
+ HBufferImage.HighBits = TRUE;
+
+ HBufferImage.BufferPosition.Row = 1;
+ HBufferImage.BufferPosition.Column = 1;
+
+ if (!Recover) {
+ Str = CatSPrint(NULL, L"%d Lines Read", HBufferImage.NumLines);
+ if (Str == NULL) {
+ StatusBarSetStatusString (L"Read Memory Failed");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ StatusBarSetStatusString (Str);
+ SHELL_FREE_NON_NULL (Str);
+
+ HMainEditor.SelectStart = 0;
+ HMainEditor.SelectEnd = 0;
+
+ }
+
+ //
+ // has line
+ //
+ if (HBufferImage.Lines != NULL) {
+ HBufferImage.CurrentLine = CR (HBufferImage.ListHead->ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+ } else {
+ //
+ // create a dummy line
+ //
+ Line = HBufferImageCreateLine ();
+ if (Line == NULL) {
+ StatusBarSetStatusString (L"Read Memory Failed");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ HBufferImage.CurrentLine = Line;
+ }
+
+ HBufferImage.Modified = FALSE;
+ HBufferImageNeedRefresh = TRUE;
+ HBufferImageOnlyLineNeedRefresh = FALSE;
+ HBufferImageMouseNeedRefresh = TRUE;
+
+ return EFI_SUCCESS;
+
+}
+
+/**
+ Save lines in HBufferImage to disk.
+
+ @param[in] Offset The offset.
+ @param[in] Size The size.
+
+ @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+HMemImageSave (
+ IN UINTN Offset,
+ IN UINTN Size
+ )
+{
+
+ EFI_STATUS Status;
+ VOID *Buffer;
+
+ //
+ // not modified, so directly return
+ //
+ if (HBufferImage.Modified == FALSE) {
+ return EFI_SUCCESS;
+ }
+
+ HBufferImage.BufferType = FileTypeMemBuffer;
+
+ Buffer = AllocateZeroPool (Size);
+
+ if (Buffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = HBufferImageListToBuffer (Buffer, Size);
+ if (EFI_ERROR (Status)) {
+ FreePool (Buffer);
+ return Status;
+ }
+ //
+ // write back to memory
+ //
+ Status = HMemImage.IoFncs->Mem.Write (
+ HMemImage.IoFncs,
+ EfiPciWidthUint8,
+ Offset,
+ Size,
+ Buffer
+ );
+
+ FreePool (Buffer);
+
+ if (EFI_ERROR (Status)) {
+ return EFI_LOAD_ERROR;
+ }
+ //
+ // now not modified
+ //
+ HBufferImage.Modified = FALSE;
+
+ return EFI_SUCCESS;
+}
+
+
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.h
new file mode 100644
index 0000000000..54fe517858
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/MemImage.h
@@ -0,0 +1,92 @@
+/** @file
+ Defines MemImage - the view of the file that is visible at any point,
+ as well as the event handlers for editing the file
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LIB_MEM_IMAGE_H_
+#define _LIB_MEM_IMAGE_H_
+
+#include "HexEditor.h"
+
+/**
+ Initialization function for HDiskImage.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_LOAD_ERROR A load error occured.
+**/
+EFI_STATUS
+HMemImageInit (
+ VOID
+ );
+
+/**
+ Backup function for HDiskImage. Only a few fields need to be backup.
+ This is for making the Disk buffer refresh as few as possible.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HMemImageBackup (
+ VOID
+ );
+
+/**
+ Set FileName field in HFileImage.
+
+ @param[in] Offset The offset.
+ @param[in] Size The size.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+HMemImageSetMemOffsetSize (
+ IN UINTN Offset,
+ IN UINTN Size
+ );
+
+/**
+ Read a disk from disk into HBufferImage.
+
+ @param[in] Offset The offset.
+ @param[in] Size The size.
+ @param[in] Recover if is for recover, no information print.
+
+ @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+HMemImageRead (
+ IN UINTN Offset,
+ IN UINTN Size,
+ IN BOOLEAN Recover
+ );
+
+/**
+ Save lines in HBufferImage to disk.
+
+ @param[in] Offset The offset.
+ @param[in] Size The size.
+
+ @retval EFI_LOAD_ERROR A load error occured.
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+HMemImageSave (
+ IN UINTN Offset,
+ IN UINTN Size
+ );
+
+#endif
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.c
new file mode 100644
index 0000000000..c3ed341936
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.c
@@ -0,0 +1,262 @@
+/** @file
+ Implementation of various string and line routines
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "HexEditor.h"
+
+extern BOOLEAN HEditorMouseAction;
+
+/**
+ Free a line and it's internal buffer.
+
+ @param[in] Src The line to be freed.
+**/
+VOID
+HLineFree (
+ IN HEFI_EDITOR_LINE *Src
+ )
+{
+ if (Src == NULL) {
+ return ;
+ }
+
+ SHELL_FREE_NON_NULL (Src);
+
+}
+
+/**
+ Advance to the next Count lines.
+
+ @param[in] Count The line number to advance.
+
+ @retval NULL An error occured.
+ @return A pointer to the line after advance.
+**/
+HEFI_EDITOR_LINE *
+HLineAdvance (
+ IN UINTN Count
+ )
+{
+ UINTN Index;
+ HEFI_EDITOR_LINE *Line;
+
+ Line = HMainEditor.BufferImage->CurrentLine;
+ if (Line == NULL) {
+ return NULL;
+ }
+
+ for (Index = 0; Index < Count; Index++) {
+ //
+ // if already last line
+ //
+ if (Line->Link.ForwardLink == HMainEditor.BufferImage->ListHead) {
+ return NULL;
+ }
+
+ Line = CR (Line->Link.ForwardLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+ }
+
+ return Line;
+}
+
+/**
+ Retreat to the previous Count lines.
+
+ @param[in] Count The line number to retreat.
+
+ @retval NULL An error occured.
+ @return A pointer to the line after retreat.
+**/
+HEFI_EDITOR_LINE *
+HLineRetreat (
+ IN UINTN Count
+ )
+{
+ UINTN Index;
+ HEFI_EDITOR_LINE *Line;
+
+ Line = HMainEditor.BufferImage->CurrentLine;
+ if (Line == NULL) {
+ return NULL;
+ }
+
+ for (Index = 0; Index < Count; Index++) {
+ //
+ // already the first line
+ //
+ if (Line->Link.BackLink == HMainEditor.BufferImage->ListHead) {
+ return NULL;
+ }
+
+ Line = CR (Line->Link.BackLink, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+ }
+
+ return Line;
+}
+
+/**
+ Advance/Retreat lines.
+
+ @param[in] Count The line number to advance/retreat.
+ >0 : advance
+ <0: retreat
+
+ @retval NULL An error occured.
+ @return A pointer to the line after move.
+**/
+HEFI_EDITOR_LINE *
+HMoveLine (
+ IN INTN Count
+ )
+{
+ HEFI_EDITOR_LINE *Line;
+ UINTN AbsCount;
+
+ //
+ // difference with MoveCurrentLine
+ // just return Line
+ // do not set currentline to Line
+ //
+ if (Count <= 0) {
+ AbsCount = (UINTN)ABS(Count);
+ Line = HLineRetreat (AbsCount);
+ } else {
+ Line = HLineAdvance ((UINTN)Count);
+ }
+
+ return Line;
+}
+
+/**
+ Advance/Retreat lines and set CurrentLine in BufferImage to it.
+
+ @param[in] Count The line number to advance/retreat.
+ >0 : advance
+ <0: retreat
+
+ @retval NULL An error occured.
+ @return A pointer to the line after move.
+**/
+HEFI_EDITOR_LINE *
+HMoveCurrentLine (
+ IN INTN Count
+ )
+{
+ HEFI_EDITOR_LINE *Line;
+ UINTN AbsCount;
+
+ //
+ // <0: retreat
+ // >0: advance
+ //
+ if (Count <= 0) {
+ AbsCount = (UINTN)ABS(Count);
+ Line = HLineRetreat (AbsCount);
+ } else {
+ Line = HLineAdvance ((UINTN)Count);
+ }
+
+ if (Line == NULL) {
+ return NULL;
+ }
+
+ HMainEditor.BufferImage->CurrentLine = Line;
+
+ return Line;
+}
+
+
+/**
+ Free all the lines in HBufferImage.
+ Fields affected:
+ Lines
+ CurrentLine
+ NumLines
+ ListHead
+
+ @param[in] ListHead The list head.
+ @param[in] Lines The lines.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HFreeLines (
+ IN LIST_ENTRY *ListHead,
+ IN HEFI_EDITOR_LINE *Lines
+ )
+{
+ LIST_ENTRY *Link;
+ HEFI_EDITOR_LINE *Line;
+
+ //
+ // release all the lines
+ //
+ if (Lines != NULL) {
+
+ Line = Lines;
+ Link = &(Line->Link);
+ do {
+ Line = CR (Link, HEFI_EDITOR_LINE, Link, EFI_EDITOR_LINE_LIST);
+ Link = Link->ForwardLink;
+ HLineFree (Line);
+ } while (Link != ListHead);
+ }
+
+ ListHead->ForwardLink = ListHead;
+ ListHead->BackLink = ListHead;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get the X information for the mouse.
+
+ @param[in] GuidX The change.
+
+ @return the new information.
+**/
+INT32
+HGetTextX (
+ IN INT32 GuidX
+ )
+{
+ INT32 Gap;
+
+ HMainEditor.MouseAccumulatorX += GuidX;
+ Gap = (HMainEditor.MouseAccumulatorX * (INT32) HMainEditor.ScreenSize.Column) / (INT32) (50 * (INT32) HMainEditor.MouseInterface->Mode->ResolutionX);
+ HMainEditor.MouseAccumulatorX = (HMainEditor.MouseAccumulatorX * (INT32) HMainEditor.ScreenSize.Column) % (INT32) (50 * (INT32) HMainEditor.MouseInterface->Mode->ResolutionX);
+ HMainEditor.MouseAccumulatorX = HMainEditor.MouseAccumulatorX / (INT32) HMainEditor.ScreenSize.Column;
+ return Gap;
+}
+
+/**
+ Get the Y information for the mouse.
+
+ @param[in] GuidY The change.
+
+ @return the new information.
+**/
+INT32
+HGetTextY (
+ IN INT32 GuidY
+ )
+{
+ INT32 Gap;
+
+ HMainEditor.MouseAccumulatorY += GuidY;
+ Gap = (HMainEditor.MouseAccumulatorY * (INT32) HMainEditor.ScreenSize.Row) / (INT32) (50 * (INT32) HMainEditor.MouseInterface->Mode->ResolutionY);
+ HMainEditor.MouseAccumulatorY = (HMainEditor.MouseAccumulatorY * (INT32) HMainEditor.ScreenSize.Row) % (INT32) (50 * (INT32) HMainEditor.MouseInterface->Mode->ResolutionY);
+ HMainEditor.MouseAccumulatorY = HMainEditor.MouseAccumulatorY / (INT32) HMainEditor.ScreenSize.Row;
+
+ return Gap;
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.h
new file mode 100644
index 0000000000..df947935b0
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/HexEdit/Misc.h
@@ -0,0 +1,93 @@
+/** @file
+ Definitions for various line and string routines
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LIB_MISC_H_
+#define _LIB_MISC_H_
+
+#include "HexEditor.h"
+
+/**
+ Advance/Retreat lines.
+
+ @param[in] Count The line number to advance/retreat.
+ >0 : advance
+ <0: retreat
+
+ @retval NULL An error occured.
+ @return A pointer to the line after move.
+**/
+HEFI_EDITOR_LINE *
+HMoveLine (
+ IN INTN Count
+ );
+
+/**
+ Advance/Retreat lines and set CurrentLine in BufferImage to it.
+
+ @param[in] Count The line number to advance/retreat.
+ >0 : advance
+ <0: retreat
+
+ @retval NULL An error occured.
+ @return A pointer to the line after move.
+**/
+HEFI_EDITOR_LINE *
+HMoveCurrentLine (
+ IN INTN Count
+ );
+
+/**
+ Free all the lines in HBufferImage.
+ Fields affected:
+ Lines
+ CurrentLine
+ NumLines
+ ListHead
+
+ @param[in] ListHead The list head.
+ @param[in] Lines The lines.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+HFreeLines (
+ IN LIST_ENTRY *ListHead,
+ IN HEFI_EDITOR_LINE *Lines
+ );
+
+/**
+ Get the X information for the mouse.
+
+ @param[in] GuidX The change.
+
+ @return the new information.
+**/
+INT32
+HGetTextX (
+ IN INT32 GuidX
+ );
+
+/**
+ Get the Y information for the mouse.
+
+ @param[in] GuidY The change.
+
+ @return the new information.
+**/
+INT32
+HGetTextY (
+ IN INT32 GuidY
+ );
+
+#endif
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/LoadPciRom.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/LoadPciRom.c
new file mode 100644
index 0000000000..c9078f7614
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/LoadPciRom.c
@@ -0,0 +1,411 @@
+/** @file
+ Main file for LoadPciRom shell Debug1 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDebug1CommandsLib.h"
+#include <IndustryStandard/Pci22.h>
+#include <IndustryStandard/Pci23.h>
+#include <IndustryStandard/PeImage.h>
+#include <Protocol/Decompress.h>
+
+/**
+ Connects all available drives and controllers.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_ABORTED The abort mechanism was received.
+**/
+EFI_STATUS
+LoadPciRomConnectAllDriversToAllControllers (
+ VOID
+ );
+
+/**
+ Command entry point.
+
+ @param[in] RomBar The Rom Base address.
+ @param[in] RomSize The Rom size.
+ @param[in] FileName The file name.
+
+ @retval EFI_SUCCESS The command completed successfully.
+ @retval EFI_INVALID_PARAMETER Command usage error.
+ @retval EFI_UNSUPPORTED Protocols unsupported.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+ @retval Other value Unknown error.
+**/
+EFI_STATUS
+EFIAPI
+LoadEfiDriversFromRomImage (
+ VOID *RomBar,
+ UINTN RomSize,
+ CONST CHAR16 *FileName
+ );
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-nc", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'loadpcirom' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunLoadPciRom (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_SHELL_FILE_INFO *FileList;
+ UINTN SourceSize;
+ UINT8 *File1Buffer;
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ BOOLEAN Connect;
+ CONST CHAR16 *Param;
+ UINTN ParamCount;
+ EFI_SHELL_FILE_INFO *Node;
+ //
+ // Local variable initializations
+ //
+ File1Buffer = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ FileList = NULL;
+
+
+ //
+ // verify number of arguments
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"loadpcirom", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetCount(Package) < 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"loadpcirom");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ if (ShellCommandLineGetFlag(Package, L"-nc")) {
+ Connect = FALSE;
+ } else {
+ Connect = TRUE;
+ }
+
+ //
+ // get a list with each file specified by parameters
+ // if parameter is a directory then add all the files below it to the list
+ //
+ for ( ParamCount = 1, Param = ShellCommandLineGetRawValue(Package, ParamCount)
+ ; Param != NULL
+ ; ParamCount++, Param = ShellCommandLineGetRawValue(Package, ParamCount)
+ ){
+ Status = ShellOpenFileMetaArg((CHAR16*)Param, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"loadpcirom", Param);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ break;
+ }
+ }
+ if (ShellStatus == SHELL_SUCCESS && FileList != NULL) {
+ //
+ // loop through the list and make sure we are not aborting...
+ //
+ for ( Node = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link)
+ ; !IsNull(&FileList->Link, &Node->Link) && !ShellGetExecutionBreakFlag()
+ ; Node = (EFI_SHELL_FILE_INFO*)GetNextNode(&FileList->Link, &Node->Link)
+ ){
+ if (EFI_ERROR(Node->Status)){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"loadpcirom", Node->FullName);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ continue;
+ }
+ if (FileHandleIsDirectory(Node->Handle) == EFI_SUCCESS) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_NOT_DIR), gShellDebug1HiiHandle, L"loadpcirom", Node->FullName);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ continue;
+ }
+ SourceSize = (UINTN) Node->Info->FileSize;
+ File1Buffer = AllocateZeroPool (SourceSize);
+ if (File1Buffer == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle, L"loadpcirom");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ continue;
+ }
+ Status = gEfiShellProtocol->ReadFile(Node->Handle, &SourceSize, File1Buffer);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_READ_FAIL), gShellDebug1HiiHandle, L"loadpcirom", Node->FullName);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Status = LoadEfiDriversFromRomImage (
+ File1Buffer,
+ SourceSize,
+ Node->FullName
+ );
+
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_PCI_ROM_RES), gShellDebug1HiiHandle, Node->FullName, Status);
+ }
+ FreePool(File1Buffer);
+ }
+ } else if (ShellStatus == SHELL_SUCCESS) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_NOT_SPEC), gShellDebug1HiiHandle, "loadpcirom");
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ if (FileList != NULL && !IsListEmpty(&FileList->Link)) {
+ Status = ShellCloseFileMetaArg(&FileList);
+ }
+ FileList = NULL;
+
+ if (Connect) {
+ Status = LoadPciRomConnectAllDriversToAllControllers ();
+ }
+ }
+ }
+
+ return (ShellStatus);
+}
+
+/**
+ Command entry point.
+
+ @param[in] RomBar The Rom Base address.
+ @param[in] RomSize The Rom size.
+ @param[in] FileName The file name.
+
+ @retval EFI_SUCCESS The command completed successfully.
+ @retval EFI_INVALID_PARAMETER Command usage error.
+ @retval EFI_UNSUPPORTED Protocols unsupported.
+ @retval EFI_OUT_OF_RESOURCES Out of memory.
+ @retval Other value Unknown error.
+**/
+EFI_STATUS
+EFIAPI
+LoadEfiDriversFromRomImage (
+ VOID *RomBar,
+ UINTN RomSize,
+ CONST CHAR16 *FileName
+ )
+
+{
+ EFI_PCI_EXPANSION_ROM_HEADER *EfiRomHeader;
+ PCI_DATA_STRUCTURE *Pcir;
+ UINTN ImageIndex;
+ UINTN RomBarOffset;
+ UINT32 ImageSize;
+ UINT16 ImageOffset;
+ EFI_HANDLE ImageHandle;
+ EFI_STATUS Status;
+ EFI_STATUS ReturnStatus;
+ CHAR16 RomFileName[280];
+ EFI_DEVICE_PATH_PROTOCOL *FilePath;
+ BOOLEAN SkipImage;
+ UINT32 DestinationSize;
+ UINT32 ScratchSize;
+ UINT8 *Scratch;
+ VOID *ImageBuffer;
+ VOID *DecompressedImageBuffer;
+ UINT32 ImageLength;
+ EFI_DECOMPRESS_PROTOCOL *Decompress;
+ UINT32 InitializationSize;
+
+ ImageIndex = 0;
+ ReturnStatus = EFI_NOT_FOUND;
+ RomBarOffset = (UINTN) RomBar;
+
+ do {
+
+ EfiRomHeader = (EFI_PCI_EXPANSION_ROM_HEADER *) (UINTN) RomBarOffset;
+
+ if (EfiRomHeader->Signature != PCI_EXPANSION_ROM_HEADER_SIGNATURE) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOADPCIROM_CORRUPT), gShellDebug1HiiHandle, L"loadpcirom", FileName, ImageIndex);
+// PrintToken (STRING_TOKEN (STR_LOADPCIROM_IMAGE_CORRUPT), HiiHandle, ImageIndex);
+ return ReturnStatus;
+ }
+
+ //
+ // If the pointer to the PCI Data Structure is invalid, no further images can be located.
+ // The PCI Data Structure must be DWORD aligned.
+ //
+ if (EfiRomHeader->PcirOffset == 0 ||
+ (EfiRomHeader->PcirOffset & 3) != 0 ||
+ RomBarOffset - (UINTN)RomBar + EfiRomHeader->PcirOffset + sizeof (PCI_DATA_STRUCTURE) > RomSize) {
+ break;
+ }
+
+ Pcir = (PCI_DATA_STRUCTURE *) (UINTN) (RomBarOffset + EfiRomHeader->PcirOffset);
+ //
+ // If a valid signature is not present in the PCI Data Structure, no further images can be located.
+ //
+ if (Pcir->Signature != PCI_DATA_STRUCTURE_SIGNATURE) {
+ break;
+ }
+ ImageSize = Pcir->ImageLength * 512;
+ if (RomBarOffset - (UINTN)RomBar + ImageSize > RomSize) {
+ break;
+ }
+
+ if ((Pcir->CodeType == PCI_CODE_TYPE_EFI_IMAGE) &&
+ (EfiRomHeader->EfiSignature == EFI_PCI_EXPANSION_ROM_HEADER_EFISIGNATURE) &&
+ ((EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER) ||
+ (EfiRomHeader->EfiSubsystem == EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER))) {
+
+ ImageOffset = EfiRomHeader->EfiImageHeaderOffset;
+ InitializationSize = EfiRomHeader->InitializationSize * 512;
+
+ if (InitializationSize <= ImageSize && ImageOffset < InitializationSize) {
+
+ ImageBuffer = (VOID *) (UINTN) (RomBarOffset + ImageOffset);
+ ImageLength = InitializationSize - ImageOffset;
+ DecompressedImageBuffer = NULL;
+
+ //
+ // decompress here if needed
+ //
+ SkipImage = FALSE;
+ if (EfiRomHeader->CompressionType > EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
+ SkipImage = TRUE;
+ }
+
+ if (EfiRomHeader->CompressionType == EFI_PCI_EXPANSION_ROM_HEADER_COMPRESSED) {
+ Status = gBS->LocateProtocol (&gEfiDecompressProtocolGuid, NULL, (VOID**)&Decompress);
+ ASSERT_EFI_ERROR(Status);
+ if (EFI_ERROR (Status)) {
+ SkipImage = TRUE;
+ } else {
+ SkipImage = TRUE;
+ Status = Decompress->GetInfo (
+ Decompress,
+ ImageBuffer,
+ ImageLength,
+ &DestinationSize,
+ &ScratchSize
+ );
+ if (!EFI_ERROR (Status)) {
+ DecompressedImageBuffer = AllocateZeroPool (DestinationSize);
+ if (ImageBuffer != NULL) {
+ Scratch = AllocateZeroPool (ScratchSize);
+ if (Scratch != NULL) {
+ Status = Decompress->Decompress (
+ Decompress,
+ ImageBuffer,
+ ImageLength,
+ DecompressedImageBuffer,
+ DestinationSize,
+ Scratch,
+ ScratchSize
+ );
+ if (!EFI_ERROR (Status)) {
+ ImageBuffer = DecompressedImageBuffer;
+ ImageLength = DestinationSize;
+ SkipImage = FALSE;
+ }
+
+ FreePool (Scratch);
+ }
+ }
+ }
+ }
+ }
+
+ if (!SkipImage) {
+ //
+ // load image and start image
+ //
+ UnicodeSPrint (RomFileName, sizeof (RomFileName), L"%s[%d]", FileName, ImageIndex);
+ FilePath = FileDevicePath (NULL, RomFileName);
+
+ Status = gBS->LoadImage (
+ TRUE,
+ gImageHandle,
+ FilePath,
+ ImageBuffer,
+ ImageLength,
+ &ImageHandle
+ );
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOADPCIROM_LOAD_FAIL), gShellDebug1HiiHandle, L"loadpcirom", FileName, ImageIndex);
+// PrintToken (STRING_TOKEN (STR_LOADPCIROM_LOAD_IMAGE_ERROR), HiiHandle, ImageIndex, Status);
+ } else {
+ Status = gBS->StartImage (ImageHandle, NULL, NULL);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOADPCIROM_START_FAIL), gShellDebug1HiiHandle, L"loadpcirom", FileName, ImageIndex);
+// PrintToken (STRING_TOKEN (STR_LOADPCIROM_START_IMAGE), HiiHandle, ImageIndex, Status);
+ } else {
+ ReturnStatus = Status;
+ }
+ }
+ }
+
+ if (DecompressedImageBuffer != NULL) {
+ FreePool (DecompressedImageBuffer);
+ }
+
+ }
+ }
+
+ RomBarOffset = RomBarOffset + ImageSize;
+ ImageIndex++;
+ } while (((Pcir->Indicator & 0x80) == 0x00) && ((RomBarOffset - (UINTN) RomBar) < RomSize));
+
+ return ReturnStatus;
+}
+
+/**
+ Connects all available drives and controllers.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_ABORTED The abort mechanism was received.
+**/
+EFI_STATUS
+LoadPciRomConnectAllDriversToAllControllers (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+
+ Status = gBS->LocateHandleBuffer (
+ AllHandles,
+ NULL,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ if (ShellGetExecutionBreakFlag ()) {
+ Status = EFI_ABORTED;
+ break;
+ }
+ gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
+ }
+
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+ return Status;
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/MemMap.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/MemMap.c
new file mode 100644
index 0000000000..81c561f680
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/MemMap.c
@@ -0,0 +1,312 @@
+/** @file
+ Main file for Mode shell Debug1 function.
+
+ (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which acModeanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+//
+// Need full names for Standard-Format Output
+//
+STATIC CONST CHAR16 NameEfiReservedMemoryType[] = L"Reserved";
+STATIC CONST CHAR16 NameEfiLoaderCode[] = L"LoaderCode";
+STATIC CONST CHAR16 NameEfiLoaderData[] = L"LoaderData";
+STATIC CONST CHAR16 NameEfiBootServicesCode[] = L"BootServiceCode";
+STATIC CONST CHAR16 NameEfiBootServicesData[] = L"BootServiceData";
+STATIC CONST CHAR16 NameEfiRuntimeServicesCode[] = L"RuntimeCode";
+STATIC CONST CHAR16 NameEfiRuntimeServicesData[] = L"RuntimeData";
+STATIC CONST CHAR16 NameEfiConventionalMemory[] = L"Available";
+STATIC CONST CHAR16 NameEfiPersistentMemory[] = L"Persistent";
+STATIC CONST CHAR16 NameEfiUnusableMemory[] = L"UnusableMemory";
+STATIC CONST CHAR16 NameEfiACPIReclaimMemory[] = L"ACPIReclaimMemory";
+STATIC CONST CHAR16 NameEfiACPIMemoryNVS[] = L"ACPIMemoryNVS";
+STATIC CONST CHAR16 NameEfiMemoryMappedIO[] = L"MemoryMappedIO";
+STATIC CONST CHAR16 NameEfiMemoryMappedIOPortSpace[] = L"MemoryMappedIOPortSpace";
+STATIC CONST CHAR16 NameEfiPalCode[] = L"PalCode";
+
+//
+// Need short names for some memory types
+//
+STATIC CONST CHAR16 NameEfiBootServicesCodeShort[] = L"BS_Code";
+STATIC CONST CHAR16 NameEfiBootServicesDataShort[] = L"BS_Data";
+STATIC CONST CHAR16 NameEfiRuntimeServicesCodeShort[] = L"RT_Code";
+STATIC CONST CHAR16 NameEfiRuntimeServicesDataShort[] = L"RT_Data";
+STATIC CONST CHAR16 NameEfiUnusableMemoryShort[] = L"Unusable";
+STATIC CONST CHAR16 NameEfiACPIReclaimMemoryShort[] = L"ACPI_Recl";
+STATIC CONST CHAR16 NameEfiACPIMemoryNVSShort[] = L"ACPI_NVS";
+STATIC CONST CHAR16 NameEfiMemoryMappedIOShort[] = L"MMIO";
+STATIC CONST CHAR16 NameEfiMemoryMappedIOPortSpaceShort[] = L"MMIO_Port";
+
+#include "UefiShellDebug1CommandsLib.h"
+
+/**
+ Function for 'memmap' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunMemMap (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ UINTN Size;
+ EFI_MEMORY_DESCRIPTOR *Buffer;
+ UINTN MapKey;
+ UINTN ItemSize;
+ UINT32 Version;
+ UINT8 *Walker;
+ UINT64 ReservedPages;
+ UINT64 LoadCodePages;
+ UINT64 LoadDataPages;
+ UINT64 BSCodePages;
+ UINT64 BSDataPages;
+ UINT64 RTDataPages;
+ UINT64 RTCodePages;
+ UINT64 AvailPages;
+ UINT64 TotalPages;
+ UINT64 ReservedPagesSize;
+ UINT64 LoadCodePagesSize;
+ UINT64 LoadDataPagesSize;
+ UINT64 BSCodePagesSize;
+ UINT64 BSDataPagesSize;
+ UINT64 RTDataPagesSize;
+ UINT64 RTCodePagesSize;
+ UINT64 AvailPagesSize;
+ UINT64 TotalPagesSize;
+ UINT64 AcpiReclaimPages;
+ UINT64 AcpiNvsPages;
+ UINT64 MmioSpacePages;
+ UINT64 AcpiReclaimPagesSize;
+ UINT64 AcpiNvsPagesSize;
+ UINT64 MmioSpacePagesSize;
+ UINT64 MmioPortPages;
+ UINT64 MmioPortPagesSize;
+ UINT64 UnusableMemoryPages;
+ UINT64 UnusableMemoryPagesSize;
+ UINT64 PalCodePages;
+ UINT64 PalCodePagesSize;
+ BOOLEAN Sfo;
+
+ AcpiReclaimPages = 0;
+ AcpiNvsPages = 0;
+ MmioSpacePages = 0;
+ TotalPages = 0;
+ ReservedPages = 0;
+ LoadCodePages = 0;
+ LoadDataPages = 0;
+ BSCodePages = 0;
+ BSDataPages = 0;
+ RTDataPages = 0;
+ RTCodePages = 0;
+ AvailPages = 0;
+ MmioPortPages = 0;
+ UnusableMemoryPages = 0;
+ PalCodePages = 0;
+ Size = 0;
+ Buffer = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ Status = EFI_SUCCESS;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (SfoParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"memmap", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetCount(Package) > 1) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"memmap");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Status = gBS->GetMemoryMap(&Size, Buffer, &MapKey, &ItemSize, &Version);
+ if (Status == EFI_BUFFER_TOO_SMALL){
+ Size += SIZE_1KB;
+ Buffer = AllocateZeroPool(Size);
+ Status = gBS->GetMemoryMap(&Size, Buffer, &MapKey, &ItemSize, &Version);
+ }
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MEMMAP_GET_FAILED), gShellDebug1HiiHandle, L"memmap");
+ ShellStatus = SHELL_ACCESS_DENIED;
+ } else {
+ ASSERT(Version == EFI_MEMORY_DESCRIPTOR_VERSION);
+
+ Sfo = ShellCommandLineGetFlag(Package, L"-sfo");
+ if (!Sfo) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MEMMAP_LIST_HEAD), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_SFO_HEADER), gShellDebug1HiiHandle, L"memmap");
+ }
+
+ for (Walker = (UINT8*)Buffer; Walker < (((UINT8*)Buffer)+Size) && Walker != NULL; Walker += ItemSize){
+ switch (((EFI_MEMORY_DESCRIPTOR*)Walker)->Type) {
+ case EfiReservedMemoryType:
+ ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, NameEfiReservedMemoryType, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute);
+ ReservedPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ break;
+ case EfiLoaderCode:
+ ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, NameEfiLoaderCode, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute);
+ LoadCodePages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ TotalPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ break;
+ case EfiLoaderData:
+ ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, NameEfiLoaderData, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute);
+ LoadDataPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ TotalPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ break;
+ case EfiBootServicesCode:
+ ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiBootServicesCodeShort:NameEfiBootServicesCode, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute);
+ BSCodePages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ TotalPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ break;
+ case EfiBootServicesData:
+ ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiBootServicesDataShort:NameEfiBootServicesData, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute);
+ BSDataPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ TotalPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ break;
+ case EfiRuntimeServicesCode:
+ ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiRuntimeServicesCodeShort:NameEfiRuntimeServicesCode, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute);
+ RTCodePages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ TotalPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ break;
+ case EfiRuntimeServicesData:
+ ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiRuntimeServicesDataShort:NameEfiRuntimeServicesData, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute);
+ RTDataPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ TotalPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ break;
+ case EfiConventionalMemory:
+ ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, NameEfiConventionalMemory, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute);
+ AvailPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ TotalPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ break;
+ case EfiPersistentMemory:
+ ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, NameEfiPersistentMemory, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute);
+ AvailPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ TotalPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ break;
+ case EfiUnusableMemory:
+ ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiUnusableMemoryShort:NameEfiUnusableMemory, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute);
+ UnusableMemoryPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ break;
+ case EfiACPIReclaimMemory:
+ ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiACPIReclaimMemoryShort:NameEfiACPIReclaimMemory, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute);
+ TotalPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ AcpiReclaimPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ break;
+ case EfiACPIMemoryNVS:
+ ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiACPIMemoryNVSShort:NameEfiACPIMemoryNVS, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute);
+ TotalPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ AcpiNvsPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ break;
+ case EfiMemoryMappedIO:
+ ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiMemoryMappedIOShort:NameEfiMemoryMappedIO, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute);
+ MmioSpacePages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ break;
+ case EfiMemoryMappedIOPortSpace:
+ ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, !Sfo?NameEfiMemoryMappedIOPortSpaceShort:NameEfiMemoryMappedIOPortSpace, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute);
+ MmioPortPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ break;
+ case EfiPalCode:
+ ShellPrintHiiEx(-1, -1, NULL, (EFI_STRING_ID)(!Sfo?STRING_TOKEN (STR_MEMMAP_LIST_ITEM):STRING_TOKEN (STR_MEMMAP_LIST_ITEM_SFO)), gShellDebug1HiiHandle, NameEfiPalCode, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart, ((EFI_MEMORY_DESCRIPTOR*)Walker)->PhysicalStart+MultU64x64(SIZE_4KB,((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages)-1, ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages, ((EFI_MEMORY_DESCRIPTOR*)Walker)->Attribute);
+ TotalPages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ PalCodePages += ((EFI_MEMORY_DESCRIPTOR*)Walker)->NumberOfPages;
+ break;
+ default:
+ ASSERT(FALSE);
+ }
+ }
+ //
+ // print the summary
+ //
+ ReservedPagesSize = MultU64x64(SIZE_4KB,ReservedPages);
+ LoadCodePagesSize = MultU64x64(SIZE_4KB,LoadCodePages);
+ LoadDataPagesSize = MultU64x64(SIZE_4KB,LoadDataPages);
+ BSCodePagesSize = MultU64x64(SIZE_4KB,BSCodePages);
+ BSDataPagesSize = MultU64x64(SIZE_4KB,BSDataPages);
+ RTDataPagesSize = MultU64x64(SIZE_4KB,RTDataPages);
+ RTCodePagesSize = MultU64x64(SIZE_4KB,RTCodePages);
+ AvailPagesSize = MultU64x64(SIZE_4KB,AvailPages);
+ TotalPagesSize = MultU64x64(SIZE_4KB,TotalPages);
+ AcpiReclaimPagesSize = MultU64x64(SIZE_4KB,AcpiReclaimPages);
+ AcpiNvsPagesSize = MultU64x64(SIZE_4KB,AcpiNvsPages);
+ MmioSpacePagesSize = MultU64x64(SIZE_4KB,MmioSpacePages);
+ MmioPortPagesSize = MultU64x64(SIZE_4KB,MmioPortPages);
+ PalCodePagesSize = MultU64x64(SIZE_4KB,PalCodePages);
+ UnusableMemoryPagesSize = MultU64x64(SIZE_4KB,UnusableMemoryPages);
+ if (!Sfo) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MEMMAP_LIST_SUMM), gShellDebug1HiiHandle,
+ ReservedPages, ReservedPagesSize,
+ LoadCodePages, LoadCodePagesSize,
+ LoadDataPages, LoadDataPagesSize,
+ BSCodePages, BSCodePagesSize,
+ BSDataPages, BSDataPagesSize,
+ RTCodePages, RTCodePagesSize,
+ RTDataPages, RTDataPagesSize,
+ AcpiReclaimPages, AcpiReclaimPagesSize,
+ AcpiNvsPages, AcpiNvsPagesSize,
+ MmioSpacePages, MmioSpacePagesSize,
+ MmioPortPages, MmioPortPagesSize,
+ PalCodePages, PalCodePagesSize,
+ AvailPages, AvailPagesSize,
+ DivU64x32(MultU64x64(SIZE_4KB,TotalPages), SIZE_1MB), TotalPagesSize
+ );
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MEMMAP_LIST_SUMM_SFO), gShellDebug1HiiHandle,
+ TotalPagesSize,
+ ReservedPagesSize,
+ BSCodePagesSize,
+ BSDataPagesSize,
+ RTCodePagesSize,
+ RTDataPagesSize,
+ LoadCodePagesSize,
+ LoadDataPagesSize,
+ AvailPagesSize,
+ MmioSpacePagesSize,
+ MmioPortPagesSize,
+ UnusableMemoryPagesSize,
+ AcpiReclaimPagesSize,
+ AcpiNvsPagesSize,
+ PalCodePagesSize
+ );
+ }
+ }
+ }
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ if (Buffer != NULL) {
+ FreePool(Buffer);
+ }
+
+ return (ShellStatus);
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Mm.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Mm.c
new file mode 100644
index 0000000000..26a758b6cd
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Mm.c
@@ -0,0 +1,649 @@
+/** @file
+ Main file for Mm shell Debug1 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDebug1CommandsLib.h"
+#include <Library/ShellLib.h>
+#include <Library/IoLib.h>
+#include <Protocol/PciRootBridgeIo.h>
+#include <Protocol/DeviceIo.h>
+
+typedef enum {
+ ShellMmMemory,
+ ShellMmMemoryMappedIo,
+ ShellMmIo,
+ ShellMmPci,
+ ShellMmPciExpress
+} SHELL_MM_ACCESS_TYPE;
+
+CONST UINT16 mShellMmAccessTypeStr[] = {
+ STRING_TOKEN (STR_MM_MEM),
+ STRING_TOKEN (STR_MM_MMIO),
+ STRING_TOKEN (STR_MM_IO),
+ STRING_TOKEN (STR_MM_PCI),
+ STRING_TOKEN (STR_MM_PCIE)
+};
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-mmio", TypeFlag},
+ {L"-mem", TypeFlag},
+ {L"-io", TypeFlag},
+ {L"-pci", TypeFlag},
+ {L"-pcie", TypeFlag},
+ {L"-n", TypeFlag},
+ {L"-w", TypeValue},
+ {NULL, TypeMax}
+ };
+
+CONST UINT64 mShellMmMaxNumber[] = {
+ 0, MAX_UINT8, MAX_UINT16, 0, MAX_UINT32, 0, 0, 0, MAX_UINT64
+};
+CONST EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_WIDTH mShellMmRootBridgeIoWidth[] = {
+ 0, EfiPciWidthUint8, EfiPciWidthUint16, 0, EfiPciWidthUint32, 0, 0, 0, EfiPciWidthUint64
+};
+CONST EFI_CPU_IO_PROTOCOL_WIDTH mShellMmCpuIoWidth[] = {
+ 0, EfiCpuIoWidthUint8, EfiCpuIoWidthUint16, 0, EfiCpuIoWidthUint32, 0, 0, 0, EfiCpuIoWidthUint64
+};
+
+/**
+ Extract the PCI segment, bus, device, function, register from
+ from a SHELL_MM_PCI or SHELL_MM_PCIE format of address..
+
+ @param[in] PciFormat Whether the address is of PCI format of PCIE format.
+ @param[in] Address SHELL_MM_PCI or SHELL_MM_PCIE address.
+ @param[out] Segment PCI segment number.
+ @param[out] Bus PCI bus number.
+ @param[out] Device PCI device number.
+ @param[out] Function PCI function number.
+ @param[out] Register PCI register offset.
+**/
+VOID
+EFIAPI
+ShellMmDecodePciAddress (
+ IN BOOLEAN PciFormat,
+ IN UINT64 Address,
+ OUT UINT32 *Segment,
+ OUT UINT8 *Bus,
+ OUT UINT8 *Device, OPTIONAL
+ OUT UINT8 *Function, OPTIONAL
+ OUT UINT32 *Register OPTIONAL
+ )
+{
+ if (PciFormat) {
+ //
+ // PCI Configuration Space.The address will have the format 0x000000ssbbddffrr,
+ // where ss = Segment, bb = Bus, dd = Device, ff = Function and rr = Register.
+ //
+ *Segment = (UINT32) (RShiftU64 (Address, 32) & 0xFF);
+ *Bus = (UINT8) (((UINT32) Address) >> 24);
+
+ if (Device != NULL) {
+ *Device = (UINT8) (((UINT32) Address) >> 16);
+ }
+ if (Function != NULL) {
+ *Function = (UINT8) (((UINT32) Address) >> 8);
+ }
+ if (Register != NULL) {
+ *Register = (UINT8) Address;
+ }
+ } else {
+ //
+ // PCI Express Configuration Space.The address will have the format 0x0000000ssbbddffrrr,
+ // where ss = Segment, bb = Bus, dd = Device, ff = Function and rrr = Register.
+ //
+ *Segment = (UINT32) (RShiftU64 (Address, 36) & 0xFF);
+ *Bus = (UINT8) RShiftU64 (Address, 28);
+ if (Device != NULL) {
+ *Device = (UINT8) (((UINT32) Address) >> 20);
+ }
+ if (Function != NULL) {
+ *Function = (UINT8) (((UINT32) Address) >> 12);
+ }
+ if (Register != NULL) {
+ *Register = (UINT32) (Address & 0xFFF);
+ }
+ }
+}
+
+/**
+ Read or write some data from or into the Address.
+
+ @param[in] AccessType Access type.
+ @param[in] PciRootBridgeIo PciRootBridgeIo instance.
+ @param[in] CpuIo CpuIo instance.
+ @param[in] Read TRUE for read, FALSE for write.
+ @param[in] Addresss The memory location to access.
+ @param[in] Size The size of Buffer in Width sized units.
+ @param[in, out] Buffer The buffer to read into or write from.
+**/
+VOID
+ShellMmAccess (
+ IN SHELL_MM_ACCESS_TYPE AccessType,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo,
+ IN EFI_CPU_IO2_PROTOCOL *CpuIo,
+ IN BOOLEAN Read,
+ IN UINT64 Address,
+ IN UINTN Size,
+ IN OUT VOID *Buffer
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL_IO_MEM RootBridgeIoMem;
+ EFI_CPU_IO_PROTOCOL_IO_MEM CpuIoMem;
+ UINT32 Segment;
+ UINT8 Bus;
+ UINT8 Device;
+ UINT8 Function;
+ UINT32 Register;
+
+ if (AccessType == ShellMmMemory) {
+ if (Read) {
+ CopyMem (Buffer, (VOID *) (UINTN) Address, Size);
+ } else {
+ CopyMem ((VOID *) (UINTN) Address, Buffer, Size);
+ }
+ } else {
+ RootBridgeIoMem = NULL;
+ CpuIoMem = NULL;
+ switch (AccessType) {
+ case ShellMmPci:
+ case ShellMmPciExpress:
+ ASSERT (PciRootBridgeIo != NULL);
+ ShellMmDecodePciAddress ((BOOLEAN) (AccessType == ShellMmPci), Address, &Segment, &Bus, &Device, &Function, &Register);
+ if (Read) {
+ Status = PciRootBridgeIo->Pci.Read (
+ PciRootBridgeIo, mShellMmRootBridgeIoWidth[Size],
+ EFI_PCI_ADDRESS (Bus, Device, Function, Register),
+ 1, Buffer
+ );
+ } else {
+ Status = PciRootBridgeIo->Pci.Write (
+ PciRootBridgeIo, mShellMmRootBridgeIoWidth[Size],
+ EFI_PCI_ADDRESS (Bus, Device, Function, Register),
+ 1, Buffer
+ );
+ }
+ ASSERT_EFI_ERROR (Status);
+ return;
+
+ case ShellMmMemoryMappedIo:
+ if (PciRootBridgeIo != NULL) {
+ RootBridgeIoMem = Read ? PciRootBridgeIo->Mem.Read : PciRootBridgeIo->Mem.Write;
+ }
+ if (CpuIo != NULL) {
+ CpuIoMem = Read ? CpuIo->Mem.Read : CpuIo->Mem.Write;
+ }
+ break;
+
+ case ShellMmIo:
+ if (PciRootBridgeIo != NULL) {
+ RootBridgeIoMem = Read ? PciRootBridgeIo->Io.Read : PciRootBridgeIo->Io.Write;
+ }
+ if (CpuIo != NULL) {
+ CpuIoMem = Read ? CpuIo->Io.Read : CpuIo->Io.Write;
+ }
+ break;
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+
+ Status = EFI_UNSUPPORTED;
+ if (RootBridgeIoMem != NULL) {
+ Status = RootBridgeIoMem (PciRootBridgeIo, mShellMmRootBridgeIoWidth[Size], Address, 1, Buffer);
+ }
+ if (EFI_ERROR (Status) && (CpuIoMem != NULL)) {
+ Status = CpuIoMem (CpuIo, mShellMmCpuIoWidth[Size], Address, 1, Buffer);
+ }
+
+ if (EFI_ERROR (Status)) {
+ if (AccessType == ShellMmIo) {
+ switch (Size) {
+ case 1:
+ if (Read) {
+ *(UINT8 *) Buffer = IoRead8 ((UINTN) Address);
+ } else {
+ IoWrite8 ((UINTN) Address, *(UINT8 *) Buffer);
+ }
+ break;
+ case 2:
+ if (Read) {
+ *(UINT16 *) Buffer = IoRead16 ((UINTN) Address);
+ } else {
+ IoWrite16 ((UINTN) Address, *(UINT16 *) Buffer);
+ }
+ break;
+ case 4:
+ if (Read) {
+ *(UINT32 *) Buffer = IoRead32 ((UINTN) Address);
+ } else {
+ IoWrite32 ((UINTN) Address, *(UINT32 *) Buffer);
+ }
+ break;
+ case 8:
+ if (Read) {
+ *(UINT64 *) Buffer = IoRead64 ((UINTN) Address);
+ } else {
+ IoWrite64 ((UINTN) Address, *(UINT64 *) Buffer);
+ }
+ break;
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+ } else {
+ switch (Size) {
+ case 1:
+ if (Read) {
+ *(UINT8 *) Buffer = MmioRead8 ((UINTN) Address);
+ } else {
+ MmioWrite8 ((UINTN) Address, *(UINT8 *) Buffer);
+ }
+ break;
+ case 2:
+ if (Read) {
+ *(UINT16 *) Buffer = MmioRead16 ((UINTN) Address);
+ } else {
+ MmioWrite16 ((UINTN) Address, *(UINT16 *) Buffer);
+ }
+ break;
+ case 4:
+ if (Read) {
+ *(UINT32 *) Buffer = MmioRead32 ((UINTN) Address);
+ } else {
+ MmioWrite32 ((UINTN) Address, *(UINT32 *) Buffer);
+ }
+ break;
+ case 8:
+ if (Read) {
+ *(UINT64 *) Buffer = MmioRead64 ((UINTN) Address);
+ } else {
+ MmioWrite64 ((UINTN) Address, *(UINT64 *) Buffer);
+ }
+ break;
+ default:
+ ASSERT (FALSE);
+ break;
+ }
+ }
+ }
+ }
+}
+
+/**
+ Find the CpuIo instance and PciRootBridgeIo instance in the platform.
+ If there are multiple PciRootBridgeIo instances, the instance which manages
+ the Address is returned.
+
+ @param[in] AccessType Access type.
+ @param[in] Address Address to access.
+ @param[out] CpuIo Return the CpuIo instance.
+ @param[out] PciRootBridgeIo Return the proper PciRootBridgeIo instance.
+
+ @retval TRUE There are PciRootBridgeIo instances in the platform.
+ @retval FALSE There isn't PciRootBridgeIo instance in the platform.
+**/
+BOOLEAN
+ShellMmLocateIoProtocol (
+ IN SHELL_MM_ACCESS_TYPE AccessType,
+ IN UINT64 Address,
+ OUT EFI_CPU_IO2_PROTOCOL **CpuIo,
+ OUT EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL **PciRootBridgeIo
+ )
+{
+ EFI_STATUS Status;
+ UINTN Index;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *Io;
+ UINT32 Segment;
+ UINT8 Bus;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
+
+ Status = gBS->LocateProtocol (&gEfiCpuIo2ProtocolGuid, NULL, (VOID **) CpuIo);
+ if (EFI_ERROR (Status)) {
+ *CpuIo = NULL;
+ }
+
+ *PciRootBridgeIo = NULL;
+ HandleBuffer = NULL;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status) || (HandleCount == 0) || (HandleBuffer == NULL)) {
+ return FALSE;
+ }
+
+ Segment = 0;
+ Bus = 0;
+ if ((AccessType == ShellMmPci) || (AccessType == ShellMmPciExpress)) {
+ ShellMmDecodePciAddress ((BOOLEAN) (AccessType == ShellMmPci), Address, &Segment, &Bus, NULL, NULL, NULL);
+ }
+
+ //
+ // Find the EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL of the specified segment & bus number
+ //
+ for (Index = 0; (Index < HandleCount) && (*PciRootBridgeIo == NULL); Index++) {
+ Status = gBS->HandleProtocol (
+ HandleBuffer[Index],
+ &gEfiPciRootBridgeIoProtocolGuid,
+ (VOID *) &Io
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if ((((AccessType == ShellMmPci) || (AccessType == ShellMmPciExpress)) && (Io->SegmentNumber == Segment)) ||
+ ((AccessType == ShellMmIo) || (AccessType == ShellMmMemoryMappedIo))
+ ) {
+ Status = Io->Configuration (Io, (VOID **) &Descriptors);
+ if (!EFI_ERROR (Status)) {
+ while (Descriptors->Desc != ACPI_END_TAG_DESCRIPTOR) {
+ //
+ // Compare the segment and bus range for PCI/PCIE access
+ //
+ if ((Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) &&
+ ((AccessType == ShellMmPci) || (AccessType == ShellMmPciExpress)) &&
+ ((Bus >= Descriptors->AddrRangeMin) && (Bus <= Descriptors->AddrRangeMax))
+ ) {
+ *PciRootBridgeIo = Io;
+ break;
+
+ //
+ // Compare the address range for MMIO/IO access
+ //
+ } else if ((((Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_IO) && (AccessType == ShellMmIo)) ||
+ ((Descriptors->ResType == ACPI_ADDRESS_SPACE_TYPE_MEM) && (AccessType == ShellMmMemoryMappedIo))
+ ) && ((Address >= Descriptors->AddrRangeMin) && (Address <= Descriptors->AddrRangeMax))
+ ) {
+ *PciRootBridgeIo = Io;
+ break;
+ }
+ Descriptors++;
+ }
+ }
+ }
+ }
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+
+ return TRUE;
+}
+
+/**
+ Function for 'mm' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunMm (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *PciRootBridgeIo;
+ EFI_CPU_IO2_PROTOCOL *CpuIo;
+ UINT64 Address;
+ UINT64 Value;
+ SHELL_MM_ACCESS_TYPE AccessType;
+ UINT64 Buffer;
+ UINTN Index;
+ UINTN Size;
+ BOOLEAN Complete;
+ CHAR16 *InputStr;
+ BOOLEAN Interactive;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ CONST CHAR16 *Temp;
+ BOOLEAN HasPciRootBridgeIo;
+
+ Value = 0;
+ Address = 0;
+ ShellStatus = SHELL_SUCCESS;
+ InputStr = NULL;
+ Size = 1;
+ AccessType = ShellMmMemory;
+
+ //
+ // Parse arguments
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"mm", ProblemParam);
+ FreePool (ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ } else {
+ ASSERT (FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetCount (Package) < 2) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"mm");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ } else if (ShellCommandLineGetCount (Package) > 3) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ } else if (ShellCommandLineGetFlag (Package, L"-w") && ShellCommandLineGetValue (Package, L"-w") == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"mm", L"-w");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ } else {
+ if (ShellCommandLineGetFlag (Package, L"-mmio")) {
+ AccessType = ShellMmMemoryMappedIo;
+ if (ShellCommandLineGetFlag (Package, L"-mem")
+ || ShellCommandLineGetFlag (Package, L"-io")
+ || ShellCommandLineGetFlag (Package, L"-pci")
+ || ShellCommandLineGetFlag (Package, L"-pcie")
+ ) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ } else if (ShellCommandLineGetFlag (Package, L"-mem")) {
+ AccessType = ShellMmMemory;
+ if (ShellCommandLineGetFlag (Package, L"-io")
+ || ShellCommandLineGetFlag (Package, L"-pci")
+ || ShellCommandLineGetFlag (Package, L"-pcie")
+ ) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ } else if (ShellCommandLineGetFlag (Package, L"-io")) {
+ AccessType = ShellMmIo;
+ if (ShellCommandLineGetFlag (Package, L"-pci")
+ || ShellCommandLineGetFlag (Package, L"-pcie")
+ ) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ } else if (ShellCommandLineGetFlag (Package, L"-pci")) {
+ AccessType = ShellMmPci;
+ if (ShellCommandLineGetFlag (Package, L"-pcie")
+ ) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mm");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ } else if (ShellCommandLineGetFlag (Package, L"-pcie")) {
+ AccessType = ShellMmPciExpress;
+ }
+ }
+
+ //
+ // Non interactive for a script file or for the specific parameter
+ //
+ Interactive = TRUE;
+ if (gEfiShellProtocol->BatchIsActive () || ShellCommandLineGetFlag (Package, L"-n")) {
+ Interactive = FALSE;
+ }
+
+ Temp = ShellCommandLineGetValue (Package, L"-w");
+ if (Temp != NULL) {
+ Size = ShellStrToUintn (Temp);
+ }
+ if ((Size != 1) && (Size != 2) && (Size != 4) && (Size != 8)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellDebug1HiiHandle, L"mm", Temp, L"-w");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ Temp = ShellCommandLineGetRawValue (Package, 1);
+ Status = ShellConvertStringToUint64 (Temp, &Address, TRUE, FALSE);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mm", Temp);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if ((Address & (Size - 1)) != 0) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_NOT_ALIGNED), gShellDebug1HiiHandle, L"mm", Address);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if ((AccessType == ShellMmIo) && (Address + Size > MAX_UINT16 + 1)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_IO_ADDRESS_RANGE), gShellDebug1HiiHandle, L"mm");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ //
+ // locate IO protocol interface
+ //
+ HasPciRootBridgeIo = ShellMmLocateIoProtocol (AccessType, Address, &CpuIo, &PciRootBridgeIo);
+ if ((AccessType == ShellMmPci) || (AccessType == ShellMmPciExpress)) {
+ if (!HasPciRootBridgeIo) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PCIRBIO_NF), gShellDebug1HiiHandle, L"mm");
+ ShellStatus = SHELL_NOT_FOUND;
+ goto Done;
+ }
+ if (PciRootBridgeIo == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_PCIE_ADDRESS_RANGE), gShellDebug1HiiHandle, L"mm", Address);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ }
+
+ //
+ // Mode 1: Directly set a value
+ //
+ Temp = ShellCommandLineGetRawValue (Package, 2);
+ if (Temp != NULL) {
+ Status = ShellConvertStringToUint64 (Temp, &Value, TRUE, FALSE);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mm", Temp);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if (Value > mShellMmMaxNumber[Size]) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mm", Temp);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, FALSE, Address, Size, &Value);
+ goto Done;
+ }
+
+ //
+ // Mode 2: Directly show a value
+ //
+ if (!Interactive) {
+ if (!gEfiShellProtocol->BatchIsActive ()) {
+ ShellPrintHiiEx (-1, -1, NULL, mShellMmAccessTypeStr[AccessType], gShellDebug1HiiHandle);
+ }
+ ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, TRUE, Address, Size, &Buffer);
+
+ if (!gEfiShellProtocol->BatchIsActive ()) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS), gShellDebug1HiiHandle, Address);
+ }
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_BUF), gShellDebug1HiiHandle, Size * 2, Buffer & mShellMmMaxNumber[Size]);
+ ShellPrintEx (-1, -1, L"\r\n");
+ goto Done;
+ }
+
+ //
+ // Mode 3: Show or set values in interactive mode
+ //
+ Complete = FALSE;
+ do {
+ if ((AccessType == ShellMmIo) && (Address + Size > MAX_UINT16 + 1)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS_RANGE2), gShellDebug1HiiHandle, L"mm");
+ break;
+ }
+
+ ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, TRUE, Address, Size, &Buffer);
+ ShellPrintHiiEx (-1, -1, NULL, mShellMmAccessTypeStr[AccessType], gShellDebug1HiiHandle);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ADDRESS), gShellDebug1HiiHandle, Address);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_BUF), gShellDebug1HiiHandle, Size * 2, Buffer & mShellMmMaxNumber[Size]);
+ ShellPrintEx (-1, -1, L" > ");
+ //
+ // wait user input to modify
+ //
+ if (InputStr != NULL) {
+ FreePool (InputStr);
+ InputStr = NULL;
+ }
+ ShellPromptForResponse (ShellPromptResponseTypeFreeform, NULL, (VOID**) &InputStr);
+
+ if (InputStr != NULL) {
+ //
+ // skip space characters
+ //
+ for (Index = 0; InputStr[Index] == ' '; Index++);
+
+ if (InputStr[Index] != CHAR_NULL) {
+ if ((InputStr[Index] == '.') || (InputStr[Index] == 'q') || (InputStr[Index] == 'Q')) {
+ Complete = TRUE;
+ } else if (!EFI_ERROR (ShellConvertStringToUint64 (InputStr + Index, &Buffer, TRUE, TRUE)) &&
+ (Buffer <= mShellMmMaxNumber[Size])
+ ) {
+ ShellMmAccess (AccessType, PciRootBridgeIo, CpuIo, FALSE, Address, Size, &Buffer);
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_MM_ERROR), gShellDebug1HiiHandle, L"mm");
+ continue;
+ }
+ }
+ }
+
+ Address += Size;
+ ShellPrintEx (-1, -1, L"\r\n");
+ } while (!Complete);
+ }
+ ASSERT (ShellStatus == SHELL_SUCCESS);
+
+Done:
+ if (InputStr != NULL) {
+ FreePool (InputStr);
+ }
+ if (Package != NULL) {
+ ShellCommandLineFreeVarList (Package);
+ }
+ return ShellStatus;
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Mode.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Mode.c
new file mode 100644
index 0000000000..7696e3fbbd
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Mode.c
@@ -0,0 +1,128 @@
+/** @file
+ Main file for Mode shell Debug1 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2010 - 2013, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which acModeanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDebug1CommandsLib.h"
+
+/**
+ Function for 'mode' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunMode (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ UINTN NewCol;
+ UINTN NewRow;
+ UINTN Col;
+ UINTN Row;
+ CONST CHAR16 *Temp;
+ BOOLEAN Done;
+ INT32 LoopVar;
+
+ ShellStatus = SHELL_SUCCESS;
+ Status = EFI_SUCCESS;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"mode", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetCount(Package) > 3) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"mode");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetCount(Package) == 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"mode");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetCount(Package) == 3) {
+ Temp = ShellCommandLineGetRawValue(Package, 1);
+ if (!ShellIsHexOrDecimalNumber(Temp, FALSE, FALSE)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mode", Temp);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ NewCol = ShellStrToUintn(Temp);
+ Temp = ShellCommandLineGetRawValue(Package, 2);
+ if (!ShellIsHexOrDecimalNumber(Temp, FALSE, FALSE)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"mode", Temp);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ NewRow = ShellStrToUintn(Temp);
+
+ for (LoopVar = 0, Done = FALSE; LoopVar < gST->ConOut->Mode->MaxMode && ShellStatus == SHELL_SUCCESS ; LoopVar++) {
+ Status = gST->ConOut->QueryMode(gST->ConOut, LoopVar, &Col, &Row);
+ if (EFI_ERROR(Status)) {
+ continue;
+ }
+ if (Col == NewCol && Row == NewRow) {
+ Status = gST->ConOut->SetMode(gST->ConOut, LoopVar);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MODE_SET_FAIL), gShellDebug1HiiHandle, L"mode");
+ ShellStatus = SHELL_DEVICE_ERROR;
+ } else {
+ // worked fine...
+ Done = TRUE;
+ }
+ break;
+ }
+ }
+
+ if (!Done) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MODE_NO_MATCH), gShellDebug1HiiHandle, L"mode");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+
+ } else if (ShellCommandLineGetCount(Package) == 1) {
+ //
+ // print out valid
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MODE_LIST_HEAD), gShellDebug1HiiHandle);
+ for (LoopVar = 0, Done = FALSE; LoopVar < gST->ConOut->Mode->MaxMode && ShellStatus == SHELL_SUCCESS ; LoopVar++) {
+ Status = gST->ConOut->QueryMode(gST->ConOut, LoopVar, &Col, &Row);
+ if (EFI_ERROR(Status)) {
+ continue;
+ }
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MODE_LIST_ITEM), gShellDebug1HiiHandle, Col, Row, LoopVar == gST->ConOut->Mode->Mode?L'*':L' ');
+ }
+ }
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ return (ShellStatus);
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.c
new file mode 100644
index 0000000000..337495e168
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.c
@@ -0,0 +1,5927 @@
+/** @file
+ Main file for Pci shell Debug1 function.
+
+ Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDebug1CommandsLib.h"
+#include <Protocol/PciRootBridgeIo.h>
+#include <Library/ShellLib.h>
+#include <IndustryStandard/Pci.h>
+#include <IndustryStandard/Acpi.h>
+#include "Pci.h"
+
+//
+// Printable strings for Pci class code
+//
+typedef struct {
+ CHAR16 *BaseClass; // Pointer to the PCI base class string
+ CHAR16 *SubClass; // Pointer to the PCI sub class string
+ CHAR16 *PIFClass; // Pointer to the PCI programming interface string
+} PCI_CLASS_STRINGS;
+
+//
+// a structure holding a single entry, which also points to its lower level
+// class
+//
+typedef struct PCI_CLASS_ENTRY_TAG {
+ UINT8 Code; // Class, subclass or I/F code
+ CHAR16 *DescText; // Description string
+ struct PCI_CLASS_ENTRY_TAG *LowerLevelClass; // Subclass or I/F if any
+} PCI_CLASS_ENTRY;
+
+//
+// Declarations of entries which contain printable strings for class codes
+// in PCI configuration space
+//
+PCI_CLASS_ENTRY PCIBlankEntry[];
+PCI_CLASS_ENTRY PCISubClass_00[];
+PCI_CLASS_ENTRY PCISubClass_01[];
+PCI_CLASS_ENTRY PCISubClass_02[];
+PCI_CLASS_ENTRY PCISubClass_03[];
+PCI_CLASS_ENTRY PCISubClass_04[];
+PCI_CLASS_ENTRY PCISubClass_05[];
+PCI_CLASS_ENTRY PCISubClass_06[];
+PCI_CLASS_ENTRY PCISubClass_07[];
+PCI_CLASS_ENTRY PCISubClass_08[];
+PCI_CLASS_ENTRY PCISubClass_09[];
+PCI_CLASS_ENTRY PCISubClass_0a[];
+PCI_CLASS_ENTRY PCISubClass_0b[];
+PCI_CLASS_ENTRY PCISubClass_0c[];
+PCI_CLASS_ENTRY PCISubClass_0d[];
+PCI_CLASS_ENTRY PCISubClass_0e[];
+PCI_CLASS_ENTRY PCISubClass_0f[];
+PCI_CLASS_ENTRY PCISubClass_10[];
+PCI_CLASS_ENTRY PCISubClass_11[];
+PCI_CLASS_ENTRY PCISubClass_12[];
+PCI_CLASS_ENTRY PCISubClass_13[];
+PCI_CLASS_ENTRY PCIPIFClass_0100[];
+PCI_CLASS_ENTRY PCIPIFClass_0101[];
+PCI_CLASS_ENTRY PCIPIFClass_0105[];
+PCI_CLASS_ENTRY PCIPIFClass_0106[];
+PCI_CLASS_ENTRY PCIPIFClass_0107[];
+PCI_CLASS_ENTRY PCIPIFClass_0108[];
+PCI_CLASS_ENTRY PCIPIFClass_0109[];
+PCI_CLASS_ENTRY PCIPIFClass_0300[];
+PCI_CLASS_ENTRY PCIPIFClass_0604[];
+PCI_CLASS_ENTRY PCIPIFClass_0609[];
+PCI_CLASS_ENTRY PCIPIFClass_060b[];
+PCI_CLASS_ENTRY PCIPIFClass_0700[];
+PCI_CLASS_ENTRY PCIPIFClass_0701[];
+PCI_CLASS_ENTRY PCIPIFClass_0703[];
+PCI_CLASS_ENTRY PCIPIFClass_0800[];
+PCI_CLASS_ENTRY PCIPIFClass_0801[];
+PCI_CLASS_ENTRY PCIPIFClass_0802[];
+PCI_CLASS_ENTRY PCIPIFClass_0803[];
+PCI_CLASS_ENTRY PCIPIFClass_0904[];
+PCI_CLASS_ENTRY PCIPIFClass_0c00[];
+PCI_CLASS_ENTRY PCIPIFClass_0c03[];
+PCI_CLASS_ENTRY PCIPIFClass_0c07[];
+PCI_CLASS_ENTRY PCIPIFClass_0d01[];
+PCI_CLASS_ENTRY PCIPIFClass_0e00[];
+
+//
+// Base class strings entries
+//
+PCI_CLASS_ENTRY gClassStringList[] = {
+ {
+ 0x00,
+ L"Pre 2.0 device",
+ PCISubClass_00
+ },
+ {
+ 0x01,
+ L"Mass Storage Controller",
+ PCISubClass_01
+ },
+ {
+ 0x02,
+ L"Network Controller",
+ PCISubClass_02
+ },
+ {
+ 0x03,
+ L"Display Controller",
+ PCISubClass_03
+ },
+ {
+ 0x04,
+ L"Multimedia Device",
+ PCISubClass_04
+ },
+ {
+ 0x05,
+ L"Memory Controller",
+ PCISubClass_05
+ },
+ {
+ 0x06,
+ L"Bridge Device",
+ PCISubClass_06
+ },
+ {
+ 0x07,
+ L"Simple Communications Controllers",
+ PCISubClass_07
+ },
+ {
+ 0x08,
+ L"Base System Peripherals",
+ PCISubClass_08
+ },
+ {
+ 0x09,
+ L"Input Devices",
+ PCISubClass_09
+ },
+ {
+ 0x0a,
+ L"Docking Stations",
+ PCISubClass_0a
+ },
+ {
+ 0x0b,
+ L"Processors",
+ PCISubClass_0b
+ },
+ {
+ 0x0c,
+ L"Serial Bus Controllers",
+ PCISubClass_0c
+ },
+ {
+ 0x0d,
+ L"Wireless Controllers",
+ PCISubClass_0d
+ },
+ {
+ 0x0e,
+ L"Intelligent IO Controllers",
+ PCISubClass_0e
+ },
+ {
+ 0x0f,
+ L"Satellite Communications Controllers",
+ PCISubClass_0f
+ },
+ {
+ 0x10,
+ L"Encryption/Decryption Controllers",
+ PCISubClass_10
+ },
+ {
+ 0x11,
+ L"Data Acquisition & Signal Processing Controllers",
+ PCISubClass_11
+ },
+ {
+ 0x12,
+ L"Processing Accelerators",
+ PCISubClass_12
+ },
+ {
+ 0x13,
+ L"Non-Essential Instrumentation",
+ PCISubClass_13
+ },
+ {
+ 0xff,
+ L"Device does not fit in any defined classes",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+//
+// Subclass strings entries
+//
+PCI_CLASS_ENTRY PCIBlankEntry[] = {
+ {
+ 0x00,
+ L"",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCISubClass_00[] = {
+ {
+ 0x00,
+ L"All devices other than VGA",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"VGA-compatible devices",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCISubClass_01[] = {
+ {
+ 0x00,
+ L"SCSI",
+ PCIPIFClass_0100
+ },
+ {
+ 0x01,
+ L"IDE controller",
+ PCIPIFClass_0101
+ },
+ {
+ 0x02,
+ L"Floppy disk controller",
+ PCIBlankEntry
+ },
+ {
+ 0x03,
+ L"IPI controller",
+ PCIBlankEntry
+ },
+ {
+ 0x04,
+ L"RAID controller",
+ PCIBlankEntry
+ },
+ {
+ 0x05,
+ L"ATA controller with ADMA interface",
+ PCIPIFClass_0105
+ },
+ {
+ 0x06,
+ L"Serial ATA controller",
+ PCIPIFClass_0106
+ },
+ {
+ 0x07,
+ L"Serial Attached SCSI (SAS) controller ",
+ PCIPIFClass_0107
+ },
+ {
+ 0x08,
+ L"Non-volatile memory subsystem",
+ PCIPIFClass_0108
+ },
+ {
+ 0x09,
+ L"Universal Flash Storage (UFS) controller ",
+ PCIPIFClass_0109
+ },
+ {
+ 0x80,
+ L"Other mass storage controller",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCISubClass_02[] = {
+ {
+ 0x00,
+ L"Ethernet controller",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"Token ring controller",
+ PCIBlankEntry
+ },
+ {
+ 0x02,
+ L"FDDI controller",
+ PCIBlankEntry
+ },
+ {
+ 0x03,
+ L"ATM controller",
+ PCIBlankEntry
+ },
+ {
+ 0x04,
+ L"ISDN controller",
+ PCIBlankEntry
+ },
+ {
+ 0x05,
+ L"WorldFip controller",
+ PCIBlankEntry
+ },
+ {
+ 0x06,
+ L"PICMG 2.14 Multi Computing",
+ PCIBlankEntry
+ },
+ {
+ 0x07,
+ L"InfiniBand controller",
+ PCIBlankEntry
+ },
+ {
+ 0x80,
+ L"Other network controller",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCISubClass_03[] = {
+ {
+ 0x00,
+ L"VGA/8514 controller",
+ PCIPIFClass_0300
+ },
+ {
+ 0x01,
+ L"XGA controller",
+ PCIBlankEntry
+ },
+ {
+ 0x02,
+ L"3D controller",
+ PCIBlankEntry
+ },
+ {
+ 0x80,
+ L"Other display controller",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */PCIBlankEntry
+ }
+};
+
+PCI_CLASS_ENTRY PCISubClass_04[] = {
+ {
+ 0x00,
+ L"Video device",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"Audio device",
+ PCIBlankEntry
+ },
+ {
+ 0x02,
+ L"Computer Telephony device",
+ PCIBlankEntry
+ },
+ {
+ 0x03,
+ L"Mixed mode device",
+ PCIBlankEntry
+ },
+ {
+ 0x80,
+ L"Other multimedia device",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCISubClass_05[] = {
+ {
+ 0x00,
+ L"RAM memory controller",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"Flash memory controller",
+ PCIBlankEntry
+ },
+ {
+ 0x80,
+ L"Other memory controller",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCISubClass_06[] = {
+ {
+ 0x00,
+ L"Host/PCI bridge",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"PCI/ISA bridge",
+ PCIBlankEntry
+ },
+ {
+ 0x02,
+ L"PCI/EISA bridge",
+ PCIBlankEntry
+ },
+ {
+ 0x03,
+ L"PCI/Micro Channel bridge",
+ PCIBlankEntry
+ },
+ {
+ 0x04,
+ L"PCI/PCI bridge",
+ PCIPIFClass_0604
+ },
+ {
+ 0x05,
+ L"PCI/PCMCIA bridge",
+ PCIBlankEntry
+ },
+ {
+ 0x06,
+ L"NuBus bridge",
+ PCIBlankEntry
+ },
+ {
+ 0x07,
+ L"CardBus bridge",
+ PCIBlankEntry
+ },
+ {
+ 0x08,
+ L"RACEway bridge",
+ PCIBlankEntry
+ },
+ {
+ 0x09,
+ L"Semi-transparent PCI-to-PCI bridge",
+ PCIPIFClass_0609
+ },
+ {
+ 0x0A,
+ L"InfiniBand-to-PCI host bridge",
+ PCIBlankEntry
+ },
+ {
+ 0x0B,
+ L"Advanced Switching to PCI host bridge",
+ PCIPIFClass_060b
+ },
+ {
+ 0x80,
+ L"Other bridge type",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCISubClass_07[] = {
+ {
+ 0x00,
+ L"Serial controller",
+ PCIPIFClass_0700
+ },
+ {
+ 0x01,
+ L"Parallel port",
+ PCIPIFClass_0701
+ },
+ {
+ 0x02,
+ L"Multiport serial controller",
+ PCIBlankEntry
+ },
+ {
+ 0x03,
+ L"Modem",
+ PCIPIFClass_0703
+ },
+ {
+ 0x04,
+ L"GPIB (IEEE 488.1/2) controller",
+ PCIBlankEntry
+ },
+ {
+ 0x05,
+ L"Smart Card",
+ PCIBlankEntry
+ },
+ {
+ 0x80,
+ L"Other communication device",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCISubClass_08[] = {
+ {
+ 0x00,
+ L"PIC",
+ PCIPIFClass_0800
+ },
+ {
+ 0x01,
+ L"DMA controller",
+ PCIPIFClass_0801
+ },
+ {
+ 0x02,
+ L"System timer",
+ PCIPIFClass_0802
+ },
+ {
+ 0x03,
+ L"RTC controller",
+ PCIPIFClass_0803
+ },
+ {
+ 0x04,
+ L"Generic PCI Hot-Plug controller",
+ PCIBlankEntry
+ },
+ {
+ 0x05,
+ L"SD Host controller",
+ PCIBlankEntry
+ },
+ {
+ 0x06,
+ L"IOMMU",
+ PCIBlankEntry
+ },
+ {
+ 0x07,
+ L"Root Complex Event Collector",
+ PCIBlankEntry
+ },
+ {
+ 0x80,
+ L"Other system peripheral",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCISubClass_09[] = {
+ {
+ 0x00,
+ L"Keyboard controller",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"Digitizer (pen)",
+ PCIBlankEntry
+ },
+ {
+ 0x02,
+ L"Mouse controller",
+ PCIBlankEntry
+ },
+ {
+ 0x03,
+ L"Scanner controller",
+ PCIBlankEntry
+ },
+ {
+ 0x04,
+ L"Gameport controller",
+ PCIPIFClass_0904
+ },
+ {
+ 0x80,
+ L"Other input controller",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCISubClass_0a[] = {
+ {
+ 0x00,
+ L"Generic docking station",
+ PCIBlankEntry
+ },
+ {
+ 0x80,
+ L"Other type of docking station",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCISubClass_0b[] = {
+ {
+ 0x00,
+ L"386",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"486",
+ PCIBlankEntry
+ },
+ {
+ 0x02,
+ L"Pentium",
+ PCIBlankEntry
+ },
+ {
+ 0x10,
+ L"Alpha",
+ PCIBlankEntry
+ },
+ {
+ 0x20,
+ L"PowerPC",
+ PCIBlankEntry
+ },
+ {
+ 0x30,
+ L"MIPS",
+ PCIBlankEntry
+ },
+ {
+ 0x40,
+ L"Co-processor",
+ PCIBlankEntry
+ },
+ {
+ 0x80,
+ L"Other processor",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCISubClass_0c[] = {
+ {
+ 0x00,
+ L"IEEE 1394",
+ PCIPIFClass_0c00
+ },
+ {
+ 0x01,
+ L"ACCESS.bus",
+ PCIBlankEntry
+ },
+ {
+ 0x02,
+ L"SSA",
+ PCIBlankEntry
+ },
+ {
+ 0x03,
+ L"USB",
+ PCIPIFClass_0c03
+ },
+ {
+ 0x04,
+ L"Fibre Channel",
+ PCIBlankEntry
+ },
+ {
+ 0x05,
+ L"System Management Bus",
+ PCIBlankEntry
+ },
+ {
+ 0x06,
+ L"InfiniBand",
+ PCIBlankEntry
+ },
+ {
+ 0x07,
+ L"IPMI",
+ PCIPIFClass_0c07
+ },
+ {
+ 0x08,
+ L"SERCOS Interface Standard (IEC 61491)",
+ PCIBlankEntry
+ },
+ {
+ 0x09,
+ L"CANbus",
+ PCIBlankEntry
+ },
+ {
+ 0x80,
+ L"Other bus type",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCISubClass_0d[] = {
+ {
+ 0x00,
+ L"iRDA compatible controller",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"",
+ PCIPIFClass_0d01
+ },
+ {
+ 0x10,
+ L"RF controller",
+ PCIBlankEntry
+ },
+ {
+ 0x11,
+ L"Bluetooth",
+ PCIBlankEntry
+ },
+ {
+ 0x12,
+ L"Broadband",
+ PCIBlankEntry
+ },
+ {
+ 0x20,
+ L"Ethernet (802.11a - 5 GHz)",
+ PCIBlankEntry
+ },
+ {
+ 0x21,
+ L"Ethernet (802.11b - 2.4 GHz)",
+ PCIBlankEntry
+ },
+ {
+ 0x80,
+ L"Other type of wireless controller",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCISubClass_0e[] = {
+ {
+ 0x00,
+ L"I2O Architecture",
+ PCIPIFClass_0e00
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCISubClass_0f[] = {
+ {
+ 0x01,
+ L"TV",
+ PCIBlankEntry
+ },
+ {
+ 0x02,
+ L"Audio",
+ PCIBlankEntry
+ },
+ {
+ 0x03,
+ L"Voice",
+ PCIBlankEntry
+ },
+ {
+ 0x04,
+ L"Data",
+ PCIBlankEntry
+ },
+ {
+ 0x80,
+ L"Other satellite communication controller",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCISubClass_10[] = {
+ {
+ 0x00,
+ L"Network & computing Encrypt/Decrypt",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"Entertainment Encrypt/Decrypt",
+ PCIBlankEntry
+ },
+ {
+ 0x80,
+ L"Other Encrypt/Decrypt",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCISubClass_11[] = {
+ {
+ 0x00,
+ L"DPIO modules",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"Performance Counters",
+ PCIBlankEntry
+ },
+ {
+ 0x10,
+ L"Communications synchronization plus time and frequency test/measurement ",
+ PCIBlankEntry
+ },
+ {
+ 0x20,
+ L"Management card",
+ PCIBlankEntry
+ },
+ {
+ 0x80,
+ L"Other DAQ & SP controllers",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCISubClass_12[] = {
+ {
+ 0x00,
+ L"Processing Accelerator",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCISubClass_13[] = {
+ {
+ 0x00,
+ L"Non-Essential Instrumentation Function",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+//
+// Programming Interface entries
+//
+PCI_CLASS_ENTRY PCIPIFClass_0100[] = {
+ {
+ 0x00,
+ L"SCSI controller",
+ PCIBlankEntry
+ },
+ {
+ 0x11,
+ L"SCSI storage device SOP using PQI",
+ PCIBlankEntry
+ },
+ {
+ 0x12,
+ L"SCSI controller SOP using PQI",
+ PCIBlankEntry
+ },
+ {
+ 0x13,
+ L"SCSI storage device and controller SOP using PQI",
+ PCIBlankEntry
+ },
+ {
+ 0x21,
+ L"SCSI storage device SOP using NVMe",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCIPIFClass_0101[] = {
+ {
+ 0x00,
+ L"",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"OM-primary",
+ PCIBlankEntry
+ },
+ {
+ 0x02,
+ L"PI-primary",
+ PCIBlankEntry
+ },
+ {
+ 0x03,
+ L"OM/PI-primary",
+ PCIBlankEntry
+ },
+ {
+ 0x04,
+ L"OM-secondary",
+ PCIBlankEntry
+ },
+ {
+ 0x05,
+ L"OM-primary, OM-secondary",
+ PCIBlankEntry
+ },
+ {
+ 0x06,
+ L"PI-primary, OM-secondary",
+ PCIBlankEntry
+ },
+ {
+ 0x07,
+ L"OM/PI-primary, OM-secondary",
+ PCIBlankEntry
+ },
+ {
+ 0x08,
+ L"OM-secondary",
+ PCIBlankEntry
+ },
+ {
+ 0x09,
+ L"OM-primary, PI-secondary",
+ PCIBlankEntry
+ },
+ {
+ 0x0a,
+ L"PI-primary, PI-secondary",
+ PCIBlankEntry
+ },
+ {
+ 0x0b,
+ L"OM/PI-primary, PI-secondary",
+ PCIBlankEntry
+ },
+ {
+ 0x0c,
+ L"OM-secondary",
+ PCIBlankEntry
+ },
+ {
+ 0x0d,
+ L"OM-primary, OM/PI-secondary",
+ PCIBlankEntry
+ },
+ {
+ 0x0e,
+ L"PI-primary, OM/PI-secondary",
+ PCIBlankEntry
+ },
+ {
+ 0x0f,
+ L"OM/PI-primary, OM/PI-secondary",
+ PCIBlankEntry
+ },
+ {
+ 0x80,
+ L"Master",
+ PCIBlankEntry
+ },
+ {
+ 0x81,
+ L"Master, OM-primary",
+ PCIBlankEntry
+ },
+ {
+ 0x82,
+ L"Master, PI-primary",
+ PCIBlankEntry
+ },
+ {
+ 0x83,
+ L"Master, OM/PI-primary",
+ PCIBlankEntry
+ },
+ {
+ 0x84,
+ L"Master, OM-secondary",
+ PCIBlankEntry
+ },
+ {
+ 0x85,
+ L"Master, OM-primary, OM-secondary",
+ PCIBlankEntry
+ },
+ {
+ 0x86,
+ L"Master, PI-primary, OM-secondary",
+ PCIBlankEntry
+ },
+ {
+ 0x87,
+ L"Master, OM/PI-primary, OM-secondary",
+ PCIBlankEntry
+ },
+ {
+ 0x88,
+ L"Master, OM-secondary",
+ PCIBlankEntry
+ },
+ {
+ 0x89,
+ L"Master, OM-primary, PI-secondary",
+ PCIBlankEntry
+ },
+ {
+ 0x8a,
+ L"Master, PI-primary, PI-secondary",
+ PCIBlankEntry
+ },
+ {
+ 0x8b,
+ L"Master, OM/PI-primary, PI-secondary",
+ PCIBlankEntry
+ },
+ {
+ 0x8c,
+ L"Master, OM-secondary",
+ PCIBlankEntry
+ },
+ {
+ 0x8d,
+ L"Master, OM-primary, OM/PI-secondary",
+ PCIBlankEntry
+ },
+ {
+ 0x8e,
+ L"Master, PI-primary, OM/PI-secondary",
+ PCIBlankEntry
+ },
+ {
+ 0x8f,
+ L"Master, OM/PI-primary, OM/PI-secondary",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCIPIFClass_0105[] = {
+ {
+ 0x20,
+ L"Single stepping",
+ PCIBlankEntry
+ },
+ {
+ 0x30,
+ L"Continuous operation",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCIPIFClass_0106[] = {
+ {
+ 0x00,
+ L"",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"AHCI",
+ PCIBlankEntry
+ },
+ {
+ 0x02,
+ L"Serial Storage Bus",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCIPIFClass_0107[] = {
+ {
+ 0x00,
+ L"",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"Obsolete",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCIPIFClass_0108[] = {
+ {
+ 0x00,
+ L"",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"NVMHCI",
+ PCIBlankEntry
+ },
+ {
+ 0x02,
+ L"NVM Express",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCIPIFClass_0109[] = {
+ {
+ 0x00,
+ L"",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"UFSHCI",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCIPIFClass_0300[] = {
+ {
+ 0x00,
+ L"VGA compatible",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"8514 compatible",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCIPIFClass_0604[] = {
+ {
+ 0x00,
+ L"",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"Subtractive decode",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCIPIFClass_0609[] = {
+ {
+ 0x40,
+ L"Primary PCI bus side facing the system host processor",
+ PCIBlankEntry
+ },
+ {
+ 0x80,
+ L"Secondary PCI bus side facing the system host processor",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCIPIFClass_060b[] = {
+ {
+ 0x00,
+ L"Custom",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"ASI-SIG Defined Portal",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCIPIFClass_0700[] = {
+ {
+ 0x00,
+ L"Generic XT-compatible",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"16450-compatible",
+ PCIBlankEntry
+ },
+ {
+ 0x02,
+ L"16550-compatible",
+ PCIBlankEntry
+ },
+ {
+ 0x03,
+ L"16650-compatible",
+ PCIBlankEntry
+ },
+ {
+ 0x04,
+ L"16750-compatible",
+ PCIBlankEntry
+ },
+ {
+ 0x05,
+ L"16850-compatible",
+ PCIBlankEntry
+ },
+ {
+ 0x06,
+ L"16950-compatible",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCIPIFClass_0701[] = {
+ {
+ 0x00,
+ L"",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"Bi-directional",
+ PCIBlankEntry
+ },
+ {
+ 0x02,
+ L"ECP 1.X-compliant",
+ PCIBlankEntry
+ },
+ {
+ 0x03,
+ L"IEEE 1284",
+ PCIBlankEntry
+ },
+ {
+ 0xfe,
+ L"IEEE 1284 target (not a controller)",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCIPIFClass_0703[] = {
+ {
+ 0x00,
+ L"Generic",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"Hayes-compatible 16450",
+ PCIBlankEntry
+ },
+ {
+ 0x02,
+ L"Hayes-compatible 16550",
+ PCIBlankEntry
+ },
+ {
+ 0x03,
+ L"Hayes-compatible 16650",
+ PCIBlankEntry
+ },
+ {
+ 0x04,
+ L"Hayes-compatible 16750",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCIPIFClass_0800[] = {
+ {
+ 0x00,
+ L"Generic 8259",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"ISA",
+ PCIBlankEntry
+ },
+ {
+ 0x02,
+ L"EISA",
+ PCIBlankEntry
+ },
+ {
+ 0x10,
+ L"IO APIC",
+ PCIBlankEntry
+ },
+ {
+ 0x20,
+ L"IO(x) APIC interrupt controller",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCIPIFClass_0801[] = {
+ {
+ 0x00,
+ L"Generic 8237",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"ISA",
+ PCIBlankEntry
+ },
+ {
+ 0x02,
+ L"EISA",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCIPIFClass_0802[] = {
+ {
+ 0x00,
+ L"Generic 8254",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"ISA",
+ PCIBlankEntry
+ },
+ {
+ 0x02,
+ L"EISA",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCIPIFClass_0803[] = {
+ {
+ 0x00,
+ L"Generic",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"ISA",
+ PCIBlankEntry
+ },
+ {
+ 0x02,
+ L"EISA",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCIPIFClass_0904[] = {
+ {
+ 0x00,
+ L"Generic",
+ PCIBlankEntry
+ },
+ {
+ 0x10,
+ L"",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCIPIFClass_0c00[] = {
+ {
+ 0x00,
+ L"",
+ PCIBlankEntry
+ },
+ {
+ 0x10,
+ L"Using 1394 OpenHCI spec",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCIPIFClass_0c03[] = {
+ {
+ 0x00,
+ L"UHCI",
+ PCIBlankEntry
+ },
+ {
+ 0x10,
+ L"OHCI",
+ PCIBlankEntry
+ },
+ {
+ 0x20,
+ L"EHCI",
+ PCIBlankEntry
+ },
+ {
+ 0x30,
+ L"xHCI",
+ PCIBlankEntry
+ },
+ {
+ 0x80,
+ L"No specific programming interface",
+ PCIBlankEntry
+ },
+ {
+ 0xfe,
+ L"(Not Host Controller)",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCIPIFClass_0c07[] = {
+ {
+ 0x00,
+ L"SMIC",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"Keyboard Controller Style",
+ PCIBlankEntry
+ },
+ {
+ 0x02,
+ L"Block Transfer",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCIPIFClass_0d01[] = {
+ {
+ 0x00,
+ L"Consumer IR controller",
+ PCIBlankEntry
+ },
+ {
+ 0x10,
+ L"UWB Radio controller",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+PCI_CLASS_ENTRY PCIPIFClass_0e00[] = {
+ {
+ 0x00,
+ L"Message FIFO at offset 40h",
+ PCIBlankEntry
+ },
+ {
+ 0x01,
+ L"",
+ PCIBlankEntry
+ },
+ {
+ 0x00,
+ NULL,
+ /* null string ends the list */NULL
+ }
+};
+
+
+/**
+ Generates printable Unicode strings that represent PCI device class,
+ subclass and programmed I/F based on a value passed to the function.
+
+ @param[in] ClassCode Value representing the PCI "Class Code" register read from a
+ PCI device. The encodings are:
+ bits 23:16 - Base Class Code
+ bits 15:8 - Sub-Class Code
+ bits 7:0 - Programming Interface
+ @param[in, out] ClassStrings Pointer of PCI_CLASS_STRINGS structure, which contains
+ printable class strings corresponding to ClassCode. The
+ caller must not modify the strings that are pointed by
+ the fields in ClassStrings.
+**/
+VOID
+PciGetClassStrings (
+ IN UINT32 ClassCode,
+ IN OUT PCI_CLASS_STRINGS *ClassStrings
+ )
+{
+ INTN Index;
+ UINT8 Code;
+ PCI_CLASS_ENTRY *CurrentClass;
+
+ //
+ // Assume no strings found
+ //
+ ClassStrings->BaseClass = L"UNDEFINED";
+ ClassStrings->SubClass = L"UNDEFINED";
+ ClassStrings->PIFClass = L"UNDEFINED";
+
+ CurrentClass = gClassStringList;
+ Code = (UINT8) (ClassCode >> 16);
+ Index = 0;
+
+ //
+ // Go through all entries of the base class, until the entry with a matching
+ // base class code is found. If reaches an entry with a null description
+ // text, the last entry is met, which means no text for the base class was
+ // found, so no more action is needed.
+ //
+ while (Code != CurrentClass[Index].Code) {
+ if (NULL == CurrentClass[Index].DescText) {
+ return ;
+ }
+
+ Index++;
+ }
+ //
+ // A base class was found. Assign description, and check if this class has
+ // sub-class defined. If sub-class defined, no more action is needed,
+ // otherwise, continue to find description for the sub-class code.
+ //
+ ClassStrings->BaseClass = CurrentClass[Index].DescText;
+ if (NULL == CurrentClass[Index].LowerLevelClass) {
+ return ;
+ }
+ //
+ // find Subclass entry
+ //
+ CurrentClass = CurrentClass[Index].LowerLevelClass;
+ Code = (UINT8) (ClassCode >> 8);
+ Index = 0;
+
+ //
+ // Go through all entries of the sub-class, until the entry with a matching
+ // sub-class code is found. If reaches an entry with a null description
+ // text, the last entry is met, which means no text for the sub-class was
+ // found, so no more action is needed.
+ //
+ while (Code != CurrentClass[Index].Code) {
+ if (NULL == CurrentClass[Index].DescText) {
+ return ;
+ }
+
+ Index++;
+ }
+ //
+ // A class was found for the sub-class code. Assign description, and check if
+ // this sub-class has programming interface defined. If no, no more action is
+ // needed, otherwise, continue to find description for the programming
+ // interface.
+ //
+ ClassStrings->SubClass = CurrentClass[Index].DescText;
+ if (NULL == CurrentClass[Index].LowerLevelClass) {
+ return ;
+ }
+ //
+ // Find programming interface entry
+ //
+ CurrentClass = CurrentClass[Index].LowerLevelClass;
+ Code = (UINT8) ClassCode;
+ Index = 0;
+
+ //
+ // Go through all entries of the I/F entries, until the entry with a
+ // matching I/F code is found. If reaches an entry with a null description
+ // text, the last entry is met, which means no text was found, so no more
+ // action is needed.
+ //
+ while (Code != CurrentClass[Index].Code) {
+ if (NULL == CurrentClass[Index].DescText) {
+ return ;
+ }
+
+ Index++;
+ }
+ //
+ // A class was found for the I/F code. Assign description, done!
+ //
+ ClassStrings->PIFClass = CurrentClass[Index].DescText;
+ return ;
+}
+
+/**
+ Print strings that represent PCI device class, subclass and programmed I/F.
+
+ @param[in] ClassCodePtr Points to the memory which stores register Class Code in PCI
+ configuration space.
+ @param[in] IncludePIF If the printed string should include the programming I/F part
+**/
+VOID
+PciPrintClassCode (
+ IN UINT8 *ClassCodePtr,
+ IN BOOLEAN IncludePIF
+ )
+{
+ UINT32 ClassCode;
+ PCI_CLASS_STRINGS ClassStrings;
+
+ ClassCode = 0;
+ ClassCode |= (UINT32)ClassCodePtr[0];
+ ClassCode |= (UINT32)(ClassCodePtr[1] << 8);
+ ClassCode |= (UINT32)(ClassCodePtr[2] << 16);
+
+ //
+ // Get name from class code
+ //
+ PciGetClassStrings (ClassCode, &ClassStrings);
+
+ if (IncludePIF) {
+ //
+ // Print base class, sub class, and programming inferface name
+ //
+ ShellPrintEx (-1, -1, L"%s - %s - %s",
+ ClassStrings.BaseClass,
+ ClassStrings.SubClass,
+ ClassStrings.PIFClass
+ );
+
+ } else {
+ //
+ // Only print base class and sub class name
+ //
+ ShellPrintEx (-1, -1, L"%s - %s",
+ ClassStrings.BaseClass,
+ ClassStrings.SubClass
+ );
+ }
+}
+
+/**
+ This function finds out the protocol which is in charge of the given
+ segment, and its bus range covers the current bus number. It lookes
+ each instances of RootBridgeIoProtocol handle, until the one meets the
+ criteria is found.
+
+ @param[in] HandleBuf Buffer which holds all PCI_ROOT_BRIDIGE_IO_PROTOCOL handles.
+ @param[in] HandleCount Count of all PCI_ROOT_BRIDIGE_IO_PROTOCOL handles.
+ @param[in] Segment Segment number of device we are dealing with.
+ @param[in] Bus Bus number of device we are dealing with.
+ @param[out] IoDev Handle used to access configuration space of PCI device.
+
+ @retval EFI_SUCCESS The command completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+
+**/
+EFI_STATUS
+PciFindProtocolInterface (
+ IN EFI_HANDLE *HandleBuf,
+ IN UINTN HandleCount,
+ IN UINT16 Segment,
+ IN UINT16 Bus,
+ OUT EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL **IoDev
+ );
+
+/**
+ This function gets the protocol interface from the given handle, and
+ obtains its address space descriptors.
+
+ @param[in] Handle The PCI_ROOT_BRIDIGE_IO_PROTOCOL handle.
+ @param[out] IoDev Handle used to access configuration space of PCI device.
+ @param[out] Descriptors Points to the address space descriptors.
+
+ @retval EFI_SUCCESS The command completed successfully
+**/
+EFI_STATUS
+PciGetProtocolAndResource (
+ IN EFI_HANDLE Handle,
+ OUT EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL **IoDev,
+ OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors
+ );
+
+/**
+ This function get the next bus range of given address space descriptors.
+ It also moves the pointer backward a node, to get prepared to be called
+ again.
+
+ @param[in, out] Descriptors Points to current position of a serial of address space
+ descriptors.
+ @param[out] MinBus The lower range of bus number.
+ @param[out] MaxBus The upper range of bus number.
+ @param[out] IsEnd Meet end of the serial of descriptors.
+
+ @retval EFI_SUCCESS The command completed successfully.
+**/
+EFI_STATUS
+PciGetNextBusRange (
+ IN OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,
+ OUT UINT16 *MinBus,
+ OUT UINT16 *MaxBus,
+ OUT BOOLEAN *IsEnd
+ );
+
+/**
+ Explain the data in PCI configuration space. The part which is common for
+ PCI device and bridge is interpreted in this function. It calls other
+ functions to interpret data unique for device or bridge.
+
+ @param[in] ConfigSpace Data in PCI configuration space.
+ @param[in] Address Address used to access configuration space of this PCI device.
+ @param[in] IoDev Handle used to access configuration space of PCI device.
+ @param[in] EnhancedDump The print format for the dump data.
+
+ @retval EFI_SUCCESS The command completed successfully.
+**/
+EFI_STATUS
+PciExplainData (
+ IN PCI_CONFIG_SPACE *ConfigSpace,
+ IN UINT64 Address,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ IN CONST UINT16 EnhancedDump
+ );
+
+/**
+ Explain the device specific part of data in PCI configuration space.
+
+ @param[in] Device Data in PCI configuration space.
+ @param[in] Address Address used to access configuration space of this PCI device.
+ @param[in] IoDev Handle used to access configuration space of PCI device.
+
+ @retval EFI_SUCCESS The command completed successfully.
+**/
+EFI_STATUS
+PciExplainDeviceData (
+ IN PCI_DEVICE_HEADER *Device,
+ IN UINT64 Address,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev
+ );
+
+/**
+ Explain the bridge specific part of data in PCI configuration space.
+
+ @param[in] Bridge Bridge specific data region in PCI configuration space.
+ @param[in] Address Address used to access configuration space of this PCI device.
+ @param[in] IoDev Handle used to access configuration space of PCI device.
+
+ @retval EFI_SUCCESS The command completed successfully.
+**/
+EFI_STATUS
+PciExplainBridgeData (
+ IN PCI_BRIDGE_HEADER *Bridge,
+ IN UINT64 Address,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev
+ );
+
+/**
+ Explain the Base Address Register(Bar) in PCI configuration space.
+
+ @param[in] Bar Points to the Base Address Register intended to interpret.
+ @param[in] Command Points to the register Command.
+ @param[in] Address Address used to access configuration space of this PCI device.
+ @param[in] IoDev Handle used to access configuration space of PCI device.
+ @param[in, out] Index The Index.
+
+ @retval EFI_SUCCESS The command completed successfully.
+**/
+EFI_STATUS
+PciExplainBar (
+ IN UINT32 *Bar,
+ IN UINT16 *Command,
+ IN UINT64 Address,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ IN OUT UINTN *Index
+ );
+
+/**
+ Explain the cardbus specific part of data in PCI configuration space.
+
+ @param[in] CardBus CardBus specific region of PCI configuration space.
+ @param[in] Address Address used to access configuration space of this PCI device.
+ @param[in] IoDev Handle used to access configuration space of PCI device.
+
+ @retval EFI_SUCCESS The command completed successfully.
+**/
+EFI_STATUS
+PciExplainCardBusData (
+ IN PCI_CARDBUS_HEADER *CardBus,
+ IN UINT64 Address,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev
+ );
+
+/**
+ Explain each meaningful bit of register Status. The definition of Status is
+ slightly different depending on the PCI header type.
+
+ @param[in] Status Points to the content of register Status.
+ @param[in] MainStatus Indicates if this register is main status(not secondary
+ status).
+ @param[in] HeaderType Header type of this PCI device.
+
+ @retval EFI_SUCCESS The command completed successfully.
+**/
+EFI_STATUS
+PciExplainStatus (
+ IN UINT16 *Status,
+ IN BOOLEAN MainStatus,
+ IN PCI_HEADER_TYPE HeaderType
+ );
+
+/**
+ Explain each meaningful bit of register Command.
+
+ @param[in] Command Points to the content of register Command.
+
+ @retval EFI_SUCCESS The command completed successfully.
+**/
+EFI_STATUS
+PciExplainCommand (
+ IN UINT16 *Command
+ );
+
+/**
+ Explain each meaningful bit of register Bridge Control.
+
+ @param[in] BridgeControl Points to the content of register Bridge Control.
+ @param[in] HeaderType The headertype.
+
+ @retval EFI_SUCCESS The command completed successfully.
+**/
+EFI_STATUS
+PciExplainBridgeControl (
+ IN UINT16 *BridgeControl,
+ IN PCI_HEADER_TYPE HeaderType
+ );
+
+/**
+ Print each capability structure.
+
+ @param[in] IoDev The pointer to the deivce.
+ @param[in] Address The address to start at.
+ @param[in] CapPtr The offset from the address.
+ @param[in] EnhancedDump The print format for the dump data.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+PciExplainCapabilityStruct (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ IN UINT64 Address,
+ IN UINT8 CapPtr,
+ IN CONST UINT16 EnhancedDump
+ );
+
+/**
+ Display Pcie device structure.
+
+ @param[in] IoDev The pointer to the root pci protocol.
+ @param[in] Address The Address to start at.
+ @param[in] CapabilityPtr The offset from the address to start.
+ @param[in] EnhancedDump The print format for the dump data.
+
+ @retval EFI_SUCCESS The command completed successfully.
+ @retval @retval EFI_SUCCESS Pci express extend space IO is not suppoted.
+**/
+EFI_STATUS
+PciExplainPciExpress (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ IN UINT64 Address,
+ IN UINT8 CapabilityPtr,
+ IN CONST UINT16 EnhancedDump
+ );
+
+/**
+ Print out information of the capability information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieCapReg (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ );
+
+/**
+ Print out information of the device capability information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieDeviceCap (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ );
+
+/**
+ Print out information of the device control information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieDeviceControl (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ );
+
+/**
+ Print out information of the device status information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieDeviceStatus (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ );
+
+/**
+ Print out information of the device link information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieLinkCap (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ );
+
+/**
+ Print out information of the device link control information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieLinkControl (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ );
+
+/**
+ Print out information of the device link status information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieLinkStatus (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ );
+
+/**
+ Print out information of the device slot information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieSlotCap (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ );
+
+/**
+ Print out information of the device slot control information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieSlotControl (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ );
+
+/**
+ Print out information of the device slot status information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieSlotStatus (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ );
+
+/**
+ Print out information of the device root information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieRootControl (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ );
+
+/**
+ Print out information of the device root capability information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieRootCap (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ );
+
+/**
+ Print out information of the device root status information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieRootStatus (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ );
+
+typedef EFI_STATUS (*PCIE_EXPLAIN_FUNCTION) (IN PCIE_CAP_STRUCTURE *PciExpressCap);
+
+typedef enum {
+ FieldWidthUINT8,
+ FieldWidthUINT16,
+ FieldWidthUINT32
+} PCIE_CAPREG_FIELD_WIDTH;
+
+typedef enum {
+ PcieExplainTypeCommon,
+ PcieExplainTypeDevice,
+ PcieExplainTypeLink,
+ PcieExplainTypeSlot,
+ PcieExplainTypeRoot,
+ PcieExplainTypeMax
+} PCIE_EXPLAIN_TYPE;
+
+typedef struct
+{
+ UINT16 Token;
+ UINTN Offset;
+ PCIE_CAPREG_FIELD_WIDTH Width;
+ PCIE_EXPLAIN_FUNCTION Func;
+ PCIE_EXPLAIN_TYPE Type;
+} PCIE_EXPLAIN_STRUCT;
+
+PCIE_EXPLAIN_STRUCT PcieExplainList[] = {
+ {
+ STRING_TOKEN (STR_PCIEX_CAPABILITY_CAPID),
+ 0x00,
+ FieldWidthUINT8,
+ NULL,
+ PcieExplainTypeCommon
+ },
+ {
+ STRING_TOKEN (STR_PCIEX_NEXTCAP_PTR),
+ 0x01,
+ FieldWidthUINT8,
+ NULL,
+ PcieExplainTypeCommon
+ },
+ {
+ STRING_TOKEN (STR_PCIEX_CAP_REGISTER),
+ 0x02,
+ FieldWidthUINT16,
+ ExplainPcieCapReg,
+ PcieExplainTypeCommon
+ },
+ {
+ STRING_TOKEN (STR_PCIEX_DEVICE_CAP),
+ 0x04,
+ FieldWidthUINT32,
+ ExplainPcieDeviceCap,
+ PcieExplainTypeDevice
+ },
+ {
+ STRING_TOKEN (STR_PCIEX_DEVICE_CONTROL),
+ 0x08,
+ FieldWidthUINT16,
+ ExplainPcieDeviceControl,
+ PcieExplainTypeDevice
+ },
+ {
+ STRING_TOKEN (STR_PCIEX_DEVICE_STATUS),
+ 0x0a,
+ FieldWidthUINT16,
+ ExplainPcieDeviceStatus,
+ PcieExplainTypeDevice
+ },
+ {
+ STRING_TOKEN (STR_PCIEX_LINK_CAPABILITIES),
+ 0x0c,
+ FieldWidthUINT32,
+ ExplainPcieLinkCap,
+ PcieExplainTypeLink
+ },
+ {
+ STRING_TOKEN (STR_PCIEX_LINK_CONTROL),
+ 0x10,
+ FieldWidthUINT16,
+ ExplainPcieLinkControl,
+ PcieExplainTypeLink
+ },
+ {
+ STRING_TOKEN (STR_PCIEX_LINK_STATUS),
+ 0x12,
+ FieldWidthUINT16,
+ ExplainPcieLinkStatus,
+ PcieExplainTypeLink
+ },
+ {
+ STRING_TOKEN (STR_PCIEX_SLOT_CAPABILITIES),
+ 0x14,
+ FieldWidthUINT32,
+ ExplainPcieSlotCap,
+ PcieExplainTypeSlot
+ },
+ {
+ STRING_TOKEN (STR_PCIEX_SLOT_CONTROL),
+ 0x18,
+ FieldWidthUINT16,
+ ExplainPcieSlotControl,
+ PcieExplainTypeSlot
+ },
+ {
+ STRING_TOKEN (STR_PCIEX_SLOT_STATUS),
+ 0x1a,
+ FieldWidthUINT16,
+ ExplainPcieSlotStatus,
+ PcieExplainTypeSlot
+ },
+ {
+ STRING_TOKEN (STR_PCIEX_ROOT_CONTROL),
+ 0x1c,
+ FieldWidthUINT16,
+ ExplainPcieRootControl,
+ PcieExplainTypeRoot
+ },
+ {
+ STRING_TOKEN (STR_PCIEX_RSVDP),
+ 0x1e,
+ FieldWidthUINT16,
+ ExplainPcieRootCap,
+ PcieExplainTypeRoot
+ },
+ {
+ STRING_TOKEN (STR_PCIEX_ROOT_STATUS),
+ 0x20,
+ FieldWidthUINT32,
+ ExplainPcieRootStatus,
+ PcieExplainTypeRoot
+ },
+ {
+ 0,
+ 0,
+ (PCIE_CAPREG_FIELD_WIDTH)0,
+ NULL,
+ PcieExplainTypeMax
+ }
+};
+
+//
+// Global Variables
+//
+PCI_CONFIG_SPACE *mConfigSpace = NULL;
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-s", TypeValue},
+ {L"-i", TypeFlag},
+ {L"-_e", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+CHAR16 *DevicePortTypeTable[] = {
+ L"PCI Express Endpoint",
+ L"Legacy PCI Express Endpoint",
+ L"Unknown Type",
+ L"Unknonw Type",
+ L"Root Port of PCI Express Root Complex",
+ L"Upstream Port of PCI Express Switch",
+ L"Downstream Port of PCI Express Switch",
+ L"PCI Express to PCI/PCI-X Bridge",
+ L"PCI/PCI-X to PCI Express Bridge",
+ L"Root Complex Integrated Endpoint",
+ L"Root Complex Event Collector"
+};
+
+CHAR16 *L0sLatencyStrTable[] = {
+ L"Less than 64ns",
+ L"64ns to less than 128ns",
+ L"128ns to less than 256ns",
+ L"256ns to less than 512ns",
+ L"512ns to less than 1us",
+ L"1us to less than 2us",
+ L"2us-4us",
+ L"More than 4us"
+};
+
+CHAR16 *L1LatencyStrTable[] = {
+ L"Less than 1us",
+ L"1us to less than 2us",
+ L"2us to less than 4us",
+ L"4us to less than 8us",
+ L"8us to less than 16us",
+ L"16us to less than 32us",
+ L"32us-64us",
+ L"More than 64us"
+};
+
+CHAR16 *ASPMCtrlStrTable[] = {
+ L"Disabled",
+ L"L0s Entry Enabled",
+ L"L1 Entry Enabled",
+ L"L0s and L1 Entry Enabled"
+};
+
+CHAR16 *SlotPwrLmtScaleTable[] = {
+ L"1.0x",
+ L"0.1x",
+ L"0.01x",
+ L"0.001x"
+};
+
+CHAR16 *IndicatorTable[] = {
+ L"Reserved",
+ L"On",
+ L"Blink",
+ L"Off"
+};
+
+
+/**
+ Function for 'pci' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunPci (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ UINT16 Segment;
+ UINT16 Bus;
+ UINT16 Device;
+ UINT16 Func;
+ UINT64 Address;
+ EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev;
+ EFI_STATUS Status;
+ PCI_COMMON_HEADER PciHeader;
+ PCI_CONFIG_SPACE ConfigSpace;
+ UINTN ScreenCount;
+ UINTN TempColumn;
+ UINTN ScreenSize;
+ BOOLEAN ExplainData;
+ UINTN Index;
+ UINTN SizeOfHeader;
+ BOOLEAN PrintTitle;
+ UINTN HandleBufSize;
+ EFI_HANDLE *HandleBuf;
+ UINTN HandleCount;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
+ UINT16 MinBus;
+ UINT16 MaxBus;
+ BOOLEAN IsEnd;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ CONST CHAR16 *Temp;
+ UINT64 RetVal;
+ UINT16 EnhancedDump;
+
+ ShellStatus = SHELL_SUCCESS;
+ Status = EFI_SUCCESS;
+ Address = 0;
+ IoDev = NULL;
+ HandleBuf = NULL;
+ Package = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"pci", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+
+ if (ShellCommandLineGetCount(Package) == 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"pci");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if (ShellCommandLineGetCount(Package) > 4) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"pci");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ if (ShellCommandLineGetFlag(Package, L"-s") && ShellCommandLineGetValue(Package, L"-s") == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"pci", L"-s");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ //
+ // Get all instances of PciRootBridgeIo. Allocate space for 1 EFI_HANDLE and
+ // call LibLocateHandle(), if EFI_BUFFER_TOO_SMALL is returned, allocate enough
+ // space for handles and call it again.
+ //
+ HandleBufSize = sizeof (EFI_HANDLE);
+ HandleBuf = (EFI_HANDLE *) AllocateZeroPool (HandleBufSize);
+ if (HandleBuf == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle, L"pci");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ Status = gBS->LocateHandle (
+ ByProtocol,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ NULL,
+ &HandleBufSize,
+ HandleBuf
+ );
+
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HandleBuf = ReallocatePool (sizeof (EFI_HANDLE), HandleBufSize, HandleBuf);
+ if (HandleBuf == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle, L"pci");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ Status = gBS->LocateHandle (
+ ByProtocol,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ NULL,
+ &HandleBufSize,
+ HandleBuf
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PCIRBIO_NF), gShellDebug1HiiHandle, L"pci");
+ ShellStatus = SHELL_NOT_FOUND;
+ goto Done;
+ }
+
+ HandleCount = HandleBufSize / sizeof (EFI_HANDLE);
+ //
+ // Argument Count == 1(no other argument): enumerate all pci functions
+ //
+ if (ShellCommandLineGetCount(Package) == 1) {
+ gST->ConOut->QueryMode (
+ gST->ConOut,
+ gST->ConOut->Mode->Mode,
+ &TempColumn,
+ &ScreenSize
+ );
+
+ ScreenCount = 0;
+ ScreenSize -= 4;
+ if ((ScreenSize & 1) == 1) {
+ ScreenSize -= 1;
+ }
+
+ PrintTitle = TRUE;
+
+ //
+ // For each handle, which decides a segment and a bus number range,
+ // enumerate all devices on it.
+ //
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = PciGetProtocolAndResource (
+ HandleBuf[Index],
+ &IoDev,
+ &Descriptors
+ );
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_HANDLE_CFG_ERR), gShellDebug1HiiHandle, L"pci");
+ ShellStatus = SHELL_NOT_FOUND;
+ goto Done;
+ }
+ //
+ // No document say it's impossible for a RootBridgeIo protocol handle
+ // to have more than one address space descriptors, so find out every
+ // bus range and for each of them do device enumeration.
+ //
+ while (TRUE) {
+ Status = PciGetNextBusRange (&Descriptors, &MinBus, &MaxBus, &IsEnd);
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_BUS_RANGE_ERR), gShellDebug1HiiHandle, L"pci");
+ ShellStatus = SHELL_NOT_FOUND;
+ goto Done;
+ }
+
+ if (IsEnd) {
+ break;
+ }
+
+ for (Bus = MinBus; Bus <= MaxBus; Bus++) {
+ //
+ // For each devices, enumerate all functions it contains
+ //
+ for (Device = 0; Device <= PCI_MAX_DEVICE; Device++) {
+ //
+ // For each function, read its configuration space and print summary
+ //
+ for (Func = 0; Func <= PCI_MAX_FUNC; Func++) {
+ if (ShellGetExecutionBreakFlag ()) {
+ ShellStatus = SHELL_ABORTED;
+ goto Done;
+ }
+ Address = CALC_EFI_PCI_ADDRESS (Bus, Device, Func, 0);
+ IoDev->Pci.Read (
+ IoDev,
+ EfiPciWidthUint16,
+ Address,
+ 1,
+ &PciHeader.VendorId
+ );
+
+ //
+ // If VendorId = 0xffff, there does not exist a device at this
+ // location. For each device, if there is any function on it,
+ // there must be 1 function at Function 0. So if Func = 0, there
+ // will be no more functions in the same device, so we can break
+ // loop to deal with the next device.
+ //
+ if (PciHeader.VendorId == 0xffff && Func == 0) {
+ break;
+ }
+
+ if (PciHeader.VendorId != 0xffff) {
+
+ if (PrintTitle) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_TITLE), gShellDebug1HiiHandle);
+ PrintTitle = FALSE;
+ }
+
+ IoDev->Pci.Read (
+ IoDev,
+ EfiPciWidthUint32,
+ Address,
+ sizeof (PciHeader) / sizeof (UINT32),
+ &PciHeader
+ );
+
+ ShellPrintHiiEx(
+ -1, -1, NULL, STRING_TOKEN (STR_PCI_LINE_P1), gShellDebug1HiiHandle,
+ IoDev->SegmentNumber,
+ Bus,
+ Device,
+ Func
+ );
+
+ PciPrintClassCode (PciHeader.ClassCode, FALSE);
+ ShellPrintHiiEx(
+ -1, -1, NULL, STRING_TOKEN (STR_PCI_LINE_P2), gShellDebug1HiiHandle,
+ PciHeader.VendorId,
+ PciHeader.DeviceId,
+ PciHeader.ClassCode[0]
+ );
+
+ ScreenCount += 2;
+ if (ScreenCount >= ScreenSize && ScreenSize != 0) {
+ //
+ // If ScreenSize == 0 we have the console redirected so don't
+ // block updates
+ //
+ ScreenCount = 0;
+ }
+ //
+ // If this is not a multi-function device, we can leave the loop
+ // to deal with the next device.
+ //
+ if (Func == 0 && ((PciHeader.HeaderType & HEADER_TYPE_MULTI_FUNCTION) == 0x00)) {
+ break;
+ }
+ }
+ }
+ }
+ }
+ //
+ // If Descriptor is NULL, Configuration() returns EFI_UNSUPPRORED,
+ // we assume the bus range is 0~PCI_MAX_BUS. After enumerated all
+ // devices on all bus, we can leave loop.
+ //
+ if (Descriptors == NULL) {
+ break;
+ }
+ }
+ }
+
+ Status = EFI_SUCCESS;
+ goto Done;
+ }
+
+ ExplainData = FALSE;
+ Segment = 0;
+ Bus = 0;
+ Device = 0;
+ Func = 0;
+ if (ShellCommandLineGetFlag(Package, L"-i")) {
+ ExplainData = TRUE;
+ }
+
+ Temp = ShellCommandLineGetValue(Package, L"-s");
+ if (Temp != NULL) {
+ //
+ // Input converted to hexadecimal number.
+ //
+ if (!EFI_ERROR (ShellConvertStringToUint64 (Temp, &RetVal, TRUE, TRUE))) {
+ Segment = (UINT16) RetVal;
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV_HEX), gShellDebug1HiiHandle, L"pci", Temp);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ }
+
+ //
+ // The first Argument(except "-i") is assumed to be Bus number, second
+ // to be Device number, and third to be Func number.
+ //
+ Temp = ShellCommandLineGetRawValue(Package, 1);
+ if (Temp != NULL) {
+ //
+ // Input converted to hexadecimal number.
+ //
+ if (!EFI_ERROR (ShellConvertStringToUint64 (Temp, &RetVal, TRUE, TRUE))) {
+ Bus = (UINT16) RetVal;
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV_HEX), gShellDebug1HiiHandle, L"pci", Temp);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if (Bus > MAX_BUS_NUMBER) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"pci", Temp);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ }
+ Temp = ShellCommandLineGetRawValue(Package, 2);
+ if (Temp != NULL) {
+ //
+ // Input converted to hexadecimal number.
+ //
+ if (!EFI_ERROR (ShellConvertStringToUint64 (Temp, &RetVal, TRUE, TRUE))) {
+ Device = (UINT16) RetVal;
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV_HEX), gShellDebug1HiiHandle, L"pci", Temp);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if (Device > MAX_DEVICE_NUMBER){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"pci", Temp);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ }
+
+ Temp = ShellCommandLineGetRawValue(Package, 3);
+ if (Temp != NULL) {
+ //
+ // Input converted to hexadecimal number.
+ //
+ if (!EFI_ERROR (ShellConvertStringToUint64 (Temp, &RetVal, TRUE, TRUE))) {
+ Func = (UINT16) RetVal;
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV_HEX), gShellDebug1HiiHandle, L"pci", Temp);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ if (Func > MAX_FUNCTION_NUMBER){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"pci", Temp);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ }
+
+ //
+ // Find the protocol interface who's in charge of current segment, and its
+ // bus range covers the current bus
+ //
+ Status = PciFindProtocolInterface (
+ HandleBuf,
+ HandleCount,
+ Segment,
+ Bus,
+ &IoDev
+ );
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(
+ -1, -1, NULL, STRING_TOKEN (STR_PCI_NO_FIND), gShellDebug1HiiHandle, L"pci",
+ Segment,
+ Bus
+ );
+ ShellStatus = SHELL_NOT_FOUND;
+ goto Done;
+ }
+
+ Address = CALC_EFI_PCI_ADDRESS (Bus, Device, Func, 0);
+ Status = IoDev->Pci.Read (
+ IoDev,
+ EfiPciWidthUint8,
+ Address,
+ sizeof (ConfigSpace),
+ &ConfigSpace
+ );
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_NO_CFG), gShellDebug1HiiHandle, L"pci");
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto Done;
+ }
+
+ mConfigSpace = &ConfigSpace;
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_PCI_INFO),
+ gShellDebug1HiiHandle,
+ Segment,
+ Bus,
+ Device,
+ Func,
+ Segment,
+ Bus,
+ Device,
+ Func
+ );
+
+ //
+ // Dump standard header of configuration space
+ //
+ SizeOfHeader = sizeof (ConfigSpace.Common) + sizeof (ConfigSpace.NonCommon);
+
+ DumpHex (2, 0, SizeOfHeader, &ConfigSpace);
+ ShellPrintEx(-1,-1, L"\r\n");
+
+ //
+ // Dump device dependent Part of configuration space
+ //
+ DumpHex (
+ 2,
+ SizeOfHeader,
+ sizeof (ConfigSpace) - SizeOfHeader,
+ ConfigSpace.Data
+ );
+
+ //
+ // If "-i" appears in command line, interpret data in configuration space
+ //
+ if (ExplainData) {
+ EnhancedDump = 0;
+ if (ShellCommandLineGetFlag(Package, L"-_e")) {
+ EnhancedDump = 0xFFFF;
+ Temp = ShellCommandLineGetValue(Package, L"-_e");
+ if (Temp != NULL) {
+ EnhancedDump = (UINT16) ShellHexStrToUintn (Temp);
+ }
+ }
+ Status = PciExplainData (&ConfigSpace, Address, IoDev, EnhancedDump);
+ }
+ }
+Done:
+ if (HandleBuf != NULL) {
+ FreePool (HandleBuf);
+ }
+ if (Package != NULL) {
+ ShellCommandLineFreeVarList (Package);
+ }
+ mConfigSpace = NULL;
+ return ShellStatus;
+}
+
+/**
+ This function finds out the protocol which is in charge of the given
+ segment, and its bus range covers the current bus number. It lookes
+ each instances of RootBridgeIoProtocol handle, until the one meets the
+ criteria is found.
+
+ @param[in] HandleBuf Buffer which holds all PCI_ROOT_BRIDIGE_IO_PROTOCOL handles.
+ @param[in] HandleCount Count of all PCI_ROOT_BRIDIGE_IO_PROTOCOL handles.
+ @param[in] Segment Segment number of device we are dealing with.
+ @param[in] Bus Bus number of device we are dealing with.
+ @param[out] IoDev Handle used to access configuration space of PCI device.
+
+ @retval EFI_SUCCESS The command completed successfully.
+ @retval EFI_INVALID_PARAMETER Invalid parameter.
+
+**/
+EFI_STATUS
+PciFindProtocolInterface (
+ IN EFI_HANDLE *HandleBuf,
+ IN UINTN HandleCount,
+ IN UINT16 Segment,
+ IN UINT16 Bus,
+ OUT EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL **IoDev
+ )
+{
+ UINTN Index;
+ EFI_STATUS Status;
+ EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *Descriptors;
+ UINT16 MinBus;
+ UINT16 MaxBus;
+ BOOLEAN IsEnd;
+
+ //
+ // Go through all handles, until the one meets the criteria is found
+ //
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = PciGetProtocolAndResource (HandleBuf[Index], IoDev, &Descriptors);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // When Descriptors == NULL, the Configuration() is not implemented,
+ // so we only check the Segment number
+ //
+ if (Descriptors == NULL && Segment == (*IoDev)->SegmentNumber) {
+ return EFI_SUCCESS;
+ }
+
+ if ((*IoDev)->SegmentNumber != Segment) {
+ continue;
+ }
+
+ while (TRUE) {
+ Status = PciGetNextBusRange (&Descriptors, &MinBus, &MaxBus, &IsEnd);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (IsEnd) {
+ break;
+ }
+
+ if (MinBus <= Bus && MaxBus >= Bus) {
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ This function gets the protocol interface from the given handle, and
+ obtains its address space descriptors.
+
+ @param[in] Handle The PCI_ROOT_BRIDIGE_IO_PROTOCOL handle.
+ @param[out] IoDev Handle used to access configuration space of PCI device.
+ @param[out] Descriptors Points to the address space descriptors.
+
+ @retval EFI_SUCCESS The command completed successfully
+**/
+EFI_STATUS
+PciGetProtocolAndResource (
+ IN EFI_HANDLE Handle,
+ OUT EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL **IoDev,
+ OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Get inferface from protocol
+ //
+ Status = gBS->HandleProtocol (
+ Handle,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ (VOID**)IoDev
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // Call Configuration() to get address space descriptors
+ //
+ Status = (*IoDev)->Configuration (*IoDev, (VOID**)Descriptors);
+ if (Status == EFI_UNSUPPORTED) {
+ *Descriptors = NULL;
+ return EFI_SUCCESS;
+
+ } else {
+ return Status;
+ }
+}
+
+/**
+ This function get the next bus range of given address space descriptors.
+ It also moves the pointer backward a node, to get prepared to be called
+ again.
+
+ @param[in, out] Descriptors Points to current position of a serial of address space
+ descriptors.
+ @param[out] MinBus The lower range of bus number.
+ @param[out] MaxBus The upper range of bus number.
+ @param[out] IsEnd Meet end of the serial of descriptors.
+
+ @retval EFI_SUCCESS The command completed successfully.
+**/
+EFI_STATUS
+PciGetNextBusRange (
+ IN OUT EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR **Descriptors,
+ OUT UINT16 *MinBus,
+ OUT UINT16 *MaxBus,
+ OUT BOOLEAN *IsEnd
+ )
+{
+ *IsEnd = FALSE;
+
+ //
+ // When *Descriptors is NULL, Configuration() is not implemented, so assume
+ // range is 0~PCI_MAX_BUS
+ //
+ if ((*Descriptors) == NULL) {
+ *MinBus = 0;
+ *MaxBus = PCI_MAX_BUS;
+ return EFI_SUCCESS;
+ }
+ //
+ // *Descriptors points to one or more address space descriptors, which
+ // ends with a end tagged descriptor. Examine each of the descriptors,
+ // if a bus typed one is found and its bus range covers bus, this handle
+ // is the handle we are looking for.
+ //
+
+ while ((*Descriptors)->Desc != ACPI_END_TAG_DESCRIPTOR) {
+ if ((*Descriptors)->ResType == ACPI_ADDRESS_SPACE_TYPE_BUS) {
+ *MinBus = (UINT16) (*Descriptors)->AddrRangeMin;
+ *MaxBus = (UINT16) (*Descriptors)->AddrRangeMax;
+ (*Descriptors)++;
+ return (EFI_SUCCESS);
+ }
+
+ (*Descriptors)++;
+ }
+
+ if ((*Descriptors)->Desc == ACPI_END_TAG_DESCRIPTOR) {
+ *IsEnd = TRUE;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Explain the data in PCI configuration space. The part which is common for
+ PCI device and bridge is interpreted in this function. It calls other
+ functions to interpret data unique for device or bridge.
+
+ @param[in] ConfigSpace Data in PCI configuration space.
+ @param[in] Address Address used to access configuration space of this PCI device.
+ @param[in] IoDev Handle used to access configuration space of PCI device.
+ @param[in] EnhancedDump The print format for the dump data.
+
+ @retval EFI_SUCCESS The command completed successfully.
+**/
+EFI_STATUS
+PciExplainData (
+ IN PCI_CONFIG_SPACE *ConfigSpace,
+ IN UINT64 Address,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ IN CONST UINT16 EnhancedDump
+ )
+{
+ PCI_COMMON_HEADER *Common;
+ PCI_HEADER_TYPE HeaderType;
+ EFI_STATUS Status;
+ UINT8 CapPtr;
+
+ Common = &(ConfigSpace->Common);
+
+ ShellPrintEx (-1, -1, L"\r\n");
+
+ //
+ // Print Vendor Id and Device Id
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_LINE_VID_DID), gShellDebug1HiiHandle,
+ INDEX_OF (&(Common->VendorId)),
+ Common->VendorId,
+ INDEX_OF (&(Common->DeviceId)),
+ Common->DeviceId
+ );
+
+ //
+ // Print register Command
+ //
+ PciExplainCommand (&(Common->Command));
+
+ //
+ // Print register Status
+ //
+ PciExplainStatus (&(Common->Status), TRUE, PciUndefined);
+
+ //
+ // Print register Revision ID
+ //
+ ShellPrintEx(-1, -1, L"\r\n");
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_LINE_RID), gShellDebug1HiiHandle,
+ INDEX_OF (&(Common->RevisionId)),
+ Common->RevisionId
+ );
+
+ //
+ // Print register BIST
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_LINE_BIST), gShellDebug1HiiHandle, INDEX_OF (&(Common->Bist)));
+ if ((Common->Bist & PCI_BIT_7) != 0) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_LINE_CAP), gShellDebug1HiiHandle, 0x0f & Common->Bist);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_PCI_LINE_CAP_NO), gShellDebug1HiiHandle);
+ }
+ //
+ // Print register Cache Line Size
+ //
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_CACHE_LINE_SIZE),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(Common->CacheLineSize)),
+ Common->CacheLineSize
+ );
+
+ //
+ // Print register Latency Timer
+ //
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_LATENCY_TIMER),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(Common->PrimaryLatencyTimer)),
+ Common->PrimaryLatencyTimer
+ );
+
+ //
+ // Print register Header Type
+ //
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_HEADER_TYPE),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(Common->HeaderType)),
+ Common->HeaderType
+ );
+
+ if ((Common->HeaderType & PCI_BIT_7) != 0) {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_MULTI_FUNCTION), gShellDebug1HiiHandle);
+
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_SINGLE_FUNCTION), gShellDebug1HiiHandle);
+ }
+
+ HeaderType = (PCI_HEADER_TYPE)(UINT8) (Common->HeaderType & 0x7f);
+ switch (HeaderType) {
+ case PciDevice:
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_PCI_DEVICE), gShellDebug1HiiHandle);
+ break;
+
+ case PciP2pBridge:
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_P2P_BRIDGE), gShellDebug1HiiHandle);
+ break;
+
+ case PciCardBusBridge:
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_CARDBUS_BRIDGE), gShellDebug1HiiHandle);
+ break;
+
+ default:
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_RESERVED), gShellDebug1HiiHandle);
+ HeaderType = PciUndefined;
+ }
+
+ //
+ // Print register Class Code
+ //
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_CLASS), gShellDebug1HiiHandle);
+ PciPrintClassCode ((UINT8 *) Common->ClassCode, TRUE);
+ ShellPrintEx (-1, -1, L"\r\n");
+
+ if (ShellGetExecutionBreakFlag()) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Interpret remaining part of PCI configuration header depending on
+ // HeaderType
+ //
+ CapPtr = 0;
+ Status = EFI_SUCCESS;
+ switch (HeaderType) {
+ case PciDevice:
+ Status = PciExplainDeviceData (
+ &(ConfigSpace->NonCommon.Device),
+ Address,
+ IoDev
+ );
+ CapPtr = ConfigSpace->NonCommon.Device.CapabilitiesPtr;
+ break;
+
+ case PciP2pBridge:
+ Status = PciExplainBridgeData (
+ &(ConfigSpace->NonCommon.Bridge),
+ Address,
+ IoDev
+ );
+ CapPtr = ConfigSpace->NonCommon.Bridge.CapabilitiesPtr;
+ break;
+
+ case PciCardBusBridge:
+ Status = PciExplainCardBusData (
+ &(ConfigSpace->NonCommon.CardBus),
+ Address,
+ IoDev
+ );
+ CapPtr = ConfigSpace->NonCommon.CardBus.CapabilitiesPtr;
+ break;
+ case PciUndefined:
+ default:
+ break;
+ }
+ //
+ // If Status bit4 is 1, dump or explain capability structure
+ //
+ if ((Common->Status) & EFI_PCI_STATUS_CAPABILITY) {
+ PciExplainCapabilityStruct (IoDev, Address, CapPtr, EnhancedDump);
+ }
+
+ return Status;
+}
+
+/**
+ Explain the device specific part of data in PCI configuration space.
+
+ @param[in] Device Data in PCI configuration space.
+ @param[in] Address Address used to access configuration space of this PCI device.
+ @param[in] IoDev Handle used to access configuration space of PCI device.
+
+ @retval EFI_SUCCESS The command completed successfully.
+**/
+EFI_STATUS
+PciExplainDeviceData (
+ IN PCI_DEVICE_HEADER *Device,
+ IN UINT64 Address,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev
+ )
+{
+ UINTN Index;
+ BOOLEAN BarExist;
+ EFI_STATUS Status;
+ UINTN BarCount;
+
+ //
+ // Print Base Address Registers(Bar). When Bar = 0, this Bar does not
+ // exist. If these no Bar for this function, print "none", otherwise
+ // list detail information about this Bar.
+ //
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_BASE_ADDR), gShellDebug1HiiHandle, INDEX_OF (Device->Bar));
+
+ BarExist = FALSE;
+ BarCount = sizeof (Device->Bar) / sizeof (Device->Bar[0]);
+ for (Index = 0; Index < BarCount; Index++) {
+ if (Device->Bar[Index] == 0) {
+ continue;
+ }
+
+ if (!BarExist) {
+ BarExist = TRUE;
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_START_TYPE), gShellDebug1HiiHandle);
+ ShellPrintEx (-1, -1, L" --------------------------------------------------------------------------");
+ }
+
+ Status = PciExplainBar (
+ &(Device->Bar[Index]),
+ &(mConfigSpace->Common.Command),
+ Address,
+ IoDev,
+ &Index
+ );
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+
+ if (!BarExist) {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NONE), gShellDebug1HiiHandle);
+
+ } else {
+ ShellPrintEx (-1, -1, L"\r\n --------------------------------------------------------------------------");
+ }
+
+ //
+ // Print register Expansion ROM Base Address
+ //
+ if ((Device->ROMBar & PCI_BIT_0) == 0) {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_EXPANSION_ROM_DISABLED), gShellDebug1HiiHandle, INDEX_OF (&(Device->ROMBar)));
+
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_EXPANSION_ROM_BASE),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(Device->ROMBar)),
+ Device->ROMBar
+ );
+ }
+ //
+ // Print register Cardbus CIS ptr
+ //
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_CARDBUS_CIS),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(Device->CardBusCISPtr)),
+ Device->CardBusCISPtr
+ );
+
+ //
+ // Print register Sub-vendor ID and subsystem ID
+ //
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_SUB_VENDOR_ID),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(Device->SubVendorId)),
+ Device->SubVendorId
+ );
+
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_SUBSYSTEM_ID),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(Device->SubSystemId)),
+ Device->SubSystemId
+ );
+
+ //
+ // Print register Capabilities Ptr
+ //
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_CAPABILITIES_PTR),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(Device->CapabilitiesPtr)),
+ Device->CapabilitiesPtr
+ );
+
+ //
+ // Print register Interrupt Line and interrupt pin
+ //
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_INTERRUPT_LINE),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(Device->InterruptLine)),
+ Device->InterruptLine
+ );
+
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_INTERRUPT_PIN),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(Device->InterruptPin)),
+ Device->InterruptPin
+ );
+
+ //
+ // Print register Min_Gnt and Max_Lat
+ //
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_MIN_GNT),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(Device->MinGnt)),
+ Device->MinGnt
+ );
+
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_MAX_LAT),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(Device->MaxLat)),
+ Device->MaxLat
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Explain the bridge specific part of data in PCI configuration space.
+
+ @param[in] Bridge Bridge specific data region in PCI configuration space.
+ @param[in] Address Address used to access configuration space of this PCI device.
+ @param[in] IoDev Handle used to access configuration space of PCI device.
+
+ @retval EFI_SUCCESS The command completed successfully.
+**/
+EFI_STATUS
+PciExplainBridgeData (
+ IN PCI_BRIDGE_HEADER *Bridge,
+ IN UINT64 Address,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev
+ )
+{
+ UINTN Index;
+ BOOLEAN BarExist;
+ UINTN BarCount;
+ UINT32 IoAddress32;
+ EFI_STATUS Status;
+
+ //
+ // Print Base Address Registers. When Bar = 0, this Bar does not
+ // exist. If these no Bar for this function, print "none", otherwise
+ // list detail information about this Bar.
+ //
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_BASE_ADDRESS), gShellDebug1HiiHandle, INDEX_OF (&(Bridge->Bar)));
+
+ BarExist = FALSE;
+ BarCount = sizeof (Bridge->Bar) / sizeof (Bridge->Bar[0]);
+
+ for (Index = 0; Index < BarCount; Index++) {
+ if (Bridge->Bar[Index] == 0) {
+ continue;
+ }
+
+ if (!BarExist) {
+ BarExist = TRUE;
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_START_TYPE_2), gShellDebug1HiiHandle);
+ ShellPrintEx (-1, -1, L" --------------------------------------------------------------------------");
+ }
+
+ Status = PciExplainBar (
+ &(Bridge->Bar[Index]),
+ &(mConfigSpace->Common.Command),
+ Address,
+ IoDev,
+ &Index
+ );
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+ }
+
+ if (!BarExist) {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NONE), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintEx (-1, -1, L"\r\n --------------------------------------------------------------------------");
+ }
+
+ //
+ // Expansion register ROM Base Address
+ //
+ if ((Bridge->ROMBar & PCI_BIT_0) == 0) {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NO_EXPANSION_ROM), gShellDebug1HiiHandle, INDEX_OF (&(Bridge->ROMBar)));
+
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_EXPANSION_ROM_BASE_2),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(Bridge->ROMBar)),
+ Bridge->ROMBar
+ );
+ }
+ //
+ // Print Bus Numbers(Primary, Secondary, and Subordinate
+ //
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_BUS_NUMBERS),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(Bridge->PrimaryBus)),
+ INDEX_OF (&(Bridge->SecondaryBus)),
+ INDEX_OF (&(Bridge->SubordinateBus))
+ );
+
+ ShellPrintEx (-1, -1, L" ------------------------------------------------------\r\n");
+
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_BRIDGE), gShellDebug1HiiHandle, Bridge->PrimaryBus);
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_BRIDGE), gShellDebug1HiiHandle, Bridge->SecondaryBus);
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_BRIDGE), gShellDebug1HiiHandle, Bridge->SubordinateBus);
+
+ //
+ // Print register Secondary Latency Timer
+ //
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_SECONDARY_TIMER),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(Bridge->SecondaryLatencyTimer)),
+ Bridge->SecondaryLatencyTimer
+ );
+
+ //
+ // Print register Secondary Status
+ //
+ PciExplainStatus (&(Bridge->SecondaryStatus), FALSE, PciP2pBridge);
+
+ //
+ // Print I/O and memory ranges this bridge forwards. There are 3 resource
+ // types: I/O, memory, and pre-fetchable memory. For each resource type,
+ // base and limit address are listed.
+ //
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_RESOURCE_TYPE), gShellDebug1HiiHandle);
+ ShellPrintEx (-1, -1, L"----------------------------------------------------------------------\r\n");
+
+ //
+ // IO Base & Limit
+ //
+ IoAddress32 = (Bridge->IoBaseUpper << 16 | Bridge->IoBase << 8);
+ IoAddress32 &= 0xfffff000;
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_TWO_VARS),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(Bridge->IoBase)),
+ IoAddress32
+ );
+
+ IoAddress32 = (Bridge->IoLimitUpper << 16 | Bridge->IoLimit << 8);
+ IoAddress32 |= 0x00000fff;
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_ONE_VAR), gShellDebug1HiiHandle, IoAddress32);
+
+ //
+ // Memory Base & Limit
+ //
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_MEMORY),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(Bridge->MemoryBase)),
+ (Bridge->MemoryBase << 16) & 0xfff00000
+ );
+
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_ONE_VAR),
+ gShellDebug1HiiHandle,
+ (Bridge->MemoryLimit << 16) | 0x000fffff
+ );
+
+ //
+ // Pre-fetch-able Memory Base & Limit
+ //
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_PREFETCHABLE),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(Bridge->PrefetchableMemBase)),
+ Bridge->PrefetchableBaseUpper,
+ (Bridge->PrefetchableMemBase << 16) & 0xfff00000
+ );
+
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_TWO_VARS_2),
+ gShellDebug1HiiHandle,
+ Bridge->PrefetchableLimitUpper,
+ (Bridge->PrefetchableMemLimit << 16) | 0x000fffff
+ );
+
+ //
+ // Print register Capabilities Pointer
+ //
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_CAPABILITIES_PTR_2),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(Bridge->CapabilitiesPtr)),
+ Bridge->CapabilitiesPtr
+ );
+
+ //
+ // Print register Bridge Control
+ //
+ PciExplainBridgeControl (&(Bridge->BridgeControl), PciP2pBridge);
+
+ //
+ // Print register Interrupt Line & PIN
+ //
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_INTERRUPT_LINE_2),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(Bridge->InterruptLine)),
+ Bridge->InterruptLine
+ );
+
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_INTERRUPT_PIN),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(Bridge->InterruptPin)),
+ Bridge->InterruptPin
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Explain the Base Address Register(Bar) in PCI configuration space.
+
+ @param[in] Bar Points to the Base Address Register intended to interpret.
+ @param[in] Command Points to the register Command.
+ @param[in] Address Address used to access configuration space of this PCI device.
+ @param[in] IoDev Handle used to access configuration space of PCI device.
+ @param[in, out] Index The Index.
+
+ @retval EFI_SUCCESS The command completed successfully.
+**/
+EFI_STATUS
+PciExplainBar (
+ IN UINT32 *Bar,
+ IN UINT16 *Command,
+ IN UINT64 Address,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ IN OUT UINTN *Index
+ )
+{
+ UINT16 OldCommand;
+ UINT16 NewCommand;
+ UINT64 Bar64;
+ UINT32 OldBar32;
+ UINT32 NewBar32;
+ UINT64 OldBar64;
+ UINT64 NewBar64;
+ BOOLEAN IsMem;
+ BOOLEAN IsBar32;
+ UINT64 RegAddress;
+
+ IsBar32 = TRUE;
+ Bar64 = 0;
+ NewBar32 = 0;
+ NewBar64 = 0;
+
+ //
+ // According the bar type, list detail about this bar, for example: 32 or
+ // 64 bits; pre-fetchable or not.
+ //
+ if ((*Bar & PCI_BIT_0) == 0) {
+ //
+ // This bar is of memory type
+ //
+ IsMem = TRUE;
+
+ if ((*Bar & PCI_BIT_1) == 0 && (*Bar & PCI_BIT_2) == 0) {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_BAR), gShellDebug1HiiHandle, *Bar & 0xfffffff0);
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_MEM), gShellDebug1HiiHandle);
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_32_BITS), gShellDebug1HiiHandle);
+
+ } else if ((*Bar & PCI_BIT_1) == 0 && (*Bar & PCI_BIT_2) != 0) {
+ Bar64 = 0x0;
+ CopyMem (&Bar64, Bar, sizeof (UINT64));
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_ONE_VAR_2), gShellDebug1HiiHandle, (UINT32) RShiftU64 ((Bar64 & 0xfffffffffffffff0ULL), 32));
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_ONE_VAR_3), gShellDebug1HiiHandle, (UINT32) (Bar64 & 0xfffffffffffffff0ULL));
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_MEM), gShellDebug1HiiHandle);
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_64_BITS), gShellDebug1HiiHandle);
+ IsBar32 = FALSE;
+ *Index += 1;
+
+ } else {
+ //
+ // Reserved
+ //
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_BAR), gShellDebug1HiiHandle, *Bar & 0xfffffff0);
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_MEM_2), gShellDebug1HiiHandle);
+ }
+
+ if ((*Bar & PCI_BIT_3) == 0) {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NO), gShellDebug1HiiHandle);
+
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_YES), gShellDebug1HiiHandle);
+ }
+
+ } else {
+ //
+ // This bar is of io type
+ //
+ IsMem = FALSE;
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_ONE_VAR_4), gShellDebug1HiiHandle, *Bar & 0xfffffffc);
+ ShellPrintEx (-1, -1, L"I/O ");
+ }
+
+ //
+ // Get BAR length(or the amount of resource this bar demands for). To get
+ // Bar length, first we should temporarily disable I/O and memory access
+ // of this function(by set bits in the register Command), then write all
+ // "1"s to this bar. The bar value read back is the amount of resource
+ // this bar demands for.
+ //
+ //
+ // Disable io & mem access
+ //
+ OldCommand = *Command;
+ NewCommand = (UINT16) (OldCommand & 0xfffc);
+ RegAddress = Address | INDEX_OF (Command);
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, RegAddress, 1, &NewCommand);
+
+ RegAddress = Address | INDEX_OF (Bar);
+
+ //
+ // Read after write the BAR to get the size
+ //
+ if (IsBar32) {
+ OldBar32 = *Bar;
+ NewBar32 = 0xffffffff;
+
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, RegAddress, 1, &NewBar32);
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint32, RegAddress, 1, &NewBar32);
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, RegAddress, 1, &OldBar32);
+
+ if (IsMem) {
+ NewBar32 = NewBar32 & 0xfffffff0;
+ NewBar32 = (~NewBar32) + 1;
+
+ } else {
+ NewBar32 = NewBar32 & 0xfffffffc;
+ NewBar32 = (~NewBar32) + 1;
+ NewBar32 = NewBar32 & 0x0000ffff;
+ }
+ } else {
+
+ OldBar64 = 0x0;
+ CopyMem (&OldBar64, Bar, sizeof (UINT64));
+ NewBar64 = 0xffffffffffffffffULL;
+
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, RegAddress, 2, &NewBar64);
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint32, RegAddress, 2, &NewBar64);
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint32, RegAddress, 2, &OldBar64);
+
+ if (IsMem) {
+ NewBar64 = NewBar64 & 0xfffffffffffffff0ULL;
+ NewBar64 = (~NewBar64) + 1;
+
+ } else {
+ NewBar64 = NewBar64 & 0xfffffffffffffffcULL;
+ NewBar64 = (~NewBar64) + 1;
+ NewBar64 = NewBar64 & 0x000000000000ffff;
+ }
+ }
+ //
+ // Enable io & mem access
+ //
+ RegAddress = Address | INDEX_OF (Command);
+ IoDev->Pci.Write (IoDev, EfiPciWidthUint16, RegAddress, 1, &OldCommand);
+
+ if (IsMem) {
+ if (IsBar32) {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NEWBAR_32), gShellDebug1HiiHandle, NewBar32);
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NEWBAR_32_2), gShellDebug1HiiHandle, NewBar32 + (*Bar & 0xfffffff0) - 1);
+
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_RSHIFT), gShellDebug1HiiHandle, (UINT32) RShiftU64 (NewBar64, 32));
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_RSHIFT), gShellDebug1HiiHandle, (UINT32) NewBar64);
+ ShellPrintEx (-1, -1, L" ");
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_RSHIFT),
+ gShellDebug1HiiHandle,
+ (UINT32) RShiftU64 ((NewBar64 + (Bar64 & 0xfffffffffffffff0ULL) - 1), 32)
+ );
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_RSHIFT), gShellDebug1HiiHandle, (UINT32) (NewBar64 + (Bar64 & 0xfffffffffffffff0ULL) - 1));
+
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NEWBAR_32_3), gShellDebug1HiiHandle, NewBar32);
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NEWBAR_32_4), gShellDebug1HiiHandle, NewBar32 + (*Bar & 0xfffffffc) - 1);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Explain the cardbus specific part of data in PCI configuration space.
+
+ @param[in] CardBus CardBus specific region of PCI configuration space.
+ @param[in] Address Address used to access configuration space of this PCI device.
+ @param[in] IoDev Handle used to access configuration space of PCI device.
+
+ @retval EFI_SUCCESS The command completed successfully.
+**/
+EFI_STATUS
+PciExplainCardBusData (
+ IN PCI_CARDBUS_HEADER *CardBus,
+ IN UINT64 Address,
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev
+ )
+{
+ BOOLEAN Io32Bit;
+ PCI_CARDBUS_DATA *CardBusData;
+
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_CARDBUS_SOCKET),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(CardBus->CardBusSocketReg)),
+ CardBus->CardBusSocketReg
+ );
+
+ //
+ // Print Secondary Status
+ //
+ PciExplainStatus (&(CardBus->SecondaryStatus), FALSE, PciCardBusBridge);
+
+ //
+ // Print Bus Numbers(Primary bus number, CardBus bus number, and
+ // Subordinate bus number
+ //
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_BUS_NUMBERS_2),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(CardBus->PciBusNumber)),
+ INDEX_OF (&(CardBus->CardBusBusNumber)),
+ INDEX_OF (&(CardBus->SubordinateBusNumber))
+ );
+
+ ShellPrintEx (-1, -1, L" ------------------------------------------------------\r\n");
+
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_CARDBUS), gShellDebug1HiiHandle, CardBus->PciBusNumber);
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_CARDBUS_2), gShellDebug1HiiHandle, CardBus->CardBusBusNumber);
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_CARDBUS_3), gShellDebug1HiiHandle, CardBus->SubordinateBusNumber);
+
+ //
+ // Print CardBus Latency Timer
+ //
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_CARDBUS_LATENCY),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(CardBus->CardBusLatencyTimer)),
+ CardBus->CardBusLatencyTimer
+ );
+
+ //
+ // Print Memory/Io ranges this cardbus bridge forwards
+ //
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_RESOURCE_TYPE_2), gShellDebug1HiiHandle);
+ ShellPrintEx (-1, -1, L"----------------------------------------------------------------------\r\n");
+
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_MEM_3),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(CardBus->MemoryBase0)),
+ CardBus->BridgeControl & PCI_BIT_8 ? L" Prefetchable" : L"Non-Prefetchable",
+ CardBus->MemoryBase0 & 0xfffff000,
+ CardBus->MemoryLimit0 | 0x00000fff
+ );
+
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_MEM_3),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(CardBus->MemoryBase1)),
+ CardBus->BridgeControl & PCI_BIT_9 ? L" Prefetchable" : L"Non-Prefetchable",
+ CardBus->MemoryBase1 & 0xfffff000,
+ CardBus->MemoryLimit1 | 0x00000fff
+ );
+
+ Io32Bit = (BOOLEAN) (CardBus->IoBase0 & PCI_BIT_0);
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_IO_2),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(CardBus->IoBase0)),
+ Io32Bit ? L" 32 bit" : L" 16 bit",
+ CardBus->IoBase0 & (Io32Bit ? 0xfffffffc : 0x0000fffc),
+ (CardBus->IoLimit0 & (Io32Bit ? 0xffffffff : 0x0000ffff)) | 0x00000003
+ );
+
+ Io32Bit = (BOOLEAN) (CardBus->IoBase1 & PCI_BIT_0);
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_IO_2),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(CardBus->IoBase1)),
+ Io32Bit ? L" 32 bit" : L" 16 bit",
+ CardBus->IoBase1 & (Io32Bit ? 0xfffffffc : 0x0000fffc),
+ (CardBus->IoLimit1 & (Io32Bit ? 0xffffffff : 0x0000ffff)) | 0x00000003
+ );
+
+ //
+ // Print register Interrupt Line & PIN
+ //
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_INTERRUPT_LINE_3),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(CardBus->InterruptLine)),
+ CardBus->InterruptLine,
+ INDEX_OF (&(CardBus->InterruptPin)),
+ CardBus->InterruptPin
+ );
+
+ //
+ // Print register Bridge Control
+ //
+ PciExplainBridgeControl (&(CardBus->BridgeControl), PciCardBusBridge);
+
+ //
+ // Print some registers in data region of PCI configuration space for cardbus
+ // bridge. Fields include: Sub VendorId, Subsystem ID, and Legacy Mode Base
+ // Address.
+ //
+ CardBusData = (PCI_CARDBUS_DATA *) ((UINT8 *) CardBus + sizeof (PCI_CARDBUS_HEADER));
+
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_SUB_VENDOR_ID_2),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(CardBusData->SubVendorId)),
+ CardBusData->SubVendorId,
+ INDEX_OF (&(CardBusData->SubSystemId)),
+ CardBusData->SubSystemId
+ );
+
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_OPTIONAL),
+ gShellDebug1HiiHandle,
+ INDEX_OF (&(CardBusData->LegacyBase)),
+ CardBusData->LegacyBase
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Explain each meaningful bit of register Status. The definition of Status is
+ slightly different depending on the PCI header type.
+
+ @param[in] Status Points to the content of register Status.
+ @param[in] MainStatus Indicates if this register is main status(not secondary
+ status).
+ @param[in] HeaderType Header type of this PCI device.
+
+ @retval EFI_SUCCESS The command completed successfully.
+**/
+EFI_STATUS
+PciExplainStatus (
+ IN UINT16 *Status,
+ IN BOOLEAN MainStatus,
+ IN PCI_HEADER_TYPE HeaderType
+ )
+{
+ if (MainStatus) {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_STATUS), gShellDebug1HiiHandle, INDEX_OF (Status), *Status);
+
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_SECONDARY_STATUS), gShellDebug1HiiHandle, INDEX_OF (Status), *Status);
+ }
+
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_NEW_CAPABILITIES), gShellDebug1HiiHandle, (*Status & PCI_BIT_4) != 0);
+
+ //
+ // Bit 5 is meaningless for CardBus Bridge
+ //
+ if (HeaderType == PciCardBusBridge) {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_66_CAPABLE), gShellDebug1HiiHandle, (*Status & PCI_BIT_5) != 0);
+
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_66_CAPABLE_2), gShellDebug1HiiHandle, (*Status & PCI_BIT_5) != 0);
+ }
+
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_FAST_BACK), gShellDebug1HiiHandle, (*Status & PCI_BIT_7) != 0);
+
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_MASTER_DATA), gShellDebug1HiiHandle, (*Status & PCI_BIT_8) != 0);
+ //
+ // Bit 9 and bit 10 together decides the DEVSEL timing
+ //
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_DEVSEL_TIMING), gShellDebug1HiiHandle);
+ if ((*Status & PCI_BIT_9) == 0 && (*Status & PCI_BIT_10) == 0) {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_FAST), gShellDebug1HiiHandle);
+
+ } else if ((*Status & PCI_BIT_9) != 0 && (*Status & PCI_BIT_10) == 0) {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_MEDIUM), gShellDebug1HiiHandle);
+
+ } else if ((*Status & PCI_BIT_9) == 0 && (*Status & PCI_BIT_10) != 0) {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_SLOW), gShellDebug1HiiHandle);
+
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_RESERVED_2), gShellDebug1HiiHandle);
+ }
+
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_SIGNALED_TARGET),
+ gShellDebug1HiiHandle,
+ (*Status & PCI_BIT_11) != 0
+ );
+
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_RECEIVED_TARGET),
+ gShellDebug1HiiHandle,
+ (*Status & PCI_BIT_12) != 0
+ );
+
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_RECEIVED_MASTER),
+ gShellDebug1HiiHandle,
+ (*Status & PCI_BIT_13) != 0
+ );
+
+ if (MainStatus) {
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_SIGNALED_ERROR),
+ gShellDebug1HiiHandle,
+ (*Status & PCI_BIT_14) != 0
+ );
+
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_RECEIVED_ERROR),
+ gShellDebug1HiiHandle,
+ (*Status & PCI_BIT_14) != 0
+ );
+ }
+
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_DETECTED_ERROR),
+ gShellDebug1HiiHandle,
+ (*Status & PCI_BIT_15) != 0
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Explain each meaningful bit of register Command.
+
+ @param[in] Command Points to the content of register Command.
+
+ @retval EFI_SUCCESS The command completed successfully.
+**/
+EFI_STATUS
+PciExplainCommand (
+ IN UINT16 *Command
+ )
+{
+ //
+ // Print the binary value of register Command
+ //
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_PCI2_COMMAND), gShellDebug1HiiHandle, INDEX_OF (Command), *Command);
+
+ //
+ // Explain register Command bit by bit
+ //
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_SPACE_ACCESS_DENIED),
+ gShellDebug1HiiHandle,
+ (*Command & PCI_BIT_0) != 0
+ );
+
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_MEMORY_SPACE),
+ gShellDebug1HiiHandle,
+ (*Command & PCI_BIT_1) != 0
+ );
+
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_BEHAVE_BUS_MASTER),
+ gShellDebug1HiiHandle,
+ (*Command & PCI_BIT_2) != 0
+ );
+
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_MONITOR_SPECIAL_CYCLE),
+ gShellDebug1HiiHandle,
+ (*Command & PCI_BIT_3) != 0
+ );
+
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_MEM_WRITE_INVALIDATE),
+ gShellDebug1HiiHandle,
+ (*Command & PCI_BIT_4) != 0
+ );
+
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_PALETTE_SNOOPING),
+ gShellDebug1HiiHandle,
+ (*Command & PCI_BIT_5) != 0
+ );
+
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_ASSERT_PERR),
+ gShellDebug1HiiHandle,
+ (*Command & PCI_BIT_6) != 0
+ );
+
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_DO_ADDR_STEPPING),
+ gShellDebug1HiiHandle,
+ (*Command & PCI_BIT_7) != 0
+ );
+
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_SERR_DRIVER),
+ gShellDebug1HiiHandle,
+ (*Command & PCI_BIT_8) != 0
+ );
+
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_FAST_BACK_2),
+ gShellDebug1HiiHandle,
+ (*Command & PCI_BIT_9) != 0
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Explain each meaningful bit of register Bridge Control.
+
+ @param[in] BridgeControl Points to the content of register Bridge Control.
+ @param[in] HeaderType The headertype.
+
+ @retval EFI_SUCCESS The command completed successfully.
+**/
+EFI_STATUS
+PciExplainBridgeControl (
+ IN UINT16 *BridgeControl,
+ IN PCI_HEADER_TYPE HeaderType
+ )
+{
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_BRIDGE_CONTROL),
+ gShellDebug1HiiHandle,
+ INDEX_OF (BridgeControl),
+ *BridgeControl
+ );
+
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_PARITY_ERROR),
+ gShellDebug1HiiHandle,
+ (*BridgeControl & PCI_BIT_0) != 0
+ );
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_SERR_ENABLE),
+ gShellDebug1HiiHandle,
+ (*BridgeControl & PCI_BIT_1) != 0
+ );
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_ISA_ENABLE),
+ gShellDebug1HiiHandle,
+ (*BridgeControl & PCI_BIT_2) != 0
+ );
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_VGA_ENABLE),
+ gShellDebug1HiiHandle,
+ (*BridgeControl & PCI_BIT_3) != 0
+ );
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_MASTER_ABORT),
+ gShellDebug1HiiHandle,
+ (*BridgeControl & PCI_BIT_5) != 0
+ );
+
+ //
+ // Register Bridge Control has some slight differences between P2P bridge
+ // and Cardbus bridge from bit 6 to bit 11.
+ //
+ if (HeaderType == PciP2pBridge) {
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_SECONDARY_BUS_RESET),
+ gShellDebug1HiiHandle,
+ (*BridgeControl & PCI_BIT_6) != 0
+ );
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_FAST_ENABLE),
+ gShellDebug1HiiHandle,
+ (*BridgeControl & PCI_BIT_7) != 0
+ );
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_PRIMARY_DISCARD_TIMER),
+ gShellDebug1HiiHandle,
+ (*BridgeControl & PCI_BIT_8)!=0 ? L"2^10" : L"2^15"
+ );
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_SECONDARY_DISCARD_TIMER),
+ gShellDebug1HiiHandle,
+ (*BridgeControl & PCI_BIT_9)!=0 ? L"2^10" : L"2^15"
+ );
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_DISCARD_TIMER_STATUS),
+ gShellDebug1HiiHandle,
+ (*BridgeControl & PCI_BIT_10) != 0
+ );
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_DISCARD_TIMER_SERR),
+ gShellDebug1HiiHandle,
+ (*BridgeControl & PCI_BIT_11) != 0
+ );
+
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_CARDBUS_RESET),
+ gShellDebug1HiiHandle,
+ (*BridgeControl & PCI_BIT_6) != 0
+ );
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_IREQ_ENABLE),
+ gShellDebug1HiiHandle,
+ (*BridgeControl & PCI_BIT_7) != 0
+ );
+ ShellPrintHiiEx(-1, -1, NULL,
+ STRING_TOKEN (STR_PCI2_WRITE_POSTING_ENABLE),
+ gShellDebug1HiiHandle,
+ (*BridgeControl & PCI_BIT_10) != 0
+ );
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Print each capability structure.
+
+ @param[in] IoDev The pointer to the deivce.
+ @param[in] Address The address to start at.
+ @param[in] CapPtr The offset from the address.
+ @param[in] EnhancedDump The print format for the dump data.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+PciExplainCapabilityStruct (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ IN UINT64 Address,
+ IN UINT8 CapPtr,
+ IN CONST UINT16 EnhancedDump
+ )
+{
+ UINT8 CapabilityPtr;
+ UINT16 CapabilityEntry;
+ UINT8 CapabilityID;
+ UINT64 RegAddress;
+
+ CapabilityPtr = CapPtr;
+
+ //
+ // Go through the Capability list
+ //
+ while ((CapabilityPtr >= 0x40) && ((CapabilityPtr & 0x03) == 0x00)) {
+ RegAddress = Address + CapabilityPtr;
+ IoDev->Pci.Read (IoDev, EfiPciWidthUint16, RegAddress, 1, &CapabilityEntry);
+
+ CapabilityID = (UINT8) CapabilityEntry;
+
+ //
+ // Explain PciExpress data
+ //
+ if (EFI_PCI_CAPABILITY_ID_PCIEXP == CapabilityID) {
+ PciExplainPciExpress (IoDev, Address, CapabilityPtr, EnhancedDump);
+ return EFI_SUCCESS;
+ }
+ //
+ // Explain other capabilities here
+ //
+ CapabilityPtr = (UINT8) (CapabilityEntry >> 8);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Print out information of the capability information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieCapReg (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ )
+{
+ UINT16 PcieCapReg;
+ CHAR16 *DevicePortType;
+
+ PcieCapReg = PciExpressCap->PcieCapReg;
+ ShellPrintEx (-1, -1,
+ L" Capability Version(3:0): %E0x%04x%N\r\n",
+ PCIE_CAP_VERSION (PcieCapReg)
+ );
+ if ((UINT8) PCIE_CAP_DEVICEPORT_TYPE (PcieCapReg) < PCIE_DEVICE_PORT_TYPE_MAX) {
+ DevicePortType = DevicePortTypeTable[PCIE_CAP_DEVICEPORT_TYPE (PcieCapReg)];
+ } else {
+ DevicePortType = L"Unknown Type";
+ }
+ ShellPrintEx (-1, -1,
+ L" Device/PortType(7:4): %E%s%N\r\n",
+ DevicePortType
+ );
+ //
+ // 'Slot Implemented' is only valid for:
+ // a) Root Port of PCI Express Root Complex, or
+ // b) Downstream Port of PCI Express Switch
+ //
+ if (PCIE_CAP_DEVICEPORT_TYPE (PcieCapReg) == PCIE_ROOT_COMPLEX_ROOT_PORT ||
+ PCIE_CAP_DEVICEPORT_TYPE (PcieCapReg) == PCIE_SWITCH_DOWNSTREAM_PORT) {
+ ShellPrintEx (-1, -1,
+ L" Slot Implemented(8): %E%d%N\r\n",
+ PCIE_CAP_SLOT_IMPLEMENTED (PcieCapReg)
+ );
+ }
+ ShellPrintEx (-1, -1,
+ L" Interrupt Message Number(13:9): %E0x%05x%N\r\n",
+ PCIE_CAP_INT_MSG_NUM (PcieCapReg)
+ );
+ return EFI_SUCCESS;
+}
+
+/**
+ Print out information of the device capability information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieDeviceCap (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ )
+{
+ UINT16 PcieCapReg;
+ UINT32 PcieDeviceCap;
+ UINT8 DevicePortType;
+ UINT8 L0sLatency;
+ UINT8 L1Latency;
+
+ PcieCapReg = PciExpressCap->PcieCapReg;
+ PcieDeviceCap = PciExpressCap->PcieDeviceCap;
+ DevicePortType = (UINT8) PCIE_CAP_DEVICEPORT_TYPE (PcieCapReg);
+ ShellPrintEx (-1, -1, L" Max_Payload_Size Supported(2:0): ");
+ if (PCIE_CAP_MAX_PAYLOAD (PcieDeviceCap) < 6) {
+ ShellPrintEx (-1, -1, L"%E%d bytes%N\r\n", 1 << (PCIE_CAP_MAX_PAYLOAD (PcieDeviceCap) + 7));
+ } else {
+ ShellPrintEx (-1, -1, L"%EUnknown%N\r\n");
+ }
+ ShellPrintEx (-1, -1,
+ L" Phantom Functions Supported(4:3): %E%d%N\r\n",
+ PCIE_CAP_PHANTOM_FUNC (PcieDeviceCap)
+ );
+ ShellPrintEx (-1, -1,
+ L" Extended Tag Field Supported(5): %E%d-bit Tag field supported%N\r\n",
+ PCIE_CAP_EXTENDED_TAG (PcieDeviceCap) ? 8 : 5
+ );
+ //
+ // Endpoint L0s and L1 Acceptable Latency is only valid for Endpoint
+ //
+ if (IS_PCIE_ENDPOINT (DevicePortType)) {
+ L0sLatency = (UINT8) PCIE_CAP_L0SLATENCY (PcieDeviceCap);
+ L1Latency = (UINT8) PCIE_CAP_L1LATENCY (PcieDeviceCap);
+ ShellPrintEx (-1, -1, L" Endpoint L0s Acceptable Latency(8:6): ");
+ if (L0sLatency < 4) {
+ ShellPrintEx (-1, -1, L"%EMaximum of %d ns%N\r\n", 1 << (L0sLatency + 6));
+ } else {
+ if (L0sLatency < 7) {
+ ShellPrintEx (-1, -1, L"%EMaximum of %d us%N\r\n", 1 << (L0sLatency - 3));
+ } else {
+ ShellPrintEx (-1, -1, L"%ENo limit%N\r\n");
+ }
+ }
+ ShellPrintEx (-1, -1, L" Endpoint L1 Acceptable Latency(11:9): ");
+ if (L1Latency < 7) {
+ ShellPrintEx (-1, -1, L"%EMaximum of %d us%N\r\n", 1 << (L1Latency + 1));
+ } else {
+ ShellPrintEx (-1, -1, L"%ENo limit%N\r\n");
+ }
+ }
+ ShellPrintEx (-1, -1,
+ L" Role-based Error Reporting(15): %E%d%N\r\n",
+ PCIE_CAP_ERR_REPORTING (PcieDeviceCap)
+ );
+ //
+ // Only valid for Upstream Port:
+ // a) Captured Slot Power Limit Value
+ // b) Captured Slot Power Scale
+ //
+ if (DevicePortType == PCIE_SWITCH_UPSTREAM_PORT) {
+ ShellPrintEx (-1, -1,
+ L" Captured Slot Power Limit Value(25:18): %E0x%02x%N\r\n",
+ PCIE_CAP_SLOT_POWER_VALUE (PcieDeviceCap)
+ );
+ ShellPrintEx (-1, -1,
+ L" Captured Slot Power Limit Scale(27:26): %E%s%N\r\n",
+ SlotPwrLmtScaleTable[PCIE_CAP_SLOT_POWER_SCALE (PcieDeviceCap)]
+ );
+ }
+ //
+ // Function Level Reset Capability is only valid for Endpoint
+ //
+ if (IS_PCIE_ENDPOINT (DevicePortType)) {
+ ShellPrintEx (-1, -1,
+ L" Function Level Reset Capability(28): %E%d%N\r\n",
+ PCIE_CAP_FUNC_LEVEL_RESET (PcieDeviceCap)
+ );
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Print out information of the device control information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieDeviceControl (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ )
+{
+ UINT16 PcieCapReg;
+ UINT16 PcieDeviceControl;
+
+ PcieCapReg = PciExpressCap->PcieCapReg;
+ PcieDeviceControl = PciExpressCap->DeviceControl;
+ ShellPrintEx (-1, -1,
+ L" Correctable Error Reporting Enable(0): %E%d%N\r\n",
+ PCIE_CAP_COR_ERR_REPORTING_ENABLE (PcieDeviceControl)
+ );
+ ShellPrintEx (-1, -1,
+ L" Non-Fatal Error Reporting Enable(1): %E%d%N\r\n",
+ PCIE_CAP_NONFAT_ERR_REPORTING_ENABLE (PcieDeviceControl)
+ );
+ ShellPrintEx (-1, -1,
+ L" Fatal Error Reporting Enable(2): %E%d%N\r\n",
+ PCIE_CAP_FATAL_ERR_REPORTING_ENABLE (PcieDeviceControl)
+ );
+ ShellPrintEx (-1, -1,
+ L" Unsupported Request Reporting Enable(3): %E%d%N\r\n",
+ PCIE_CAP_UNSUP_REQ_REPORTING_ENABLE (PcieDeviceControl)
+ );
+ ShellPrintEx (-1, -1,
+ L" Enable Relaxed Ordering(4): %E%d%N\r\n",
+ PCIE_CAP_RELAXED_ORDERING_ENABLE (PcieDeviceControl)
+ );
+ ShellPrintEx (-1, -1, L" Max_Payload_Size(7:5): ");
+ if (PCIE_CAP_MAX_PAYLOAD_SIZE (PcieDeviceControl) < 6) {
+ ShellPrintEx (-1, -1, L"%E%d bytes%N\r\n", 1 << (PCIE_CAP_MAX_PAYLOAD_SIZE (PcieDeviceControl) + 7));
+ } else {
+ ShellPrintEx (-1, -1, L"%EUnknown%N\r\n");
+ }
+ ShellPrintEx (-1, -1,
+ L" Extended Tag Field Enable(8): %E%d%N\r\n",
+ PCIE_CAP_EXTENDED_TAG_ENABLE (PcieDeviceControl)
+ );
+ ShellPrintEx (-1, -1,
+ L" Phantom Functions Enable(9): %E%d%N\r\n",
+ PCIE_CAP_PHANTOM_FUNC_ENABLE (PcieDeviceControl)
+ );
+ ShellPrintEx (-1, -1,
+ L" Auxiliary (AUX) Power PM Enable(10): %E%d%N\r\n",
+ PCIE_CAP_AUX_PM_ENABLE (PcieDeviceControl)
+ );
+ ShellPrintEx (-1, -1,
+ L" Enable No Snoop(11): %E%d%N\r\n",
+ PCIE_CAP_NO_SNOOP_ENABLE (PcieDeviceControl)
+ );
+ ShellPrintEx (-1, -1, L" Max_Read_Request_Size(14:12): ");
+ if (PCIE_CAP_MAX_READ_REQ_SIZE (PcieDeviceControl) < 6) {
+ ShellPrintEx (-1, -1, L"%E%d bytes%N\r\n", 1 << (PCIE_CAP_MAX_READ_REQ_SIZE (PcieDeviceControl) + 7));
+ } else {
+ ShellPrintEx (-1, -1, L"%EUnknown%N\r\n");
+ }
+ //
+ // Read operation is only valid for PCI Express to PCI/PCI-X Bridges
+ //
+ if (PCIE_CAP_DEVICEPORT_TYPE (PcieCapReg) == PCIE_PCIE_TO_PCIX_BRIDGE) {
+ ShellPrintEx (-1, -1,
+ L" Bridge Configuration Retry Enable(15): %E%d%N\r\n",
+ PCIE_CAP_BRG_CONF_RETRY (PcieDeviceControl)
+ );
+ }
+ return EFI_SUCCESS;
+}
+
+/**
+ Print out information of the device status information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieDeviceStatus (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ )
+{
+ UINT16 PcieDeviceStatus;
+
+ PcieDeviceStatus = PciExpressCap->DeviceStatus;
+ ShellPrintEx (-1, -1,
+ L" Correctable Error Detected(0): %E%d%N\r\n",
+ PCIE_CAP_COR_ERR_DETECTED (PcieDeviceStatus)
+ );
+ ShellPrintEx (-1, -1,
+ L" Non-Fatal Error Detected(1): %E%d%N\r\n",
+ PCIE_CAP_NONFAT_ERR_DETECTED (PcieDeviceStatus)
+ );
+ ShellPrintEx (-1, -1,
+ L" Fatal Error Detected(2): %E%d%N\r\n",
+ PCIE_CAP_FATAL_ERR_DETECTED (PcieDeviceStatus)
+ );
+ ShellPrintEx (-1, -1,
+ L" Unsupported Request Detected(3): %E%d%N\r\n",
+ PCIE_CAP_UNSUP_REQ_DETECTED (PcieDeviceStatus)
+ );
+ ShellPrintEx (-1, -1,
+ L" AUX Power Detected(4): %E%d%N\r\n",
+ PCIE_CAP_AUX_POWER_DETECTED (PcieDeviceStatus)
+ );
+ ShellPrintEx (-1, -1,
+ L" Transactions Pending(5): %E%d%N\r\n",
+ PCIE_CAP_TRANSACTION_PENDING (PcieDeviceStatus)
+ );
+ return EFI_SUCCESS;
+}
+
+/**
+ Print out information of the device link information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieLinkCap (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ )
+{
+ UINT32 PcieLinkCap;
+ CHAR16 *MaxLinkSpeed;
+ CHAR16 *AspmValue;
+
+ PcieLinkCap = PciExpressCap->LinkCap;
+ switch (PCIE_CAP_MAX_LINK_SPEED (PcieLinkCap)) {
+ case 1:
+ MaxLinkSpeed = L"2.5 GT/s";
+ break;
+ case 2:
+ MaxLinkSpeed = L"5.0 GT/s";
+ break;
+ case 3:
+ MaxLinkSpeed = L"8.0 GT/s";
+ break;
+ default:
+ MaxLinkSpeed = L"Unknown";
+ break;
+ }
+ ShellPrintEx (-1, -1,
+ L" Maximum Link Speed(3:0): %E%s%N\r\n",
+ MaxLinkSpeed
+ );
+ ShellPrintEx (-1, -1,
+ L" Maximum Link Width(9:4): %Ex%d%N\r\n",
+ PCIE_CAP_MAX_LINK_WIDTH (PcieLinkCap)
+ );
+ switch (PCIE_CAP_ASPM_SUPPORT (PcieLinkCap)) {
+ case 0:
+ AspmValue = L"Not";
+ break;
+ case 1:
+ AspmValue = L"L0s";
+ break;
+ case 2:
+ AspmValue = L"L1";
+ break;
+ case 3:
+ AspmValue = L"L0s and L1";
+ break;
+ default:
+ AspmValue = L"Reserved";
+ break;
+ }
+ ShellPrintEx (-1, -1,
+ L" Active State Power Management Support(11:10): %E%s Supported%N\r\n",
+ AspmValue
+ );
+ ShellPrintEx (-1, -1,
+ L" L0s Exit Latency(14:12): %E%s%N\r\n",
+ L0sLatencyStrTable[PCIE_CAP_L0S_LATENCY (PcieLinkCap)]
+ );
+ ShellPrintEx (-1, -1,
+ L" L1 Exit Latency(17:15): %E%s%N\r\n",
+ L1LatencyStrTable[PCIE_CAP_L0S_LATENCY (PcieLinkCap)]
+ );
+ ShellPrintEx (-1, -1,
+ L" Clock Power Management(18): %E%d%N\r\n",
+ PCIE_CAP_CLOCK_PM (PcieLinkCap)
+ );
+ ShellPrintEx (-1, -1,
+ L" Surprise Down Error Reporting Capable(19): %E%d%N\r\n",
+ PCIE_CAP_SUP_DOWN_ERR_REPORTING (PcieLinkCap)
+ );
+ ShellPrintEx (-1, -1,
+ L" Data Link Layer Link Active Reporting Capable(20): %E%d%N\r\n",
+ PCIE_CAP_LINK_ACTIVE_REPORTING (PcieLinkCap)
+ );
+ ShellPrintEx (-1, -1,
+ L" Link Bandwidth Notification Capability(21): %E%d%N\r\n",
+ PCIE_CAP_LINK_BWD_NOTIF_CAP (PcieLinkCap)
+ );
+ ShellPrintEx (-1, -1,
+ L" Port Number(31:24): %E0x%02x%N\r\n",
+ PCIE_CAP_PORT_NUMBER (PcieLinkCap)
+ );
+ return EFI_SUCCESS;
+}
+
+/**
+ Print out information of the device link control information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieLinkControl (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ )
+{
+ UINT16 PcieLinkControl;
+ UINT8 DevicePortType;
+
+ PcieLinkControl = PciExpressCap->LinkControl;
+ DevicePortType = (UINT8) PCIE_CAP_DEVICEPORT_TYPE (PciExpressCap->PcieCapReg);
+ ShellPrintEx (-1, -1,
+ L" Active State Power Management Control(1:0): %E%s%N\r\n",
+ ASPMCtrlStrTable[PCIE_CAP_ASPM_CONTROL (PcieLinkControl)]
+ );
+ //
+ // RCB is not applicable to switches
+ //
+ if (!IS_PCIE_SWITCH(DevicePortType)) {
+ ShellPrintEx (-1, -1,
+ L" Read Completion Boundary (RCB)(3): %E%d byte%N\r\n",
+ 1 << (PCIE_CAP_RCB (PcieLinkControl) + 6)
+ );
+ }
+ //
+ // Link Disable is reserved on
+ // a) Endpoints
+ // b) PCI Express to PCI/PCI-X bridges
+ // c) Upstream Ports of Switches
+ //
+ if (!IS_PCIE_ENDPOINT (DevicePortType) &&
+ DevicePortType != PCIE_SWITCH_UPSTREAM_PORT &&
+ DevicePortType != PCIE_PCIE_TO_PCIX_BRIDGE) {
+ ShellPrintEx (-1, -1,
+ L" Link Disable(4): %E%d%N\r\n",
+ PCIE_CAP_LINK_DISABLE (PcieLinkControl)
+ );
+ }
+ ShellPrintEx (-1, -1,
+ L" Common Clock Configuration(6): %E%d%N\r\n",
+ PCIE_CAP_COMMON_CLK_CONF (PcieLinkControl)
+ );
+ ShellPrintEx (-1, -1,
+ L" Extended Synch(7): %E%d%N\r\n",
+ PCIE_CAP_EXT_SYNC (PcieLinkControl)
+ );
+ ShellPrintEx (-1, -1,
+ L" Enable Clock Power Management(8): %E%d%N\r\n",
+ PCIE_CAP_CLK_PWR_MNG (PcieLinkControl)
+ );
+ ShellPrintEx (-1, -1,
+ L" Hardware Autonomous Width Disable(9): %E%d%N\r\n",
+ PCIE_CAP_HW_AUTO_WIDTH_DISABLE (PcieLinkControl)
+ );
+ ShellPrintEx (-1, -1,
+ L" Link Bandwidth Management Interrupt Enable(10): %E%d%N\r\n",
+ PCIE_CAP_LINK_BDW_MNG_INT_EN (PcieLinkControl)
+ );
+ ShellPrintEx (-1, -1,
+ L" Link Autonomous Bandwidth Interrupt Enable(11): %E%d%N\r\n",
+ PCIE_CAP_LINK_AUTO_BDW_INT_EN (PcieLinkControl)
+ );
+ return EFI_SUCCESS;
+}
+
+/**
+ Print out information of the device link status information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieLinkStatus (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ )
+{
+ UINT16 PcieLinkStatus;
+ CHAR16 *CurLinkSpeed;
+
+ PcieLinkStatus = PciExpressCap->LinkStatus;
+ switch (PCIE_CAP_CUR_LINK_SPEED (PcieLinkStatus)) {
+ case 1:
+ CurLinkSpeed = L"2.5 GT/s";
+ break;
+ case 2:
+ CurLinkSpeed = L"5.0 GT/s";
+ break;
+ case 3:
+ CurLinkSpeed = L"8.0 GT/s";
+ break;
+ default:
+ CurLinkSpeed = L"Reserved";
+ break;
+ }
+ ShellPrintEx (-1, -1,
+ L" Current Link Speed(3:0): %E%s%N\r\n",
+ CurLinkSpeed
+ );
+ ShellPrintEx (-1, -1,
+ L" Negotiated Link Width(9:4): %Ex%d%N\r\n",
+ PCIE_CAP_NEGO_LINK_WIDTH (PcieLinkStatus)
+ );
+ ShellPrintEx (-1, -1,
+ L" Link Training(11): %E%d%N\r\n",
+ PCIE_CAP_LINK_TRAINING (PcieLinkStatus)
+ );
+ ShellPrintEx (-1, -1,
+ L" Slot Clock Configuration(12): %E%d%N\r\n",
+ PCIE_CAP_SLOT_CLK_CONF (PcieLinkStatus)
+ );
+ ShellPrintEx (-1, -1,
+ L" Data Link Layer Link Active(13): %E%d%N\r\n",
+ PCIE_CAP_DATA_LINK_ACTIVE (PcieLinkStatus)
+ );
+ ShellPrintEx (-1, -1,
+ L" Link Bandwidth Management Status(14): %E%d%N\r\n",
+ PCIE_CAP_LINK_BDW_MNG_STAT (PcieLinkStatus)
+ );
+ ShellPrintEx (-1, -1,
+ L" Link Autonomous Bandwidth Status(15): %E%d%N\r\n",
+ PCIE_CAP_LINK_AUTO_BDW_STAT (PcieLinkStatus)
+ );
+ return EFI_SUCCESS;
+}
+
+/**
+ Print out information of the device slot information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieSlotCap (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ )
+{
+ UINT32 PcieSlotCap;
+
+ PcieSlotCap = PciExpressCap->SlotCap;
+
+ ShellPrintEx (-1, -1,
+ L" Attention Button Present(0): %E%d%N\r\n",
+ PCIE_CAP_ATT_BUT_PRESENT (PcieSlotCap)
+ );
+ ShellPrintEx (-1, -1,
+ L" Power Controller Present(1): %E%d%N\r\n",
+ PCIE_CAP_PWR_CTRLLER_PRESENT (PcieSlotCap)
+ );
+ ShellPrintEx (-1, -1,
+ L" MRL Sensor Present(2): %E%d%N\r\n",
+ PCIE_CAP_MRL_SENSOR_PRESENT (PcieSlotCap)
+ );
+ ShellPrintEx (-1, -1,
+ L" Attention Indicator Present(3): %E%d%N\r\n",
+ PCIE_CAP_ATT_IND_PRESENT (PcieSlotCap)
+ );
+ ShellPrintEx (-1, -1,
+ L" Power Indicator Present(4): %E%d%N\r\n",
+ PCIE_CAP_PWD_IND_PRESENT (PcieSlotCap)
+ );
+ ShellPrintEx (-1, -1,
+ L" Hot-Plug Surprise(5): %E%d%N\r\n",
+ PCIE_CAP_HOTPLUG_SUPPRISE (PcieSlotCap)
+ );
+ ShellPrintEx (-1, -1,
+ L" Hot-Plug Capable(6): %E%d%N\r\n",
+ PCIE_CAP_HOTPLUG_CAPABLE (PcieSlotCap)
+ );
+ ShellPrintEx (-1, -1,
+ L" Slot Power Limit Value(14:7): %E0x%02x%N\r\n",
+ PCIE_CAP_SLOT_PWR_LIMIT_VALUE (PcieSlotCap)
+ );
+ ShellPrintEx (-1, -1,
+ L" Slot Power Limit Scale(16:15): %E%s%N\r\n",
+ SlotPwrLmtScaleTable[PCIE_CAP_SLOT_PWR_LIMIT_SCALE (PcieSlotCap)]
+ );
+ ShellPrintEx (-1, -1,
+ L" Electromechanical Interlock Present(17): %E%d%N\r\n",
+ PCIE_CAP_ELEC_INTERLOCK_PRESENT (PcieSlotCap)
+ );
+ ShellPrintEx (-1, -1,
+ L" No Command Completed Support(18): %E%d%N\r\n",
+ PCIE_CAP_NO_COMM_COMPLETED_SUP (PcieSlotCap)
+ );
+ ShellPrintEx (-1, -1,
+ L" Physical Slot Number(31:19): %E%d%N\r\n",
+ PCIE_CAP_PHY_SLOT_NUM (PcieSlotCap)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Print out information of the device slot control information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieSlotControl (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ )
+{
+ UINT16 PcieSlotControl;
+
+ PcieSlotControl = PciExpressCap->SlotControl;
+ ShellPrintEx (-1, -1,
+ L" Attention Button Pressed Enable(0): %E%d%N\r\n",
+ PCIE_CAP_ATT_BUT_ENABLE (PcieSlotControl)
+ );
+ ShellPrintEx (-1, -1,
+ L" Power Fault Detected Enable(1): %E%d%N\r\n",
+ PCIE_CAP_PWR_FLT_DETECT_ENABLE (PcieSlotControl)
+ );
+ ShellPrintEx (-1, -1,
+ L" MRL Sensor Changed Enable(2): %E%d%N\r\n",
+ PCIE_CAP_MRL_SENSOR_CHANGE_ENABLE (PcieSlotControl)
+ );
+ ShellPrintEx (-1, -1,
+ L" Presence Detect Changed Enable(3): %E%d%N\r\n",
+ PCIE_CAP_PRES_DETECT_CHANGE_ENABLE (PcieSlotControl)
+ );
+ ShellPrintEx (-1, -1,
+ L" Command Completed Interrupt Enable(4): %E%d%N\r\n",
+ PCIE_CAP_COMM_CMPL_INT_ENABLE (PcieSlotControl)
+ );
+ ShellPrintEx (-1, -1,
+ L" Hot-Plug Interrupt Enable(5): %E%d%N\r\n",
+ PCIE_CAP_HOTPLUG_INT_ENABLE (PcieSlotControl)
+ );
+ ShellPrintEx (-1, -1,
+ L" Attention Indicator Control(7:6): %E%s%N\r\n",
+ IndicatorTable[PCIE_CAP_ATT_IND_CTRL (PcieSlotControl)]
+ );
+ ShellPrintEx (-1, -1,
+ L" Power Indicator Control(9:8): %E%s%N\r\n",
+ IndicatorTable[PCIE_CAP_PWR_IND_CTRL (PcieSlotControl)]
+ );
+ ShellPrintEx (-1, -1, L" Power Controller Control(10): %EPower ");
+ if (PCIE_CAP_PWR_CTRLLER_CTRL (PcieSlotControl)) {
+ ShellPrintEx (-1, -1, L"Off%N\r\n");
+ } else {
+ ShellPrintEx (-1, -1, L"On%N\r\n");
+ }
+ ShellPrintEx (-1, -1,
+ L" Electromechanical Interlock Control(11): %E%d%N\r\n",
+ PCIE_CAP_ELEC_INTERLOCK_CTRL (PcieSlotControl)
+ );
+ ShellPrintEx (-1, -1,
+ L" Data Link Layer State Changed Enable(12): %E%d%N\r\n",
+ PCIE_CAP_DLINK_STAT_CHANGE_ENABLE (PcieSlotControl)
+ );
+ return EFI_SUCCESS;
+}
+
+/**
+ Print out information of the device slot status information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieSlotStatus (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ )
+{
+ UINT16 PcieSlotStatus;
+
+ PcieSlotStatus = PciExpressCap->SlotStatus;
+
+ ShellPrintEx (-1, -1,
+ L" Attention Button Pressed(0): %E%d%N\r\n",
+ PCIE_CAP_ATT_BUT_PRESSED (PcieSlotStatus)
+ );
+ ShellPrintEx (-1, -1,
+ L" Power Fault Detected(1): %E%d%N\r\n",
+ PCIE_CAP_PWR_FLT_DETECTED (PcieSlotStatus)
+ );
+ ShellPrintEx (-1, -1,
+ L" MRL Sensor Changed(2): %E%d%N\r\n",
+ PCIE_CAP_MRL_SENSOR_CHANGED (PcieSlotStatus)
+ );
+ ShellPrintEx (-1, -1,
+ L" Presence Detect Changed(3): %E%d%N\r\n",
+ PCIE_CAP_PRES_DETECT_CHANGED (PcieSlotStatus)
+ );
+ ShellPrintEx (-1, -1,
+ L" Command Completed(4): %E%d%N\r\n",
+ PCIE_CAP_COMM_COMPLETED (PcieSlotStatus)
+ );
+ ShellPrintEx (-1, -1, L" MRL Sensor State(5): %EMRL ");
+ if (PCIE_CAP_MRL_SENSOR_STATE (PcieSlotStatus)) {
+ ShellPrintEx (-1, -1, L" Opened%N\r\n");
+ } else {
+ ShellPrintEx (-1, -1, L" Closed%N\r\n");
+ }
+ ShellPrintEx (-1, -1, L" Presence Detect State(6): ");
+ if (PCIE_CAP_PRES_DETECT_STATE (PcieSlotStatus)) {
+ ShellPrintEx (-1, -1, L"%ECard Present in slot%N\r\n");
+ } else {
+ ShellPrintEx (-1, -1, L"%ESlot Empty%N\r\n");
+ }
+ ShellPrintEx (-1, -1, L" Electromechanical Interlock Status(7): %EElectromechanical Interlock ");
+ if (PCIE_CAP_ELEC_INTERLOCK_STATE (PcieSlotStatus)) {
+ ShellPrintEx (-1, -1, L"Engaged%N\r\n");
+ } else {
+ ShellPrintEx (-1, -1, L"Disengaged%N\r\n");
+ }
+ ShellPrintEx (-1, -1,
+ L" Data Link Layer State Changed(8): %E%d%N\r\n",
+ PCIE_CAP_DLINK_STAT_CHANGED (PcieSlotStatus)
+ );
+ return EFI_SUCCESS;
+}
+
+/**
+ Print out information of the device root information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieRootControl (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ )
+{
+ UINT16 PcieRootControl;
+
+ PcieRootControl = PciExpressCap->RootControl;
+
+ ShellPrintEx (-1, -1,
+ L" System Error on Correctable Error Enable(0): %E%d%N\r\n",
+ PCIE_CAP_SYSERR_ON_CORERR_EN (PcieRootControl)
+ );
+ ShellPrintEx (-1, -1,
+ L" System Error on Non-Fatal Error Enable(1): %E%d%N\r\n",
+ PCIE_CAP_SYSERR_ON_NONFATERR_EN (PcieRootControl)
+ );
+ ShellPrintEx (-1, -1,
+ L" System Error on Fatal Error Enable(2): %E%d%N\r\n",
+ PCIE_CAP_SYSERR_ON_FATERR_EN (PcieRootControl)
+ );
+ ShellPrintEx (-1, -1,
+ L" PME Interrupt Enable(3): %E%d%N\r\n",
+ PCIE_CAP_PME_INT_ENABLE (PcieRootControl)
+ );
+ ShellPrintEx (-1, -1,
+ L" CRS Software Visibility Enable(4): %E%d%N\r\n",
+ PCIE_CAP_CRS_SW_VIS_ENABLE (PcieRootControl)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Print out information of the device root capability information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieRootCap (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ )
+{
+ UINT16 PcieRootCap;
+
+ PcieRootCap = PciExpressCap->RsvdP;
+
+ ShellPrintEx (-1, -1,
+ L" CRS Software Visibility(0): %E%d%N\r\n",
+ PCIE_CAP_CRS_SW_VIS (PcieRootCap)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Print out information of the device root status information.
+
+ @param[in] PciExpressCap The pointer to the structure about the device.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+ExplainPcieRootStatus (
+ IN PCIE_CAP_STRUCTURE *PciExpressCap
+ )
+{
+ UINT32 PcieRootStatus;
+
+ PcieRootStatus = PciExpressCap->RootStatus;
+
+ ShellPrintEx (-1, -1,
+ L" PME Requester ID(15:0): %E0x%04x%N\r\n",
+ PCIE_CAP_PME_REQ_ID (PcieRootStatus)
+ );
+ ShellPrintEx (-1, -1,
+ L" PME Status(16): %E%d%N\r\n",
+ PCIE_CAP_PME_STATUS (PcieRootStatus)
+ );
+ ShellPrintEx (-1, -1,
+ L" PME Pending(17): %E%d%N\r\n",
+ PCIE_CAP_PME_PENDING (PcieRootStatus)
+ );
+ return EFI_SUCCESS;
+}
+
+/**
+ Function to interpret and print out the link control structure
+
+ @param[in] HeaderAddress The Address of this capability header.
+ @param[in] HeadersBaseAddress The address of all the extended capability headers.
+**/
+EFI_STATUS
+EFIAPI
+PrintInterpretedExtendedCompatibilityLinkControl (
+ IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
+ IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
+ )
+{
+ CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_INTERNAL_LINK_CONTROL *Header;
+ Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_INTERNAL_LINK_CONTROL*)HeaderAddress;
+
+ ShellPrintHiiEx(
+ -1, -1, NULL,
+ STRING_TOKEN (STR_PCI_EXT_CAP_LINK_CONTROL),
+ gShellDebug1HiiHandle,
+ Header->RootComplexLinkCapabilities,
+ Header->RootComplexLinkControl,
+ Header->RootComplexLinkStatus
+ );
+ DumpHex (
+ 4,
+ EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
+ sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_INTERNAL_LINK_CONTROL),
+ (VOID *) (HeaderAddress)
+ );
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to interpret and print out the power budgeting structure
+
+ @param[in] HeaderAddress The Address of this capability header.
+ @param[in] HeadersBaseAddress The address of all the extended capability headers.
+**/
+EFI_STATUS
+EFIAPI
+PrintInterpretedExtendedCompatibilityPowerBudgeting (
+ IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
+ IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
+ )
+{
+ CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_POWER_BUDGETING *Header;
+ Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_POWER_BUDGETING*)HeaderAddress;
+
+ ShellPrintHiiEx(
+ -1, -1, NULL,
+ STRING_TOKEN (STR_PCI_EXT_CAP_POWER),
+ gShellDebug1HiiHandle,
+ Header->DataSelect,
+ Header->Data,
+ Header->PowerBudgetCapability
+ );
+ DumpHex (
+ 4,
+ EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
+ sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_POWER_BUDGETING),
+ (VOID *) (HeaderAddress)
+ );
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to interpret and print out the ACS structure
+
+ @param[in] HeaderAddress The Address of this capability header.
+ @param[in] HeadersBaseAddress The address of all the extended capability headers.
+**/
+EFI_STATUS
+EFIAPI
+PrintInterpretedExtendedCompatibilityAcs (
+ IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
+ IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
+ )
+{
+ CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_ACS_EXTENDED *Header;
+ UINT16 VectorSize;
+ UINT16 LoopCounter;
+
+ Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_ACS_EXTENDED*)HeaderAddress;
+ VectorSize = 0;
+
+ ShellPrintHiiEx(
+ -1, -1, NULL,
+ STRING_TOKEN (STR_PCI_EXT_CAP_ACS),
+ gShellDebug1HiiHandle,
+ Header->AcsCapability,
+ Header->AcsControl
+ );
+ if (PCI_EXPRESS_EXTENDED_CAPABILITY_ACS_EXTENDED_GET_EGRES_CONTROL(Header)) {
+ VectorSize = PCI_EXPRESS_EXTENDED_CAPABILITY_ACS_EXTENDED_GET_EGRES_VECTOR_SIZE(Header);
+ if (VectorSize == 0) {
+ VectorSize = 256;
+ }
+ for (LoopCounter = 0 ; LoopCounter * 8 < VectorSize ; LoopCounter++) {
+ ShellPrintHiiEx(
+ -1, -1, NULL,
+ STRING_TOKEN (STR_PCI_EXT_CAP_ACS2),
+ gShellDebug1HiiHandle,
+ LoopCounter + 1,
+ Header->EgressControlVectorArray[LoopCounter]
+ );
+ }
+ }
+ DumpHex (
+ 4,
+ EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
+ sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_ACS_EXTENDED) + (VectorSize / 8) - 1,
+ (VOID *) (HeaderAddress)
+ );
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to interpret and print out the latency tolerance reporting structure
+
+ @param[in] HeaderAddress The Address of this capability header.
+ @param[in] HeadersBaseAddress The address of all the extended capability headers.
+**/
+EFI_STATUS
+EFIAPI
+PrintInterpretedExtendedCompatibilityLatencyToleranceReporting (
+ IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
+ IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
+ )
+{
+ CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_LATENCE_TOLERANCE_REPORTING *Header;
+ Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_LATENCE_TOLERANCE_REPORTING*)HeaderAddress;
+
+ ShellPrintHiiEx(
+ -1, -1, NULL,
+ STRING_TOKEN (STR_PCI_EXT_CAP_LAT),
+ gShellDebug1HiiHandle,
+ Header->MaxSnoopLatency,
+ Header->MaxNoSnoopLatency
+ );
+ DumpHex (
+ 4,
+ EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
+ sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_LATENCE_TOLERANCE_REPORTING),
+ (VOID *) (HeaderAddress)
+ );
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to interpret and print out the serial number structure
+
+ @param[in] HeaderAddress The Address of this capability header.
+ @param[in] HeadersBaseAddress The address of all the extended capability headers.
+**/
+EFI_STATUS
+EFIAPI
+PrintInterpretedExtendedCompatibilitySerialNumber (
+ IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
+ IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
+ )
+{
+ CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_SERIAL_NUMBER *Header;
+ Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_SERIAL_NUMBER*)HeaderAddress;
+
+ ShellPrintHiiEx(
+ -1, -1, NULL,
+ STRING_TOKEN (STR_PCI_EXT_CAP_SN),
+ gShellDebug1HiiHandle,
+ Header->SerialNumber
+ );
+ DumpHex (
+ 4,
+ EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
+ sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_SERIAL_NUMBER),
+ (VOID *) (HeaderAddress)
+ );
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to interpret and print out the RCRB structure
+
+ @param[in] HeaderAddress The Address of this capability header.
+ @param[in] HeadersBaseAddress The address of all the extended capability headers.
+**/
+EFI_STATUS
+EFIAPI
+PrintInterpretedExtendedCompatibilityRcrb (
+ IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
+ IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
+ )
+{
+ CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_RCRB_HEADER *Header;
+ Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_RCRB_HEADER*)HeaderAddress;
+
+ ShellPrintHiiEx(
+ -1, -1, NULL,
+ STRING_TOKEN (STR_PCI_EXT_CAP_RCRB),
+ gShellDebug1HiiHandle,
+ Header->VendorId,
+ Header->DeviceId,
+ Header->RcrbCapabilities,
+ Header->RcrbControl
+ );
+ DumpHex (
+ 4,
+ EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
+ sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_RCRB_HEADER),
+ (VOID *) (HeaderAddress)
+ );
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to interpret and print out the vendor specific structure
+
+ @param[in] HeaderAddress The Address of this capability header.
+ @param[in] HeadersBaseAddress The address of all the extended capability headers.
+**/
+EFI_STATUS
+EFIAPI
+PrintInterpretedExtendedCompatibilityVendorSpecific (
+ IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
+ IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
+ )
+{
+ CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_VENDOR_SPECIFIC *Header;
+ Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_VENDOR_SPECIFIC*)HeaderAddress;
+
+ ShellPrintHiiEx(
+ -1, -1, NULL,
+ STRING_TOKEN (STR_PCI_EXT_CAP_VEN),
+ gShellDebug1HiiHandle,
+ Header->VendorSpecificHeader
+ );
+ DumpHex (
+ 4,
+ EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
+ PCI_EXPRESS_EXTENDED_CAPABILITY_VENDOR_SPECIFIC_GET_SIZE(Header),
+ (VOID *) (HeaderAddress)
+ );
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to interpret and print out the Event Collector Endpoint Association structure
+
+ @param[in] HeaderAddress The Address of this capability header.
+ @param[in] HeadersBaseAddress The address of all the extended capability headers.
+**/
+EFI_STATUS
+EFIAPI
+PrintInterpretedExtendedCompatibilityECEA (
+ IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
+ IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
+ )
+{
+ CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_EVENT_COLLECTOR_ENDPOINT_ASSOCIATION *Header;
+ Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_EVENT_COLLECTOR_ENDPOINT_ASSOCIATION*)HeaderAddress;
+
+ ShellPrintHiiEx(
+ -1, -1, NULL,
+ STRING_TOKEN (STR_PCI_EXT_CAP_ECEA),
+ gShellDebug1HiiHandle,
+ Header->AssociationBitmap
+ );
+ DumpHex (
+ 4,
+ EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
+ sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_EVENT_COLLECTOR_ENDPOINT_ASSOCIATION),
+ (VOID *) (HeaderAddress)
+ );
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to interpret and print out the ARI structure
+
+ @param[in] HeaderAddress The Address of this capability header.
+ @param[in] HeadersBaseAddress The address of all the extended capability headers.
+**/
+EFI_STATUS
+EFIAPI
+PrintInterpretedExtendedCompatibilityAri (
+ IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
+ IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
+ )
+{
+ CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_ARI_CAPABILITY *Header;
+ Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_ARI_CAPABILITY*)HeaderAddress;
+
+ ShellPrintHiiEx(
+ -1, -1, NULL,
+ STRING_TOKEN (STR_PCI_EXT_CAP_ARI),
+ gShellDebug1HiiHandle,
+ Header->AriCapability,
+ Header->AriControl
+ );
+ DumpHex (
+ 4,
+ EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
+ sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_ARI_CAPABILITY),
+ (VOID *) (HeaderAddress)
+ );
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to interpret and print out the DPA structure
+
+ @param[in] HeaderAddress The Address of this capability header.
+ @param[in] HeadersBaseAddress The address of all the extended capability headers.
+**/
+EFI_STATUS
+EFIAPI
+PrintInterpretedExtendedCompatibilityDynamicPowerAllocation (
+ IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
+ IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
+ )
+{
+ CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_DYNAMIC_POWER_ALLOCATION *Header;
+ UINT8 LinkCount;
+ Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_DYNAMIC_POWER_ALLOCATION*)HeaderAddress;
+
+ ShellPrintHiiEx(
+ -1, -1, NULL,
+ STRING_TOKEN (STR_PCI_EXT_CAP_DPA),
+ gShellDebug1HiiHandle,
+ Header->DpaCapability,
+ Header->DpaLatencyIndicator,
+ Header->DpaStatus,
+ Header->DpaControl
+ );
+ for (LinkCount = 0 ; LinkCount < PCI_EXPRESS_EXTENDED_CAPABILITY_DYNAMIC_POWER_ALLOCATION_GET_SUBSTATE_MAX(Header) + 1 ; LinkCount++) {
+ ShellPrintHiiEx(
+ -1, -1, NULL,
+ STRING_TOKEN (STR_PCI_EXT_CAP_DPA2),
+ gShellDebug1HiiHandle,
+ LinkCount+1,
+ Header->DpaPowerAllocationArray[LinkCount]
+ );
+ }
+ DumpHex (
+ 4,
+ EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
+ sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_DYNAMIC_POWER_ALLOCATION) - 1 + PCI_EXPRESS_EXTENDED_CAPABILITY_DYNAMIC_POWER_ALLOCATION_GET_SUBSTATE_MAX(Header),
+ (VOID *) (HeaderAddress)
+ );
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to interpret and print out the link declaration structure
+
+ @param[in] HeaderAddress The Address of this capability header.
+ @param[in] HeadersBaseAddress The address of all the extended capability headers.
+**/
+EFI_STATUS
+EFIAPI
+PrintInterpretedExtendedCompatibilityLinkDeclaration (
+ IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
+ IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
+ )
+{
+ CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_LINK_DECLARATION *Header;
+ UINT8 LinkCount;
+ Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_LINK_DECLARATION*)HeaderAddress;
+
+ ShellPrintHiiEx(
+ -1, -1, NULL,
+ STRING_TOKEN (STR_PCI_EXT_CAP_LINK_DECLAR),
+ gShellDebug1HiiHandle,
+ Header->ElementSelfDescription
+ );
+
+ for (LinkCount = 0 ; LinkCount < PCI_EXPRESS_EXTENDED_CAPABILITY_LINK_DECLARATION_GET_LINK_COUNT(Header) ; LinkCount++) {
+ ShellPrintHiiEx(
+ -1, -1, NULL,
+ STRING_TOKEN (STR_PCI_EXT_CAP_LINK_DECLAR2),
+ gShellDebug1HiiHandle,
+ LinkCount+1,
+ Header->LinkEntry[LinkCount]
+ );
+ }
+ DumpHex (
+ 4,
+ EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
+ sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_LINK_DECLARATION) + (PCI_EXPRESS_EXTENDED_CAPABILITY_LINK_DECLARATION_GET_LINK_COUNT(Header)-1)*sizeof(UINT32),
+ (VOID *) (HeaderAddress)
+ );
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to interpret and print out the Advanced Error Reporting structure
+
+ @param[in] HeaderAddress The Address of this capability header.
+ @param[in] HeadersBaseAddress The address of all the extended capability headers.
+**/
+EFI_STATUS
+EFIAPI
+PrintInterpretedExtendedCompatibilityAer (
+ IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
+ IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
+ )
+{
+ CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_ADVANCED_ERROR_REPORTING *Header;
+ Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_ADVANCED_ERROR_REPORTING*)HeaderAddress;
+
+ ShellPrintHiiEx(
+ -1, -1, NULL,
+ STRING_TOKEN (STR_PCI_EXT_CAP_AER),
+ gShellDebug1HiiHandle,
+ Header->UncorrectableErrorStatus,
+ Header->UncorrectableErrorMask,
+ Header->UncorrectableErrorSeverity,
+ Header->CorrectableErrorStatus,
+ Header->CorrectableErrorMask,
+ Header->AdvancedErrorCapabilitiesAndControl,
+ Header->HeaderLog[0],
+ Header->HeaderLog[1],
+ Header->HeaderLog[2],
+ Header->HeaderLog[3],
+ Header->RootErrorCommand,
+ Header->RootErrorStatus,
+ Header->ErrorSourceIdentification,
+ Header->CorrectableErrorSourceIdentification,
+ Header->TlpPrefixLog[0],
+ Header->TlpPrefixLog[1],
+ Header->TlpPrefixLog[2],
+ Header->TlpPrefixLog[3]
+ );
+ DumpHex (
+ 4,
+ EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
+ sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_ADVANCED_ERROR_REPORTING),
+ (VOID *) (HeaderAddress)
+ );
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to interpret and print out the multicast structure
+
+ @param[in] HeaderAddress The Address of this capability header.
+ @param[in] HeadersBaseAddress The address of all the extended capability headers.
+ @param[in] PciExpressCapPtr The address of the PCIe capabilities structure.
+**/
+EFI_STATUS
+EFIAPI
+PrintInterpretedExtendedCompatibilityMulticast (
+ IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
+ IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress,
+ IN CONST PCIE_CAP_STRUCTURE *PciExpressCapPtr
+ )
+{
+ CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_MULTICAST *Header;
+ Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_MULTICAST*)HeaderAddress;
+
+ ShellPrintHiiEx(
+ -1, -1, NULL,
+ STRING_TOKEN (STR_PCI_EXT_CAP_MULTICAST),
+ gShellDebug1HiiHandle,
+ Header->MultiCastCapability,
+ Header->MulticastControl,
+ Header->McBaseAddress,
+ Header->McReceiveAddress,
+ Header->McBlockAll,
+ Header->McBlockUntranslated,
+ Header->McOverlayBar
+ );
+
+ DumpHex (
+ 4,
+ EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
+ sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_MULTICAST),
+ (VOID *) (HeaderAddress)
+ );
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to interpret and print out the virtual channel and multi virtual channel structure
+
+ @param[in] HeaderAddress The Address of this capability header.
+ @param[in] HeadersBaseAddress The address of all the extended capability headers.
+**/
+EFI_STATUS
+EFIAPI
+PrintInterpretedExtendedCompatibilityVirtualChannel (
+ IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
+ IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
+ )
+{
+ CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_VIRTUAL_CHANNEL_CAPABILITY *Header;
+ CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_VIRTUAL_CHANNEL_VC *CapabilityItem;
+ UINT32 ItemCount;
+ Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_VIRTUAL_CHANNEL_CAPABILITY*)HeaderAddress;
+
+ ShellPrintHiiEx(
+ -1, -1, NULL,
+ STRING_TOKEN (STR_PCI_EXT_CAP_VC_BASE),
+ gShellDebug1HiiHandle,
+ Header->ExtendedVcCount,
+ Header->PortVcCapability1,
+ Header->PortVcCapability2,
+ Header->VcArbTableOffset,
+ Header->PortVcControl,
+ Header->PortVcStatus
+ );
+ for (ItemCount = 0 ; ItemCount < Header->ExtendedVcCount ; ItemCount++) {
+ CapabilityItem = &Header->Capability[ItemCount];
+ ShellPrintHiiEx(
+ -1, -1, NULL,
+ STRING_TOKEN (STR_PCI_EXT_CAP_VC_ITEM),
+ gShellDebug1HiiHandle,
+ ItemCount+1,
+ CapabilityItem->VcResourceCapability,
+ CapabilityItem->PortArbTableOffset,
+ CapabilityItem->VcResourceControl,
+ CapabilityItem->VcResourceStatus
+ );
+ }
+
+ DumpHex (
+ 4,
+ EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
+ sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_VIRTUAL_CHANNEL_VC) + (Header->ExtendedVcCount - 1) * sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_VIRTUAL_CHANNEL_CAPABILITY),
+ (VOID *) (HeaderAddress)
+ );
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to interpret and print out the resizeable bar structure
+
+ @param[in] HeaderAddress The Address of this capability header.
+ @param[in] HeadersBaseAddress The address of all the extended capability headers.
+**/
+EFI_STATUS
+EFIAPI
+PrintInterpretedExtendedCompatibilityResizeableBar (
+ IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
+ IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
+ )
+{
+ CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR *Header;
+ UINT32 ItemCount;
+ Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR*)HeaderAddress;
+
+ for (ItemCount = 0 ; ItemCount < (UINT32)GET_NUMBER_RESIZABLE_BARS(Header) ; ItemCount++) {
+ ShellPrintHiiEx(
+ -1, -1, NULL,
+ STRING_TOKEN (STR_PCI_EXT_CAP_RESIZE_BAR),
+ gShellDebug1HiiHandle,
+ ItemCount+1,
+ Header->Capability[ItemCount].ResizableBarCapability,
+ Header->Capability[ItemCount].ResizableBarControl
+ );
+ }
+
+ DumpHex (
+ 4,
+ EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
+ (UINT32)GET_NUMBER_RESIZABLE_BARS(Header) * sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_RESIZABLE_BAR_ENTRY),
+ (VOID *) (HeaderAddress)
+ );
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to interpret and print out the TPH structure
+
+ @param[in] HeaderAddress The Address of this capability header.
+ @param[in] HeadersBaseAddress The address of all the extended capability headers.
+**/
+EFI_STATUS
+EFIAPI
+PrintInterpretedExtendedCompatibilityTph (
+ IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
+ IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress
+ )
+{
+ CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_TPH *Header;
+ Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_TPH*)HeaderAddress;
+
+ ShellPrintHiiEx(
+ -1, -1, NULL,
+ STRING_TOKEN (STR_PCI_EXT_CAP_TPH),
+ gShellDebug1HiiHandle,
+ Header->TphRequesterCapability,
+ Header->TphRequesterControl
+ );
+ DumpHex (
+ 8,
+ EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)Header->TphStTable - (UINT8*)HeadersBaseAddress),
+ GET_TPH_TABLE_SIZE(Header),
+ (VOID *)Header->TphStTable
+ );
+
+ DumpHex (
+ 4,
+ EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
+ sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_TPH) + GET_TPH_TABLE_SIZE(Header) - sizeof(UINT16),
+ (VOID *) (HeaderAddress)
+ );
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to interpret and print out the secondary PCIe capability structure
+
+ @param[in] HeaderAddress The Address of this capability header.
+ @param[in] HeadersBaseAddress The address of all the extended capability headers.
+ @param[in] PciExpressCapPtr The address of the PCIe capabilities structure.
+**/
+EFI_STATUS
+EFIAPI
+PrintInterpretedExtendedCompatibilitySecondary (
+ IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
+ IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress,
+ IN CONST PCIE_CAP_STRUCTURE *PciExpressCapPtr
+ )
+{
+ CONST PCI_EXPRESS_EXTENDED_CAPABILITIES_SECONDARY_PCIE *Header;
+ Header = (PCI_EXPRESS_EXTENDED_CAPABILITIES_SECONDARY_PCIE*)HeaderAddress;
+
+ ShellPrintHiiEx(
+ -1, -1, NULL,
+ STRING_TOKEN (STR_PCI_EXT_CAP_SECONDARY),
+ gShellDebug1HiiHandle,
+ Header->LinkControl3,
+ Header->LaneErrorStatus
+ );
+ DumpHex (
+ 8,
+ EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)Header->EqualizationControl - (UINT8*)HeadersBaseAddress),
+ PCIE_CAP_MAX_LINK_WIDTH(PciExpressCapPtr->LinkCap),
+ (VOID *)Header->EqualizationControl
+ );
+
+ DumpHex (
+ 4,
+ EFI_PCIE_CAPABILITY_BASE_OFFSET + ((UINT8*)HeaderAddress - (UINT8*)HeadersBaseAddress),
+ sizeof(PCI_EXPRESS_EXTENDED_CAPABILITIES_TPH) - sizeof(Header->EqualizationControl) + PCIE_CAP_MAX_LINK_WIDTH(PciExpressCapPtr->LinkCap),
+ (VOID *) (HeaderAddress)
+ );
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Display Pcie extended capability details
+
+ @param[in] HeadersBaseAddress The address of all the extended capability headers.
+ @param[in] HeaderAddress The address of this capability header.
+ @param[in] PciExpressCapPtr The address of the PCIe capabilities structure.
+**/
+EFI_STATUS
+EFIAPI
+PrintPciExtendedCapabilityDetails(
+ IN CONST PCI_EXP_EXT_HDR *HeadersBaseAddress,
+ IN CONST PCI_EXP_EXT_HDR *HeaderAddress,
+ IN CONST PCIE_CAP_STRUCTURE *PciExpressCapPtr
+ )
+{
+ switch (HeaderAddress->CapabilityId){
+ case PCI_EXPRESS_EXTENDED_CAPABILITY_ADVANCED_ERROR_REPORTING_ID:
+ return PrintInterpretedExtendedCompatibilityAer(HeaderAddress, HeadersBaseAddress);
+ case PCI_EXPRESS_EXTENDED_CAPABILITY_LINK_CONTROL_ID:
+ return PrintInterpretedExtendedCompatibilityLinkControl(HeaderAddress, HeadersBaseAddress);
+ case PCI_EXPRESS_EXTENDED_CAPABILITY_LINK_DECLARATION_ID:
+ return PrintInterpretedExtendedCompatibilityLinkDeclaration(HeaderAddress, HeadersBaseAddress);
+ case PCI_EXPRESS_EXTENDED_CAPABILITY_SERIAL_NUMBER_ID:
+ return PrintInterpretedExtendedCompatibilitySerialNumber(HeaderAddress, HeadersBaseAddress);
+ case PCI_EXPRESS_EXTENDED_CAPABILITY_POWER_BUDGETING_ID:
+ return PrintInterpretedExtendedCompatibilityPowerBudgeting(HeaderAddress, HeadersBaseAddress);
+ case PCI_EXPRESS_EXTENDED_CAPABILITY_ACS_EXTENDED_ID:
+ return PrintInterpretedExtendedCompatibilityAcs(HeaderAddress, HeadersBaseAddress);
+ case PCI_EXPRESS_EXTENDED_CAPABILITY_LATENCE_TOLERANCE_REPORTING_ID:
+ return PrintInterpretedExtendedCompatibilityLatencyToleranceReporting(HeaderAddress, HeadersBaseAddress);
+ case PCI_EXPRESS_EXTENDED_CAPABILITY_ARI_CAPABILITY_ID:
+ return PrintInterpretedExtendedCompatibilityAri(HeaderAddress, HeadersBaseAddress);
+ case PCI_EXPRESS_EXTENDED_CAPABILITY_RCRB_HEADER_ID:
+ return PrintInterpretedExtendedCompatibilityRcrb(HeaderAddress, HeadersBaseAddress);
+ case PCI_EXPRESS_EXTENDED_CAPABILITY_VENDOR_SPECIFIC_ID:
+ return PrintInterpretedExtendedCompatibilityVendorSpecific(HeaderAddress, HeadersBaseAddress);
+ case PCI_EXPRESS_EXTENDED_CAPABILITY_DYNAMIC_POWER_ALLOCATION_ID:
+ return PrintInterpretedExtendedCompatibilityDynamicPowerAllocation(HeaderAddress, HeadersBaseAddress);
+ case PCI_EXPRESS_EXTENDED_CAPABILITY_EVENT_COLLECTOR_ENDPOINT_ASSOCIATION_ID:
+ return PrintInterpretedExtendedCompatibilityECEA(HeaderAddress, HeadersBaseAddress);
+ case PCI_EXPRESS_EXTENDED_CAPABILITY_VIRTUAL_CHANNEL_ID:
+ case PCI_EXPRESS_EXTENDED_CAPABILITY_MULTI_FUNCTION_VIRTUAL_CHANNEL_ID:
+ return PrintInterpretedExtendedCompatibilityVirtualChannel(HeaderAddress, HeadersBaseAddress);
+ case PCI_EXPRESS_EXTENDED_CAPABILITY_MULTICAST_ID:
+ //
+ // should only be present if PCIE_CAP_DEVICEPORT_TYPE(PciExpressCapPtr->PcieCapReg) == 0100b, 0101b, or 0110b
+ //
+ return PrintInterpretedExtendedCompatibilityMulticast(HeaderAddress, HeadersBaseAddress, PciExpressCapPtr);
+ case PCI_EXPRESS_EXTENDED_CAPABILITY_RESIZABLE_BAR_ID:
+ return PrintInterpretedExtendedCompatibilityResizeableBar(HeaderAddress, HeadersBaseAddress);
+ case PCI_EXPRESS_EXTENDED_CAPABILITY_TPH_ID:
+ return PrintInterpretedExtendedCompatibilityTph(HeaderAddress, HeadersBaseAddress);
+ case PCI_EXPRESS_EXTENDED_CAPABILITY_SECONDARY_PCIE_ID:
+ return PrintInterpretedExtendedCompatibilitySecondary(HeaderAddress, HeadersBaseAddress, PciExpressCapPtr);
+ default:
+ ShellPrintEx (-1, -1,
+ L"Unknown PCIe extended capability ID (%04xh). No interpretation available.\r\n",
+ HeaderAddress->CapabilityId
+ );
+ return EFI_SUCCESS;
+ };
+
+}
+
+/**
+ Display Pcie device structure.
+
+ @param[in] IoDev The pointer to the root pci protocol.
+ @param[in] Address The Address to start at.
+ @param[in] CapabilityPtr The offset from the address to start.
+ @param[in] EnhancedDump The print format for the dump data.
+
+**/
+EFI_STATUS
+PciExplainPciExpress (
+ IN EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL *IoDev,
+ IN UINT64 Address,
+ IN UINT8 CapabilityPtr,
+ IN CONST UINT16 EnhancedDump
+ )
+{
+
+ PCIE_CAP_STRUCTURE PciExpressCap;
+ EFI_STATUS Status;
+ UINT64 CapRegAddress;
+ UINT8 Bus;
+ UINT8 Dev;
+ UINT8 Func;
+ UINT8 *ExRegBuffer;
+ UINTN ExtendRegSize;
+ UINT64 Pciex_Address;
+ UINT8 DevicePortType;
+ UINTN Index;
+ UINT8 *RegAddr;
+ UINTN RegValue;
+ PCI_EXP_EXT_HDR *ExtHdr;
+
+ CapRegAddress = Address + CapabilityPtr;
+ IoDev->Pci.Read (
+ IoDev,
+ EfiPciWidthUint32,
+ CapRegAddress,
+ sizeof (PciExpressCap) / sizeof (UINT32),
+ &PciExpressCap
+ );
+
+ DevicePortType = (UINT8) PCIE_CAP_DEVICEPORT_TYPE (PciExpressCap.PcieCapReg);
+
+ ShellPrintEx (-1, -1, L"\r\nPci Express device capability structure:\r\n");
+
+ for (Index = 0; PcieExplainList[Index].Type < PcieExplainTypeMax; Index++) {
+ if (ShellGetExecutionBreakFlag()) {
+ goto Done;
+ }
+ RegAddr = ((UINT8 *) &PciExpressCap) + PcieExplainList[Index].Offset;
+ switch (PcieExplainList[Index].Width) {
+ case FieldWidthUINT8:
+ RegValue = *(UINT8 *) RegAddr;
+ break;
+ case FieldWidthUINT16:
+ RegValue = *(UINT16 *) RegAddr;
+ break;
+ case FieldWidthUINT32:
+ RegValue = *(UINT32 *) RegAddr;
+ break;
+ default:
+ RegValue = 0;
+ break;
+ }
+ ShellPrintHiiEx(-1, -1, NULL,
+ PcieExplainList[Index].Token,
+ gShellDebug1HiiHandle,
+ PcieExplainList[Index].Offset,
+ RegValue
+ );
+ if (PcieExplainList[Index].Func == NULL) {
+ continue;
+ }
+ switch (PcieExplainList[Index].Type) {
+ case PcieExplainTypeLink:
+ //
+ // Link registers should not be used by
+ // a) Root Complex Integrated Endpoint
+ // b) Root Complex Event Collector
+ //
+ if (DevicePortType == PCIE_ROOT_COMPLEX_INTEGRATED_PORT ||
+ DevicePortType == PCIE_ROOT_COMPLEX_EVENT_COLLECTOR) {
+ continue;
+ }
+ break;
+ case PcieExplainTypeSlot:
+ //
+ // Slot registers are only valid for
+ // a) Root Port of PCI Express Root Complex
+ // b) Downstream Port of PCI Express Switch
+ // and when SlotImplemented bit is set in PCIE cap register.
+ //
+ if ((DevicePortType != PCIE_ROOT_COMPLEX_ROOT_PORT &&
+ DevicePortType != PCIE_SWITCH_DOWNSTREAM_PORT) ||
+ !PCIE_CAP_SLOT_IMPLEMENTED (PciExpressCap.PcieCapReg)) {
+ continue;
+ }
+ break;
+ case PcieExplainTypeRoot:
+ //
+ // Root registers are only valid for
+ // Root Port of PCI Express Root Complex
+ //
+ if (DevicePortType != PCIE_ROOT_COMPLEX_ROOT_PORT) {
+ continue;
+ }
+ break;
+ default:
+ break;
+ }
+ PcieExplainList[Index].Func (&PciExpressCap);
+ }
+
+ Bus = (UINT8) (RShiftU64 (Address, 24));
+ Dev = (UINT8) (RShiftU64 (Address, 16));
+ Func = (UINT8) (RShiftU64 (Address, 8));
+
+ Pciex_Address = CALC_EFI_PCIEX_ADDRESS (Bus, Dev, Func, EFI_PCIE_CAPABILITY_BASE_OFFSET);
+
+ ExtendRegSize = 0x1000 - EFI_PCIE_CAPABILITY_BASE_OFFSET;
+
+ ExRegBuffer = (UINT8 *) AllocateZeroPool (ExtendRegSize);
+
+ //
+ // PciRootBridgeIo protocol should support pci express extend space IO
+ // (Begins at offset EFI_PCIE_CAPABILITY_BASE_OFFSET)
+ //
+ Status = IoDev->Pci.Read (
+ IoDev,
+ EfiPciWidthUint32,
+ Pciex_Address,
+ (ExtendRegSize) / sizeof (UINT32),
+ (VOID *) (ExRegBuffer)
+ );
+ if (EFI_ERROR (Status) || ExRegBuffer == NULL) {
+ SHELL_FREE_NON_NULL(ExRegBuffer);
+ return EFI_UNSUPPORTED;
+ }
+
+ if (EnhancedDump == 0) {
+ //
+ // Print the PciEx extend space in raw bytes ( 0xFF-0xFFF)
+ //
+ ShellPrintEx (-1, -1, L"\r\n%HStart dumping PCIex extended configuration space (0x100 - 0xFFF).%N\r\n\r\n");
+
+ DumpHex (
+ 2,
+ EFI_PCIE_CAPABILITY_BASE_OFFSET,
+ ExtendRegSize,
+ (VOID *) (ExRegBuffer)
+ );
+ } else {
+ ExtHdr = (PCI_EXP_EXT_HDR*)ExRegBuffer;
+ while (ExtHdr->CapabilityId != 0 && ExtHdr->CapabilityVersion != 0) {
+ //
+ // Process this item
+ //
+ if (EnhancedDump == 0xFFFF || EnhancedDump == ExtHdr->CapabilityId) {
+ //
+ // Print this item
+ //
+ PrintPciExtendedCapabilityDetails((PCI_EXP_EXT_HDR*)ExRegBuffer, ExtHdr, &PciExpressCap);
+ }
+
+ //
+ // Advance to the next item if it exists
+ //
+ if (ExtHdr->NextCapabilityOffset != 0) {
+ ExtHdr = (PCI_EXP_EXT_HDR*)((UINT8*)ExRegBuffer + ExtHdr->NextCapabilityOffset);
+ } else {
+ break;
+ }
+ }
+ }
+ SHELL_FREE_NON_NULL(ExRegBuffer);
+
+Done:
+ return EFI_SUCCESS;
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.h
new file mode 100644
index 0000000000..1b06154842
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/Pci.h
@@ -0,0 +1,463 @@
+/** @file
+ Header file for Pci shell Debug1 function.
+
+ Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2005 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _EFI_SHELL_PCI_H_
+#define _EFI_SHELL_PCI_H_
+
+typedef enum {
+ PciDevice,
+ PciP2pBridge,
+ PciCardBusBridge,
+ PciUndefined
+} PCI_HEADER_TYPE;
+
+#define HEADER_TYPE_MULTI_FUNCTION 0x80
+
+#define MAX_BUS_NUMBER 255
+#define MAX_DEVICE_NUMBER 31
+#define MAX_FUNCTION_NUMBER 7
+
+#define EFI_PCI_CAPABILITY_ID_PCIEXP 0x10
+#define EFI_PCI_CAPABILITY_ID_PCIX 0x07
+
+#define CALC_EFI_PCI_ADDRESS(Bus, Dev, Func, Reg) \
+ ((UINT64) ((((UINTN) Bus) << 24) + (((UINTN) Dev) << 16) + (((UINTN) Func) << 8) + ((UINTN) Reg)))
+
+#define CALC_EFI_PCIEX_ADDRESS(Bus, Dev, Func, ExReg) ( \
+ (UINT64) ((((UINTN) Bus) << 24) + (((UINTN) Dev) << 16) + (((UINTN) Func) << 8) + (LShiftU64 ((UINT64) ExReg, 32))) \
+ );
+
+#define INDEX_OF(Field) ((UINT8 *) (Field) - (UINT8 *) mConfigSpace)
+
+#define PCI_BIT_0 0x00000001
+#define PCI_BIT_1 0x00000002
+#define PCI_BIT_2 0x00000004
+#define PCI_BIT_3 0x00000008
+#define PCI_BIT_4 0x00000010
+#define PCI_BIT_5 0x00000020
+#define PCI_BIT_6 0x00000040
+#define PCI_BIT_7 0x00000080
+#define PCI_BIT_8 0x00000100
+#define PCI_BIT_9 0x00000200
+#define PCI_BIT_10 0x00000400
+#define PCI_BIT_11 0x00000800
+#define PCI_BIT_12 0x00001000
+#define PCI_BIT_13 0x00002000
+#define PCI_BIT_14 0x00004000
+#define PCI_BIT_15 0x00008000
+
+//
+// PCIE device/port types
+//
+#define PCIE_PCIE_ENDPOINT 0
+#define PCIE_LEGACY_PCIE_ENDPOINT 1
+#define PCIE_ROOT_COMPLEX_ROOT_PORT 4
+#define PCIE_SWITCH_UPSTREAM_PORT 5
+#define PCIE_SWITCH_DOWNSTREAM_PORT 6
+#define PCIE_PCIE_TO_PCIX_BRIDGE 7
+#define PCIE_PCIX_TO_PCIE_BRIDGE 8
+#define PCIE_ROOT_COMPLEX_INTEGRATED_PORT 9
+#define PCIE_ROOT_COMPLEX_EVENT_COLLECTOR 10
+#define PCIE_DEVICE_PORT_TYPE_MAX 11
+
+#define IS_PCIE_ENDPOINT(DevicePortType) \
+ ((DevicePortType) == PCIE_PCIE_ENDPOINT || \
+ (DevicePortType) == PCIE_LEGACY_PCIE_ENDPOINT || \
+ (DevicePortType) == PCIE_ROOT_COMPLEX_INTEGRATED_PORT)
+
+#define IS_PCIE_SWITCH(DevicePortType) \
+ ((DevicePortType == PCIE_SWITCH_UPSTREAM_PORT) || \
+ (DevicePortType == PCIE_SWITCH_DOWNSTREAM_PORT))
+
+//
+// Capabilities Register
+//
+#define PCIE_CAP_VERSION(PcieCapReg) \
+ ((PcieCapReg) & 0x0f)
+#define PCIE_CAP_DEVICEPORT_TYPE(PcieCapReg) \
+ (((PcieCapReg) >> 4) & 0x0f)
+#define PCIE_CAP_SLOT_IMPLEMENTED(PcieCapReg) \
+ (((PcieCapReg) >> 8) & 0x1)
+#define PCIE_CAP_INT_MSG_NUM(PcieCapReg) \
+ (((PcieCapReg) >> 9) & 0x1f)
+//
+// Device Capabilities Register
+//
+#define PCIE_CAP_MAX_PAYLOAD(PcieDeviceCap) \
+ ((PcieDeviceCap) & 0x7)
+#define PCIE_CAP_PHANTOM_FUNC(PcieDeviceCap) \
+ (((PcieDeviceCap) >> 3) & 0x3)
+#define PCIE_CAP_EXTENDED_TAG(PcieDeviceCap) \
+ (((PcieDeviceCap) >> 5) & 0x1)
+#define PCIE_CAP_L0SLATENCY(PcieDeviceCap) \
+ (((PcieDeviceCap) >> 6) & 0x7)
+#define PCIE_CAP_L1LATENCY(PcieDeviceCap) \
+ (((PcieDeviceCap) >> 9) & 0x7)
+#define PCIE_CAP_ERR_REPORTING(PcieDeviceCap) \
+ (((PcieDeviceCap) >> 15) & 0x1)
+#define PCIE_CAP_SLOT_POWER_VALUE(PcieDeviceCap) \
+ (((PcieDeviceCap) >> 18) & 0x0ff)
+#define PCIE_CAP_SLOT_POWER_SCALE(PcieDeviceCap) \
+ (((PcieDeviceCap) >> 26) & 0x3)
+#define PCIE_CAP_FUNC_LEVEL_RESET(PcieDeviceCap) \
+ (((PcieDeviceCap) >> 28) & 0x1)
+//
+// Device Control Register
+//
+#define PCIE_CAP_COR_ERR_REPORTING_ENABLE(PcieDeviceControl) \
+ ((PcieDeviceControl) & 0x1)
+#define PCIE_CAP_NONFAT_ERR_REPORTING_ENABLE(PcieDeviceControl) \
+ (((PcieDeviceControl) >> 1) & 0x1)
+#define PCIE_CAP_FATAL_ERR_REPORTING_ENABLE(PcieDeviceControl) \
+ (((PcieDeviceControl) >> 2) & 0x1)
+#define PCIE_CAP_UNSUP_REQ_REPORTING_ENABLE(PcieDeviceControl) \
+ (((PcieDeviceControl) >> 3) & 0x1)
+#define PCIE_CAP_RELAXED_ORDERING_ENABLE(PcieDeviceControl) \
+ (((PcieDeviceControl) >> 4) & 0x1)
+#define PCIE_CAP_MAX_PAYLOAD_SIZE(PcieDeviceControl) \
+ (((PcieDeviceControl) >> 5) & 0x7)
+#define PCIE_CAP_EXTENDED_TAG_ENABLE(PcieDeviceControl) \
+ (((PcieDeviceControl) >> 8) & 0x1)
+#define PCIE_CAP_PHANTOM_FUNC_ENABLE(PcieDeviceControl) \
+ (((PcieDeviceControl) >> 9) & 0x1)
+#define PCIE_CAP_AUX_PM_ENABLE(PcieDeviceControl) \
+ (((PcieDeviceControl) >> 10) & 0x1)
+#define PCIE_CAP_NO_SNOOP_ENABLE(PcieDeviceControl) \
+ (((PcieDeviceControl) >> 11) & 0x1)
+#define PCIE_CAP_MAX_READ_REQ_SIZE(PcieDeviceControl) \
+ (((PcieDeviceControl) >> 12) & 0x7)
+#define PCIE_CAP_BRG_CONF_RETRY(PcieDeviceControl) \
+ (((PcieDeviceControl) >> 15) & 0x1)
+//
+// Device Status Register
+//
+#define PCIE_CAP_COR_ERR_DETECTED(PcieDeviceStatus) \
+ ((PcieDeviceStatus) & 0x1)
+#define PCIE_CAP_NONFAT_ERR_DETECTED(PcieDeviceStatus) \
+ (((PcieDeviceStatus) >> 1) & 0x1)
+#define PCIE_CAP_FATAL_ERR_DETECTED(PcieDeviceStatus) \
+ (((PcieDeviceStatus) >> 2) & 0x1)
+#define PCIE_CAP_UNSUP_REQ_DETECTED(PcieDeviceStatus) \
+ (((PcieDeviceStatus) >> 3) & 0x1)
+#define PCIE_CAP_AUX_POWER_DETECTED(PcieDeviceStatus) \
+ (((PcieDeviceStatus) >> 4) & 0x1)
+#define PCIE_CAP_TRANSACTION_PENDING(PcieDeviceStatus) \
+ (((PcieDeviceStatus) >> 5) & 0x1)
+//
+// Link Capabilities Register
+//
+#define PCIE_CAP_MAX_LINK_SPEED(PcieLinkCap) \
+ ((PcieLinkCap) & 0x0f)
+#define PCIE_CAP_MAX_LINK_WIDTH(PcieLinkCap) \
+ (((PcieLinkCap) >> 4) & 0x3f)
+#define PCIE_CAP_ASPM_SUPPORT(PcieLinkCap) \
+ (((PcieLinkCap) >> 10) & 0x3)
+#define PCIE_CAP_L0S_LATENCY(PcieLinkCap) \
+ (((PcieLinkCap) >> 12) & 0x7)
+#define PCIE_CAP_L1_LATENCY(PcieLinkCap) \
+ (((PcieLinkCap) >> 15) & 0x7)
+#define PCIE_CAP_CLOCK_PM(PcieLinkCap) \
+ (((PcieLinkCap) >> 18) & 0x1)
+#define PCIE_CAP_SUP_DOWN_ERR_REPORTING(PcieLinkCap) \
+ (((PcieLinkCap) >> 19) & 0x1)
+#define PCIE_CAP_LINK_ACTIVE_REPORTING(PcieLinkCap) \
+ (((PcieLinkCap) >> 20) & 0x1)
+#define PCIE_CAP_LINK_BWD_NOTIF_CAP(PcieLinkCap) \
+ (((PcieLinkCap) >> 21) & 0x1)
+#define PCIE_CAP_PORT_NUMBER(PcieLinkCap) \
+ (((PcieLinkCap) >> 24) & 0x0ff)
+//
+// Link Control Register
+//
+#define PCIE_CAP_ASPM_CONTROL(PcieLinkControl) \
+ ((PcieLinkControl) & 0x3)
+#define PCIE_CAP_RCB(PcieLinkControl) \
+ (((PcieLinkControl) >> 3) & 0x1)
+#define PCIE_CAP_LINK_DISABLE(PcieLinkControl) \
+ (((PcieLinkControl) >> 4) & 0x1)
+#define PCIE_CAP_COMMON_CLK_CONF(PcieLinkControl) \
+ (((PcieLinkControl) >> 6) & 0x1)
+#define PCIE_CAP_EXT_SYNC(PcieLinkControl) \
+ (((PcieLinkControl) >> 7) & 0x1)
+#define PCIE_CAP_CLK_PWR_MNG(PcieLinkControl) \
+ (((PcieLinkControl) >> 8) & 0x1)
+#define PCIE_CAP_HW_AUTO_WIDTH_DISABLE(PcieLinkControl) \
+ (((PcieLinkControl) >> 9) & 0x1)
+#define PCIE_CAP_LINK_BDW_MNG_INT_EN(PcieLinkControl) \
+ (((PcieLinkControl) >> 10) & 0x1)
+#define PCIE_CAP_LINK_AUTO_BDW_INT_EN(PcieLinkControl) \
+ (((PcieLinkControl) >> 11) & 0x1)
+//
+// Link Status Register
+//
+#define PCIE_CAP_CUR_LINK_SPEED(PcieLinkStatus) \
+ ((PcieLinkStatus) & 0x0f)
+#define PCIE_CAP_NEGO_LINK_WIDTH(PcieLinkStatus) \
+ (((PcieLinkStatus) >> 4) & 0x3f)
+#define PCIE_CAP_LINK_TRAINING(PcieLinkStatus) \
+ (((PcieLinkStatus) >> 11) & 0x1)
+#define PCIE_CAP_SLOT_CLK_CONF(PcieLinkStatus) \
+ (((PcieLinkStatus) >> 12) & 0x1)
+#define PCIE_CAP_DATA_LINK_ACTIVE(PcieLinkStatus) \
+ (((PcieLinkStatus) >> 13) & 0x1)
+#define PCIE_CAP_LINK_BDW_MNG_STAT(PcieLinkStatus) \
+ (((PcieLinkStatus) >> 14) & 0x1)
+#define PCIE_CAP_LINK_AUTO_BDW_STAT(PcieLinkStatus) \
+ (((PcieLinkStatus) >> 15) & 0x1)
+//
+// Slot Capabilities Register
+//
+#define PCIE_CAP_ATT_BUT_PRESENT(PcieSlotCap) \
+ ((PcieSlotCap) & 0x1)
+#define PCIE_CAP_PWR_CTRLLER_PRESENT(PcieSlotCap) \
+ (((PcieSlotCap) >> 1) & 0x1)
+#define PCIE_CAP_MRL_SENSOR_PRESENT(PcieSlotCap) \
+ (((PcieSlotCap) >> 2) & 0x1)
+#define PCIE_CAP_ATT_IND_PRESENT(PcieSlotCap) \
+ (((PcieSlotCap) >> 3) & 0x1)
+#define PCIE_CAP_PWD_IND_PRESENT(PcieSlotCap) \
+ (((PcieSlotCap) >> 4) & 0x1)
+#define PCIE_CAP_HOTPLUG_SUPPRISE(PcieSlotCap) \
+ (((PcieSlotCap) >> 5) & 0x1)
+#define PCIE_CAP_HOTPLUG_CAPABLE(PcieSlotCap) \
+ (((PcieSlotCap) >> 6) & 0x1)
+#define PCIE_CAP_SLOT_PWR_LIMIT_VALUE(PcieSlotCap) \
+ (((PcieSlotCap) >> 7) & 0x0ff)
+#define PCIE_CAP_SLOT_PWR_LIMIT_SCALE(PcieSlotCap) \
+ (((PcieSlotCap) >> 15) & 0x3)
+#define PCIE_CAP_ELEC_INTERLOCK_PRESENT(PcieSlotCap) \
+ (((PcieSlotCap) >> 17) & 0x1)
+#define PCIE_CAP_NO_COMM_COMPLETED_SUP(PcieSlotCap) \
+ (((PcieSlotCap) >> 18) & 0x1)
+#define PCIE_CAP_PHY_SLOT_NUM(PcieSlotCap) \
+ (((PcieSlotCap) >> 19) & 0x1fff)
+//
+// Slot Control Register
+//
+#define PCIE_CAP_ATT_BUT_ENABLE(PcieSlotControl) \
+ ((PcieSlotControl) & 0x1)
+#define PCIE_CAP_PWR_FLT_DETECT_ENABLE(PcieSlotControl) \
+ (((PcieSlotControl) >> 1) & 0x1)
+#define PCIE_CAP_MRL_SENSOR_CHANGE_ENABLE(PcieSlotControl) \
+ (((PcieSlotControl) >> 2) & 0x1)
+#define PCIE_CAP_PRES_DETECT_CHANGE_ENABLE(PcieSlotControl) \
+ (((PcieSlotControl) >> 3) & 0x1)
+#define PCIE_CAP_COMM_CMPL_INT_ENABLE(PcieSlotControl) \
+ (((PcieSlotControl) >> 4) & 0x1)
+#define PCIE_CAP_HOTPLUG_INT_ENABLE(PcieSlotControl) \
+ (((PcieSlotControl) >> 5) & 0x1)
+#define PCIE_CAP_ATT_IND_CTRL(PcieSlotControl) \
+ (((PcieSlotControl) >> 6) & 0x3)
+#define PCIE_CAP_PWR_IND_CTRL(PcieSlotControl) \
+ (((PcieSlotControl) >> 8) & 0x3)
+#define PCIE_CAP_PWR_CTRLLER_CTRL(PcieSlotControl) \
+ (((PcieSlotControl) >> 10) & 0x1)
+#define PCIE_CAP_ELEC_INTERLOCK_CTRL(PcieSlotControl) \
+ (((PcieSlotControl) >> 11) & 0x1)
+#define PCIE_CAP_DLINK_STAT_CHANGE_ENABLE(PcieSlotControl) \
+ (((PcieSlotControl) >> 12) & 0x1)
+//
+// Slot Status Register
+//
+#define PCIE_CAP_ATT_BUT_PRESSED(PcieSlotStatus) \
+ ((PcieSlotStatus) & 0x1)
+#define PCIE_CAP_PWR_FLT_DETECTED(PcieSlotStatus) \
+ (((PcieSlotStatus) >> 1) & 0x1)
+#define PCIE_CAP_MRL_SENSOR_CHANGED(PcieSlotStatus) \
+ (((PcieSlotStatus) >> 2) & 0x1)
+#define PCIE_CAP_PRES_DETECT_CHANGED(PcieSlotStatus) \
+ (((PcieSlotStatus) >> 3) & 0x1)
+#define PCIE_CAP_COMM_COMPLETED(PcieSlotStatus) \
+ (((PcieSlotStatus) >> 4) & 0x1)
+#define PCIE_CAP_MRL_SENSOR_STATE(PcieSlotStatus) \
+ (((PcieSlotStatus) >> 5) & 0x1)
+#define PCIE_CAP_PRES_DETECT_STATE(PcieSlotStatus) \
+ (((PcieSlotStatus) >> 6) & 0x1)
+#define PCIE_CAP_ELEC_INTERLOCK_STATE(PcieSlotStatus) \
+ (((PcieSlotStatus) >> 7) & 0x1)
+#define PCIE_CAP_DLINK_STAT_CHANGED(PcieSlotStatus) \
+ (((PcieSlotStatus) >> 8) & 0x1)
+//
+// Root Control Register
+//
+#define PCIE_CAP_SYSERR_ON_CORERR_EN(PcieRootControl) \
+ ((PcieRootControl) & 0x1)
+#define PCIE_CAP_SYSERR_ON_NONFATERR_EN(PcieRootControl) \
+ (((PcieRootControl) >> 1) & 0x1)
+#define PCIE_CAP_SYSERR_ON_FATERR_EN(PcieRootControl) \
+ (((PcieRootControl) >> 2) & 0x1)
+#define PCIE_CAP_PME_INT_ENABLE(PcieRootControl) \
+ (((PcieRootControl) >> 3) & 0x1)
+#define PCIE_CAP_CRS_SW_VIS_ENABLE(PcieRootControl) \
+ (((PcieRootControl) >> 4) & 0x1)
+//
+// Root Capabilities Register
+//
+#define PCIE_CAP_CRS_SW_VIS(PcieRootCap) \
+ ((PcieRootCap) & 0x1)
+//
+// Root Status Register
+//
+#define PCIE_CAP_PME_REQ_ID(PcieRootStatus) \
+ ((PcieRootStatus) & 0x0ffff)
+#define PCIE_CAP_PME_STATUS(PcieRootStatus) \
+ (((PcieRootStatus) >> 16) & 0x1)
+#define PCIE_CAP_PME_PENDING(PcieRootStatus) \
+ (((PcieRootStatus) >> 17) & 0x1)
+
+#pragma pack(1)
+//
+// Common part of the PCI configuration space header for devices, P2P bridges,
+// and cardbus bridges
+//
+typedef struct {
+ UINT16 VendorId;
+ UINT16 DeviceId;
+
+ UINT16 Command;
+ UINT16 Status;
+
+ UINT8 RevisionId;
+ UINT8 ClassCode[3];
+
+ UINT8 CacheLineSize;
+ UINT8 PrimaryLatencyTimer;
+ UINT8 HeaderType;
+ UINT8 Bist;
+
+} PCI_COMMON_HEADER;
+
+//
+// PCI configuration space header for devices(after the common part)
+//
+typedef struct {
+ UINT32 Bar[6]; // Base Address Registers
+ UINT32 CardBusCISPtr; // CardBus CIS Pointer
+ UINT16 SubVendorId; // Subsystem Vendor ID
+ UINT16 SubSystemId; // Subsystem ID
+ UINT32 ROMBar; // Expansion ROM Base Address
+ UINT8 CapabilitiesPtr; // Capabilities Pointer
+ UINT8 Reserved[3];
+
+ UINT32 Reserved1;
+
+ UINT8 InterruptLine; // Interrupt Line
+ UINT8 InterruptPin; // Interrupt Pin
+ UINT8 MinGnt; // Min_Gnt
+ UINT8 MaxLat; // Max_Lat
+} PCI_DEVICE_HEADER;
+
+//
+// PCI configuration space header for pci-to-pci bridges(after the common part)
+//
+typedef struct {
+ UINT32 Bar[2]; // Base Address Registers
+ UINT8 PrimaryBus; // Primary Bus Number
+ UINT8 SecondaryBus; // Secondary Bus Number
+ UINT8 SubordinateBus; // Subordinate Bus Number
+ UINT8 SecondaryLatencyTimer; // Secondary Latency Timer
+ UINT8 IoBase; // I/O Base
+ UINT8 IoLimit; // I/O Limit
+ UINT16 SecondaryStatus; // Secondary Status
+ UINT16 MemoryBase; // Memory Base
+ UINT16 MemoryLimit; // Memory Limit
+ UINT16 PrefetchableMemBase; // Pre-fetchable Memory Base
+ UINT16 PrefetchableMemLimit; // Pre-fetchable Memory Limit
+ UINT32 PrefetchableBaseUpper; // Pre-fetchable Base Upper 32 bits
+ UINT32 PrefetchableLimitUpper; // Pre-fetchable Limit Upper 32 bits
+ UINT16 IoBaseUpper; // I/O Base Upper 16 bits
+ UINT16 IoLimitUpper; // I/O Limit Upper 16 bits
+ UINT8 CapabilitiesPtr; // Capabilities Pointer
+ UINT8 Reserved[3];
+
+ UINT32 ROMBar; // Expansion ROM Base Address
+ UINT8 InterruptLine; // Interrupt Line
+ UINT8 InterruptPin; // Interrupt Pin
+ UINT16 BridgeControl; // Bridge Control
+} PCI_BRIDGE_HEADER;
+
+//
+// PCI configuration space header for cardbus bridges(after the common part)
+//
+typedef struct {
+ UINT32 CardBusSocketReg; // Cardus Socket/ExCA Base
+ // Address Register
+ //
+ UINT8 CapabilitiesPtr; // 14h in pci-cardbus bridge.
+ UINT8 Reserved;
+ UINT16 SecondaryStatus; // Secondary Status
+ UINT8 PciBusNumber; // PCI Bus Number
+ UINT8 CardBusBusNumber; // CardBus Bus Number
+ UINT8 SubordinateBusNumber; // Subordinate Bus Number
+ UINT8 CardBusLatencyTimer; // CardBus Latency Timer
+ UINT32 MemoryBase0; // Memory Base Register 0
+ UINT32 MemoryLimit0; // Memory Limit Register 0
+ UINT32 MemoryBase1;
+ UINT32 MemoryLimit1;
+ UINT32 IoBase0;
+ UINT32 IoLimit0; // I/O Base Register 0
+ UINT32 IoBase1; // I/O Limit Register 0
+ UINT32 IoLimit1;
+
+ UINT8 InterruptLine; // Interrupt Line
+ UINT8 InterruptPin; // Interrupt Pin
+ UINT16 BridgeControl; // Bridge Control
+} PCI_CARDBUS_HEADER;
+
+//
+// Data region after PCI configuration header(for cardbus bridge)
+//
+typedef struct {
+ UINT16 SubVendorId; // Subsystem Vendor ID
+ UINT16 SubSystemId; // Subsystem ID
+ UINT32 LegacyBase; // Optional 16-Bit PC Card Legacy
+ // Mode Base Address
+ //
+ UINT32 Data[46];
+} PCI_CARDBUS_DATA;
+
+typedef union {
+ PCI_DEVICE_HEADER Device;
+ PCI_BRIDGE_HEADER Bridge;
+ PCI_CARDBUS_HEADER CardBus;
+} NON_COMMON_UNION;
+
+typedef struct {
+ PCI_COMMON_HEADER Common;
+ NON_COMMON_UNION NonCommon;
+ UINT32 Data[48];
+} PCI_CONFIG_SPACE;
+
+typedef struct {
+ UINT8 PcieCapId;
+ UINT8 NextCapPtr;
+ UINT16 PcieCapReg;
+ UINT32 PcieDeviceCap;
+ UINT16 DeviceControl;
+ UINT16 DeviceStatus;
+ UINT32 LinkCap;
+ UINT16 LinkControl;
+ UINT16 LinkStatus;
+ UINT32 SlotCap;
+ UINT16 SlotControl;
+ UINT16 SlotStatus;
+ UINT16 RootControl;
+ UINT16 RsvdP;
+ UINT32 RootStatus;
+} PCIE_CAP_STRUCTURE;
+
+#pragma pack()
+
+#endif // _PCI_H_
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SerMode.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SerMode.c
new file mode 100644
index 0000000000..d885677065
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SerMode.c
@@ -0,0 +1,372 @@
+/** @file
+ Main file for SerMode shell Debug1 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDebug1CommandsLib.h"
+#include <Library/ShellLib.h>
+#include <Protocol/SerialIo.h>
+
+/**
+ Display information about a serial device by it's handle.
+
+ If HandleValid is FALSE, do all devices.
+
+ @param[in] HandleIdx The handle index for the device.
+ @param[in] HandleValid TRUE if HandleIdx is valid.
+
+ @retval SHELL_INVALID_PARAMETER A parameter was invalid.
+ @retval SHELL_SUCCESS The operation was successful.
+**/
+SHELL_STATUS
+EFIAPI
+DisplaySettings (
+ IN UINTN HandleIdx,
+ IN BOOLEAN HandleValid
+ )
+{
+ EFI_SERIAL_IO_PROTOCOL *SerialIo;
+ UINTN NoHandles;
+ EFI_HANDLE *Handles;
+ EFI_STATUS Status;
+ UINTN Index;
+ CHAR16 *StopBits;
+ CHAR16 Parity;
+ SHELL_STATUS ShellStatus;
+
+ Handles = NULL;
+ StopBits = NULL;
+
+ ShellStatus = SHELL_SUCCESS;
+
+ Status = gBS->LocateHandleBuffer (ByProtocol, &gEfiSerialIoProtocolGuid, NULL, &NoHandles, &Handles);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_NO_FOUND), gShellDebug1HiiHandle, L"sermode");
+ return SHELL_INVALID_PARAMETER;
+ }
+
+ for (Index = 0; Index < NoHandles; Index++) {
+ if (HandleValid) {
+ if (ConvertHandleIndexToHandle(HandleIdx) != Handles[Index]) {
+ continue;
+ }
+ }
+
+ Status = gBS->HandleProtocol (Handles[Index], &gEfiSerialIoProtocolGuid, (VOID**)&SerialIo);
+ if (!EFI_ERROR (Status)) {
+ switch (SerialIo->Mode->Parity) {
+ case DefaultParity:
+
+ Parity = 'D';
+ break;
+
+ case NoParity:
+
+ Parity = 'N';
+ break;
+
+ case EvenParity:
+
+ Parity = 'E';
+ break;
+
+ case OddParity:
+
+ Parity = 'O';
+ break;
+
+ case MarkParity:
+
+ Parity = 'M';
+ break;
+
+ case SpaceParity:
+
+ Parity = 'S';
+ break;
+
+ default:
+
+ Parity = 'U';
+ }
+
+ switch (SerialIo->Mode->StopBits) {
+ case DefaultStopBits:
+
+ StopBits = L"Default";
+ break;
+
+ case OneStopBit:
+
+ StopBits = L"1";
+ break;
+
+ case TwoStopBits:
+
+ StopBits = L"2";
+ break;
+
+ case OneFiveStopBits:
+
+ StopBits = L"1.5";
+ break;
+
+ default:
+
+ StopBits = L"Unknown";
+ }
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_SERMODE_DISPLAY),
+ gShellDebug1HiiHandle,
+ ConvertHandleToHandleIndex (Handles[Index]),
+ Handles[Index],
+ SerialIo->Mode->BaudRate,
+ Parity,
+ SerialIo->Mode->DataBits,
+ StopBits
+ );
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_NO_FOUND), gShellDebug1HiiHandle, L"sermode");
+ ShellStatus = SHELL_NOT_FOUND;
+ break;
+ }
+
+ if (HandleValid) {
+ break;
+ }
+ }
+
+ if (Index == NoHandles) {
+ if ((NoHandles != 0 && HandleValid) || 0 == NoHandles) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_NOT_FOUND), gShellDebug1HiiHandle, L"sermode");
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ }
+
+ return ShellStatus;
+}
+
+/**
+ Function for 'sermode' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunSerMode (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ SHELL_STATUS ShellStatus;
+ UINTN Index;
+ UINTN NoHandles;
+ EFI_HANDLE *Handles;
+ EFI_PARITY_TYPE Parity;
+ EFI_STOP_BITS_TYPE StopBits;
+ UINTN HandleIdx;
+ UINTN BaudRate;
+ UINTN DataBits;
+ UINTN Value;
+ EFI_SERIAL_IO_PROTOCOL *SerialIo;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ CONST CHAR16 *Temp;
+ UINT64 Intermediate;
+
+ ShellStatus = SHELL_SUCCESS;
+ HandleIdx = 0;
+ Parity = DefaultParity;
+ Handles = NULL;
+ NoHandles = 0;
+ Index = 0;
+ Package = NULL;
+
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"sermode", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetCount(Package) < 6 && ShellCommandLineGetCount(Package) > 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"sermode");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetCount(Package) > 6) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"sermode");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Temp = ShellCommandLineGetRawValue(Package, 1);
+ if (Temp != NULL) {
+ Status = ShellConvertStringToUint64(Temp, &Intermediate, TRUE, FALSE);
+ HandleIdx = (UINTN)Intermediate;
+ Temp = ShellCommandLineGetRawValue(Package, 2);
+ if (Temp == NULL) {
+ ShellStatus = DisplaySettings (HandleIdx, TRUE);
+ goto Done;
+ }
+ } else {
+ ShellStatus = DisplaySettings (0, FALSE);
+ goto Done;
+ }
+ Temp = ShellCommandLineGetRawValue(Package, 2);
+ if (Temp != NULL) {
+ BaudRate = ShellStrToUintn(Temp);
+ } else {
+ ASSERT(FALSE);
+ BaudRate = 0;
+ }
+ Temp = ShellCommandLineGetRawValue(Package, 3);
+ if (Temp == NULL || StrLen(Temp)>1) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"sermode", Temp);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ switch(Temp[0]){
+ case 'd':
+ case 'D':
+ Parity = DefaultParity;
+ break;
+ case 'n':
+ case 'N':
+ Parity = NoParity;
+ break;
+ case 'e':
+ case 'E':
+ Parity = EvenParity;
+ break;
+ case 'o':
+ case 'O':
+ Parity = OddParity;
+ break;
+ case 'm':
+ case 'M':
+ Parity = MarkParity;
+ break;
+ case 's':
+ case 'S':
+ Parity = SpaceParity;
+ break;
+ default:
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"sermode", Temp);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ }
+ Temp = ShellCommandLineGetRawValue(Package, 4);
+ if (Temp != NULL) {
+ DataBits = ShellStrToUintn(Temp);
+ } else {
+ //
+ // make sure this is some number not in the list below.
+ //
+ DataBits = 0;
+ }
+ switch (DataBits) {
+ case 4:
+ case 7:
+ case 8:
+ break;
+ default:
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"sermode", Temp);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ Temp = ShellCommandLineGetRawValue(Package, 5);
+ Value = ShellStrToUintn(Temp);
+ switch (Value) {
+ case 0:
+ StopBits = DefaultStopBits;
+ break;
+
+ case 1:
+ StopBits = OneStopBit;
+ break;
+
+ case 2:
+ StopBits = TwoStopBits;
+ break;
+
+ case 15:
+ StopBits = OneFiveStopBits;
+ break;
+
+ default:
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"sermode", Temp);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ Status = gBS->LocateHandleBuffer(ByProtocol, &gEfiSerialIoProtocolGuid, NULL, &NoHandles, &Handles);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_NO_FOUND), gShellDebug1HiiHandle, L"sermode");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ for (Index = 0; Index < NoHandles; Index++) {
+ if (ConvertHandleIndexToHandle (HandleIdx) != Handles[Index]) {
+ continue;
+ }
+
+ Status = gBS->HandleProtocol (Handles[Index], &gEfiSerialIoProtocolGuid, (VOID**)&SerialIo);
+ if (!EFI_ERROR (Status)) {
+ Status = SerialIo->SetAttributes (
+ SerialIo,
+ (UINT64) BaudRate,
+ SerialIo->Mode->ReceiveFifoDepth,
+ SerialIo->Mode->Timeout,
+ Parity,
+ (UINT8) DataBits,
+ StopBits
+ );
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_INVALID_PARAMETER) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_SET_UNSUPPORTED), gShellDebug1HiiHandle, L"sermode", ConvertHandleToHandleIndex(Handles[Index]));
+ ShellStatus = SHELL_UNSUPPORTED;
+ } else if (Status == EFI_DEVICE_ERROR) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_SET_DEV_ERROR), gShellDebug1HiiHandle, L"sermode", ConvertHandleToHandleIndex(Handles[Index]));
+ ShellStatus = SHELL_ACCESS_DENIED;
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_SET_FAIL), gShellDebug1HiiHandle, L"sermode", ConvertHandleToHandleIndex(Handles[Index]));
+ ShellStatus = SHELL_ACCESS_DENIED;
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_SET_HANDLE), gShellDebug1HiiHandle, ConvertHandleToHandleIndex(Handles[Index]));
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ if (ShellStatus == SHELL_SUCCESS && Index == NoHandles) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SERMODE_BAD_HANDLE), gShellDebug1HiiHandle, L"sermode", HandleIdx);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+
+Done:
+ if (Package != NULL) {
+ ShellCommandLineFreeVarList (Package);
+ }
+ if (Handles != NULL) {
+ FreePool (Handles);
+ }
+ return ShellStatus;
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SetSize.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SetSize.c
new file mode 100644
index 0000000000..a33aec12a5
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SetSize.c
@@ -0,0 +1,110 @@
+/** @file
+ Main file for SetSize shell Debug1 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDebug1CommandsLib.h"
+
+/**
+ Function for 'setsize' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunSetSize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ CONST CHAR16 *Temp1;
+ UINTN NewSize;
+ UINTN LoopVar;
+ SHELL_FILE_HANDLE FileHandle;
+
+ ShellStatus = SHELL_SUCCESS;
+ Status = EFI_SUCCESS;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"setsize", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetCount(Package) < 3) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"setsize");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ NewSize = 0;
+ } else {
+ Temp1 = ShellCommandLineGetRawValue(Package, 1);
+ if (!ShellIsHexOrDecimalNumber(Temp1, FALSE, FALSE)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SIZE_NOT_SPEC), gShellDebug1HiiHandle, L"setsize");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ NewSize = 0;
+ } else {
+ NewSize = ShellStrToUintn(Temp1);
+ }
+ }
+ for (LoopVar = 2 ; LoopVar < ShellCommandLineGetCount(Package) && ShellStatus == SHELL_SUCCESS ; LoopVar++) {
+ Status = ShellOpenFileByName(ShellCommandLineGetRawValue(Package, LoopVar), &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0);
+ if (EFI_ERROR(Status)) {
+ Status = ShellOpenFileByName(ShellCommandLineGetRawValue(Package, LoopVar), &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
+ }
+ if (EFI_ERROR(Status) && LoopVar == 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_FILE_NOT_SPEC), gShellDebug1HiiHandle, L"setsize");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellDebug1HiiHandle, L"setsize", ShellCommandLineGetRawValue(Package, LoopVar));
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ break;
+ } else {
+ Status = FileHandleSetSize(FileHandle, NewSize);
+ if (Status == EFI_VOLUME_FULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_VOLUME_FULL), gShellDebug1HiiHandle, L"setsize");
+ ShellStatus = SHELL_VOLUME_FULL;
+ } else if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SET_SIZE_FAIL), gShellDebug1HiiHandle, L"setsize", ShellCommandLineGetRawValue(Package, LoopVar));
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SET_SIZE_DONE), gShellDebug1HiiHandle, ShellCommandLineGetRawValue(Package, LoopVar));
+ }
+ ShellCloseFile(&FileHandle);
+ }
+ }
+
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ return (ShellStatus);
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SetVar.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SetVar.c
new file mode 100644
index 0000000000..bffe047b8a
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SetVar.c
@@ -0,0 +1,302 @@
+/** @file
+ Main file for SetVar shell Debug1 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDebug1CommandsLib.h"
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-guid", TypeValue},
+ {L"-bs", TypeFlag},
+ {L"-rt", TypeFlag},
+ {L"-nv", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+
+/**
+ Check if the input is a (potentially empty) string of hexadecimal nibbles.
+
+ @param[in] String The CHAR16 string to check.
+
+ @retval FALSE A character has been found in String for which
+ ShellIsHexaDecimalDigitCharacter() returned FALSE.
+
+ @retval TRUE Otherwise. (Note that this covers the case when String is
+ empty.)
+**/
+BOOLEAN
+EFIAPI
+IsStringOfHexNibbles (
+ IN CONST CHAR16 *String
+ )
+{
+ CONST CHAR16 *Pos;
+
+ for (Pos = String; *Pos != L'\0'; ++Pos) {
+ if (!ShellIsHexaDecimalDigitCharacter (*Pos)) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+
+/**
+ Function for 'setvar' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunSetVar (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ CONST CHAR16 *VariableName;
+ CONST CHAR16 *Data;
+ EFI_GUID Guid;
+ CONST CHAR16 *StringGuid;
+ UINT32 Attributes;
+ VOID *Buffer;
+ UINTN Size;
+ UINTN LoopVar;
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+
+ ShellStatus = SHELL_SUCCESS;
+ Status = EFI_SUCCESS;
+ Buffer = NULL;
+ Size = 0;
+ Attributes = 0;
+ DevPath = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"setvar", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetCount(Package) < 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDebug1HiiHandle, L"setvar");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetCount(Package) > 3) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"setvar");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ VariableName = ShellCommandLineGetRawValue(Package, 1);
+ Data = ShellCommandLineGetRawValue(Package, 2);
+ if (!ShellCommandLineGetFlag(Package, L"-guid")){
+ CopyGuid(&Guid, &gEfiGlobalVariableGuid);
+ } else {
+ StringGuid = ShellCommandLineGetValue(Package, L"-guid");
+ Status = ConvertStringToGuid(StringGuid, &Guid);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"setvar", StringGuid);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ }
+ if (Data == NULL || Data[0] != L'=') {
+ //
+ // Display what's there
+ //
+ Status = gRT->GetVariable((CHAR16*)VariableName, &Guid, &Attributes, &Size, Buffer);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ Buffer = AllocateZeroPool(Size);
+ Status = gRT->GetVariable((CHAR16*)VariableName, &Guid, &Attributes, &Size, Buffer);
+ }
+ if (!EFI_ERROR(Status)&& Buffer != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_PRINT), gShellDebug1HiiHandle, &Guid, VariableName, Size);
+ for (LoopVar = 0 ; LoopVar < Size ; LoopVar++) {
+ ShellPrintEx(-1, -1, L"%02x ", ((UINT8*)Buffer)[LoopVar]);
+ }
+ ShellPrintEx(-1, -1, L"\r\n");
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_GET), gShellDebug1HiiHandle, L"setvar", &Guid, VariableName);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ }
+ } else if (StrCmp(Data, L"=") == 0) {
+ //
+ // Delete what's there!
+ //
+ Status = gRT->SetVariable((CHAR16*)VariableName, &Guid, Attributes, 0, NULL);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_SET), gShellDebug1HiiHandle, L"setvar", &Guid, VariableName);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ } else {
+ ASSERT(ShellStatus == SHELL_SUCCESS);
+ }
+ } else {
+ //
+ // Change what's there or create a new one.
+ //
+
+ ASSERT(Data[0] == L'=');
+ Data++;
+ ASSERT(Data[0] != L'\0');
+
+ //
+ // Determine if the variable exists and get the attributes
+ //
+ Status = gRT->GetVariable((CHAR16*)VariableName, &Guid, &Attributes, &Size, Buffer);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ Buffer = AllocateZeroPool(Size);
+ Status = gRT->GetVariable((CHAR16*)VariableName, &Guid, &Attributes, &Size, Buffer);
+ }
+
+ if (EFI_ERROR(Status) || Buffer == NULL) {
+ //
+ // Creating a new variable. determine attributes from command line.
+ //
+ Attributes = 0;
+ if (ShellCommandLineGetFlag(Package, L"-bs")) {
+ Attributes |= EFI_VARIABLE_BOOTSERVICE_ACCESS;
+ }
+ if (ShellCommandLineGetFlag(Package, L"-rt")) {
+ Attributes |= EFI_VARIABLE_RUNTIME_ACCESS |
+ EFI_VARIABLE_BOOTSERVICE_ACCESS;
+ }
+ if (ShellCommandLineGetFlag(Package, L"-nv")) {
+ Attributes |= EFI_VARIABLE_NON_VOLATILE;
+ }
+ }
+ SHELL_FREE_NON_NULL(Buffer);
+
+ //
+ // What type is the new data.
+ //
+ if (IsStringOfHexNibbles(Data)) {
+ if (StrLen(Data) % 2 != 0) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"setvar", Data);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // arbitrary buffer
+ //
+ Buffer = AllocateZeroPool((StrLen(Data) / 2));
+ if (Buffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ for (LoopVar = 0 ; LoopVar < (StrLen(Data) / 2) ; LoopVar++) {
+ ((UINT8*)Buffer)[LoopVar] = (UINT8)(HexCharToUintn(Data[LoopVar*2]) * 16);
+ ((UINT8*)Buffer)[LoopVar] = (UINT8)(((UINT8*)Buffer)[LoopVar] + HexCharToUintn(Data[LoopVar*2+1]));
+ }
+ Status = gRT->SetVariable((CHAR16*)VariableName, &Guid, Attributes, StrLen(Data) / 2, Buffer);
+ }
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_SET), gShellDebug1HiiHandle, L"setvar", &Guid, VariableName);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ } else {
+ ASSERT(ShellStatus == SHELL_SUCCESS);
+ }
+ }
+ } else if (StrnCmp(Data, L"\"", 1) == 0) {
+ //
+ // ascii text
+ //
+ Data++;
+ Buffer = AllocateZeroPool(StrSize(Data) / 2);
+ if (Buffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ AsciiSPrint(Buffer, StrSize(Data) / 2, "%s", Data);
+ ((CHAR8*)Buffer)[AsciiStrLen(Buffer)-1] = CHAR_NULL;
+ Status = gRT->SetVariable((CHAR16*)VariableName, &Guid, Attributes, AsciiStrSize(Buffer)-sizeof(CHAR8), Buffer);
+ }
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_SET), gShellDebug1HiiHandle, L"setvar", &Guid, VariableName);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ } else {
+ ASSERT(ShellStatus == SHELL_SUCCESS);
+ }
+ } else if (StrnCmp(Data, L"L\"", 2) == 0) {
+ //
+ // ucs2 text
+ //
+ Data++;
+ Data++;
+ Buffer = AllocateZeroPool(StrSize(Data));
+ if (Buffer == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellDebug1HiiHandle, L"setvar");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ } else {
+ UnicodeSPrint(Buffer, StrSize(Data), L"%s", Data);
+ ((CHAR16*)Buffer)[StrLen(Buffer)-1] = CHAR_NULL;
+
+ Status = gRT->SetVariable((CHAR16*)VariableName, &Guid, Attributes, StrSize(Buffer)-sizeof(CHAR16), Buffer);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_SET), gShellDebug1HiiHandle, L"setvar", &Guid, VariableName);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ } else {
+ ASSERT(ShellStatus == SHELL_SUCCESS);
+ }
+ }
+ } else if (StrnCmp(Data, L"--", 2) == 0) {
+ //
+ // device path in text format
+ //
+ Data++;
+ Data++;
+ DevPath = ConvertTextToDevicePath(Data);
+ if (DevPath == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_DPFT), gShellDebug1HiiHandle, L"setvar");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Status = gRT->SetVariable((CHAR16*)VariableName, &Guid, Attributes, GetDevicePathSize(DevPath), DevPath);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SETVAR_ERROR_SET), gShellDebug1HiiHandle, L"setvar", &Guid, VariableName);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ } else {
+ ASSERT(ShellStatus == SHELL_SUCCESS);
+ }
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDebug1HiiHandle, L"setvar", Data);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ }
+ }
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ if (Buffer != NULL) {
+ FreePool(Buffer);
+ }
+
+ if (DevPath != NULL) {
+ FreePool(DevPath);
+ }
+
+ return (ShellStatus);
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/EventLogInfo.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/EventLogInfo.c
new file mode 100644
index 0000000000..f07a4c4921
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/EventLogInfo.c
@@ -0,0 +1,412 @@
+/** @file
+ Module for clarifying the content of the smbios structure element info.
+
+ Copyright (c) 2005 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "../UefiShellDebug1CommandsLib.h"
+#include "PrintInfo.h"
+#include "QueryTable.h"
+#include "EventLogInfo.h"
+
+/**
+ Function to display system event log access information.
+
+ @param[in] Key Additional information to print.
+ @param[in] Option Whether to print the additional information.
+**/
+VOID
+EFIAPI
+DisplaySELAccessMethod (
+ IN CONST UINT8 Key,
+ IN CONST UINT8 Option
+ )
+{
+ //
+ // Print prompt
+ //
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_ACCESS_METHOD), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Key, Option);
+
+ //
+ // Print value info
+ //
+ switch (Key) {
+ case 0:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_ONE_EIGHT_BIT), gShellDebug1HiiHandle);
+ break;
+
+ case 1:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_TWO_EIGHT_BITS), gShellDebug1HiiHandle);
+ break;
+
+ case 2:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_ONE_SIXTEEN_BIT), gShellDebug1HiiHandle);
+ break;
+
+ case 3:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_MEM_MAPPED_PHYS), gShellDebug1HiiHandle);
+ break;
+
+ case 4:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_AVAIL_VIA_GENERAL), gShellDebug1HiiHandle);
+ break;
+
+ default:
+ if (Key <= 0x7f) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_AVAIL_FOR_FUTURE_ASSIGN), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_BIOS_VENDOR_OEM), gShellDebug1HiiHandle);
+ }
+ }
+}
+
+/**
+ Function to display system event log status information.
+
+ @param[in] Key Additional information to print.
+ @param[in] Option Whether to print the additional information.
+**/
+VOID
+EFIAPI
+DisplaySELLogStatus (
+ UINT8 Key,
+ UINT8 Option
+ )
+{
+ //
+ // Print prompt
+ //
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_LOG_STATUS), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Key, Option);
+
+ //
+ // Print value info
+ //
+ if ((Key & 0x01) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_LOG_AREA_VALID), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_LOG_AREA_VALID), gShellDebug1HiiHandle);
+ }
+
+ if ((Key & 0x02) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_LOG_AREA_FULL), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_LOG_AREA_NOT_FULL), gShellDebug1HiiHandle);
+ }
+
+ if ((Key & 0xFC) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_RES_BITS_NOT_ZERO), gShellDebug1HiiHandle, Key & 0xFC);
+ }
+}
+
+/**
+ Function to display system event log header format information.
+
+ @param[in] Key Additional information to print.
+ @param[in] Option Whether to print the additional information.
+**/
+VOID
+EFIAPI
+DisplaySysEventLogHeaderFormat (
+ UINT8 Key,
+ UINT8 Option
+ )
+{
+ //
+ // Print prompt
+ //
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_LOG_HEADER_FORMAT), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Key, Option);
+
+ //
+ // Print value info
+ //
+ if (Key == 0x00) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_NO_HEADER), gShellDebug1HiiHandle);
+ } else if (Key == 0x01) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_TYPE_LOG_HEADER), gShellDebug1HiiHandle);
+ } else if (Key <= 0x7f) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_AVAIL_FOR_FUTURE), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_BIOS_VENDOR), gShellDebug1HiiHandle);
+ }
+}
+
+/**
+ Display the header information for SEL log items.
+
+ @param[in] Key The information key.
+ @param[in] Option The option index.
+**/
+VOID
+DisplaySELLogHeaderLen (
+ UINT8 Key,
+ UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_LOG_HEADER_LEN), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Key, Option);
+
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_ONE_VAR_D), gShellDebug1HiiHandle, Key & 0x7F);
+
+ //
+ // The most-significant bit of the field specifies
+ // whether (0) or not (1) the record has been read
+ //
+ if ((Key & 0x80) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_THIS_RECORD_READ), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_THIS_RECORD_NOT_READ), gShellDebug1HiiHandle);
+ }
+}
+
+/**
+ Display the header information for type 1 items.
+
+ @param[in] LogHeader The buffer with the information.
+**/
+VOID
+DisplaySysEventLogHeaderType1 (
+ IN UINT8 *LogHeader
+ )
+{
+ LOG_HEADER_TYPE1_FORMAT *Header;
+
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_SYSTEM_EVENT_LOG), gShellDebug1HiiHandle);
+
+ //
+ // Print Log Header Type1 Format info
+ //
+ Header = (LOG_HEADER_TYPE1_FORMAT *) (LogHeader);
+
+ ShellPrintHiiEx(-1,-1,NULL,
+ STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_OEM_RESERVED),
+ gShellDebug1HiiHandle,
+ Header->OEMReserved[0],
+ Header->OEMReserved[1],
+ Header->OEMReserved[2],
+ Header->OEMReserved[3],
+ Header->OEMReserved[4]
+ );
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_MULTIPLE_EVENT_TIME), gShellDebug1HiiHandle, Header->Metw);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_MULTIPLE_EVENT_COUNT), gShellDebug1HiiHandle, Header->Meci);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_PREBOOT_ADDRESS), gShellDebug1HiiHandle, Header->CMOSAddress);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_PREBOOT_INDEX), gShellDebug1HiiHandle, Header->CMOSBitIndex);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_CHECKSUM_STARTING_OFF), gShellDebug1HiiHandle, Header->StartingOffset);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_CHECKSUN_BYTE_COUNT), gShellDebug1HiiHandle, Header->ChecksumOffset);
+ ShellPrintHiiEx(-1,-1,NULL,
+ STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_RESERVED),
+ gShellDebug1HiiHandle,
+ Header->OEMReserved[0],
+ Header->OEMReserved[1],
+ Header->OEMReserved[2]
+ );
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_HEADER_REVISION), gShellDebug1HiiHandle, Header->HeaderRevision);
+}
+
+/**
+ Function to display system event log header information.
+
+ @param[in] LogHeaderFormat Format identifier.
+ @param[in] LogHeader Format informcation.
+**/
+VOID
+EFIAPI
+DisplaySysEventLogHeader (
+ UINT8 LogHeaderFormat,
+ UINT8 *LogHeader
+ )
+{
+ //
+ // Print prompt
+ //
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_LOG_HEADER), gShellDebug1HiiHandle);
+
+ //
+ // Print value info
+ //
+ if (LogHeaderFormat == 0x00) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_NO_HEADER), gShellDebug1HiiHandle);
+ } else if (LogHeaderFormat == 0x01) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_TYPE_LOG_HEADER), gShellDebug1HiiHandle);
+ DisplaySysEventLogHeaderType1 (LogHeader);
+ } else if (LogHeaderFormat <= 0x7f) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_AVAIL_FUTURE_ASSIGN), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_BIOS_VENDOR), gShellDebug1HiiHandle);
+ }
+}
+
+/**
+ Display the El Vdf information.
+
+ @param[in] ElVdfType The information type.
+ @param[in] VarData The information buffer.
+**/
+VOID
+DisplayElVdfInfo (
+ UINT8 ElVdfType,
+ UINT8 *VarData
+ )
+{
+ UINT16 *Word;
+ UINT32 *Dword;
+
+ //
+ // Display Type Name
+ //
+ DisplaySELVarDataFormatType (ElVdfType, SHOW_DETAIL);
+
+ //
+ // Display Type description
+ //
+ switch (ElVdfType) {
+ case 0:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_NO_STD_FORMAT), gShellDebug1HiiHandle);
+ break;
+
+ case 1:
+ Word = (UINT16 *) (VarData + 1);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_SMBIOS_STRUCT_ASSOC), gShellDebug1HiiHandle);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_STRUCT_HANDLE), gShellDebug1HiiHandle, *Word);
+ break;
+
+ case 2:
+ Dword = (UINT32 *) (VarData + 1);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_MULT_EVENT_COUNTER), gShellDebug1HiiHandle, *Dword);
+ break;
+
+ case 3:
+ Word = (UINT16 *) (VarData + 1);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_SMBIOS_STRUCT_ASSOC), gShellDebug1HiiHandle);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_STRUCT_HANDLE), gShellDebug1HiiHandle, *Word);
+ //
+ // Followed by a multiple-event counter
+ //
+ Dword = (UINT32 *) (VarData + 1);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_MULT_EVENT_COUNTER), gShellDebug1HiiHandle, *Dword);
+ break;
+
+ case 4:
+ Dword = (UINT32 *) (VarData + 1);
+ DisplayPostResultsBitmapDw1 (*Dword, SHOW_DETAIL);
+ Dword++;
+ DisplayPostResultsBitmapDw2 (*Dword, SHOW_DETAIL);
+ break;
+
+ case 5:
+ Dword = (UINT32 *) (VarData + 1);
+ DisplaySELSysManagementTypes (*Dword, SHOW_DETAIL);
+ break;
+
+ case 6:
+ Dword = (UINT32 *) (VarData + 1);
+ DisplaySELSysManagementTypes (*Dword, SHOW_DETAIL);
+ //
+ // Followed by a multiple-event counter
+ //
+ Dword = (UINT32 *) (VarData + 1);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_MULT_EVENT_COUNTER), gShellDebug1HiiHandle, *Dword);
+ break;
+
+ default:
+ if (ElVdfType <= 0x7F) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_UNUSED_AVAIL_FOR_ASSIGN), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_AVAIL_FOR_SYSTEM), gShellDebug1HiiHandle);
+ }
+ }
+}
+
+/**
+ Function to display system event log data.
+
+ @param[in] LogData The data information.
+ @param[in] LogAreaLength Length of the data.
+**/
+VOID
+EFIAPI
+DisplaySysEventLogData (
+ UINT8 *LogData,
+ UINT16 LogAreaLength
+ )
+{
+ LOG_RECORD_FORMAT *Log;
+ UINT8 ElVdfType;
+ //
+ // Event Log Variable Data Format Types
+ //
+ UINTN Offset;
+
+ //
+ // Print prompt
+ //
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_SYSTEM_EVENT_LOG_2), gShellDebug1HiiHandle);
+
+ //
+ // Print Log info
+ //
+ Offset = 0;
+ Log = (LOG_RECORD_FORMAT *) LogData;
+ while (Log != NULL && Log->Type != END_OF_LOG && Offset < LogAreaLength) {
+ //
+ // Get a Event Log Record
+ //
+ Log = (LOG_RECORD_FORMAT *) (LogData + Offset);
+
+ if (Log != NULL) {
+ //
+ // Display Event Log Record Information
+ //
+ DisplaySELVarDataFormatType (Log->Type, SHOW_DETAIL);
+ DisplaySELLogHeaderLen (Log->Length, SHOW_DETAIL);
+
+ Offset += Log->Length;
+ //
+ // Display Log Header Date/Time Fields
+ // These fields contain the BCD representation of the date and time
+ // (as read from CMOS) of the occurrence of the event
+ // So Print as hex and represent decimal
+ //
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_DATE), gShellDebug1HiiHandle);
+ if (Log != NULL && Log->Year >= 80 && Log->Year <= 99) {
+ Print (L"19");
+ } else if (Log != NULL && Log->Year <= 79) {
+ Print (L"20");
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_ERROR), gShellDebug1HiiHandle);
+ continue;
+ }
+
+ ShellPrintHiiEx(-1,-1,NULL,
+ STRING_TOKEN (STR_SMBIOSVIEW_EVENTLOGINFO_TIME_SIX_VARS),
+ gShellDebug1HiiHandle,
+ Log->Year,
+ Log->Month,
+ Log->Day,
+ Log->Hour,
+ Log->Minute,
+ Log->Second
+ );
+
+ //
+ // Display Variable Data Format
+ //
+ if (Log->Length <= (sizeof (LOG_RECORD_FORMAT) - 1)) {
+ continue;
+ }
+
+ ElVdfType = Log->LogVariableData[0];
+ DisplayElVdfInfo (ElVdfType, Log->LogVariableData);
+ }
+ }
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/EventLogInfo.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/EventLogInfo.h
new file mode 100644
index 0000000000..b32cfea812
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/EventLogInfo.h
@@ -0,0 +1,117 @@
+/** @file
+ Module to clarify system event log of smbios structure.
+
+ Copyright (c) 2005-2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SMBIOS_EVENT_LOG_INFO_H_
+#define _SMBIOS_EVENT_LOG_INFO_H_
+
+#define END_OF_LOG 0xFF
+
+#pragma pack(1)
+
+typedef struct {
+ UINT8 Type;
+ UINT8 Length;
+ UINT8 Year;
+ UINT8 Month;
+ UINT8 Day;
+ UINT8 Hour;
+ UINT8 Minute;
+ UINT8 Second;
+ UINT8 LogVariableData[1];
+} LOG_RECORD_FORMAT;
+
+typedef struct {
+ UINT8 OEMReserved[5];
+ UINT8 Metw; // Multiple Event Time Window
+ UINT8 Meci; // Multiple Event Count Increment
+ UINT8 CMOSAddress; // Pre-boot Event Log Reset - CMOS Address
+ UINT8 CMOSBitIndex; // Pre-boot Event Log Reset - CMOS Bit Index
+ UINT8 StartingOffset; // CMOS Checksum - Starting Offset
+ UINT8 ByteCount; // CMOS Checksum - Byte Count
+ UINT8 ChecksumOffset; // CMOS Checksum - Checksum Offset
+ UINT8 Reserved[3];
+ UINT8 HeaderRevision;
+} LOG_HEADER_TYPE1_FORMAT;
+
+#pragma pack()
+//
+// System Event Log (Type 15)
+//
+
+/**
+ Function to display system event log access information.
+
+ @param[in] Key Additional information to print.
+ @param[in] Option Whether to print the additional information.
+**/
+VOID
+EFIAPI
+DisplaySELAccessMethod (
+ IN CONST UINT8 Key,
+ IN CONST UINT8 Option
+ );
+
+/**
+ Function to display system event log status information.
+
+ @param[in] Key Additional information to print.
+ @param[in] Option Whether to print the additional information.
+**/
+VOID
+EFIAPI
+DisplaySELLogStatus (
+ UINT8 Key,
+ UINT8 Option
+ );
+
+/**
+ Function to display system event log header format information.
+
+ @param[in] Key Additional information to print.
+ @param[in] Option Whether to print the additional information.
+**/
+VOID
+EFIAPI
+DisplaySysEventLogHeaderFormat (
+ UINT8 Key,
+ UINT8 Option
+ );
+
+/**
+ Function to display system event log header information.
+
+ @param[in] LogHeaderFormat Format identifier.
+ @param[in] LogHeader Format informcation.
+**/
+VOID
+EFIAPI
+DisplaySysEventLogHeader (
+ UINT8 LogHeaderFormat,
+ UINT8 *LogHeader
+ );
+
+/**
+ Function to display system event log data.
+
+ @param[in] LogData The data information.
+ @param[in] LogAreaLength Length of the data.
+**/
+VOID
+EFIAPI
+DisplaySysEventLogData (
+ UINT8 *LogData,
+ UINT16 LogAreaLength
+ );
+
+#endif
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/LibSmbiosView.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/LibSmbiosView.c
new file mode 100644
index 0000000000..6920263c92
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/LibSmbiosView.c
@@ -0,0 +1,373 @@
+/** @file
+ API for SMBIOS table.
+
+ Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+
+#include "../UefiShellDebug1CommandsLib.h"
+#include <Guid/SmBios.h>
+#include "LibSmbiosView.h"
+#include "SmbiosView.h"
+
+STATIC UINT8 mInit = 0;
+STATIC UINT8 m64Init = 0;
+STATIC SMBIOS_TABLE_ENTRY_POINT *mSmbiosTable = NULL;
+STATIC SMBIOS_TABLE_3_0_ENTRY_POINT *mSmbios64BitTable = NULL;
+STATIC SMBIOS_STRUCTURE_POINTER m_SmbiosStruct;
+STATIC SMBIOS_STRUCTURE_POINTER *mSmbiosStruct = &m_SmbiosStruct;
+STATIC SMBIOS_STRUCTURE_POINTER m_Smbios64BitStruct;
+STATIC SMBIOS_STRUCTURE_POINTER *mSmbios64BitStruct = &m_Smbios64BitStruct;
+
+/**
+ Init the SMBIOS VIEW API's environment.
+
+ @retval EFI_SUCCESS Successful to init the SMBIOS VIEW Lib.
+**/
+EFI_STATUS
+LibSmbiosInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Init only once
+ //
+ if (mInit == 1) {
+ return EFI_SUCCESS;
+ }
+ //
+ // Get SMBIOS table from System Configure table
+ //
+ Status = GetSystemConfigurationTable (&gEfiSmbiosTableGuid, (VOID**)&mSmbiosTable);
+
+ if (mSmbiosTable == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_LIBSMBIOSVIEW_GET_TABLE_ERROR), gShellDebug1HiiHandle, Status);
+ return Status;
+ }
+ //
+ // Init SMBIOS structure table address
+ //
+ mSmbiosStruct->Raw = (UINT8 *) (UINTN) (mSmbiosTable->TableAddress);
+
+ mInit = 1;
+ return EFI_SUCCESS;
+}
+
+/**
+ Init the SMBIOS VIEW API's environment.
+
+ @retval EFI_SUCCESS Successful to init the SMBIOS VIEW Lib.
+**/
+EFI_STATUS
+LibSmbios64BitInit (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // Init only once
+ //
+ if (m64Init == 1) {
+ return EFI_SUCCESS;
+ }
+ //
+ // Get SMBIOS table from System Configure table
+ //
+ Status = GetSystemConfigurationTable (&gEfiSmbios3TableGuid, (VOID**)&mSmbios64BitTable);
+
+ if (mSmbios64BitTable == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_LIBSMBIOSVIEW_GET_TABLE_ERROR), gShellDebug1HiiHandle, Status);
+ return Status;
+ }
+ //
+ // Init SMBIOS structure table address
+ //
+ mSmbios64BitStruct->Raw = (UINT8 *) (UINTN) (mSmbios64BitTable->TableAddress);
+
+ m64Init = 1;
+ return EFI_SUCCESS;
+}
+
+/**
+ Cleanup the Smbios information.
+**/
+VOID
+LibSmbiosCleanup (
+ VOID
+ )
+{
+ //
+ // Release resources
+ //
+ if (mSmbiosTable != NULL) {
+ mSmbiosTable = NULL;
+ }
+
+ mInit = 0;
+}
+
+/**
+ Cleanup the Smbios information.
+**/
+VOID
+LibSmbios64BitCleanup (
+ VOID
+ )
+{
+ //
+ // Release resources
+ //
+ if (mSmbios64BitTable != NULL) {
+ mSmbios64BitTable = NULL;
+ }
+
+ m64Init = 0;
+}
+
+/**
+ Get the entry point structure for the table.
+
+ @param[out] EntryPointStructure The pointer to populate.
+**/
+VOID
+LibSmbiosGetEPS (
+ OUT SMBIOS_TABLE_ENTRY_POINT **EntryPointStructure
+ )
+{
+ //
+ // return SMBIOS Table address
+ //
+ *EntryPointStructure = mSmbiosTable;
+}
+
+/**
+ Get the entry point structure for the table.
+
+ @param[out] EntryPointStructure The pointer to populate.
+**/
+VOID
+LibSmbios64BitGetEPS (
+ OUT SMBIOS_TABLE_3_0_ENTRY_POINT **EntryPointStructure
+ )
+{
+ //
+ // return SMBIOS Table address
+ //
+ *EntryPointStructure = mSmbios64BitTable;
+}
+
+/**
+ Return SMBIOS string for the given string number.
+
+ @param[in] Smbios Pointer to SMBIOS structure.
+ @param[in] StringNumber String number to return. -1 is used to skip all strings and
+ point to the next SMBIOS structure.
+
+ @return Pointer to string, or pointer to next SMBIOS strcuture if StringNumber == -1
+**/
+CHAR8*
+LibGetSmbiosString (
+ IN SMBIOS_STRUCTURE_POINTER *Smbios,
+ IN UINT16 StringNumber
+ )
+{
+ UINT16 Index;
+ CHAR8 *String;
+
+ ASSERT (Smbios != NULL);
+
+ //
+ // Skip over formatted section
+ //
+ String = (CHAR8 *) (Smbios->Raw + Smbios->Hdr->Length);
+
+ //
+ // Look through unformated section
+ //
+ for (Index = 1; Index <= StringNumber; Index++) {
+ if (StringNumber == Index) {
+ return String;
+ }
+ //
+ // Skip string
+ //
+ for (; *String != 0; String++);
+ String++;
+
+ if (*String == 0) {
+ //
+ // If double NULL then we are done.
+ // Return pointer to next structure in Smbios.
+ // if you pass in a -1 you will always get here
+ //
+ Smbios->Raw = (UINT8 *)++String;
+ return NULL;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ Get SMBIOS structure for the given Handle,
+ Handle is changed to the next handle or 0xFFFF when the end is
+ reached or the handle is not found.
+
+ @param[in, out] Handle 0xFFFF: get the first structure
+ Others: get a structure according to this value.
+ @param[out] Buffer The pointer to the pointer to the structure.
+ @param[out] Length Length of the structure.
+
+ @retval DMI_SUCCESS Handle is updated with next structure handle or
+ 0xFFFF(end-of-list).
+
+ @retval DMI_INVALID_HANDLE Handle is updated with first structure handle or
+ 0xFFFF(end-of-list).
+**/
+EFI_STATUS
+LibGetSmbiosStructure (
+ IN OUT UINT16 *Handle,
+ OUT UINT8 **Buffer,
+ OUT UINT16 *Length
+ )
+{
+ SMBIOS_STRUCTURE_POINTER Smbios;
+ SMBIOS_STRUCTURE_POINTER SmbiosEnd;
+ UINT8 *Raw;
+
+ if (*Handle == INVALID_HANDLE) {
+ *Handle = mSmbiosStruct->Hdr->Handle;
+ return DMI_INVALID_HANDLE;
+ }
+
+ if ((Buffer == NULL) || (Length == NULL)) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_LIBSMBIOSVIEW_NO_BUFF_LEN_SPEC), gShellDebug1HiiHandle);
+ return DMI_INVALID_HANDLE;
+ }
+
+ *Length = 0;
+ Smbios.Hdr = mSmbiosStruct->Hdr;
+ SmbiosEnd.Raw = Smbios.Raw + mSmbiosTable->TableLength;
+ while (Smbios.Raw < SmbiosEnd.Raw) {
+ if (Smbios.Hdr->Handle == *Handle) {
+ Raw = Smbios.Raw;
+ //
+ // Walk to next structure
+ //
+ LibGetSmbiosString (&Smbios, (UINT16) (-1));
+ //
+ // Length = Next structure head - this structure head
+ //
+ *Length = (UINT16) (Smbios.Raw - Raw);
+ *Buffer = Raw;
+ //
+ // update with the next structure handle.
+ //
+ if (Smbios.Raw < SmbiosEnd.Raw) {
+ *Handle = Smbios.Hdr->Handle;
+ } else {
+ *Handle = INVALID_HANDLE;
+ }
+ return DMI_SUCCESS;
+ }
+ //
+ // Walk to next structure
+ //
+ LibGetSmbiosString (&Smbios, (UINT16) (-1));
+ }
+
+ *Handle = INVALID_HANDLE;
+ return DMI_INVALID_HANDLE;
+}
+
+/**
+ Get SMBIOS structure for the given Handle,
+ Handle is changed to the next handle or 0xFFFF when the end is
+ reached or the handle is not found.
+
+ @param[in, out] Handle 0xFFFF: get the first structure
+ Others: get a structure according to this value.
+ @param[out] Buffer The pointer to the pointer to the structure.
+ @param[out] Length Length of the structure.
+
+ @retval DMI_SUCCESS Handle is updated with next structure handle or
+ 0xFFFF(end-of-list).
+
+ @retval DMI_INVALID_HANDLE Handle is updated with first structure handle or
+ 0xFFFF(end-of-list).
+**/
+EFI_STATUS
+LibGetSmbios64BitStructure (
+ IN OUT UINT16 *Handle,
+ OUT UINT8 **Buffer,
+ OUT UINT16 *Length
+ )
+{
+ SMBIOS_STRUCTURE_POINTER Smbios;
+ SMBIOS_STRUCTURE_POINTER SmbiosEnd;
+ UINT8 *Raw;
+
+ if (*Handle == INVALID_HANDLE) {
+ *Handle = mSmbios64BitStruct->Hdr->Handle;
+ return DMI_INVALID_HANDLE;
+ }
+
+ if ((Buffer == NULL) || (Length == NULL)) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_LIBSMBIOSVIEW_NO_BUFF_LEN_SPEC), gShellDebug1HiiHandle);
+ return DMI_INVALID_HANDLE;
+ }
+
+ *Length = 0;
+ Smbios.Hdr = mSmbios64BitStruct->Hdr;
+
+ SmbiosEnd.Raw = Smbios.Raw + mSmbios64BitTableLength;
+ while (Smbios.Raw < SmbiosEnd.Raw) {
+ if (Smbios.Hdr->Handle == *Handle) {
+ Raw = Smbios.Raw;
+ //
+ // Walk to next structure
+ //
+ LibGetSmbiosString (&Smbios, (UINT16) (-1));
+ //
+ // Length = Next structure head - this structure head
+ //
+ *Length = (UINT16) (Smbios.Raw - Raw);
+ *Buffer = Raw;
+ //
+ // update with the next structure handle.
+ //
+ if (Smbios.Raw < SmbiosEnd.Raw) {
+ *Handle = Smbios.Hdr->Handle;
+ } else {
+ *Handle = INVALID_HANDLE;
+ }
+ return DMI_SUCCESS;
+ }
+ //
+ // Walk to next structure
+ //
+ LibGetSmbiosString (&Smbios, (UINT16) (-1));
+ }
+
+ *Handle = INVALID_HANDLE;
+ return DMI_INVALID_HANDLE;
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/LibSmbiosView.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/LibSmbiosView.h
new file mode 100644
index 0000000000..103f022fbe
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/LibSmbiosView.h
@@ -0,0 +1,159 @@
+/** @file
+ API for SMBIOS Plug and Play functions, access to SMBIOS table and structures.
+
+ Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _LIB_SMBIOS_VIEW_H_
+#define _LIB_SMBIOS_VIEW_H_
+
+#include <IndustryStandard/SmBios.h>
+
+#define DMI_SUCCESS 0x00
+#define DMI_UNKNOWN_FUNCTION 0x81
+#define DMI_FUNCTION_NOT_SUPPORTED 0x82
+#define DMI_INVALID_HANDLE 0x83
+#define DMI_BAD_PARAMETER 0x84
+#define DMI_INVALID_SUBFUNCTION 0x85
+#define DMI_NO_CHANGE 0x86
+#define DMI_ADD_STRUCTURE_FAILED 0x87
+#define DMI_READ_ONLY 0x8D
+#define DMI_LOCK_NOT_SUPPORTED 0x90
+#define DMI_CURRENTLY_LOCKED 0x91
+#define DMI_INVALID_LOCK 0x92
+
+#define INVALID_HANDLE (UINT16) (-1)
+
+#define EFI_SMBIOSERR(val) EFIERR (0x30000 | val)
+
+#define EFI_SMBIOSERR_FAILURE EFI_SMBIOSERR (1)
+#define EFI_SMBIOSERR_STRUCT_NOT_FOUND EFI_SMBIOSERR (2)
+#define EFI_SMBIOSERR_TYPE_UNKNOWN EFI_SMBIOSERR (3)
+#define EFI_SMBIOSERR_UNSUPPORTED EFI_SMBIOSERR (4)
+
+/**
+ Init the SMBIOS VIEW API's environment for the 32-bit table..
+
+ @retval EFI_SUCCESS Successful to init the SMBIOS VIEW Lib.
+**/
+EFI_STATUS
+LibSmbiosInit (
+ VOID
+ );
+
+/**
+ Init the SMBIOS VIEW API's environment for the 64-bit table..
+
+ @retval EFI_SUCCESS Successful to init the SMBIOS VIEW Lib.
+**/
+EFI_STATUS
+LibSmbios64BitInit (
+ VOID
+ );
+
+/**
+ Cleanup the Smbios information.
+**/
+VOID
+LibSmbiosCleanup (
+ VOID
+ );
+
+/**
+ Cleanup the Smbios information.
+**/
+VOID
+LibSmbios64BitCleanup (
+ VOID
+ );
+
+/**
+ Get the entry point structure for the table.
+
+ @param[out] EntryPointStructure The pointer to populate.
+**/
+VOID
+LibSmbiosGetEPS (
+ OUT SMBIOS_TABLE_ENTRY_POINT **EntryPointStructure
+ );
+
+/**
+ Get the entry point structure for the 64-bit table.
+
+ @param[out] EntryPointStructure The pointer to populate.
+**/
+VOID
+LibSmbios64BitGetEPS (
+ OUT SMBIOS_TABLE_3_0_ENTRY_POINT **EntryPointStructure
+ );
+
+/**
+ Return SMBIOS string for the given string number.
+
+ @param[in] Smbios Pointer to SMBIOS structure.
+ @param[in] StringNumber String number to return. -1 is used to skip all strings and
+ point to the next SMBIOS structure.
+
+ @return Pointer to string, or pointer to next SMBIOS strcuture if StringNumber == -1
+**/
+CHAR8*
+LibGetSmbiosString (
+ IN SMBIOS_STRUCTURE_POINTER *Smbios,
+ IN UINT16 StringNumber
+ );
+
+/**
+ Get SMBIOS structure for the given Handle,
+ Handle is changed to the next handle or 0xFFFF when the end is
+ reached or the handle is not found.
+
+ @param[in, out] Handle 0xFFFF: get the first structure
+ Others: get a structure according to this value.
+ @param[out] Buffer The pointer to the pointer to the structure.
+ @param[out] Length Length of the structure.
+
+ @retval DMI_SUCCESS Handle is updated with next structure handle or
+ 0xFFFF(end-of-list).
+
+ @retval DMI_INVALID_HANDLE Handle is updated with first structure handle or
+ 0xFFFF(end-of-list).
+**/
+EFI_STATUS
+LibGetSmbiosStructure (
+ IN OUT UINT16 *Handle,
+ OUT UINT8 **Buffer,
+ OUT UINT16 *Length
+ );
+
+/**
+ Get SMBIOS structure for the given Handle in 64-bit table,
+ Handle is changed to the next handle or 0xFFFF when the end is
+ reached or the handle is not found.
+
+ @param[in, out] Handle 0xFFFF: get the first structure
+ Others: get a structure according to this value.
+ @param[out] Buffer The pointer to the pointer to the structure.
+ @param[out] Length Length of the structure.
+
+ @retval DMI_SUCCESS Handle is updated with next structure handle or
+ 0xFFFF(end-of-list).
+
+ @retval DMI_INVALID_HANDLE Handle is updated with first structure handle or
+ 0xFFFF(end-of-list).
+**/
+EFI_STATUS
+LibGetSmbios64BitStructure (
+ IN OUT UINT16 *Handle,
+ OUT UINT8 **Buffer,
+ OUT UINT16 *Length
+ );
+
+#endif
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/PrintInfo.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/PrintInfo.c
new file mode 100644
index 0000000000..3f99dc4825
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/PrintInfo.c
@@ -0,0 +1,3227 @@
+/** @file
+ Module for clarifying the content of the smbios structure element information.
+
+ Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
+ (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "../UefiShellDebug1CommandsLib.h"
+#include "PrintInfo.h"
+#include "LibSmbiosView.h"
+#include "QueryTable.h"
+#include "EventLogInfo.h"
+
+
+//
+// Get the certain bit of 'value'
+//
+#define BIT(value, bit) ((value) & ((UINT64) 1) << (bit))
+
+//
+// Check if above or equal to version
+//
+#define AE_SMBIOS_VERSION(MajorVersion, MinorVersion) \
+ (SmbiosMajorVersion > (MajorVersion) || (SmbiosMajorVersion == (MajorVersion) && SmbiosMinorVersion >= (MinorVersion)))
+
+//
+//////////////////////////////////////////////////////////
+// Macros of print structure element, simplify coding.
+//
+#define PRINT_PENDING_STRING(pStruct, type, element) \
+ do { \
+ CHAR8 *StringBuf; \
+ StringBuf = LibGetSmbiosString ((pStruct), (pStruct->type->element)); \
+ ShellPrintEx(-1,-1,L"%a",#element); \
+ ShellPrintEx(-1,-1,L": %a\n", (StringBuf != NULL) ? StringBuf: ""); \
+ } while (0);
+
+#define PRINT_SMBIOS_STRING(pStruct, stringnumber, element) \
+ do { \
+ CHAR8 *StringBuf; \
+ StringBuf = LibGetSmbiosString ((pStruct), (stringnumber)); \
+ ShellPrintEx(-1,-1,L"%a",#element); \
+ ShellPrintEx(-1,-1,L": %a\n", (StringBuf != NULL) ? StringBuf: ""); \
+ } while (0);
+
+#define PRINT_STRUCT_VALUE(pStruct, type, element) \
+ do { \
+ ShellPrintEx(-1,-1,L"%a",#element); \
+ ShellPrintEx(-1,-1,L": %d\n", (pStruct->type->element)); \
+ } while (0);
+
+#define PRINT_STRUCT_VALUE_H(pStruct, type, element) \
+ do { \
+ ShellPrintEx(-1,-1,L"%a",#element); \
+ ShellPrintEx(-1,-1,L": 0x%x\n", (pStruct->type->element)); \
+ } while (0);
+
+#define PRINT_STRUCT_VALUE_LH(pStruct, type, element) \
+ do { \
+ ShellPrintEx(-1,-1,L"%a",#element); \
+ ShellPrintEx(-1,-1,L": 0x%lx\n", (pStruct->type->element)); \
+ } while (0);
+
+#define PRINT_BIT_FIELD(pStruct, type, element, size) \
+ do { \
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DUMP), gShellDebug1HiiHandle); \
+ ShellPrintEx(-1,-1,L"%a",#element); \
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SIZE), gShellDebug1HiiHandle, size); \
+ DumpHex (0, 0, size, &(pStruct->type->element)); \
+ } while (0);
+
+#define PRINT_SMBIOS_BIT_FIELD(pStruct, startaddress, element, size) \
+ do { \
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DUMP), gShellDebug1HiiHandle); \
+ ShellPrintEx(-1,-1,L"%a",#element); \
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SIZE), gShellDebug1HiiHandle, size); \
+ DumpHex (0, 0, size, startaddress); \
+ } while (0);
+
+//
+/////////////////////////////////////////
+//
+
+/**
+ Copy Length of Src buffer to Dest buffer,
+ add a NULL termination to Dest buffer.
+
+ @param[in, out] Dest Destination buffer head.
+ @param[in] Src Source buffer head.
+ @param[in] Length Length of buffer to be copied.
+**/
+VOID
+MemToString (
+ IN OUT VOID *Dest,
+ IN VOID *Src,
+ IN UINTN Length
+ )
+{
+ UINT8 *SrcBuffer;
+ UINT8 *DestBuffer;
+ SrcBuffer = (UINT8 *) Src;
+ DestBuffer = (UINT8 *) Dest;
+ //
+ // copy byte by byte
+ //
+ while ((Length--)!=0) {
+ *DestBuffer++ = *SrcBuffer++;
+ }
+ //
+ // append a NULL terminator
+ //
+ *DestBuffer = '\0';
+}
+
+//
+//////////////////////////////////////////////
+//
+// Functions below is to show the information
+//
+
+/**
+ Print the info of EPS(Entry Point Structure).
+
+ @param[in] SmbiosTable Pointer to the SMBIOS table entry point.
+ @param[in] Option Display option.
+**/
+VOID
+SmbiosPrintEPSInfo (
+ IN SMBIOS_TABLE_ENTRY_POINT *SmbiosTable,
+ IN UINT8 Option
+ )
+{
+ UINT8 Anchor[5];
+ UINT8 InAnchor[6];
+
+ if (SmbiosTable == NULL) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SMBIOSTABLE_NULL), gShellDebug1HiiHandle);
+ return ;
+ }
+
+ if (Option == SHOW_NONE) {
+ return ;
+ }
+
+ if (Option >= SHOW_NORMAL) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ENTRY_POINT_SIGN), gShellDebug1HiiHandle);
+ MemToString (Anchor, SmbiosTable->AnchorString, 4);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ANCHOR_STR), gShellDebug1HiiHandle, Anchor);
+ ShellPrintHiiEx(-1,-1,NULL,
+ STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_EPS_CHECKSUM),
+ gShellDebug1HiiHandle,
+ SmbiosTable->EntryPointStructureChecksum
+ );
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ENTRY_POINT_LEN), gShellDebug1HiiHandle, SmbiosTable->EntryPointLength);
+ ShellPrintHiiEx(-1,-1,NULL,
+ STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_VERSION),
+ gShellDebug1HiiHandle,
+ SmbiosTable->MajorVersion,
+ SmbiosTable->MinorVersion
+ );
+ ShellPrintHiiEx(-1,-1,NULL,
+ STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NUMBER_STRUCT),
+ gShellDebug1HiiHandle,
+ SmbiosTable->NumberOfSmbiosStructures
+ );
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MAX_STRUCT_SIZE), gShellDebug1HiiHandle, SmbiosTable->MaxStructureSize);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_TABLE_ADDR), gShellDebug1HiiHandle, SmbiosTable->TableAddress);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_TABLE_LENGTH), gShellDebug1HiiHandle, SmbiosTable->TableLength);
+
+ }
+ //
+ // If SHOW_ALL, also print followings.
+ //
+ if (Option >= SHOW_DETAIL) {
+ ShellPrintHiiEx(-1,-1,NULL,
+ STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ENTRY_POINT_REVISION),
+ gShellDebug1HiiHandle,
+ SmbiosTable->EntryPointRevision
+ );
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BCD_REVISION), gShellDebug1HiiHandle, SmbiosTable->SmbiosBcdRevision);
+ //
+ // Since raw data is not string, add a NULL terminater.
+ //
+ MemToString (InAnchor, SmbiosTable->IntermediateAnchorString, 5);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTER_ACHOR), gShellDebug1HiiHandle, InAnchor);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTER_CHECKSUM), gShellDebug1HiiHandle, SmbiosTable->IntermediateChecksum);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_FORMATTED_AREA), gShellDebug1HiiHandle);
+ DumpHex (2, 0, 5, SmbiosTable->FormattedArea);
+ }
+
+ Print (L"\n");
+}
+
+/**
+ Print the info of 64-bit EPS(Entry Point Structure).
+
+ @param[in] SmbiosTable Pointer to the SMBIOS table entry point.
+ @param[in] Option Display option.
+**/
+VOID
+Smbios64BitPrintEPSInfo (
+ IN SMBIOS_TABLE_3_0_ENTRY_POINT *SmbiosTable,
+ IN UINT8 Option
+ )
+{
+ UINT8 Anchor[5];
+
+ if (SmbiosTable == NULL) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SMBIOSTABLE_NULL), gShellDebug1HiiHandle);
+ return ;
+ }
+
+ if (Option == SHOW_NONE) {
+ return ;
+ }
+
+ if (Option >= SHOW_NORMAL) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_64_BIT_ENTRY_POINT_SIGN), gShellDebug1HiiHandle);
+
+ MemToString (Anchor, SmbiosTable->AnchorString, 5);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ANCHOR_STR), gShellDebug1HiiHandle, Anchor);
+
+ ShellPrintHiiEx(-1,-1,NULL,
+ STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_EPS_CHECKSUM),
+ gShellDebug1HiiHandle,
+ SmbiosTable->EntryPointStructureChecksum
+ );
+
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ENTRY_POINT_LEN), gShellDebug1HiiHandle, SmbiosTable->EntryPointLength);
+
+ ShellPrintHiiEx(-1,-1,NULL,
+ STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_VERSION),
+ gShellDebug1HiiHandle,
+ SmbiosTable->MajorVersion,
+ SmbiosTable->MinorVersion
+ );
+
+ ShellPrintHiiEx(-1,-1,NULL,
+ STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DOCREV),
+ gShellDebug1HiiHandle,
+ SmbiosTable->DocRev
+ );
+
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_TABLE_MAX_SIZE), gShellDebug1HiiHandle, SmbiosTable->TableMaximumSize);
+
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_TABLE_ADDR), gShellDebug1HiiHandle, SmbiosTable->TableAddress);
+
+ }
+ //
+ // If SHOW_ALL, also print followings.
+ //
+ if (Option >= SHOW_DETAIL) {
+ ShellPrintHiiEx(-1,-1,NULL,
+ STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ENTRY_POINT_REVISION),
+ gShellDebug1HiiHandle,
+ SmbiosTable->EntryPointRevision
+ );
+ }
+
+ Print (L"\n");
+}
+
+/**
+ This function print the content of the structure pointed by Struct.
+
+ @param[in] Struct Point to the structure to be printed.
+ @param[in] Option Print option of information detail.
+
+ @retval EFI_SUCCESS Successfully Printing this function.
+ @retval EFI_INVALID_PARAMETER Invalid Structure.
+ @retval EFI_UNSUPPORTED Unsupported.
+**/
+EFI_STATUS
+SmbiosPrintStructure (
+ IN SMBIOS_STRUCTURE_POINTER *Struct,
+ IN UINT8 Option
+ )
+{
+ UINT8 Index;
+ UINT8 *Buffer;
+
+ if (Struct == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Option == SHOW_NONE) {
+ return EFI_SUCCESS;
+ }
+
+ Buffer = (UINT8 *) (UINTN) (Struct->Raw);
+
+ //
+ // Display structure header
+ //
+ DisplayStructureTypeInfo (Struct->Hdr->Type, SHOW_DETAIL);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_FORMAT_PART_LEN), gShellDebug1HiiHandle, Struct->Hdr->Length);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_STRUCT_HANDLE), gShellDebug1HiiHandle, Struct->Hdr->Handle);
+
+ if (Option == SHOW_OUTLINE) {
+ return EFI_SUCCESS;
+ }
+
+ switch (Struct->Hdr->Type) {
+ //
+ // BIOS Information (Type 0)
+ //
+ case 0:
+ PRINT_PENDING_STRING (Struct, Type0, Vendor);
+ PRINT_PENDING_STRING (Struct, Type0, BiosVersion);
+ PRINT_STRUCT_VALUE (Struct, Type0, BiosSegment);
+ PRINT_PENDING_STRING (Struct, Type0, BiosReleaseDate);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIOS_SIZE), gShellDebug1HiiHandle, 64 * (Struct->Type0->BiosSize + 1));
+
+ DisplayBiosCharacteristics (ReadUnaligned64 ((UINT64 *) (UINTN) &(Struct->Type0->BiosCharacteristics)), Option);
+
+ if (Struct->Hdr->Length > 0x12) {
+ DisplayBiosCharacteristicsExt1 (Struct->Type0->BIOSCharacteristicsExtensionBytes[0], Option);
+ }
+ if (Struct->Hdr->Length > 0x13) {
+ DisplayBiosCharacteristicsExt2 (Struct->Type0->BIOSCharacteristicsExtensionBytes[1], Option);
+ }
+
+ if (AE_SMBIOS_VERSION (0x2, 0x4) && (Struct->Hdr->Length > 0x14)) {
+ PRINT_STRUCT_VALUE (Struct, Type0, SystemBiosMajorRelease);
+ PRINT_STRUCT_VALUE (Struct, Type0, SystemBiosMinorRelease);
+ PRINT_STRUCT_VALUE (Struct, Type0, EmbeddedControllerFirmwareMajorRelease);
+ PRINT_STRUCT_VALUE (Struct, Type0, EmbeddedControllerFirmwareMinorRelease);
+ }
+
+ break;
+
+ //
+ // System Information (Type 1)
+ //
+ case 1:
+ PRINT_PENDING_STRING (Struct, Type1, Manufacturer);
+ PRINT_PENDING_STRING (Struct, Type1, ProductName);
+ PRINT_PENDING_STRING (Struct, Type1, Version);
+ PRINT_PENDING_STRING (Struct, Type1, SerialNumber);
+ PRINT_BIT_FIELD (Struct, Type1, Uuid, 16);
+ DisplaySystemWakeupType (Struct->Type1->WakeUpType, Option);
+ if (AE_SMBIOS_VERSION (0x2, 0x4) && (Struct->Hdr->Length > 0x19)) {
+ PRINT_PENDING_STRING (Struct, Type1, SKUNumber);
+ PRINT_PENDING_STRING (Struct, Type1, Family);
+ }
+
+ break;
+
+ //
+ // Baseboard Information (Type 2)
+ //
+ case 2:
+ PRINT_PENDING_STRING (Struct, Type2, Manufacturer);
+ PRINT_PENDING_STRING (Struct, Type2, ProductName);
+ PRINT_PENDING_STRING (Struct, Type2, Version);
+ PRINT_PENDING_STRING (Struct, Type2, SerialNumber);
+ if (Struct->Hdr->Length > 0x8) {
+ PRINT_PENDING_STRING (Struct, Type2, AssetTag);
+ DisplayBaseBoardFeatureFlags (*(UINT8 *) &Struct->Type2->FeatureFlag, Option);
+ PRINT_PENDING_STRING (Struct, Type2, LocationInChassis);
+ PRINT_STRUCT_VALUE_H (Struct, Type2, ChassisHandle);
+ DisplayBaseBoardBoardType (Struct->Type2->BoardType, Option);
+ }
+ break;
+
+ //
+ // System Enclosure (Type 3)
+ //
+ case 3:
+ PRINT_PENDING_STRING (Struct, Type3, Manufacturer);
+ PRINT_STRUCT_VALUE (Struct, Type3, Type);
+ DisplaySystemEnclosureType (Struct->Type3->Type, Option);
+ PRINT_PENDING_STRING (Struct, Type3, Version);
+ PRINT_PENDING_STRING (Struct, Type3, SerialNumber);
+ PRINT_PENDING_STRING (Struct, Type3, AssetTag);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BOOTUP_STATE), gShellDebug1HiiHandle);
+ DisplaySystemEnclosureStatus (Struct->Type3->BootupState, Option);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_STATE), gShellDebug1HiiHandle);
+ DisplaySystemEnclosureStatus (Struct->Type3->PowerSupplyState, Option);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_THERMAL_STATE), gShellDebug1HiiHandle);
+ DisplaySystemEnclosureStatus (Struct->Type3->ThermalState, Option);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SECURITY_STATUS), gShellDebug1HiiHandle);
+ DisplaySESecurityStatus (Struct->Type3->SecurityStatus, Option);
+ if (AE_SMBIOS_VERSION (0x2, 0x3) && (Struct->Hdr->Length > 0xD)) {
+ PRINT_BIT_FIELD (Struct, Type3, OemDefined, 4);
+ }
+ break;
+
+ //
+ // Processor Information (Type 4)
+ //
+ case 4:
+ PRINT_PENDING_STRING (Struct, Type4, Socket);
+ DisplayProcessorType (Struct->Type4->ProcessorType, Option);
+ if (AE_SMBIOS_VERSION (0x2, 0x6) && (Struct->Hdr->Length > 0x28) &&
+ (Struct->Type4->ProcessorFamily == 0xFE)) {
+ //
+ // Get family from ProcessorFamily2 field
+ //
+ DisplayProcessorFamily2 (Struct->Type4->ProcessorFamily2, Option);
+ } else {
+ DisplayProcessorFamily (Struct->Type4->ProcessorFamily, Option);
+ }
+ PRINT_PENDING_STRING (Struct, Type4, ProcessorManufacture);
+ PRINT_BIT_FIELD (Struct, Type4, ProcessorId, 8);
+ PRINT_PENDING_STRING (Struct, Type4, ProcessorVersion);
+ DisplayProcessorVoltage (*(UINT8 *) &(Struct->Type4->Voltage), Option);
+ PRINT_STRUCT_VALUE (Struct, Type4, ExternalClock);
+ PRINT_STRUCT_VALUE (Struct, Type4, MaxSpeed);
+ PRINT_STRUCT_VALUE (Struct, Type4, CurrentSpeed);
+ DisplayProcessorStatus (Struct->Type4->Status, Option);
+ DisplayProcessorUpgrade (Struct->Type4->ProcessorUpgrade, Option);
+ PRINT_STRUCT_VALUE_H (Struct, Type4, L1CacheHandle);
+ PRINT_STRUCT_VALUE_H (Struct, Type4, L2CacheHandle);
+ PRINT_STRUCT_VALUE_H (Struct, Type4, L3CacheHandle);
+ if (AE_SMBIOS_VERSION (0x2, 0x3) && (Struct->Hdr->Length > 0x20)) {
+ PRINT_PENDING_STRING (Struct, Type4, SerialNumber);
+ PRINT_PENDING_STRING (Struct, Type4, AssetTag);
+ PRINT_PENDING_STRING (Struct, Type4, PartNumber);
+ }
+ if (AE_SMBIOS_VERSION (0x2, 0x5) && (Struct->Hdr->Length > 0x23)) {
+ PRINT_STRUCT_VALUE (Struct, Type4, CoreCount);
+ PRINT_STRUCT_VALUE (Struct, Type4, EnabledCoreCount);
+ PRINT_STRUCT_VALUE (Struct, Type4, ThreadCount);
+ DisplayProcessorCharacteristics (Struct->Type4->ProcessorCharacteristics, Option);
+ }
+ if ((SmbiosMajorVersion >= 0x3) && (Struct->Hdr->Length > 0x2A)) {
+ PRINT_STRUCT_VALUE (Struct, Type4, CoreCount2);
+ PRINT_STRUCT_VALUE (Struct, Type4, EnabledCoreCount2);
+ PRINT_STRUCT_VALUE (Struct, Type4, ThreadCount2);
+ }
+ break;
+
+ //
+ // Memory Controller Information (Type 5)
+ //
+ case 5:
+ {
+ UINT8 SlotNum;
+ SlotNum = Struct->Type5->AssociatedMemorySlotNum;
+
+ DisplayMcErrorDetectMethod (Struct->Type5->ErrDetectMethod, Option);
+ DisplayMcErrorCorrectCapability (*(UINT8 *) &(Struct->Type5->ErrCorrectCapability), Option);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SUPOPRT), gShellDebug1HiiHandle);
+ DisplayMcInterleaveSupport (Struct->Type5->SupportInterleave, Option);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CURRENT), gShellDebug1HiiHandle);
+ DisplayMcInterleaveSupport (Struct->Type5->CurrentInterleave, Option);
+ DisplayMaxMemoryModuleSize (Struct->Type5->MaxMemoryModuleSize, SlotNum, Option);
+ DisplayMcMemorySpeeds (*(UINT16 *) &(Struct->Type5->SupportSpeed), Option);
+ DisplayMmMemoryType (Struct->Type5->SupportMemoryType, Option);
+ DisplayMemoryModuleVoltage (Struct->Type5->MemoryModuleVoltage, Option);
+ PRINT_STRUCT_VALUE (Struct, Type5, AssociatedMemorySlotNum);
+ //
+ // According to SMBIOS Specification, offset 0x0F
+ //
+ DisplayMemoryModuleConfigHandles ((UINT16 *) (&Buffer[0x0F]), SlotNum, Option);
+ DisplayMcErrorCorrectCapability (Buffer[0x0F + 2 * SlotNum], Option);
+ }
+ break;
+
+ //
+ // Memory Module Information (Type 6)
+ //
+ case 6:
+ PRINT_PENDING_STRING (Struct, Type6, SocketDesignation);
+ DisplayMmBankConnections (Struct->Type6->BankConnections, Option);
+ PRINT_STRUCT_VALUE (Struct, Type6, CurrentSpeed);
+ DisplayMmMemoryType (*(UINT16 *) &(Struct->Type6->CurrentMemoryType), Option);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INSTALLED), gShellDebug1HiiHandle);
+ DisplayMmMemorySize (*(UINT8 *) &(Struct->Type6->InstalledSize), Option);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ENABLED), gShellDebug1HiiHandle);
+ DisplayMmMemorySize (*(UINT8 *) &(Struct->Type6->EnabledSize), Option);
+ DisplayMmErrorStatus (Struct->Type6->ErrorStatus, Option);
+ break;
+
+ //
+ // Cache Information (Type 7)
+ //
+ case 7:
+ PRINT_PENDING_STRING (Struct, Type7, SocketDesignation);
+ DisplayCacheConfiguration (Struct->Type7->CacheConfiguration, Option);
+ PRINT_STRUCT_VALUE_H (Struct, Type7, MaximumCacheSize);
+ PRINT_STRUCT_VALUE_H (Struct, Type7, InstalledSize);
+ PRINT_STRUCT_VALUE_H (Struct, Type7, SupportedSRAMType);
+ PRINT_STRUCT_VALUE_H (Struct, Type7, CurrentSRAMType);
+ DisplayCacheSRAMType (ReadUnaligned16 ((UINT16 *) (UINTN) &(Struct->Type7->CurrentSRAMType)), Option);
+ PRINT_STRUCT_VALUE_H (Struct, Type7, CacheSpeed);
+ DisplayCacheErrCorrectingType (Struct->Type7->ErrorCorrectionType, Option);
+ DisplayCacheSystemCacheType (Struct->Type7->SystemCacheType, Option);
+ DisplayCacheAssociativity (Struct->Type7->Associativity, Option);
+ break;
+
+ //
+ // Port Connector Information (Type 8)
+ //
+ case 8:
+ PRINT_PENDING_STRING (Struct, Type8, InternalReferenceDesignator);
+ Print (L"Internal ");
+ DisplayPortConnectorType (Struct->Type8->InternalConnectorType, Option);
+ PRINT_PENDING_STRING (Struct, Type8, ExternalReferenceDesignator);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_EXTERNAL), gShellDebug1HiiHandle);
+ DisplayPortConnectorType (Struct->Type8->ExternalConnectorType, Option);
+ DisplayPortType (Struct->Type8->PortType, Option);
+ break;
+
+ //
+ // System Slots (Type 9)
+ //
+ case 9:
+ PRINT_PENDING_STRING (Struct, Type9, SlotDesignation);
+ DisplaySystemSlotType (Struct->Type9->SlotType, Option);
+ DisplaySystemSlotDataBusWidth (Struct->Type9->SlotDataBusWidth, Option);
+ DisplaySystemSlotCurrentUsage (Struct->Type9->CurrentUsage, Option);
+ DisplaySystemSlotLength (Struct->Type9->SlotLength, Option);
+ DisplaySystemSlotId (
+ Struct->Type9->SlotID,
+ Struct->Type9->SlotType,
+ Option
+ );
+ DisplaySlotCharacteristics1 (*(UINT8 *) &(Struct->Type9->SlotCharacteristics1), Option);
+ DisplaySlotCharacteristics2 (*(UINT8 *) &(Struct->Type9->SlotCharacteristics2), Option);
+ if (AE_SMBIOS_VERSION (0x2, 0x6) && (Struct->Hdr->Length > 0xD)) {
+ PRINT_STRUCT_VALUE_H (Struct, Type9, SegmentGroupNum);
+ PRINT_STRUCT_VALUE_H (Struct, Type9, BusNum);
+ PRINT_STRUCT_VALUE_H (Struct, Type9, DevFuncNum);
+ }
+ break;
+
+ //
+ // On Board Devices Information (Type 10)
+ //
+ case 10:
+ {
+ UINTN NumOfDevice;
+ NumOfDevice = (Struct->Type10->Hdr.Length - sizeof (SMBIOS_STRUCTURE)) / (2 * sizeof (UINT8));
+ for (Index = 0; Index < NumOfDevice; Index++) {
+ DisplayOnboardDeviceTypes (Struct->Type10->Device[Index].DeviceType, Option);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DESC_STRING), gShellDebug1HiiHandle);
+ ShellPrintEx(-1,-1,L"%a\n",LibGetSmbiosString (Struct, Struct->Type10->Device[Index].DescriptionString));
+ }
+ }
+ break;
+
+ //
+ // Oem Strings (Type 11)
+ //
+ case 11:
+ PRINT_STRUCT_VALUE (Struct, Type11, StringCount);
+ for (Index = 1; Index <= Struct->Type11->StringCount; Index++) {
+ ShellPrintEx(-1,-1,L"%a\n", LibGetSmbiosString (Struct, Index));
+ }
+ break;
+
+ //
+ // System Configuration Options (Type 12)
+ //
+ case 12:
+ PRINT_STRUCT_VALUE (Struct, Type12, StringCount);
+ for (Index = 1; Index <= Struct->Type12->StringCount; Index++) {
+ ShellPrintEx(-1,-1,L"%a\n", LibGetSmbiosString (Struct, Index));
+ }
+ break;
+
+ //
+ // BIOS Language Information (Type 13)
+ //
+ case 13:
+ PRINT_STRUCT_VALUE (Struct, Type13, InstallableLanguages);
+ PRINT_STRUCT_VALUE (Struct, Type13, Flags);
+ PRINT_BIT_FIELD (Struct, Type13, Reserved, 15);
+ PRINT_PENDING_STRING (Struct, Type13, CurrentLanguages);
+ break;
+
+ //
+ // Group Associations (Type 14)
+ //
+ case 14:
+ {
+ UINT8 NumOfItem;
+ NumOfItem = (Struct->Type14->Hdr.Length - 5) / 3;
+ PRINT_PENDING_STRING (Struct, Type14, GroupName);
+ for (Index = 0; Index < NumOfItem; Index++) {
+ ShellPrintEx(-1,-1,L"ItemType %d: %d\n", Index + 1, Struct->Type14->Group[Index].ItemType);
+ ShellPrintEx(-1,-1,L"ItemHandle %d: %d\n", Index + 1, Struct->Type14->Group[Index].ItemHandle);
+ }
+ }
+ break;
+
+ //
+ // System Event Log (Type 15)
+ //
+ case 15:
+ {
+ EVENT_LOG_TYPE *Ptr;
+ UINT8 Count;
+ UINT8 *AccessMethodAddress;
+
+ PRINT_STRUCT_VALUE_H (Struct, Type15, LogAreaLength);
+ PRINT_STRUCT_VALUE_H (Struct, Type15, LogHeaderStartOffset);
+ PRINT_STRUCT_VALUE_H (Struct, Type15, LogDataStartOffset);
+ DisplaySELAccessMethod (Struct->Type15->AccessMethod, Option);
+ PRINT_STRUCT_VALUE_H (Struct, Type15, AccessMethodAddress);
+ DisplaySELLogStatus (Struct->Type15->LogStatus, Option);
+ PRINT_STRUCT_VALUE_H (Struct, Type15, LogChangeToken);
+ DisplaySysEventLogHeaderFormat (Struct->Type15->LogHeaderFormat, Option);
+ PRINT_STRUCT_VALUE_H (Struct, Type15, NumberOfSupportedLogTypeDescriptors);
+ PRINT_STRUCT_VALUE_H (Struct, Type15, LengthOfLogTypeDescriptor);
+
+ Count = Struct->Type15->NumberOfSupportedLogTypeDescriptors;
+ if (Count > 0) {
+ Ptr = Struct->Type15->EventLogTypeDescriptors;
+
+ //
+ // Display all Event Log type descriptors supported by system
+ //
+ for (Index = 0; Index < Count; Index++, Ptr++) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SUPOPRTED_EVENT), gShellDebug1HiiHandle, Index + 1);
+ DisplaySELTypes (Ptr->LogType, Option);
+ DisplaySELVarDataFormatType (Ptr->DataFormatType, Option);
+ }
+
+ if (Option >= SHOW_DETAIL) {
+ switch (Struct->Type15->AccessMethod) {
+ case 03:
+ AccessMethodAddress = (UINT8 *) (UINTN) (Struct->Type15->AccessMethodAddress);
+ break;
+
+ case 00:
+ case 01:
+ case 02:
+ case 04:
+ default:
+ ShellPrintHiiEx(-1,-1,NULL,
+ STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ACCESS_METHOD_NOT_SUPOPRTED),
+ gShellDebug1HiiHandle,
+ Struct->Type15->AccessMethod
+ );
+ return EFI_UNSUPPORTED;
+ }
+ //
+ // Display Event Log Header
+ //
+ // Starting offset (or index) within the nonvolatile storage
+ // of the event-log's header, from the Access Method Address
+ //
+ DisplaySysEventLogHeader (
+ Struct->Type15->LogHeaderFormat,
+ AccessMethodAddress + Struct->Type15->LogHeaderStartOffset
+ );
+
+ //
+ // Display all Event Log data
+ //
+ // Starting offset (or index) within the nonvolatile storage
+ // of the event-log's first data byte, from the Access Method Address(0x14)
+ //
+ DisplaySysEventLogData (
+ AccessMethodAddress + Struct->Type15->LogDataStartOffset,
+ (UINT16)
+ (
+ Struct->Type15->LogAreaLength -
+ (Struct->Type15->LogDataStartOffset - Struct->Type15->LogHeaderStartOffset)
+ )
+ );
+ }
+
+ }
+ }
+ break;
+
+ //
+ // Physical Memory Array (Type 16)
+ //
+ case 16:
+ DisplayPMALocation (Struct->Type16->Location, Option);
+ DisplayPMAUse (Struct->Type16->Use, Option);
+ DisplayPMAErrorCorrectionTypes (
+ Struct->Type16->MemoryErrorCorrection,
+ Option
+ );
+ PRINT_STRUCT_VALUE_H (Struct, Type16, MaximumCapacity);
+ PRINT_STRUCT_VALUE_H (Struct, Type16, MemoryErrorInformationHandle);
+ PRINT_STRUCT_VALUE_H (Struct, Type16, NumberOfMemoryDevices);
+ if (AE_SMBIOS_VERSION (0x2, 0x7) && Struct->Hdr->Length > 0xF) {
+ PRINT_STRUCT_VALUE_LH (Struct, Type16, ExtendedMaximumCapacity);
+ }
+ break;
+
+ //
+ // Memory Device (Type 17)
+ //
+ case 17:
+ PRINT_STRUCT_VALUE_H (Struct, Type17, MemoryArrayHandle);
+ PRINT_STRUCT_VALUE_H (Struct, Type17, MemoryErrorInformationHandle);
+ PRINT_STRUCT_VALUE (Struct, Type17, TotalWidth);
+ PRINT_STRUCT_VALUE (Struct, Type17, DataWidth);
+ PRINT_STRUCT_VALUE (Struct, Type17, Size);
+ DisplayMemoryDeviceFormFactor (Struct->Type17->FormFactor, Option);
+ PRINT_STRUCT_VALUE_H (Struct, Type17, DeviceSet);
+ PRINT_PENDING_STRING (Struct, Type17, DeviceLocator);
+ PRINT_PENDING_STRING (Struct, Type17, BankLocator);
+ DisplayMemoryDeviceType (Struct->Type17->MemoryType, Option);
+ DisplayMemoryDeviceTypeDetail (ReadUnaligned16 ((UINT16 *) (UINTN) &(Struct->Type17->TypeDetail)), Option);
+ PRINT_STRUCT_VALUE_H (Struct, Type17, Speed);
+ PRINT_PENDING_STRING (Struct, Type17, Manufacturer);
+ PRINT_PENDING_STRING (Struct, Type17, SerialNumber);
+ PRINT_PENDING_STRING (Struct, Type17, AssetTag);
+ PRINT_PENDING_STRING (Struct, Type17, PartNumber);
+ if (AE_SMBIOS_VERSION (0x2, 0x6) && (Struct->Hdr->Length > 0x1B)) {
+ PRINT_STRUCT_VALUE_H (Struct, Type17, Attributes);
+ }
+ if (AE_SMBIOS_VERSION (0x2, 0x7) && (Struct->Hdr->Length > 0x1C)) {
+ PRINT_STRUCT_VALUE (Struct, Type17, ExtendedSize);
+ PRINT_STRUCT_VALUE (Struct, Type17, ConfiguredMemoryClockSpeed);
+ }
+ if (AE_SMBIOS_VERSION (0x2, 0x8) && (Struct->Hdr->Length > 0x22)) {
+ PRINT_STRUCT_VALUE (Struct, Type17, MinimumVoltage);
+ PRINT_STRUCT_VALUE (Struct, Type17, MaximumVoltage);
+ PRINT_STRUCT_VALUE (Struct, Type17, ConfiguredVoltage);
+ }
+ break;
+
+ //
+ // 32-bit Memory Error Information (Type 18)
+ //
+ case 18:
+ DisplayMemoryErrorType (Struct->Type18->ErrorType, Option);
+ DisplayMemoryErrorGranularity (
+ Struct->Type18->ErrorGranularity,
+ Option
+ );
+ DisplayMemoryErrorOperation (Struct->Type18->ErrorOperation, Option);
+ PRINT_STRUCT_VALUE_H (Struct, Type18, VendorSyndrome);
+ PRINT_STRUCT_VALUE_H (Struct, Type18, MemoryArrayErrorAddress);
+ PRINT_STRUCT_VALUE_H (Struct, Type18, DeviceErrorAddress);
+ PRINT_STRUCT_VALUE_H (Struct, Type18, ErrorResolution);
+ break;
+
+ //
+ // Memory Array Mapped Address (Type 19)
+ //
+ case 19:
+ PRINT_STRUCT_VALUE_H (Struct, Type19, StartingAddress);
+ PRINT_STRUCT_VALUE_H (Struct, Type19, EndingAddress);
+ PRINT_STRUCT_VALUE_H (Struct, Type19, MemoryArrayHandle);
+ PRINT_STRUCT_VALUE_H (Struct, Type19, PartitionWidth);
+ if (AE_SMBIOS_VERSION (0x2, 0x7) && (Struct->Hdr->Length > 0xF)) {
+ PRINT_STRUCT_VALUE_LH (Struct, Type19, ExtendedStartingAddress);
+ PRINT_STRUCT_VALUE_LH (Struct, Type19, ExtendedEndingAddress);
+ }
+ break;
+
+ //
+ // Memory Device Mapped Address (Type 20)
+ //
+ case 20:
+ PRINT_STRUCT_VALUE_H (Struct, Type20, StartingAddress);
+ PRINT_STRUCT_VALUE_H (Struct, Type20, EndingAddress);
+ PRINT_STRUCT_VALUE_H (Struct, Type20, MemoryDeviceHandle);
+ PRINT_STRUCT_VALUE_H (Struct, Type20, MemoryArrayMappedAddressHandle);
+ PRINT_STRUCT_VALUE_H (Struct, Type20, PartitionRowPosition);
+ PRINT_STRUCT_VALUE_H (Struct, Type20, InterleavePosition);
+ PRINT_STRUCT_VALUE_H (Struct, Type20, InterleavedDataDepth);
+ if (AE_SMBIOS_VERSION (0x2, 0x7) && (Struct->Hdr->Length > 0x13)) {
+ PRINT_STRUCT_VALUE_LH (Struct, Type19, ExtendedStartingAddress);
+ PRINT_STRUCT_VALUE_LH (Struct, Type19, ExtendedEndingAddress);
+ }
+ break;
+
+ //
+ // Built-in Pointing Device (Type 21)
+ //
+ case 21:
+ DisplayPointingDeviceType (Struct->Type21->Type, Option);
+ DisplayPointingDeviceInterface (Struct->Type21->Interface, Option);
+ PRINT_STRUCT_VALUE (Struct, Type21, NumberOfButtons);
+ break;
+
+ //
+ // Portable Battery (Type 22)
+ //
+ case 22:
+ PRINT_PENDING_STRING (Struct, Type22, Location);
+ PRINT_PENDING_STRING (Struct, Type22, Manufacturer);
+ PRINT_PENDING_STRING (Struct, Type22, ManufactureDate);
+ PRINT_PENDING_STRING (Struct, Type22, SerialNumber);
+ PRINT_PENDING_STRING (Struct, Type22, DeviceName);
+ DisplayPBDeviceChemistry (
+ Struct->Type22->DeviceChemistry,
+ Option
+ );
+ PRINT_STRUCT_VALUE_H (Struct, Type22, DeviceCapacity);
+ PRINT_STRUCT_VALUE_H (Struct, Type22, DesignVoltage);
+ PRINT_PENDING_STRING (Struct, Type22, SBDSVersionNumber);
+ PRINT_STRUCT_VALUE_H (Struct, Type22, MaximumErrorInBatteryData);
+ PRINT_STRUCT_VALUE_H (Struct, Type22, SBDSSerialNumber);
+ DisplaySBDSManufactureDate (
+ Struct->Type22->SBDSManufactureDate,
+ Option
+ );
+ PRINT_PENDING_STRING (Struct, Type22, SBDSDeviceChemistry);
+ PRINT_STRUCT_VALUE_H (Struct, Type22, DesignCapacityMultiplier);
+ PRINT_STRUCT_VALUE_H (Struct, Type22, OEMSpecific);
+ break;
+
+ //
+ // System Reset (Type 23)
+ //
+ case 23:
+ DisplaySystemResetCapabilities (
+ Struct->Type23->Capabilities,
+ Option
+ );
+ PRINT_STRUCT_VALUE_H (Struct, Type23, ResetCount);
+ PRINT_STRUCT_VALUE_H (Struct, Type23, ResetLimit);
+ PRINT_STRUCT_VALUE_H (Struct, Type23, TimerInterval);
+ PRINT_STRUCT_VALUE_H (Struct, Type23, Timeout);
+ break;
+
+ //
+ // Hardware Security (Type 24)
+ //
+ case 24:
+ DisplayHardwareSecuritySettings (
+ Struct->Type24->HardwareSecuritySettings,
+ Option
+ );
+ break;
+
+ //
+ // System Power Controls (Type 25)
+ //
+ case 25:
+ PRINT_STRUCT_VALUE_H (Struct, Type25, NextScheduledPowerOnMonth);
+ PRINT_STRUCT_VALUE_H (Struct, Type25, NextScheduledPowerOnDayOfMonth);
+ PRINT_STRUCT_VALUE_H (Struct, Type25, NextScheduledPowerOnHour);
+ PRINT_STRUCT_VALUE_H (Struct, Type25, NextScheduledPowerOnMinute);
+ PRINT_STRUCT_VALUE_H (Struct, Type25, NextScheduledPowerOnSecond);
+ break;
+
+ //
+ // Voltage Probe (Type 26)
+ //
+ case 26:
+ PRINT_PENDING_STRING (Struct, Type26, Description);
+ DisplayVPLocation (*(UINT8 *) &(Struct->Type26->LocationAndStatus), Option);
+ DisplayVPStatus (*(UINT8 *) &(Struct->Type26->LocationAndStatus), Option);
+ PRINT_STRUCT_VALUE_H (Struct, Type26, MaximumValue);
+ PRINT_STRUCT_VALUE_H (Struct, Type26, MinimumValue);
+ PRINT_STRUCT_VALUE_H (Struct, Type26, Resolution);
+ PRINT_STRUCT_VALUE_H (Struct, Type26, Tolerance);
+ PRINT_STRUCT_VALUE_H (Struct, Type26, Accuracy);
+ PRINT_STRUCT_VALUE_H (Struct, Type26, OEMDefined);
+ PRINT_STRUCT_VALUE_H (Struct, Type26, NominalValue);
+ break;
+
+ //
+ // Cooling Device (Type 27)
+ //
+ case 27:
+ PRINT_STRUCT_VALUE_H (Struct, Type27, TemperatureProbeHandle);
+ DisplayCoolingDeviceStatus (*(UINT8 *) &(Struct->Type27->DeviceTypeAndStatus), Option);
+ DisplayCoolingDeviceType (*(UINT8 *) &(Struct->Type27->DeviceTypeAndStatus), Option);
+ PRINT_STRUCT_VALUE_H (Struct, Type27, CoolingUnitGroup);
+ PRINT_STRUCT_VALUE_H (Struct, Type27, OEMDefined);
+ PRINT_STRUCT_VALUE_H (Struct, Type27, NominalSpeed);
+ if (AE_SMBIOS_VERSION (0x2, 0x7) && (Struct->Hdr->Length > 0xE)) {
+ PRINT_PENDING_STRING (Struct, Type27, Description);
+ }
+ break;
+
+ //
+ // Temperature Probe (Type 28)
+ //
+ case 28:
+ PRINT_PENDING_STRING (Struct, Type28, Description);
+ DisplayTemperatureProbeStatus (*(UINT8 *) &(Struct->Type28->LocationAndStatus), Option);
+ DisplayTemperatureProbeLoc (*(UINT8 *) &(Struct->Type28->LocationAndStatus), Option);
+ PRINT_STRUCT_VALUE_H (Struct, Type28, MaximumValue);
+ PRINT_STRUCT_VALUE_H (Struct, Type28, MinimumValue);
+ PRINT_STRUCT_VALUE_H (Struct, Type28, Resolution);
+ PRINT_STRUCT_VALUE_H (Struct, Type28, Tolerance);
+ PRINT_STRUCT_VALUE_H (Struct, Type28, Accuracy);
+ PRINT_STRUCT_VALUE_H (Struct, Type28, OEMDefined);
+ PRINT_STRUCT_VALUE_H (Struct, Type28, NominalValue);
+ break;
+
+ //
+ // Electrical Current Probe (Type 29)
+ //
+ case 29:
+ PRINT_PENDING_STRING (Struct, Type29, Description);
+ DisplayECPStatus (*(UINT8 *) &(Struct->Type29->LocationAndStatus), Option);
+ DisplayECPLoc (*(UINT8 *) &(Struct->Type29->LocationAndStatus), Option);
+ PRINT_STRUCT_VALUE_H (Struct, Type29, MaximumValue);
+ PRINT_STRUCT_VALUE_H (Struct, Type29, MinimumValue);
+ PRINT_STRUCT_VALUE_H (Struct, Type29, Resolution);
+ PRINT_STRUCT_VALUE_H (Struct, Type29, Tolerance);
+ PRINT_STRUCT_VALUE_H (Struct, Type29, Accuracy);
+ PRINT_STRUCT_VALUE_H (Struct, Type29, OEMDefined);
+ PRINT_STRUCT_VALUE_H (Struct, Type29, NominalValue);
+ break;
+
+ //
+ // Out-of-Band Remote Access (Type 30)
+ //
+ case 30:
+ PRINT_PENDING_STRING (Struct, Type30, ManufacturerName);
+ DisplayOBRAConnections (Struct->Type30->Connections, Option);
+ break;
+
+ //
+ // Boot Integrity Services (BIS) Entry Point (Type 31)
+ //
+ case 31:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_STRUCT_TYPE31), gShellDebug1HiiHandle);
+ break;
+
+ //
+ // System Boot Information (Type 32)
+ //
+ case 32:
+ PRINT_BIT_FIELD (Struct, Type32, Reserved, 6);
+ DisplaySystemBootStatus (Struct->Type32->BootStatus, Option);
+ break;
+
+ //
+ // 64-Bit Memory Error Information (Type 33)
+ //
+ case 33:
+ DisplayMemoryErrorType (Struct->Type33->ErrorType, Option);
+ DisplayMemoryErrorGranularity (
+ Struct->Type33->ErrorGranularity,
+ Option
+ );
+ DisplayMemoryErrorOperation (Struct->Type33->ErrorOperation, Option);
+ PRINT_STRUCT_VALUE_H (Struct, Type33, VendorSyndrome);
+ PRINT_STRUCT_VALUE_LH (Struct, Type33, MemoryArrayErrorAddress);
+ PRINT_STRUCT_VALUE_LH (Struct, Type33, DeviceErrorAddress);
+ PRINT_STRUCT_VALUE_H (Struct, Type33, ErrorResolution);
+ break;
+
+ //
+ // Management Device (Type 34)
+ //
+ case 34:
+ PRINT_PENDING_STRING (Struct, Type34, Description);
+ DisplayMDType (Struct->Type34->Type, Option);
+ PRINT_STRUCT_VALUE_H (Struct, Type34, Address);
+ DisplayMDAddressType (Struct->Type34->AddressType, Option);
+ break;
+
+ //
+ // Management Device Component (Type 35)
+ //
+ case 35:
+ PRINT_PENDING_STRING (Struct, Type35, Description);
+ PRINT_STRUCT_VALUE_H (Struct, Type35, ManagementDeviceHandle);
+ PRINT_STRUCT_VALUE_H (Struct, Type35, ComponentHandle);
+ PRINT_STRUCT_VALUE_H (Struct, Type35, ThresholdHandle);
+ break;
+
+ //
+ // Management Device Threshold Data (Type 36)
+ //
+ case 36:
+ PRINT_STRUCT_VALUE_H (Struct, Type36, LowerThresholdNonCritical);
+ PRINT_STRUCT_VALUE_H (Struct, Type36, UpperThresholdNonCritical);
+ PRINT_STRUCT_VALUE_H (Struct, Type36, LowerThresholdCritical);
+ PRINT_STRUCT_VALUE_H (Struct, Type36, UpperThresholdCritical);
+ PRINT_STRUCT_VALUE_H (Struct, Type36, LowerThresholdNonRecoverable);
+ PRINT_STRUCT_VALUE_H (Struct, Type36, UpperThresholdNonRecoverable);
+ break;
+
+ //
+ // Memory Channel (Type 37)
+ //
+ case 37:
+ {
+ UINT8 Count;
+ MEMORY_DEVICE *Ptr;
+ DisplayMemoryChannelType (Struct->Type37->ChannelType, Option);
+ PRINT_STRUCT_VALUE_H (Struct, Type37, MaximumChannelLoad);
+ PRINT_STRUCT_VALUE_H (Struct, Type37, MemoryDeviceCount);
+
+ Count = Struct->Type37->MemoryDeviceCount;
+ Ptr = Struct->Type37->MemoryDevice;
+ for (Index = 0; Index < Count; Index++) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MEM_DEVICE), gShellDebug1HiiHandle, Index + 1);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DEV_LOAD), gShellDebug1HiiHandle, Ptr[Index].DeviceLoad);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DEV_HANDLE), gShellDebug1HiiHandle, Ptr[Index].DeviceHandle);
+ }
+ }
+ break;
+
+ //
+ // IPMI Device Information (Type 38)
+ //
+ case 38:
+ DisplayIPMIDIBMCInterfaceType (Struct->Type38->InterfaceType, Option);
+ PRINT_STRUCT_VALUE_H (Struct, Type38, IPMISpecificationRevision);
+ PRINT_STRUCT_VALUE_H (Struct, Type38, I2CSlaveAddress);
+ PRINT_STRUCT_VALUE_H (Struct, Type38, NVStorageDeviceAddress);
+ PRINT_STRUCT_VALUE_LH (Struct, Type38, BaseAddress);
+ break;
+
+ //
+ // System Power Supply (Type 39)
+ //
+ case 39:
+ PRINT_STRUCT_VALUE_H (Struct, Type39, PowerUnitGroup);
+ PRINT_PENDING_STRING (Struct, Type39, Location);
+ PRINT_PENDING_STRING (Struct, Type39, DeviceName);
+ PRINT_PENDING_STRING (Struct, Type39, Manufacturer);
+ PRINT_PENDING_STRING (Struct, Type39, SerialNumber);
+ PRINT_PENDING_STRING (Struct, Type39, AssetTagNumber);
+ PRINT_PENDING_STRING (Struct, Type39, ModelPartNumber);
+ PRINT_PENDING_STRING (Struct, Type39, RevisionLevel);
+ PRINT_STRUCT_VALUE_H (Struct, Type39, MaxPowerCapacity);
+ DisplaySPSCharacteristics (
+ *(UINT16 *) &(Struct->Type39->PowerSupplyCharacteristics),
+ Option
+ );
+ PRINT_STRUCT_VALUE_H (Struct, Type39, InputVoltageProbeHandle);
+ PRINT_STRUCT_VALUE_H (Struct, Type39, CoolingDeviceHandle);
+ PRINT_STRUCT_VALUE_H (Struct, Type39, InputCurrentProbeHandle);
+ break;
+
+ //
+ // Additional Information (Type 40)
+ //
+ case 40:
+ {
+ UINT8 NumberOfEntries;
+ UINT8 EntryLength;
+ ADDITIONAL_INFORMATION_ENTRY *Entries;
+
+ EntryLength = 0;
+ Entries = Struct->Type40->AdditionalInfoEntries;
+ NumberOfEntries = Struct->Type40->NumberOfAdditionalInformationEntries;
+
+ PRINT_STRUCT_VALUE_H (Struct, Type40, NumberOfAdditionalInformationEntries);
+
+ for (Index = 0; Index < NumberOfEntries; Index++) {
+ EntryLength = Entries->EntryLength;
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_ENTRYLEN), gShellDebug1HiiHandle, EntryLength);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_REFERENCEDHANDLE), gShellDebug1HiiHandle, Entries->ReferencedHandle);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_REFERENCEDOFFSET), gShellDebug1HiiHandle, Entries->ReferencedOffset);
+ PRINT_SMBIOS_STRING (Struct, Entries->EntryString, String);
+ PRINT_SMBIOS_BIT_FIELD (Struct, Entries->Value, Value, EntryLength - 5);
+ Entries = (ADDITIONAL_INFORMATION_ENTRY *) ((UINT8 *)Entries + EntryLength);
+ }
+ }
+ break;
+
+ //
+ // Onboard Devices Extended Information (Type 41)
+ //
+ case 41:
+ PRINT_PENDING_STRING (Struct, Type41, ReferenceDesignation);
+ ShellPrintEx(-1,-1,(((Struct->Type41->DeviceType) & 0x80) != 0) ? L"Device Enabled\n": L"Device Disabled\n");
+ DisplayOnboardDeviceTypes ((Struct->Type41->DeviceType) & 0x7F, Option);
+ PRINT_STRUCT_VALUE_H (Struct, Type41, DeviceTypeInstance);
+ PRINT_STRUCT_VALUE_H (Struct, Type41, SegmentGroupNum);
+ PRINT_STRUCT_VALUE_H (Struct, Type41, BusNum);
+ PRINT_STRUCT_VALUE_H (Struct, Type41, DevFuncNum);
+ break;
+
+ //
+ // Management Controller Host Interface (Type 42)
+ //
+ case 42:
+ PRINT_STRUCT_VALUE_H (Struct, Type42, InterfaceType);
+ break;
+
+ //
+ // Inactive (Type 126)
+ //
+ case 126:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INACTIVE_STRUCT), gShellDebug1HiiHandle);
+ break;
+
+ //
+ // End-of-Table (Type 127)
+ //
+ case 127:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_THIS_STRUCT_END_TABLE), gShellDebug1HiiHandle);
+ break;
+
+ default:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_STRUCT_TYPE_UNDEFINED), gShellDebug1HiiHandle);
+ break;
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Display BIOS Information (Type 0) information.
+
+ @param[in] Chara The information bits.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayBiosCharacteristics (
+ IN UINT64 Chara,
+ IN UINT8 Option
+ )
+{
+ //
+ // Print header
+ //
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIOS_CHAR), gShellDebug1HiiHandle);
+ //
+ // print option
+ //
+ PRINT_INFO_OPTION (Chara, Option);
+
+ //
+ // Check all the bits and print information
+ // This function does not use Table because table of bits
+ // are designed not to deal with UINT64
+ //
+ if (BIT (Chara, 0) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_RESERVED_BIT), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 1) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_RESERVED_BIT), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 2) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNKNOWN_BIT), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 3) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIOS_CHAR_NOT_SUPPORTED), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 4) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ISA_SUPPORTED), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 5) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MSA_SUPPORTED), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 6) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_EISA_SUPPORTED), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 7) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PCI_SUPPORTED), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 8) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PC_CARD_SUPPORTED), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 9) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PLUG_PLAY_SUPPORTED), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 10) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_APM_SUPPORTED), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 11) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIOS_UPGRADEABLE), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 12) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIOS_SHADOWING), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 13) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_VESA_SUPPORTED), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 14) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ECSD_SUPPORT), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 15) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BOOT_FORM_CD_SUPPORTED), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 16) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SELECTED_BOOT_SUPPORTED), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 17) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIOS_ROM_SOCKETED), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 18) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BOOT_FROM_PC_CARD), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 19) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_EDD_ENHANCED_DRIVER), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 20) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_JAPANESE_FLOPPY_NEC), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 21) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_JAPANESE_FLOPPY_TOSHIBA), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 22) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_FLOPPY_SERVICES_SUPPORTED), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 23) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ONE_POINT_TWO_MB), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 24) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_720_KB), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 25) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_TWO_POINT_EIGHT_EIGHT_MB), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 26) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PRINT_SCREEN_SUPPORT), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 27) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_KEYBOARD_SERV_SUPPORT), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 28) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SERIAL_SERVICES_SUPPORT), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 29) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PRINTER_SERVICES_SUPPORT), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 30) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MONO_VIDEO_SUPPORT), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Chara, 31) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NEC_PC_98), gShellDebug1HiiHandle);
+ }
+ //
+ // Just print the Reserved
+ //
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BITS_32_47), gShellDebug1HiiHandle);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BITS_48_64), gShellDebug1HiiHandle);
+}
+
+/**
+ Display Bios Characteristice extensions1 information.
+
+ @param[in] Byte1 The information.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayBiosCharacteristicsExt1 (
+ IN UINT8 Byte1,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIOS_CHAR_EXTENSION), gShellDebug1HiiHandle);
+ //
+ // Print option
+ //
+ PRINT_INFO_OPTION (Byte1, Option);
+
+ //
+ // check bit and print
+ //
+ if (BIT (Byte1, 0) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ACPI_SUPPORTED), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Byte1, 1) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_USB_LEGACY_SUPPORTED), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Byte1, 2) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AGP_SUPPORTED), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Byte1, 3) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_I2O_BOOT_SUPPORTED), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Byte1, 4) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_LS_120_BOOT_SUPPORTED), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Byte1, 5) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ATAPI_ZIP_DRIVE), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Byte1, 6) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_1394_BOOT_SUPPORTED), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Byte1, 7) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SMART_BATTERY_SUPPORTED), gShellDebug1HiiHandle);
+ }
+}
+
+/**
+ Display Bios Characteristice extensions2 information.
+
+ @param[in] byte2 The information.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayBiosCharacteristicsExt2 (
+ IN UINT8 byte2,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIOS_CHAR_EXTENSION_2), gShellDebug1HiiHandle);
+ //
+ // Print option
+ //
+ PRINT_INFO_OPTION (byte2, Option);
+
+ if (BIT (byte2, 0) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIOS_BOOT_SPEC_SUPP), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (byte2, 1) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_FUNCTION_KEY_INIT), gShellDebug1HiiHandle);
+ }
+
+ if (AE_SMBIOS_VERSION (0x2, 0x4)) {
+ if (BIT (byte2, 2) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ENABLE_TAR_CONT_DIST), gShellDebug1HiiHandle);
+ }
+ if (AE_SMBIOS_VERSION (0x2, 0x7)) {
+ if (BIT (byte2, 3) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UEFI_SPEC_SUPPORT), gShellDebug1HiiHandle);
+ }
+ if (BIT (byte2, 4) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_VIRTUAL_MACHINE), gShellDebug1HiiHandle);
+ }
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BITS_RSVD_FOR_FUTURE), gShellDebug1HiiHandle, 5);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BITS_RSVD_FOR_FUTURE), gShellDebug1HiiHandle, 3);
+ }
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BITS_RSVD_FOR_FUTURE), gShellDebug1HiiHandle, 2);
+ }
+}
+
+/**
+ Display Processor Information (Type 4) information.
+
+ @param[in] Family The family value.
+ @param[in] Option The option value.
+**/
+VOID
+DisplayProcessorFamily (
+ UINT8 Family,
+ UINT8 Option
+ )
+{
+ //
+ // Print prompt message
+ //
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PROCESSOR_FAMILY), gShellDebug1HiiHandle);
+ //
+ // Print option
+ //
+ PRINT_INFO_OPTION (Family, Option);
+
+ //
+ // Use switch to check
+ //
+ switch (Family) {
+ case 0x01:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_OTHER), gShellDebug1HiiHandle);
+ break;
+
+ case 0x02:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNKNOWN), gShellDebug1HiiHandle);
+ break;
+
+ case 0x03:
+ Print (L"8086\n");
+ break;
+
+ case 0x04:
+ Print (L"80286\n");
+ break;
+
+ case 0x05:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL386_PROCESSOR), gShellDebug1HiiHandle);
+ break;
+
+ case 0x06:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL486_PROCESSOR), gShellDebug1HiiHandle);
+ break;
+
+ case 0x07:
+ Print (L"8087\n");
+ break;
+
+ case 0x08:
+ Print (L"80287\n");
+ break;
+
+ case 0x09:
+ Print (L"80387\n");
+ break;
+
+ case 0x0A:
+ Print (L"80487\n");
+ break;
+
+ case 0x0B:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PENTIUM_PROC_FAMILY), gShellDebug1HiiHandle);
+ break;
+
+ case 0x0C:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PENTIUM_PRO_PROC), gShellDebug1HiiHandle);
+ break;
+
+ case 0x0D:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PENTIUM_II_PROC), gShellDebug1HiiHandle);
+ break;
+
+ case 0x0E:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PENTIUM_PROC_MMX), gShellDebug1HiiHandle);
+ break;
+
+ case 0x0F:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CELERON_PROC), gShellDebug1HiiHandle);
+ break;
+
+ case 0x10:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PENTIUM_XEON_PROC), gShellDebug1HiiHandle);
+ break;
+
+ case 0x11:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PENTIUM_III_PROC), gShellDebug1HiiHandle);
+ break;
+
+ case 0x12:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_M1_FAMILY), gShellDebug1HiiHandle);
+ break;
+
+ case 0x13:
+ Print (L"M2 Family\n");
+ break;
+
+ case 0x14:
+ Print (L"Intel Celeron M\n");
+ break;
+
+ case 0x15:
+ Print (L"Intel Pentium 4 HT\n");
+ break;
+
+ case 0x18:
+ Print (L"AMD Duron\n");
+ break;
+
+ case 0x19:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_K5_FAMILY), gShellDebug1HiiHandle);
+ break;
+
+ case 0x1A:
+ Print (L"K6 Family\n");
+ break;
+
+ case 0x1B:
+ Print (L"K6-2\n");
+ break;
+
+ case 0x1C:
+ Print (L"K6-3\n");
+ break;
+
+ case 0x1D:
+ Print (L"AMD Althon Processor Family\n");
+ break;
+
+ case 0x1E:
+ Print (L"AMD 29000 Family\n");
+ break;
+
+ case 0x1F:
+ Print (L"K6-2+\n");
+ break;
+
+ case 0x20:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_PC_FAMILY), gShellDebug1HiiHandle);
+ break;
+
+ case 0x21:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_PC_601), gShellDebug1HiiHandle);
+ break;
+
+ case 0x22:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_PC_603), gShellDebug1HiiHandle);
+ break;
+
+ case 0x23:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_PC_603_PLUS), gShellDebug1HiiHandle);
+ break;
+
+ case 0x24:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_PC_604), gShellDebug1HiiHandle);
+ break;
+
+ case 0x25:
+ Print (L"Power PC 620\n");
+ break;
+
+ case 0x26:
+ Print (L"Power PC 704\n");
+ break;
+
+ case 0x27:
+ Print (L"Power PC 750\n");
+ break;
+
+ case 0x28:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE_DUO), gShellDebug1HiiHandle);
+ break;
+
+ case 0x29:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE_DUO_MOBILE), gShellDebug1HiiHandle);
+ break;
+
+ case 0x2A:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE_SOLO_MOBILE), gShellDebug1HiiHandle);
+ break;
+
+ case 0x2B:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_ATOM), gShellDebug1HiiHandle);
+ break;
+
+ case 0x30:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ALPHA_FAMILY_2), gShellDebug1HiiHandle);
+ break;
+
+ case 0x31:
+ Print (L"Alpha 21064\n");
+ break;
+
+ case 0x32:
+ Print (L"Alpha 21066\n");
+ break;
+
+ case 0x33:
+ Print (L"Alpha 21164\n");
+ break;
+
+ case 0x34:
+ Print (L"Alpha 21164PC\n");
+ break;
+
+ case 0x35:
+ Print (L"Alpha 21164a\n");
+ break;
+
+ case 0x36:
+ Print (L"Alpha 21264\n");
+ break;
+
+ case 0x37:
+ Print (L"Alpha 21364\n");
+ break;
+
+ case 0x38:
+ Print (L"AMD Turion II Ultra Dual-Core Mobile M Processor Family\n");
+ break;
+
+ case 0x39:
+ Print (L"AMD Turion II Dual-Core Mobile M Processor Family\n");
+ break;
+
+ case 0x3A:
+ Print (L"AMD Althon II Dual-Core M Processor Family\n");
+ break;
+
+ case 0x3B:
+ Print (L"AMD Opteron 6100 Series Processor\n");
+ break;
+
+ case 0x3C:
+ Print (L"AMD Opteron 4100 Series Processor\n");
+ break;
+
+ case 0x3D:
+ Print (L"AMD Opteron 6200 Series Processor\n");
+ break;
+
+ case 0x3E:
+ Print (L"AMD Opteron 4200 Series Processor\n");
+ break;
+
+ case 0x3F:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_FX_SERIES), gShellDebug1HiiHandle);
+ break;
+
+ case 0x40:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MIPS_FAMILY), gShellDebug1HiiHandle);
+ break;
+
+ case 0x41:
+ Print (L"MIPS R4000\n");
+ break;
+
+ case 0x42:
+ Print (L"MIPS R4200\n");
+ break;
+
+ case 0x43:
+ Print (L"MIPS R4400\n");
+ break;
+
+ case 0x44:
+ Print (L"MIPS R4600\n");
+ break;
+
+ case 0x45:
+ Print (L"MIPS R10000\n");
+ break;
+
+ case 0x46:
+ Print (L"AMD C-Series Processor\n");
+ break;
+
+ case 0x47:
+ Print (L"AMD E-Series Processor\n");
+ break;
+
+ case 0x48:
+ Print (L"AMD A-Series Processor\n");
+ break;
+
+ case 0x49:
+ Print (L"AMD G-Series Processor\n");
+ break;
+
+ case 0x4A:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_Z_SERIES), gShellDebug1HiiHandle);
+ break;
+
+ case 0x4B:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_R_SERIES), gShellDebug1HiiHandle);
+ break;
+
+ case 0x4C:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_4300_SERIES), gShellDebug1HiiHandle);
+ break;
+
+ case 0x4D:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_6300_SERIES), gShellDebug1HiiHandle);
+ break;
+
+ case 0x4E:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_3300_SERIES), gShellDebug1HiiHandle);
+ break;
+
+ case 0x4F:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_FIREPRO_SERIES), gShellDebug1HiiHandle);
+ break;
+
+ case 0x50:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SPARC_FAMILY), gShellDebug1HiiHandle);
+ break;
+
+ case 0x51:
+ Print (L"SuperSparc\n");
+ break;
+
+ case 0x52:
+ Print (L"microSparc II\n");
+ break;
+
+ case 0x53:
+ Print (L"microSparc IIep\n");
+ break;
+
+ case 0x54:
+ Print (L"UltraSparc\n");
+ break;
+
+ case 0x55:
+ Print (L"UltraSparc II\n");
+ break;
+
+ case 0x56:
+ Print (L"UltraSparcIIi\n");
+ break;
+
+ case 0x57:
+ Print (L"UltraSparcIII\n");
+ break;
+
+ case 0x58:
+ Print (L"UltraSparcIIIi\n");
+ break;
+
+ case 0x60:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_68040_FAMILY), gShellDebug1HiiHandle);
+ break;
+
+ case 0x61:
+ Print (L"68xx\n");
+ break;
+
+ case 0x62:
+ Print (L"68000\n");
+ break;
+
+ case 0x63:
+ Print (L"68010\n");
+ break;
+
+ case 0x64:
+ Print (L"68020\n");
+ break;
+
+ case 0x65:
+ Print (L"68030\n");
+ break;
+
+ case 0x70:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_HOBBIT_FAMILY), gShellDebug1HiiHandle);
+ break;
+
+ case 0x78:
+ Print (L"Crusoe TM5000\n");
+ break;
+
+ case 0x79:
+ Print (L"Crusoe TM3000\n");
+ break;
+
+ case 0x7A:
+ Print (L"Efficeon TM8000\n");
+ break;
+
+ case 0x80:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_WEITEK), gShellDebug1HiiHandle);
+ break;
+
+ case 0x82:
+ Print (L"Itanium\n");
+ break;
+
+ case 0x83:
+ Print (L"AMD Athlon64\n");
+ break;
+
+ case 0x84:
+ Print (L"AMD Opteron\n");
+ break;
+
+ case 0x85:
+ Print (L"AMD Sempron\n");
+ break;
+
+ case 0x86:
+ Print (L"AMD Turion64 Mobile\n");
+ break;
+
+ case 0x87:
+ Print (L"Dual-Core AMD Opteron\n");
+ break;
+
+ case 0x88:
+ Print (L"AMD Athlon 64X2 DualCore\n");
+ break;
+
+ case 0x89:
+ Print (L"AMD Turion 64X2 Mobile\n");
+ break;
+
+ case 0x8A:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_QUAD_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0x8B:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_THIRD_GENERATION), gShellDebug1HiiHandle);
+ break;
+
+ case 0x8C:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_PHENOM_FX_QUAD_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0x8D:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_PHENOM_X4_QUAD_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0x8E:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_PHENOM_X2_DUAL_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0x8F:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_ATHLON_X2_DUAL_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0x90:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PA_RISC_FAMILY), gShellDebug1HiiHandle);
+ break;
+
+ case 0x91:
+ Print (L"PA-RISC 8500\n");
+ break;
+
+ case 0x92:
+ Print (L"PA-RISC 8000\n");
+ break;
+
+ case 0x93:
+ Print (L"PA-RISC 7300LC\n");
+ break;
+
+ case 0x94:
+ Print (L"PA-RISC 7200\n");
+ break;
+
+ case 0x95:
+ Print (L"PA-RISC 7100LC\n");
+ break;
+
+ case 0x96:
+ Print (L"PA-RISC 7100\n");
+ break;
+
+ case 0xA0:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_V30_FAMILY), gShellDebug1HiiHandle);
+ break;
+
+ case 0xA1:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_3200_SERIES_QUAD_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xA2:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_3000_SERIES_DUAL_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xA3:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5300_SERIES_QUAD_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xA4:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5100_SERIES_DUAL_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xA5:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5000_SERIES_DUAL_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xA6:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_LV_DUAL_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xA7:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_ULV_DUAL_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xA8:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7100_SERIES_DUAL_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xA9:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5400_SERIES_QUAD_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xAA:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_QUAD_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xAB:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5200_SERIES_DUAL_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xAC:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7200_SERIES_DUAL_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xAD:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7300_SERIES_QUAD_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xAE:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7400_SERIES_QUAD_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xAF:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7400_SERIES_MULTI_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xB0:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PENTIUM_III_XEON), gShellDebug1HiiHandle);
+ break;
+
+ case 0xB1:
+ Print (L"Pentium III Processorwith Intel SpeedStep Technology\n");
+ break;
+
+ case 0xB2:
+ Print (L"Pentium 4 processor\n");
+ break;
+
+ case 0xB3:
+ Print (L"Intel Xeon Processor\n");
+ break;
+
+ case 0xB4:
+ Print (L"AS400 Family\n");
+ break;
+
+ case 0xB5:
+ Print (L"Intel Xeon processor MP\n");
+ break;
+
+ case 0xB6:
+ Print (L"AMD Althon XP Processor Family\n");
+ break;
+
+ case 0xB7:
+ Print (L"AMD Althon MP Promcessor Family\n");
+ break;
+
+ case 0xB8:
+ Print (L"Intel Itanium 2 processor\n");
+ break;
+
+ case 0xB9:
+ Print (L"Intel Penium M processor\n");
+ break;
+
+ case 0xBA:
+ Print (L"Intel Celeron D processor\n");
+ break;
+
+ case 0xBB:
+ Print (L"Intel Pentium D processor\n");
+ break;
+
+ case 0xBC:
+ Print (L"Intel Pentium Processor Extreme Edition\n");
+ break;
+
+ case 0xBD:
+ Print (L"Intel Core Solo Processor\n");
+ break;
+
+ case 0xBF:
+ Print (L"Intel Core 2 Duo Processor\n");
+ break;
+
+ case 0xC0:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE2_SOLO), gShellDebug1HiiHandle);
+ break;
+
+ case 0xC1:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE2_EXTREME), gShellDebug1HiiHandle);
+ break;
+
+ case 0xC2:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE2_QUAD), gShellDebug1HiiHandle);
+ break;
+
+ case 0xC3:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE2_EXTREME), gShellDebug1HiiHandle);
+ break;
+
+ case 0xC4:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE2_DUO_MOBILE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xC5:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE2_SOLO_MOBILE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xC6:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE_I7), gShellDebug1HiiHandle);
+ break;
+
+ case 0xC7:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_CELERON_DUAL_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xC8:
+ Print (L"IBM 390\n");
+ break;
+
+ case 0xC9:
+ Print (L"G4\n");
+ break;
+
+ case 0xCA:
+ Print (L"G5\n");
+ break;
+
+ case 0xCB:
+ Print (L"G6\n");
+ break;
+
+ case 0xCC:
+ Print (L"zArchitecture\n");
+ break;
+
+ case 0xCD:
+ Print (L"Intel Core i5 processor\n");
+ break;
+
+ case 0xCE:
+ Print (L"Intel Core i3 processor\n");
+ break;
+
+ case 0xD2:
+ Print (L"ViaC7M\n");
+ break;
+
+ case 0xD3:
+ Print (L"ViaC7D\n");
+ break;
+
+ case 0xD4:
+ Print (L"ViaC7\n");
+ break;
+
+ case 0xD5:
+ Print (L"Eden\n");
+ break;
+
+ case 0xD6:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_MULTI_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xD7:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_3_SERIES_DUAL_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xD8:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_3_SERIES_QUAD_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xDA:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5_SERIES_DUAL_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xDB:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5_SERIES_QUAD_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xDD:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7_SERIES_DUAL_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xDE:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7_SERIES_QUAD_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xDF:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7_SERIES_MULTI_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xE0:
+ Print (L"Multi-Core Intel Xeon processor 3400 Series\n");
+ break;
+
+ case 0xE4:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_3000_SERIES), gShellDebug1HiiHandle);
+ break;
+
+ case 0xE5:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_SEMPRON_II), gShellDebug1HiiHandle);
+ break;
+
+
+ case 0xE6:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_EMBEDDED_OPTERON_QUAD_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xE7:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_PHENOM_TRIPLE_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xE8:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_TURION_ULTRA_DUAL_CORE_MOBILE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xE9:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_TURION_DUAL_CORE_MOBILE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xEA:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_ATHLON_DUAL_CORE), gShellDebug1HiiHandle);
+ break;
+
+ case 0xEB:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AMD_SEMPRON_SI), gShellDebug1HiiHandle);
+ break;
+
+ case 0xEC:
+ Print (L"AMD Phenom II Processor Family\n");
+ break;
+
+ case 0xED:
+ Print (L"AMD Althon II Processor Family\n");
+ break;
+
+ case 0xEE:
+ Print (L"Six-Core AMD Opteron Processor Family\n");
+ break;
+
+ case 0xEF:
+ Print (L"AMD Sempron M Processor Family\n");
+ break;
+
+ case 0xFA:
+ Print (L"i860\n");
+ break;
+
+ case 0xFB:
+ Print (L"i960\n");
+ break;
+
+ default:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNDEFINED_PROC_FAMILY), gShellDebug1HiiHandle);
+ }
+ //
+ // end switch
+ //
+}
+
+/**
+ Display processor family information.
+
+ @param[in] Family2 The family value.
+ @param[in] Option The option value.
+**/
+VOID
+DisplayProcessorFamily2 (
+ IN UINT16 Family2,
+ IN UINT8 Option
+ )
+{
+ //
+ // Print prompt message
+ //
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PROCESSOR_FAMILY), gShellDebug1HiiHandle);
+
+ //
+ // Print option
+ //
+ PRINT_INFO_OPTION (Family2, Option);
+
+ //
+ // Use switch to check
+ //
+ switch (Family2) {
+ case 0x104:
+ Print (L"SH-3\n");
+ break;
+
+ case 0x105:
+ Print (L"SH-4\n");
+ break;
+
+ case 0x118:
+ Print (L"ARM\n");
+ break;
+
+ case 0x119:
+ Print (L"StrongARM\n");
+ break;
+
+ case 0x12C:
+ Print (L"6x86\n");
+ break;
+
+ case 0x12D:
+ Print (L"MediaGX\n");
+ break;
+
+ case 0x12E:
+ Print (L"MII\n");
+ break;
+
+ case 0x140:
+ Print (L"WinChip\n");
+ break;
+
+ case 0x15E:
+ Print (L"DSP\n");
+ break;
+
+ case 0x1F4:
+ Print (L"Video Processor\n");
+ break;
+
+ default:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNDEFINED_PROC_FAMILY), gShellDebug1HiiHandle);
+ }
+
+}
+
+/**
+ Display processor voltage information.
+
+ @param[in] Voltage The Voltage.
+ Bit 7 Set to 0, indicating 'legacy' mode for processor voltage
+ Bits 6:4 Reserved, must be zero
+ Bits 3:0 Voltage Capability.
+ A Set bit indicates that the voltage is supported.
+ Bit 0 - 5V
+ Bit 1 - 3.3V
+ Bit 2 - 2.9V
+ Bit 3 - Reserved, must be zero.
+
+ Note:
+ Setting of multiple bits indicates the socket is configurable
+ If bit 7 is set to 1, the remaining seven bits of the field are set to
+ contain the processor's current voltage times 10.
+ For example, the field value for a processor voltage of 1.8 volts would be
+ 92h = 80h + (1.8 * 10) = 80h + 18 = 80h +12h.
+
+ @param[in] Option The option.
+**/
+VOID
+DisplayProcessorVoltage (
+ IN UINT8 Voltage,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PROC_INFO), gShellDebug1HiiHandle);
+ //
+ // Print option
+ //
+ PRINT_INFO_OPTION (Voltage, Option);
+
+ if (BIT (Voltage, 7) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PROC_CURRENT_VOLTAGE), gShellDebug1HiiHandle, (Voltage - 0x80));
+ } else {
+ if (BIT (Voltage, 0) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_5V_SUPOPRTED), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Voltage, 1) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_33V_SUPPORTED), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Voltage, 2) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_29V_SUPPORTED), gShellDebug1HiiHandle);
+ }
+ //
+ // check the reserved zero bits:
+ //
+ if (BIT (Voltage, 3) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT3_NOT_ZERO), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Voltage, 4) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT4_NOT_ZERO), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Voltage, 5) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT5_NOT_ZERO), gShellDebug1HiiHandle);
+ }
+
+ if (BIT (Voltage, 6) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT6_NOT_ZERO), gShellDebug1HiiHandle);
+ }
+ }
+}
+
+/**
+ Display processor information.
+
+ @param[in] Status The status.
+Bit 7 Reserved, must be 0
+Bit 6 CPU Socket Populated
+ 1 - CPU Socket Populated
+ 0 - CPU Socket Unpopulated
+Bits 5:3 Reserved, must be zero
+Bits 2:0 CPU Status
+ 0h - Unknown
+ 1h - CPU Enabled
+ 2h - CPU Disabled by User via BIOS Setup
+ 3h - CPU Disabled By BIOS (POST Error)
+ 4h - CPU is Idle, waiting to be enabled.
+ 5-6h - Reserved
+ 7h - Other
+
+ @param[in] Option The option
+**/
+VOID
+DisplayProcessorStatus (
+ IN UINT8 Status,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PROC_STATUS), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Status, Option);
+
+ if (BIT (Status, 7) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT7_NOT_ZERO), gShellDebug1HiiHandle);
+ } else if (BIT (Status, 5) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT5_NOT_ZERO), gShellDebug1HiiHandle);
+ } else if (BIT (Status, 4) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT4_NOT_ZERO), gShellDebug1HiiHandle);
+ } else if (BIT (Status, 3) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT3_NOT_ZERO), gShellDebug1HiiHandle);
+ }
+ //
+ // Check BIT 6
+ //
+ if (BIT (Status, 6) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CPU_SOCKET_POPULATED), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CPU_SOCKET_UNPOPULATED), gShellDebug1HiiHandle);
+ }
+ //
+ // Check BITs 2:0
+ //
+ switch (Status & 0x07) {
+ case 0:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNKNOWN), gShellDebug1HiiHandle);
+ break;
+
+ case 1:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CPU_ENABLED), gShellDebug1HiiHandle);
+ break;
+
+ case 2:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CPU_DISABLED_BY_USER), gShellDebug1HiiHandle);
+ break;
+
+ case 3:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CPU_DIABLED_BY_BIOS), gShellDebug1HiiHandle);
+ break;
+
+ case 4:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CPU_IDLE), gShellDebug1HiiHandle);
+ break;
+
+ case 7:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_OTHERS), gShellDebug1HiiHandle);
+ break;
+
+ default:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_RESERVED), gShellDebug1HiiHandle);
+ }
+}
+
+/**
+ Display information about Memory Controller Information (Type 5).
+
+ @param[in] Size Memory size.
+ @param[in] SlotNum Which slot is this about.
+ @param[in] Option Option for the level of detail output required.
+**/
+VOID
+DisplayMaxMemoryModuleSize (
+ IN UINT8 Size,
+ IN UINT8 SlotNum,
+ IN UINT8 Option
+ )
+{
+ UINTN MaxSize;
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SIZE_LARGEST_MEM), gShellDebug1HiiHandle);
+ //
+ // MaxSize is determined by follow formula
+ //
+ MaxSize = (UINTN) 1 << Size;
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ONE_VAR_MB), gShellDebug1HiiHandle, MaxSize);
+
+ if (Option >= SHOW_DETAIL) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MAX_AMOUNT_MEM), gShellDebug1HiiHandle);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ONE_VAR_MB), gShellDebug1HiiHandle, MaxSize, SlotNum, MaxSize * SlotNum);
+ }
+}
+
+/**
+ Display information about memory configuration handles.
+
+ @param[in] Handles The buffer of handles to output info on.
+ @param[in] SlotNum The number of handles in the above buffer.
+ @param[in] Option Option for the level of detail output required.
+**/
+VOID
+DisplayMemoryModuleConfigHandles (
+ IN UINT16 *Handles,
+ IN UINT8 SlotNum,
+ IN UINT8 Option
+ )
+{
+ UINT8 Index;
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_HANDLES_CONTROLLED), gShellDebug1HiiHandle, SlotNum);
+
+ if (Option >= SHOW_DETAIL) {
+ //
+ // No handle, Handles is INVALID.
+ //
+ if (SlotNum == 0) {
+ return ;
+ }
+
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_HANDLES_LIST_CONTROLLED), gShellDebug1HiiHandle);
+ for (Index = 0; Index < SlotNum; Index++) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_HANDLE), gShellDebug1HiiHandle, Index + 1, Handles[Index]);
+ }
+ }
+}
+
+/**
+ Display Memory Module Information (Type 6).
+
+ @param[in] BankConnections
+ @param[in] Option
+**/
+VOID
+DisplayMmBankConnections (
+ IN UINT8 BankConnections,
+ IN UINT8 Option
+ )
+{
+ UINT8 High;
+ UINT8 Low;
+
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BANK_CONNECTIONS), gShellDebug1HiiHandle);
+ //
+ // Print option
+ //
+ PRINT_INFO_OPTION (BankConnections, Option);
+
+ //
+ // Divide it to high and low
+ //
+ High = (UINT8) (BankConnections & 0xF0);
+ Low = (UINT8) (BankConnections & 0x0F);
+ if (High != 0xF) {
+ if (Low != 0xF) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BANK_RAS), gShellDebug1HiiHandle, High, Low, High, Low);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BANK_RAS_2), gShellDebug1HiiHandle, High, High);
+ }
+ } else {
+ if (Low != 0xF) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BANK_RAS_2), gShellDebug1HiiHandle, Low, Low);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NO_BANKS_CONNECTED), gShellDebug1HiiHandle);
+ }
+ }
+}
+
+/**
+ Display memory informcation.
+
+ Bits 0:6 Size (n),
+ where 2**n is the size in MB with three special-case values:
+ 7Dh Not determinable (Installed Size only)
+ 7Eh Module is installed, but no memory has been enabled
+ 7Fh Not installed
+ Bit 7 Defines whether the memory module has a single- (0)
+ or double-bank (1) connection.
+
+ @param[in] Size - The size
+ @param[in] Option - The option
+**/
+VOID
+DisplayMmMemorySize (
+ IN UINT8 Size,
+ IN UINT8 Option
+ )
+{
+ UINT8 Value;
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MEMORY_SIZE), gShellDebug1HiiHandle);
+ //
+ // Print option
+ //
+ PRINT_INFO_OPTION (Size, Option);
+
+ //
+ // Get the low bits(0-6 bit)
+ //
+ Value = (UINT8) (Size & 0x7F);
+ if (Value == 0x7D) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MEM_SIZE_NOT_DETERMINABLE), gShellDebug1HiiHandle);
+ } else if (Value == 0x7E) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MODULE_INSTALLED), gShellDebug1HiiHandle);
+ } else if (Value == 0x7F) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NOT_INSTALLED), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MEM_SIZE), gShellDebug1HiiHandle, 1 << Value);
+ }
+
+ if (BIT (Size, 7) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MEM_MODULE_DOUBLE_BANK), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MEM_MODULE_SINGLE_BANK), gShellDebug1HiiHandle);
+ }
+}
+
+/**
+ Display Cache Configuration.
+
+ @param[in] CacheConfiguration Cache Configuration.
+Bits 15:10 Reserved, must be 0
+Bits 9:8 Operational Mode
+ 0h - Write Through
+ 1h - Write Back
+ 2h - Varies with Memory Address
+ 3h - Unknown
+Bit 7 Enabled/Disabled
+ 1 - Enabled
+ 0 - Disabled
+Bits 6:5 Location
+ 0h - Internal
+ 1h - External
+ 2h - Reserved
+ 3h - Unknown
+Bit 4 Reserved, must be zero
+Bit 3 Cache Socketed
+ 1 - Socketed
+ 0 - Unsocketed
+Bits 2:0 Cache Level
+ 1 through 8 (For example, an L1 cache would
+ use value 000b and an L3 cache would use 010b.)
+
+ @param[in] Option The option
+**/
+VOID
+DisplayCacheConfiguration (
+ IN UINT16 CacheConfiguration,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CACHE_CONFIGURATION), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (CacheConfiguration, Option);
+
+ if (BIT (CacheConfiguration, 15) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT15_NOT_ZERO), gShellDebug1HiiHandle);
+ } else if (BIT (CacheConfiguration, 14) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT14_NOT_ZERO), gShellDebug1HiiHandle);
+ } else if (BIT (CacheConfiguration, 13) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT13_NOT_ZERO), gShellDebug1HiiHandle);
+ } else if (BIT (CacheConfiguration, 12) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT12_NOT_ZERO), gShellDebug1HiiHandle);
+ } else if (BIT (CacheConfiguration, 11) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT11_NOT_ZERO), gShellDebug1HiiHandle);
+ } else if (BIT (CacheConfiguration, 10) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT10_NOT_ZERO), gShellDebug1HiiHandle);
+ } else if (BIT (CacheConfiguration, 4) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BIT4_NOT_ZERO), gShellDebug1HiiHandle);
+ }
+
+ //
+ // Check BITs 9:8
+ //
+ switch ((CacheConfiguration & 0x300) >> 8) {
+ case 0:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CACHE_WRITE_THROUGH), gShellDebug1HiiHandle);
+ break;
+
+ case 1:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CACHE_WRITE_BACK), gShellDebug1HiiHandle);
+ break;
+
+ case 2:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CACHE_VARIES_WITH_MEM_ADDR), gShellDebug1HiiHandle);
+ break;
+
+ case 3:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNKNOWN), gShellDebug1HiiHandle);
+ break;
+ }
+
+ //
+ // Check BIT 7
+ //
+ if (BIT (CacheConfiguration, 7) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ENABLED), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DISABLED), gShellDebug1HiiHandle);
+ }
+
+ //
+ // Check BITs 6:5
+ //
+ switch ((CacheConfiguration & 0x60) >> 5) {
+ case 0:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CACHE_INTERNAL), gShellDebug1HiiHandle);
+ break;
+
+ case 1:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CACHE_EXTERNAL), gShellDebug1HiiHandle);
+ break;
+
+ case 2:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_RESERVED), gShellDebug1HiiHandle);
+ break;
+
+ case 3:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNKNOWN), gShellDebug1HiiHandle);
+ break;
+ }
+
+ //
+ // Check BIT 3
+ //
+ if (BIT (CacheConfiguration, 3) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CACHE_SOCKETED), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CACHE_NOT_SOCKETED), gShellDebug1HiiHandle);
+ }
+
+
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CACHE_LEVEL), gShellDebug1HiiHandle, (CacheConfiguration & 0x07) + 1);
+}
+
+/**
+ The Slot ID field of the System Slot structure provides a mechanism to
+ correlate the physical attributes of the slot to its logical access method
+ (which varies based on the Slot Type field).
+
+ @param[in] SlotId - The slot ID
+ @param[in] SlotType - The slot type
+ @param[in] Option - The Option
+**/
+VOID
+DisplaySystemSlotId (
+ IN UINT16 SlotId,
+ IN UINT8 SlotType,
+ IN UINT8 Option
+ )
+{
+ //
+ // Display slot type first
+ //
+ DisplaySystemSlotType (SlotType, Option);
+
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SLOT_ID), gShellDebug1HiiHandle);
+ //
+ // print option
+ //
+ PRINT_INFO_OPTION (SlotType, Option);
+
+ switch (SlotType) {
+ //
+ // Slot Type: MCA
+ //
+ case 0x04:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_LOGICAL_MICRO_CHAN), gShellDebug1HiiHandle);
+ if (SlotId > 0 && SlotId < 15) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ONE_VAR_D), gShellDebug1HiiHandle, SlotId);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ERROR_NOT_1_15), gShellDebug1HiiHandle);
+ }
+ break;
+
+ //
+ // EISA
+ //
+ case 0x05:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_LOGICAL_EISA_NUM), gShellDebug1HiiHandle);
+ if (SlotId > 0 && SlotId < 15) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ONE_VAR_D), gShellDebug1HiiHandle, SlotId);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ERROR_NOT_1_15), gShellDebug1HiiHandle);
+ }
+ break;
+
+ //
+ // Slot Type: PCI
+ //
+ case 0x06:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_VALUE_PRESENT), gShellDebug1HiiHandle, SlotId);
+ break;
+
+ //
+ // PCMCIA
+ //
+ case 0x07:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_IDENTIFIES_ADAPTER_NUM), gShellDebug1HiiHandle, SlotId);
+ break;
+
+ //
+ // Slot Type: PCI-E
+ //
+ case 0xA5:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_VALUE_PRESENT), gShellDebug1HiiHandle, SlotId);
+ break;
+
+ default:
+ if ((SlotType >= 0x0E && SlotType <= 0x12) || (SlotType >= 0xA6 && SlotType <= 0xB6)){
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_VALUE_PRESENT), gShellDebug1HiiHandle, SlotId);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNDEFINED_SLOT_ID), gShellDebug1HiiHandle);
+ }
+ }
+}
+
+/**
+ Display System Boot Information (Type 32) information.
+
+ @param[in] Parameter The parameter.
+ @param[in] Option The options.
+**/
+VOID
+DisplaySystemBootStatus (
+ IN UINT8 Parameter,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SYSTEM_BOOT_STATUS), gShellDebug1HiiHandle);
+ //
+ // Print option
+ //
+ PRINT_INFO_OPTION (Parameter, Option);
+
+ //
+ // Check value and print
+ //
+ if (Parameter == 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NO_ERRORS_DETECTED), gShellDebug1HiiHandle);
+ } else if (Parameter == 1) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NO_BOOTABLE_MEDIA), gShellDebug1HiiHandle);
+ } else if (Parameter == 2) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NORMAL_OP_SYSTEM), gShellDebug1HiiHandle);
+ } else if (Parameter == 3) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_FIRMWARE_DETECTED), gShellDebug1HiiHandle);
+ } else if (Parameter == 4) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_OP_SYSTEM), gShellDebug1HiiHandle);
+ } else if (Parameter == 5) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_USER_REQUESTED_BOOT), gShellDebug1HiiHandle);
+ } else if (Parameter == 6) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SYSTEM_SECURITY_VIOLATION), gShellDebug1HiiHandle);
+ } else if (Parameter == 7) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PREV_REQ_IMAGE), gShellDebug1HiiHandle);
+ } else if (Parameter == 8) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_WATCHDOG_TIMER), gShellDebug1HiiHandle);
+ } else if (Parameter >= 9 && Parameter <= 127) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_RSVD_FUTURE_ASSIGNMENT), gShellDebug1HiiHandle);
+ } else if (Parameter >= 128 && Parameter <= 191) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_VENDOR_OEM_SPECIFIC), gShellDebug1HiiHandle);
+ } else if (Parameter >= 192) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_PRODUCT_SPEC_IMPLMENTATION), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ERROR_VALUE), gShellDebug1HiiHandle);
+ }
+}
+
+/**
+ Display Portable Battery (Type 22) information.
+
+ The date the cell pack was manufactured, in packed format:
+ Bits 15:9 Year, biased by 1980, in the range 0 to 127.
+ Bits 8:5 Month, in the range 1 to 12.
+ Bits 4:0 Date, in the range 1 to 31.
+ For example, 01 February 2000 would be identified as
+ 0010 1000 0100 0001b (0x2841).
+
+ @param[in] Date The date
+ @param[in] Option The option
+**/
+VOID
+DisplaySBDSManufactureDate (
+ IN UINT16 Date,
+ IN UINT8 Option
+ )
+{
+ UINTN Day;
+ UINTN Month;
+ UINTN Year;
+
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SBDS_MANUFACTURE_DATE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Date, Option);
+ //
+ // Print date
+ //
+ Day = Date & 0x001F;
+ Month = (Date & 0x01E0) >> 5;
+ Year = ((Date & 0xFE00) >> 9) + 1980;
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MONTH_DAY_YEAR), gShellDebug1HiiHandle, Day, Month, Year);
+
+}
+
+/**
+ Display System Reset (Type 23) information.
+
+
+Identifies the system-reset capabilities for the system.
+ Bits 7:6 Reserved for future assignment via this specification, set to 00b.
+ Bit 5 System contains a watchdog timer, either True (1) or False (0).
+ Bits 4:3 Boot Option on Limit.
+ Identifies the system action to be taken when the Reset Limit is reached, one of:
+ 00b Reserved, do not use.
+ 01b Operating system
+ 10b System utilities
+ 11b Do not rebootBits
+ 2:1 Boot Option. Indicates the action to be taken following a watchdog reset, one of:
+ 00b Reserved, do not use.
+ 01b Operating system
+ 10b System utilities
+ 11b Do not reboot
+ Bit 0 Status.
+ 1b The system reset is enabled by the user
+ 0b The system reset is not enabled by the user
+
+ @param[in] Reset Reset
+ @param[in] Option The option
+**/
+VOID
+DisplaySystemResetCapabilities (
+ IN UINT8 Reset,
+ IN UINT8 Option
+ )
+{
+ UINTN Temp;
+
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SYSTEM_RESET_CAPABILITIES), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Reset, Option);
+
+ //
+ // Check reserved bits 7:6
+ //
+ if ((Reset & 0xC0) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BITS_RESERVED_ZERO), gShellDebug1HiiHandle);
+ }
+ //
+ // Watch dog
+ //
+ if (BIT (Reset, 5) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_WATCHDOG_TIMER_2), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SYSTEM_NOT_CONTAIN_TIMER), gShellDebug1HiiHandle);
+ }
+ //
+ // Boot Option on Limit
+ //
+ Temp = (Reset & 0x18) >> 3;
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BOOT_OPTION_LIMIT), gShellDebug1HiiHandle);
+ switch (Temp) {
+ case 0:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_RESERVED), gShellDebug1HiiHandle);
+ break;
+
+ case 1:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_OP_SYSTEM_2), gShellDebug1HiiHandle);
+ break;
+
+ case 2:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SYSTEM_UTIL), gShellDebug1HiiHandle);
+ break;
+
+ case 3:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DO_NOT_REBOOT_BITS), gShellDebug1HiiHandle);
+ break;
+ }
+ //
+ // Boot Option
+ //
+ Temp = (Reset & 0x06) >> 1;
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BOOT_OPTION), gShellDebug1HiiHandle);
+ switch (Temp) {
+ case 0:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_RESERVED), gShellDebug1HiiHandle);
+ break;
+
+ case 1:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_OP_SYSTEM_2), gShellDebug1HiiHandle);
+ break;
+
+ case 2:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SYSTEM_UTIL), gShellDebug1HiiHandle);
+ break;
+
+ case 3:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DO_NOT_REBOOT), gShellDebug1HiiHandle);
+ break;
+ }
+ //
+ // Reset enable flag
+ //
+ if ((Reset & 0x01) != 0) {
+ Print (L"The system reset is enabled by the user\n");
+ } else {
+ Print (L"The system reset is disabled by the user\n");
+ }
+}
+
+/**
+ Display Hardware Security (Type 24) information.
+
+
+Identifies the password and reset status for the system:
+
+Bits 7:6 Power-on Password Status, one of:
+ 00b Disabled
+ 01b Enabled
+ 10b Not Implemented
+ 11b Unknown
+Bits 5:4 Keyboard Password Status, one of:
+ 00b Disabled
+ 01b Enabled
+ 10b Not Implemented
+ 11b Unknown
+Bits 3:2 Administrator Password Status, one of:
+ 00b Disabled
+ 01b Enabled
+ 10b Not Implemented
+ 11b Unknown
+Bits 1:0 Front Panel Reset Status, one of:
+ 00b Disabled
+ 01b Enabled
+ 10b Not Implemented
+ 11b Unknown
+
+ @param[in] Settings The device settings.
+ @param[in] Option The device options.
+**/
+VOID
+DisplayHardwareSecuritySettings (
+ IN UINT8 Settings,
+ IN UINT8 Option
+ )
+{
+ UINTN Temp;
+
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_HARDWARE_SECURITY_SET), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Settings, Option);
+
+ //
+ // Power-on Password Status
+ //
+ Temp = (Settings & 0xC0) >> 6;
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_ON_PASSWORD), gShellDebug1HiiHandle);
+ switch (Temp) {
+ case 0:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DISABLED), gShellDebug1HiiHandle);
+ break;
+
+ case 1:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ENABLED_NEWLINE), gShellDebug1HiiHandle);
+ break;
+
+ case 2:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NOT_IMPLEMENTED), gShellDebug1HiiHandle);
+ break;
+
+ case 3:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNKNOWN), gShellDebug1HiiHandle);
+ break;
+ }
+ //
+ // Keyboard Password Status
+ //
+ Temp = (Settings & 0x30) >> 4;
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_KEYBOARD_PASSWORD), gShellDebug1HiiHandle);
+ switch (Temp) {
+ case 0:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DISABLED), gShellDebug1HiiHandle);
+ break;
+
+ case 1:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ENABLED_NEWLINE), gShellDebug1HiiHandle);
+ break;
+
+ case 2:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NOT_IMPLEMENTED), gShellDebug1HiiHandle);
+ break;
+
+ case 3:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNKNOWN), gShellDebug1HiiHandle);
+ break;
+ }
+ //
+ // Administrator Password Status
+ //
+ Temp = (Settings & 0x0C) >> 2;
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ADMIN_PASSWORD_STATUS), gShellDebug1HiiHandle);
+ switch (Temp) {
+ case 0:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DISABLED), gShellDebug1HiiHandle);
+ break;
+
+ case 1:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ENABLED_NEWLINE), gShellDebug1HiiHandle);
+ break;
+
+ case 2:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NOT_IMPLEMENTED), gShellDebug1HiiHandle);
+ break;
+
+ case 3:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNKNOWN), gShellDebug1HiiHandle);
+ break;
+ }
+ //
+ // Front Panel Reset Status
+ //
+ Temp = Settings & 0x3;
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_FRONT_PANEL_RESET), gShellDebug1HiiHandle);
+ switch (Temp) {
+ case 0:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_DISABLED), gShellDebug1HiiHandle);
+ break;
+
+ case 1:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_ENABLED_NEWLINE), gShellDebug1HiiHandle);
+ break;
+
+ case 2:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NOT_IMPLEMENTED), gShellDebug1HiiHandle);
+ break;
+
+ case 3:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNKNOWN), gShellDebug1HiiHandle);
+ break;
+ }
+}
+
+/**
+ Display Out-of-Band Remote Access (Type 30) information.
+
+ @param[in] Connections The device characteristics.
+ @param[in] Option The device options.
+**/
+VOID
+DisplayOBRAConnections (
+ IN UINT8 Connections,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CONNECTIONS), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Connections, Option);
+
+ //
+ // Check reserved bits 7:2
+ //
+ if ((Connections & 0xFC) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BITS_RESERVED_ZERO_2), gShellDebug1HiiHandle);
+ }
+ //
+ // Outbound Connection
+ //
+ if (BIT (Connections, 1) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_OUTBOUND_CONN_ENABLED), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_OTUBOUND_CONN_DISABLED), gShellDebug1HiiHandle);
+ }
+ //
+ // Inbound Connection
+ //
+ if (BIT (Connections, 0) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INBOIUND_CONN_ENABLED), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INBOUND_CONN_DISABLED), gShellDebug1HiiHandle);
+ }
+}
+
+/**
+ Display System Power Supply (Type 39) information.
+
+ @param[in] Characteristics The device characteristics.
+ @param[in] Option The device options.
+**/
+VOID
+DisplaySPSCharacteristics (
+ IN UINT16 Characteristics,
+ IN UINT8 Option
+ )
+{
+ UINTN Temp;
+
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_CHAR), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Characteristics, Option);
+
+ //
+ // Check reserved bits 15:14
+ //
+ if ((Characteristics & 0xC000) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BITS_15_14_RSVD), gShellDebug1HiiHandle);
+ }
+ //
+ // Bits 13:10 - DMTF Power Supply Type
+ //
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_TYPE), gShellDebug1HiiHandle);
+ Temp = (Characteristics & 0x1C00) >> 10;
+ switch (Temp) {
+ case 1:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_OTHER_SPACE), gShellDebug1HiiHandle);
+ break;
+
+ case 2:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNKNOWN), gShellDebug1HiiHandle);
+ break;
+
+ case 3:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_LINEAR), gShellDebug1HiiHandle);
+ break;
+
+ case 4:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_SWITCHING), gShellDebug1HiiHandle);
+ break;
+
+ case 5:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_BATTERY), gShellDebug1HiiHandle);
+ break;
+
+ case 6:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UPS), gShellDebug1HiiHandle);
+ break;
+
+ case 7:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CONVERTER), gShellDebug1HiiHandle);
+ break;
+
+ case 8:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_REGULATOR), gShellDebug1HiiHandle);
+ break;
+
+ default:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_RESERVED_2), gShellDebug1HiiHandle);
+ }
+ //
+ // Bits 9:7 - Status
+ //
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_STATUS_DASH), gShellDebug1HiiHandle);
+ Temp = (Characteristics & 0x380) >> 7;
+ switch (Temp) {
+ case 1:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_OTHER_SPACE), gShellDebug1HiiHandle);
+ break;
+
+ case 2:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNKNOWN), gShellDebug1HiiHandle);
+ break;
+
+ case 3:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_OK), gShellDebug1HiiHandle);
+ break;
+
+ case 4:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NON_CRITICAL), gShellDebug1HiiHandle);
+ break;
+
+ case 5:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_CRITICAL_POWER_SUPPLY), gShellDebug1HiiHandle);
+ break;
+
+ default:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNDEFINED), gShellDebug1HiiHandle);
+ }
+ //
+ // Bits 6:3 - DMTF Input Voltage Range Switching
+ //
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_INPUT_VOLTAGE_RANGE), gShellDebug1HiiHandle);
+ Temp = (Characteristics & 0x78) >> 3;
+ switch (Temp) {
+ case 1:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_OTHER_SPACE), gShellDebug1HiiHandle);
+ break;
+
+ case 2:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_UNKNOWN), gShellDebug1HiiHandle);
+ break;
+
+ case 3:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_MANUAL), gShellDebug1HiiHandle);
+ break;
+
+ case 4:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_AUTO_SWITCH), gShellDebug1HiiHandle);
+ break;
+
+ case 5:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_WIDE_RANGE), gShellDebug1HiiHandle);
+ break;
+
+ case 6:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_NOT_APPLICABLE), gShellDebug1HiiHandle);
+ break;
+
+ default:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_RESERVED_3), gShellDebug1HiiHandle);
+ break;
+ }
+ //
+ // Power supply is unplugged from the wall
+ //
+ if (BIT (Characteristics, 2) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_UNPLUGGED), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_PLUGGED), gShellDebug1HiiHandle);
+ }
+ //
+ // Power supply is present
+ //
+ if (BIT (Characteristics, 1) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_PRESENT), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_NOT_PRESENT), gShellDebug1HiiHandle);
+ }
+ //
+ // hot replaceable
+ //
+ if (BIT (Characteristics, 0) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_REPLACE), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_NOT_REPLACE), gShellDebug1HiiHandle);
+ }
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/PrintInfo.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/PrintInfo.h
new file mode 100644
index 0000000000..50667b684c
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/PrintInfo.h
@@ -0,0 +1,423 @@
+/** @file
+ Module to clarify the element info of the smbios structure.
+
+ Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SMBIOS_PRINT_INFO_H_
+#define _SMBIOS_PRINT_INFO_H_
+
+#include <IndustryStandard/SmBios.h>
+
+extern UINT8 SmbiosMajorVersion;
+extern UINT8 SmbiosMinorVersion;
+
+#define SHOW_NONE 0x00
+#define SHOW_OUTLINE 0x01
+#define SHOW_NORMAL 0x02
+#define SHOW_DETAIL 0x03
+//
+// SHOW_ALL: WaitEnter() not wait input.
+//
+#define SHOW_ALL 0x04
+#define SHOW_STATISTICS 0x05
+
+#define AS_UINT16(pData) (*((UINT16 *) pData))
+#define AS_UINT32(pData) (*((UINT32 *) pData))
+#define AS_UINT64(pData) (*((UINT64 *) pData))
+
+/**
+ Print the info of EPS(Entry Point Structure).
+
+ @param[in] SmbiosTable Pointer to the SMBIOS table entry point.
+ @param[in] Option Display option.
+**/
+VOID
+SmbiosPrintEPSInfo (
+ IN SMBIOS_TABLE_ENTRY_POINT *SmbiosTable,
+ IN UINT8 Option
+ );
+
+/**
+ Print the info of 64-bit EPS(Entry Point Structure).
+
+ @param[in] SmbiosTable Pointer to the SMBIOS table entry point.
+ @param[in] Option Display option.
+**/
+VOID
+Smbios64BitPrintEPSInfo (
+ IN SMBIOS_TABLE_3_0_ENTRY_POINT *SmbiosTable,
+ IN UINT8 Option
+ );
+
+/**
+ This function print the content of the structure pointed by Struct.
+
+ @param[in] Struct Point to the structure to be printed.
+ @param[in] Option Print option of information detail.
+
+ @retval EFI_SUCCESS Successfully Printing this function.
+ @retval EFI_INVALID_PARAMETER Invalid Structure.
+ @retval EFI_UNSUPPORTED Unsupported.
+**/
+EFI_STATUS
+SmbiosPrintStructure (
+ IN SMBIOS_STRUCTURE_POINTER *Struct,
+ IN UINT8 Option
+ );
+
+/**
+ Display BIOS Information (Type 0) information.
+
+ @param[in] Chara The information bits.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayBiosCharacteristics (
+ IN UINT64 Chara,
+ IN UINT8 Option
+ );
+
+/**
+ Display Bios Characteristice extensions1 information.
+
+ @param[in] Byte1 The information.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayBiosCharacteristicsExt1 (
+ IN UINT8 Byte1,
+ IN UINT8 Option
+ );
+
+/**
+ Display Bios Characteristice extensions2 information.
+
+ @param[in] Byte2 The information.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayBiosCharacteristicsExt2 (
+ IN UINT8 Byte2,
+ IN UINT8 Option
+ );
+
+/**
+ Display Processor Information (Type 4) information.
+
+ @param[in] Family The family value.
+ @param[in] Option The option value.
+**/
+VOID
+DisplayProcessorFamily (
+ UINT8 Family,
+ UINT8 Option
+ );
+
+/**
+ Display processor family information.
+
+ @param[in] Family2 The family value.
+ @param[in] Option The option value.
+**/
+VOID
+DisplayProcessorFamily2 (
+ IN UINT16 Family2,
+ IN UINT8 Option
+ );
+
+/**
+ Display processor voltage information.
+
+ @param[in] Voltage The Voltage.
+ Bit 7 Set to 0, indicating 'legacy' mode for processor voltage
+ Bits 6:4 Reserved, must be zero
+ Bits 3:0 Voltage Capability.
+ A Set bit indicates that the voltage is supported.
+ Bit 0 - 5V
+ Bit 1 - 3.3V
+ Bit 2 - 2.9V
+ Bit 3 - Reserved, must be zero.
+
+ Note:
+ Setting of multiple bits indicates the socket is configurable
+ If bit 7 is set to 1, the remaining seven bits of the field are set to
+ contain the processor's current voltage times 10.
+ For example, the field value for a processor voltage of 1.8 volts would be
+ 92h = 80h + (1.8 * 10) = 80h + 18 = 80h +12h.
+
+ @param[in] Option The option.
+**/
+VOID
+DisplayProcessorVoltage (
+ IN UINT8 Voltage,
+ IN UINT8 Option
+ );
+
+/**
+ Display processor information.
+
+ @param[in] Status The status.
+Bit 7 Reserved, must be 0
+Bit 6 CPU Socket Populated
+ 1 - CPU Socket Populated
+ 0 - CPU Socket Unpopulated
+Bits 5:3 Reserved, must be zero
+Bits 2:0 CPU Status
+ 0h - Unknown
+ 1h - CPU Enabled
+ 2h - CPU Disabled by User via BIOS Setup
+ 3h - CPU Disabled By BIOS (POST Error)
+ 4h - CPU is Idle, waiting to be enabled.
+ 5-6h - Reserved
+ 7h - Other
+
+ @param[in] Option The option
+**/
+VOID
+DisplayProcessorStatus (
+ IN UINT8 Status,
+ IN UINT8 Option
+ );
+
+/**
+ Display information about Memory Controller Information (Type 5).
+
+ @param[in] Size Memory size.
+ @param[in] SlotNum Which slot is this about.
+ @param[in] Option Option for the level of detail output required.
+**/
+VOID
+DisplayMaxMemoryModuleSize (
+ IN UINT8 Size,
+ IN UINT8 SlotNum,
+ IN UINT8 Option
+ );
+
+/**
+ Display information about memory configuration handles.
+
+ @param[in] Handles The buffer of handles to output info on.
+ @param[in] SlotNum The number of handles in the above buffer.
+ @param[in] Option Option for the level of detail output required.
+**/
+VOID
+DisplayMemoryModuleConfigHandles (
+ IN UINT16 *Handles,
+ IN UINT8 SlotNum,
+ IN UINT8 Option
+ );
+
+/**
+ Display Memory Module Information (Type 6).
+
+ @param[in] BankConnections
+ @param[in] Option
+**/
+VOID
+DisplayMmBankConnections (
+ IN UINT8 BankConnections,
+ IN UINT8 Option
+ );
+
+/**
+ Display memory informcation.
+
+ Bits 0:6 Size (n),
+ where 2**n is the size in MB with three special-case values:
+ 7Dh Not determinable (Installed Size only)
+ 7Eh Module is installed, but no memory has been enabled
+ 7Fh Not installed
+ Bit 7 Defines whether the memory module has a single- (0)
+ or double-bank (1) connection.
+
+ @param[in] Size - The size
+ @param[in] Option - The option
+**/
+VOID
+DisplayMmMemorySize (
+ IN UINT8 Size,
+ IN UINT8 Option
+ );
+
+/**
+ Display Cache Configuration.
+
+ @param[in] CacheConfiguration Cache Configuration.
+Bits 15:10 Reserved, must be 0
+Bits 9:8 Operational Mode
+ 0h - Write Through
+ 1h - Write Back
+ 2h - Varies with Memory Address
+ 3h - Unknown
+Bit 7 Enabled/Disabled
+ 1 - Enabled
+ 0 - Disabled
+Bits 6:5 Location
+ 0h - Internal
+ 1h - External
+ 2h - Reserved
+ 3h - Unknown
+Bit 4 Reserved, must be zero
+Bit 3 Cache Socketed
+ 1 - Socketed
+ 0 - Unsocketed
+Bits 2:0 Cache Level
+ 1 through 8 (For example, an L1 cache would
+ use value 000b and an L3 cache would use 010b.)
+
+ @param[in] Option The option
+**/
+VOID
+DisplayCacheConfiguration (
+ IN UINT16 CacheConfiguration,
+ IN UINT8 Option
+ );
+
+/**
+ The Slot ID field of the System Slot structure provides a mechanism to
+ correlate the physical attributes of the slot to its logical access method
+ (which varies based on the Slot Type field).
+
+ @param[in] SlotId - The slot ID
+ @param[in] SlotType - The slot type
+ @param[in] Option - The Option
+**/
+VOID
+DisplaySystemSlotId (
+ IN UINT16 SlotId,
+ IN UINT8 SlotType,
+ IN UINT8 Option
+ );
+
+/**
+ Display Portable Battery (Type 22) information.
+
+ The date the cell pack was manufactured, in packed format:
+ Bits 15:9 Year, biased by 1980, in the range 0 to 127.
+ Bits 8:5 Month, in the range 1 to 12.
+ Bits 4:0 Date, in the range 1 to 31.
+ For example, 01 February 2000 would be identified as
+ 0010 1000 0100 0001b (0x2841).
+
+ @param[in] Date The date
+ @param[in] Option The option
+**/
+VOID
+DisplaySBDSManufactureDate (
+ IN UINT16 Date,
+ IN UINT8 Option
+ );
+
+/**
+ Display System Reset (Type 23) information.
+
+ Routine Description:
+ Identifies the system-reset capabilities for the system.
+ Bits 7:6 Reserved for future assignment via this specification, set to 00b.
+ Bit 5 System contains a watchdog timer, either True (1) or False (0).
+ Bits 4:3 Boot Option on Limit.
+ Identifies the system action to be taken when the Reset Limit is reached, one of:
+ 00b Reserved, do not use.
+ 01b Operating system
+ 10b System utilities
+ 11b Do not rebootBits
+ 2:1 Boot Option. Indicates the action to be taken following a watchdog reset, one of:
+ 00b Reserved, do not use.
+ 01b Operating system
+ 10b System utilities
+ 11b Do not reboot
+ Bit 0 Status.
+ 1b The system reset is enabled by the user
+ 0b The system reset is not enabled by the user
+
+ @param[in] Reset Reset
+ @param[in] Option The option
+**/
+VOID
+DisplaySystemResetCapabilities (
+ IN UINT8 Reset,
+ IN UINT8 Option
+ );
+
+/**
+ Display Hardware Security (Type 24) information.
+
+ Routine Description:
+ Identifies the password and reset status for the system:
+
+ Bits 7:6 Power-on Password Status, one of:
+ 00b Disabled
+ 01b Enabled
+ 10b Not Implemented
+ 11b Unknown
+ Bits 5:4 Keyboard Password Status, one of:
+ 00b Disabled
+ 01b Enabled
+ 10b Not Implemented
+ 11b Unknown
+ Bits 3:2 Administrator Password Status, one of:
+ 00b Disabled
+ 01b Enabled
+ 10b Not Implemented
+ 11b Unknown
+ Bits 1:0 Front Panel Reset Status, one of:
+ 00b Disabled
+ 01b Enabled
+ 10b Not Implemented
+ 11b Unknown
+
+ @param[in] Settings The device settings.
+ @param[in] Option The device options.
+**/
+VOID
+DisplayHardwareSecuritySettings (
+ IN UINT8 Settings,
+ IN UINT8 Option
+ );
+
+/**
+ Display Out-of-Band Remote Access (Type 30) information.
+
+ @param[in] Connections The device characteristics.
+ @param[in] Option The device options.
+**/
+VOID
+DisplayOBRAConnections (
+ IN UINT8 Connections,
+ IN UINT8 Option
+ );
+
+/**
+ Display System Boot Information (Type 32) information.
+
+ @param[in] Parameter The parameter.
+ @param[in] Option The options.
+**/
+VOID
+DisplaySystemBootStatus (
+ IN UINT8 Parameter,
+ IN UINT8 Option
+ );
+
+/**
+ Display System Power Supply (Type 39) information.
+
+ @param[in] Characteristics The device characteristics.
+ @param[in] Option The device options.
+**/
+VOID
+DisplaySPSCharacteristics (
+ IN UINT16 Characteristics,
+ IN UINT8 Option
+ );
+
+#endif
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/QueryTable.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/QueryTable.c
new file mode 100644
index 0000000000..d0106c0b55
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/QueryTable.c
@@ -0,0 +1,4401 @@
+/** @file
+ Build a table, each item is (Key, Info) pair.
+ And give a interface of query a string out of a table.
+
+ Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "../UefiShellDebug1CommandsLib.h"
+#include "QueryTable.h"
+#include "PrintInfo.h"
+
+TABLE_ITEM SystemWakeupTypeTable[] = {
+ {
+ 0x0,
+ L" Reserved"
+ },
+ {
+ 0x1,
+ L" Other"
+ },
+ {
+ 0x2,
+ L" Unknown"
+ },
+ {
+ 0x3,
+ L" APM Timer"
+ },
+ {
+ 0x4,
+ L" Modem Ring"
+ },
+ {
+ 0x5,
+ L" LAN Remote"
+ },
+ {
+ 0x6,
+ L" Power Switch"
+ },
+ {
+ 0x7,
+ L" AC Power Restored"
+ }
+};
+
+TABLE_ITEM BaseBoardFeatureFlagsTable[] = {
+ {
+ 0,
+ L" Hosting board"
+ },
+ {
+ 1,
+ L" Requires at least one daughter board or auxiliary card"
+ },
+ {
+ 2,
+ L" Removable"
+ },
+ {
+ 3,
+ L" Replaceable"
+ },
+ {
+ 4,
+ L" Hot swappable"
+ }
+};
+
+TABLE_ITEM BaseBoardBoardTypeTable[] = {
+ {
+ 0x01,
+ L" Unknown"
+ },
+ {
+ 0x02,
+ L" Other"
+ },
+ {
+ 0x03,
+ L" Server Blade"
+ },
+ {
+ 0x04,
+ L" Connectivity Switch"
+ },
+ {
+ 0x05,
+ L" System Management Module"
+ },
+ {
+ 0x06,
+ L" Processor Module"
+ },
+ {
+ 0x07,
+ L" I/O Module"
+ },
+ {
+ 0x08,
+ L" Memory Module"
+ },
+ {
+ 0x09,
+ L" Daughter board"
+ },
+ {
+ 0x0A,
+ L" Motherboard"
+ },
+ {
+ 0x0B,
+ L" Processor/Memory Module"
+ },
+ {
+ 0x0C,
+ L" Processor/IO Module"
+ },
+ {
+ 0x0D,
+ L" Interconnect Board"
+ }
+};
+
+TABLE_ITEM SystemEnclosureTypeTable[] = {
+ {
+ 0x01,
+ L" Other"
+ },
+ {
+ 0x02,
+ L" Unknown"
+ },
+ {
+ 0x03,
+ L" Desktop"
+ },
+ {
+ 0x04,
+ L" Low Profile Desktop"
+ },
+ {
+ 0x05,
+ L" Pizza Box"
+ },
+ {
+ 0x06,
+ L" Mini Tower"
+ },
+ {
+ 0x07,
+ L" Tower"
+ },
+ {
+ 0x08,
+ L" Portable"
+ },
+ {
+ 0x09,
+ L" LapTop"
+ },
+ {
+ 0x0A,
+ L" Notebook"
+ },
+ {
+ 0x0B,
+ L" Hand Held"
+ },
+ {
+ 0x0C,
+ L" Docking Station"
+ },
+ {
+ 0x0D,
+ L" All in One"
+ },
+ {
+ 0x0E,
+ L" Sub Notebook"
+ },
+ {
+ 0x0F,
+ L" Space-saving"
+ },
+ {
+ 0x10,
+ L" Main Server Chassis"
+ },
+ {
+ 0x11,
+ L" Expansion Chassis"
+ },
+ {
+ 0x12,
+ L" SubChassis"
+ },
+ {
+ 0x13,
+ L" Sub Notebook"
+ },
+ {
+ 0x14,
+ L" Bus Expansion Chassis"
+ },
+ {
+ 0x15,
+ L" Peripheral Chassis"
+ },
+ {
+ 0x16,
+ L" RAID Chassis"
+ },
+ {
+ 0x17,
+ L" Rack Mount Chassis"
+ },
+ {
+ 0x18,
+ L" Sealed-case PC"
+ },
+ {
+ 0x19,
+ L" Multi-system Chassis"
+ },
+ {
+ 0x1A,
+ L" CompactPCI"
+ },
+ {
+ 0x1B,
+ L" AdvancedTCA"
+ },
+ {
+ 0x1C,
+ L" Blade"
+ },
+ {
+ 0x1D,
+ L" Blade Enclosure"
+ },
+};
+
+TABLE_ITEM SystemEnclosureStatusTable[] = {
+ {
+ 0x1,
+ L" Other"
+ },
+ {
+ 0x2,
+ L" Unknown"
+ },
+ {
+ 0x3,
+ L" Safe"
+ },
+ {
+ 0x4,
+ L" Warning"
+ },
+ {
+ 0x5,
+ L" Critical"
+ },
+ {
+ 0x6,
+ L" Non-recoverable"
+ }
+};
+
+TABLE_ITEM SESecurityStatusTable[] = {
+ {
+ 0x1,
+ L" Other"
+ },
+ {
+ 0x2,
+ L" Unknown"
+ },
+ {
+ 0x3,
+ L" None"
+ },
+ {
+ 0x4,
+ L" External interface locked out"
+ },
+ {
+ 0x5,
+ L" External interface enabled"
+ }
+};
+
+TABLE_ITEM ProcessorTypeTable[] = {
+ {
+ 0x1,
+ L" Other"
+ },
+ {
+ 0x2,
+ L" Unknown"
+ },
+ {
+ 0x3,
+ L" Central Processor"
+ },
+ {
+ 0x4,
+ L" Math Processor"
+ },
+ {
+ 0x5,
+ L" DSP Processor"
+ },
+ {
+ 0x6,
+ L" Video Processor "
+ },
+};
+
+TABLE_ITEM ProcessorUpgradeTable[] = {
+ {
+ 0x01,
+ L"Other"
+ },
+ {
+ 0x02,
+ L"Unknown"
+ },
+ {
+ 0x03,
+ L"Daughter Board"
+ },
+ {
+ 0x04,
+ L"ZIF Socket"
+ },
+ {
+ 0x05,
+ L"Replaceable Piggy Back"
+ },
+ {
+ 0x06,
+ L"None"
+ },
+ {
+ 0x07,
+ L"LIF Socket"
+ },
+ {
+ 0x08,
+ L"Slot 1"
+ },
+ {
+ 0x09,
+ L"Slot 2"
+ },
+ {
+ 0x0A,
+ L"370-pin socket"
+ },
+ {
+ 0x0B,
+ L"Slot A"
+ },
+ {
+ 0x0C,
+ L"Slot M"
+ },
+ {
+ 0x0D,
+ L"Socket 423"
+ },
+ {
+ 0x0E,
+ L"Socket A"
+ },
+ {
+ 0x0F,
+ L"Socket 478"
+ },
+ {
+ 0x10,
+ L"Socket 754"
+ },
+ {
+ 0x11,
+ L"Socket 940"
+ },
+ {
+ 0x12,
+ L"Socket 939"
+ },
+ {
+ 0x13,
+ L"Socket mPGA604"
+ },
+ {
+ 0x14,
+ L"Socket LGA771"
+ },
+ {
+ 0x15,
+ L"Socket LGA775"
+ },
+ {
+ 0x16,
+ L"Socket S1"
+ },
+ {
+ 0x17,
+ L"Socket AM2"
+ },
+ {
+ 0x18,
+ L"Socket F"
+ },
+ {
+ 0x19,
+ L"Socket LGA1366"
+ },
+ {
+ 0x1A,
+ L"Socket G34"
+ },
+ {
+ 0x1B,
+ L"Socket AM3"
+ },
+ {
+ 0x1C,
+ L"Socket C32"
+ },
+ {
+ 0x1D,
+ L"Socket LGA1156"
+ },
+ {
+ 0x1E,
+ L"Socket LGA1567"
+ },
+ {
+ 0x1F,
+ L"Socket PGA988A"
+ },
+ {
+ 0x20,
+ L"Socket BGA1288"
+ },
+ {
+ 0x21,
+ L"Socket rPGA988B"
+ },
+ {
+ 0x22,
+ L"Socket BGA1023"
+ },
+ {
+ 0x23,
+ L"Socket BGA1224"
+ },
+ {
+ 0x24,
+ L"Socket LGA1155"
+ },
+ {
+ 0x25,
+ L"Socket LGA1356"
+ },
+ {
+ 0x26,
+ L"Socket LGA2011"
+ },
+ {
+ 0x27,
+ L"Socket FS1"
+ },
+ {
+ 0x28,
+ L"Socket FS2"
+ },
+ {
+ 0x29,
+ L"Socket FM1"
+ },
+ {
+ 0x2A,
+ L"Socket FM2"
+ },
+ {
+ 0x2B,
+ L"Socket LGA2011-3"
+ },
+ {
+ 0x2C,
+ L"Socket LGA1356-3"
+ }
+};
+
+TABLE_ITEM ProcessorCharacteristicsTable[] = {
+ {
+ 1,
+ L" Unknown"
+ },
+ {
+ 2,
+ L" 64-bit Capable"
+ },
+ {
+ 3,
+ L" Multi-Core"
+ },
+ {
+ 4,
+ L" Hardware Thread"
+ },
+ {
+ 5,
+ L" Execute Protection"
+ },
+ {
+ 6,
+ L" Enhanced Virtualization"
+ },
+ {
+ 7,
+ L" Power/Performance Control"
+ }
+};
+
+
+TABLE_ITEM McErrorDetectMethodTable[] = {
+ {
+ 0x01,
+ L"Other"
+ },
+ {
+ 0x02,
+ L"Unknown"
+ },
+ {
+ 0x03,
+ L"None"
+ },
+ {
+ 0x04,
+ L"8-bit Parity"
+ },
+ {
+ 0x05,
+ L"32-bit ECC"
+ },
+ {
+ 0x06,
+ L"64-bit ECC"
+ },
+ {
+ 0x07,
+ L"128-bit ECC"
+ },
+ {
+ 0x08,
+ L"CRC"
+ },
+};
+
+TABLE_ITEM McErrorCorrectCapabilityTable[] = {
+ {
+ 0,
+ L"Other"
+ },
+ {
+ 1,
+ L"Unknown"
+ },
+ {
+ 2,
+ L"None"
+ },
+ {
+ 3,
+ L"Single Bit Error Correcting"
+ },
+ {
+ 4,
+ L"Double Bit Error Correcting"
+ },
+ {
+ 5,
+ L"Error Scrubbing"
+ },
+};
+
+TABLE_ITEM McInterleaveSupportTable[] = {
+ {
+ 0x01,
+ L"Other"
+ },
+ {
+ 0x02,
+ L"Unknown"
+ },
+ {
+ 0x03,
+ L"One Way Interleave"
+ },
+ {
+ 0x04,
+ L"Two Way Interleave"
+ },
+ {
+ 0x05,
+ L"Four Way Interleave"
+ },
+ {
+ 0x06,
+ L"Eight Way Interleave"
+ },
+ {
+ 0x07,
+ L"Sixteen Way Interleave"
+ }
+};
+
+TABLE_ITEM McMemorySpeedsTable[] = {
+ {
+ 0,
+ L" Other"
+ },
+ {
+ 1,
+ L" Unknown"
+ },
+ {
+ 2,
+ L" 70ns"
+ },
+ {
+ 3,
+ L" 60ns"
+ },
+ {
+ 4,
+ L" 50ns"
+ },
+};
+
+TABLE_ITEM MemoryModuleVoltageTable[] = {
+ {
+ 0,
+ L" 5V"
+ },
+ {
+ 1,
+ L" 3.3V"
+ },
+ {
+ 2,
+ L" 2.9V"
+ },
+};
+
+TABLE_ITEM MmMemoryTypeTable[] = {
+ {
+ 0,
+ L" Other"
+ },
+ {
+ 1,
+ L" Unknown"
+ },
+ {
+ 2,
+ L" Standard"
+ },
+ {
+ 3,
+ L" Fast Page Mode"
+ },
+ {
+ 4,
+ L" EDO"
+ },
+ {
+ 5,
+ L" Parity"
+ },
+ {
+ 6,
+ L" ECC "
+ },
+ {
+ 7,
+ L" SIMM"
+ },
+ {
+ 8,
+ L" DIMM"
+ },
+ {
+ 9,
+ L" Burst EDO"
+ },
+ {
+ 10,
+ L" SDRAM"
+ }
+};
+
+TABLE_ITEM MmErrorStatusTable[] = {
+ {
+ 0,
+ L" Uncorrectable errors received"
+ },
+ {
+ 1,
+ L" Correctable errors received"
+ },
+ {
+ 2,
+ L" Error Status obtained from the event log"
+ }
+};
+
+TABLE_ITEM CacheSRAMTypeTable[] = {
+ {
+ 0,
+ L" Other"
+ },
+ {
+ 1,
+ L" Unknown"
+ },
+ {
+ 2,
+ L" Non-Burst"
+ },
+ {
+ 3,
+ L" Burst"
+ },
+ {
+ 4,
+ L" Pipeline Burst"
+ },
+ {
+ 5,
+ L" Synchronous"
+ },
+ {
+ 6,
+ L" Asynchronous"
+ },
+};
+
+TABLE_ITEM CacheErrCorrectingTypeTable[] = {
+ {
+ 0x01,
+ L"Other"
+ },
+ {
+ 0x02,
+ L"Unknown"
+ },
+ {
+ 0x03,
+ L"None"
+ },
+ {
+ 0x04,
+ L"Parity"
+ },
+ {
+ 0x05,
+ L"Single-bit ECC"
+ },
+ {
+ 0x06,
+ L"Multi-bit ECC"
+ }
+};
+
+TABLE_ITEM CacheSystemCacheTypeTable[] = {
+ {
+ 0x01,
+ L"Other"
+ },
+ {
+ 0x02,
+ L"Unknown"
+ },
+ {
+ 0x03,
+ L"Instruction"
+ },
+ {
+ 0x04,
+ L"Data"
+ },
+ {
+ 0x05,
+ L"Unified"
+ }
+};
+
+TABLE_ITEM CacheAssociativityTable[] = {
+ {
+ 0x01,
+ L"Other"
+ },
+ {
+ 0x02,
+ L"Unknown"
+ },
+ {
+ 0x03,
+ L"Direct Mapped"
+ },
+ {
+ 0x04,
+ L"2-way Set-Associative"
+ },
+ {
+ 0x05,
+ L"4-way Set-Associative"
+ },
+ {
+ 0x06,
+ L"Fully Associative"
+ },
+ {
+ 0x07,
+ L"8-way Set-Associative"
+ },
+ {
+ 0x08,
+ L"16-way Set-Associative"
+ },
+ {
+ 0x09,
+ L"12-way Set-Associative"
+ },
+ {
+ 0x0A,
+ L"24-way Set-Associative"
+ },
+ {
+ 0x0B,
+ L"32-way Set-Associative"
+ },
+ {
+ 0x0C,
+ L"48-way Set-Associative"
+ },
+ {
+ 0x0D,
+ L"64-way Set-Associative"
+ },
+ {
+ 0x0E,
+ L"20-way Set-Associative"
+ }
+};
+
+TABLE_ITEM PortConnectorTypeTable[] = {
+ {
+ 0x00,
+ L"None"
+ },
+ {
+ 0x01,
+ L"Centronics"
+ },
+ {
+ 0x02,
+ L"Mini Centronics"
+ },
+ {
+ 0x03,
+ L"Proprietary"
+ },
+ {
+ 0x04,
+ L"DB-25 pin male"
+ },
+ {
+ 0x05,
+ L"DB-25 pin female"
+ },
+ {
+ 0x06,
+ L"DB-15 pin male"
+ },
+ {
+ 0x07,
+ L"DB-15 pin female"
+ },
+ {
+ 0x08,
+ L"DB-9 pin male"
+ },
+ {
+ 0x09,
+ L"DB-9 pin female"
+ },
+ {
+ 0x0A,
+ L"RJ-11"
+ },
+ {
+ 0x0B,
+ L"RJ-45"
+ },
+ {
+ 0x0C,
+ L"50 Pin MiniSCSI"
+ },
+ {
+ 0x0D,
+ L"Mini-DIN"
+ },
+ {
+ 0x0E,
+ L"Micro-DIN"
+ },
+ {
+ 0x0F,
+ L"PS/2"
+ },
+ {
+ 0x10,
+ L"Infrared"
+ },
+ {
+ 0x11,
+ L"HP-HIL"
+ },
+ {
+ 0x12,
+ L"Access Bus (USB)"
+ },
+ {
+ 0x13,
+ L"SSA SCSI"
+ },
+ {
+ 0x14,
+ L"Circular DIN-8 male"
+ },
+ {
+ 0x15,
+ L"Circular DIN-8 female"
+ },
+ {
+ 0x16,
+ L"On Board IDE"
+ },
+ {
+ 0x17,
+ L"On Board Floppy"
+ },
+ {
+ 0x18,
+ L"9 Pin Dual Inline (pin 10 cut)"
+ },
+ {
+ 0x19,
+ L"25 Pin Dual Inline (pin 26 cut)"
+ },
+ {
+ 0x1A,
+ L"50 Pin Dual Inline"
+ },
+ {
+ 0x1B,
+ L"68 Pin Dual Inline"
+ },
+ {
+ 0x1C,
+ L"On Board Sound Input from CD-ROM"
+ },
+ {
+ 0x1D,
+ L"Mini-Centronics Type-14"
+ },
+ {
+ 0x1E,
+ L"Mini-Centronics Type-26"
+ },
+ {
+ 0x1F,
+ L"Mini-jack (headphones)"
+ },
+ {
+ 0x20,
+ L"BNC"
+ },
+ {
+ 0x21,
+ L"1394"
+ },
+ {
+ 0x22,
+ L"SAS/SATA Plug Receptacle"
+ },
+ {
+ 0xA0,
+ L"PC-98"
+ },
+ {
+ 0xA1,
+ L"PC-98Hireso"
+ },
+ {
+ 0xA2,
+ L"PC-H98"
+ },
+ {
+ 0xA3,
+ L"PC-98Note"
+ },
+ {
+ 0xA4,
+ L"PC-98Full"
+ },
+ {
+ 0xFF,
+ L"Other"
+ },
+};
+
+TABLE_ITEM PortTypeTable[] = {
+ {
+ 0x00,
+ L"None"
+ },
+ {
+ 0x01,
+ L"Parallel Port XT/AT Compatible"
+ },
+ {
+ 0x02,
+ L"Parallel Port PS/2"
+ },
+ {
+ 0x03,
+ L"Parallel Port ECP"
+ },
+ {
+ 0x04,
+ L"Parallel Port EPP"
+ },
+ {
+ 0x05,
+ L"Parallel Port ECP/EPP"
+ },
+ {
+ 0x06,
+ L"Serial Port XT/AT Compatible"
+ },
+ {
+ 0x07,
+ L"Serial Port 16450 Compatible"
+ },
+ {
+ 0x08,
+ L"Serial Port 16550 Compatible"
+ },
+ {
+ 0x09,
+ L"Serial Port 16550A Compatible"
+ },
+ {
+ 0x0A,
+ L"SCSI Port"
+ },
+ {
+ 0x0B,
+ L"MIDI Port"
+ },
+ {
+ 0x0C,
+ L"Joy Stick Port"
+ },
+ {
+ 0x0D,
+ L"Keyboard Port"
+ },
+ {
+ 0x0E,
+ L"Mouse Port"
+ },
+ {
+ 0x0F,
+ L"SSA SCSI"
+ },
+ {
+ 0x10,
+ L"USB"
+ },
+ {
+ 0x11,
+ L"FireWire (IEEE P1394)"
+ },
+ {
+ 0x12,
+ L"PCMCIA Type II"
+ },
+ {
+ 0x13,
+ L"PCMCIA Type II"
+ },
+ {
+ 0x14,
+ L"PCMCIA Type III"
+ },
+ {
+ 0x15,
+ L"Cardbus"
+ },
+ {
+ 0x16,
+ L"Access Bus Port"
+ },
+ {
+ 0x17,
+ L"SCSI II"
+ },
+ {
+ 0x18,
+ L"SCSI Wide"
+ },
+ {
+ 0x19,
+ L"PC-98"
+ },
+ {
+ 0x1A,
+ L"PC-98-Hireso"
+ },
+ {
+ 0x1B,
+ L"PC-H98"
+ },
+ {
+ 0x1C,
+ L"Video Port"
+ },
+ {
+ 0x1D,
+ L"Audio Port"
+ },
+ {
+ 0x1E,
+ L"Modem Port"
+ },
+ {
+ 0x1F,
+ L"Network Port"
+ },
+ {
+ 0x20,
+ L"SATA Port"
+ },
+ {
+ 0x21,
+ L"SAS Port"
+ },
+ {
+ 0xA0,
+ L"8251 Compatible"
+ },
+ {
+ 0xA1,
+ L"8251 FIFO Compatible"
+ },
+ {
+ 0xFF,
+ L"Other "
+ },
+};
+
+TABLE_ITEM SystemSlotTypeTable[] = {
+ {
+ 0x01,
+ L"Other"
+ },
+ {
+ 0x02,
+ L"Unknown"
+ },
+ {
+ 0x03,
+ L"ISA"
+ },
+ {
+ 0x04,
+ L"MCA"
+ },
+ {
+ 0x05,
+ L"EISA"
+ },
+ {
+ 0x06,
+ L"PCI"
+ },
+ {
+ 0x07,
+ L"PC Card (PCMCIA)"
+ },
+ {
+ 0x08,
+ L"VL-VESA"
+ },
+ {
+ 0x09,
+ L"Proprietary"
+ },
+ {
+ 0x0A,
+ L"Processor Card Slot"
+ },
+ {
+ 0x0B,
+ L"Proprietary Memory Card Slot"
+ },
+ {
+ 0x0C,
+ L"I/O Riser Card Slot"
+ },
+ {
+ 0x0D,
+ L"NuBus"
+ },
+ {
+ 0x0E,
+ L"PCI - 66MHz Capable"
+ },
+ {
+ 0x0F,
+ L"AGP"
+ },
+ {
+ 0x10,
+ L"AGP 2X"
+ },
+ {
+ 0x11,
+ L"AGP 4X"
+ },
+ {
+ 0x12,
+ L"PCI-X"
+ },
+ {
+ 0xA0,
+ L"PC-98/C20 "
+ },
+ {
+ 0xA1,
+ L"PC-98/C24 "
+ },
+ {
+ 0xA2,
+ L"PC-98/E "
+ },
+ {
+ 0xA3,
+ L"PC-98/Local Bus "
+ },
+ {
+ 0xA4,
+ L"PC-98/Card "
+ },
+ {
+ 0xA5,
+ L"PCI Express "
+ },
+ {
+ 0xA6,
+ L"PCI Express X1"
+ },
+ {
+ 0xA7,
+ L"PCI Express X2"
+ },
+ {
+ 0xA8,
+ L"PCI Express X4"
+ },
+ {
+ 0xA9,
+ L"PCI Express X8"
+ },
+ {
+ 0xAA,
+ L"PCI Express X16"
+ },
+ {
+ 0xAB,
+ L"PCI Express Gen 2"
+ },
+ {
+ 0xAC,
+ L"PCI Express Gen 2 X1"
+ },
+ {
+ 0xAD,
+ L"PCI Express Gen 2 X2"
+ },
+ {
+ 0xAE,
+ L"PCI Express Gen 2 X4"
+ },
+ {
+ 0xAF,
+ L"PCI Express Gen 2 X8"
+ },
+ {
+ 0xB0,
+ L"PCI Express Gen 2 X16"
+ },
+ {
+ 0xB1,
+ L"PCI Express Gen 3"
+ },
+ {
+ 0xB2,
+ L"PCI Express Gen 3 X1"
+ },
+ {
+ 0xB3,
+ L"PCI Express Gen 3 X2"
+ },
+ {
+ 0xB4,
+ L"PCI Express Gen 3 X4"
+ },
+ {
+ 0xB5,
+ L"PCI Express Gen 3 X8"
+ },
+ {
+ 0xB6,
+ L"PCI Express Gen 3 X16"
+ }
+};
+
+TABLE_ITEM SystemSlotDataBusWidthTable[] = {
+ {
+ 0x01,
+ L" Other"
+ },
+ {
+ 0x02,
+ L" Unknown"
+ },
+ {
+ 0x03,
+ L" 8 bit"
+ },
+ {
+ 0x04,
+ L" 16 bit"
+ },
+ {
+ 0x05,
+ L" 32 bit"
+ },
+ {
+ 0x06,
+ L" 64 bit"
+ },
+ {
+ 0x07,
+ L" 128 bit"
+ },
+ {
+ 0x08,
+ L" 1x or x1"
+ },
+ {
+ 0x09,
+ L" 2x or x2"
+ },
+ {
+ 0x0A,
+ L" 4x or x4"
+ },
+ {
+ 0x0B,
+ L" 8x or x8"
+ },
+ {
+ 0x0C,
+ L" 12x or x12"
+ },
+ {
+ 0x0D,
+ L" 16x or x16"
+ },
+ {
+ 0x0E,
+ L" 32x or x32"
+ }
+};
+
+TABLE_ITEM SystemSlotCurrentUsageTable[] = {
+ {
+ 0x01,
+ L" Other"
+ },
+ {
+ 0x02,
+ L" Unknown"
+ },
+ {
+ 0x03,
+ L" Available"
+ },
+ {
+ 0x04,
+ L" In use"
+ },
+};
+
+TABLE_ITEM SystemSlotLengthTable[] = {
+ {
+ 0x01,
+ L" Other"
+ },
+ {
+ 0x02,
+ L" Unknown"
+ },
+ {
+ 0x03,
+ L" Short length"
+ },
+ {
+ 0x04,
+ L" Long Length"
+ },
+};
+
+TABLE_ITEM SlotCharacteristics1Table[] = {
+ {
+ 0,
+ L" Characteristics Unknown"
+ },
+ {
+ 1,
+ L" Provides 5.0 Volts"
+ },
+ {
+ 2,
+ L" Provides 3.3 Volts"
+ },
+ {
+ 3,
+ L" Slot's opening is shared with another slot, e.g. PCI/EISA shared slot."
+ },
+
+ {
+ 4,
+ L" PC Card slot supports PC Card-16"
+ },
+ {
+ 5,
+ L" PC Card slot supports CardBus"
+ },
+ {
+ 6,
+ L" PC Card slot supports Zoom Video "
+ },
+ {
+ 7,
+ L" PC Card slot supports Modem Ring Resume "
+ }
+};
+
+TABLE_ITEM SlotCharacteristics2Table[] = {
+ {
+ 0,
+ L" PCI slot supports Power Management Enable (PME#) signal"
+ },
+ {
+ 1,
+ L" Slot supports hot-plug devices"
+ },
+ {
+ 2,
+ L" PCI slot supports SMBus signal"
+ }
+};
+
+TABLE_ITEM OnboardDeviceTypesTable[] = {
+ {
+ 0x01,
+ L" Other"
+ },
+ {
+ 0x02,
+ L" Unknown"
+ },
+ {
+ 0x03,
+ L" Video"
+ },
+ {
+ 0x04,
+ L" SCSI Controller"
+ },
+ {
+ 0x05,
+ L" Ethernet"
+ },
+ {
+ 0x06,
+ L" Token Ring"
+ },
+ {
+ 0x07,
+ L" Sound"
+ },
+ {
+ 0x08,
+ L" Pata Controller"
+ },
+ {
+ 0x09,
+ L" Sata Controller"
+ },
+ {
+ 0x0A,
+ L" Sas Controller"
+ },
+};
+
+TABLE_ITEM SELTypesTable[] = {
+ {
+ 0x00,
+ L" Reserved."
+ },
+ {
+ 0x01,
+ L" Single-bit ECC memory error"
+ },
+ {
+ 0x02,
+ L" Multi-bit ECC memory error"
+ },
+ {
+ 0x03,
+ L" Parity memory error"
+ },
+ {
+ 0x04,
+ L" Bus time-out"
+ },
+ {
+ 0x05,
+ L" I/O Channel Check"
+ },
+ {
+ 0x06,
+ L" Software NMI"
+ },
+ {
+ 0x07,
+ L" POST Memory Resize"
+ },
+ {
+ 0x08,
+ L" POST Error"
+ },
+ {
+ 0x09,
+ L" PCI Parity Error"
+ },
+ {
+ 0x0A,
+ L" PCI System Error"
+ },
+ {
+ 0x0B,
+ L" CPU Failure"
+ },
+ {
+ 0x0C,
+ L" EISA FailSafe Timer time-out"
+ },
+ {
+ 0x0D,
+ L" Correctable memory log disabled"
+ },
+ {
+ 0x0E,
+ L" Logging disabled for a specific Event Type"
+ },
+ {
+ 0x0F,
+ L" Reserved"
+ },
+ {
+ 0x10,
+ L" System Limit Exceeded"
+ },
+ {
+ 0x11,
+ L" Asynchronous hardware timer expired and issued a system reset"
+ },
+ {
+ 0x12,
+ L" System configuration information"
+ },
+ {
+ 0x13,
+ L" Hard-disk information"
+ },
+ {
+ 0x14,
+ L" System reconfigured"
+ },
+ {
+ 0x15,
+ L" Uncorrectable CPU-complex error"
+ },
+ {
+ 0x16,
+ L" Log Area Reset/Cleared"
+ },
+ {
+ 0x17,
+ L" System boot"
+ },
+ {
+ 0x7F18,
+ L" Unused by SMBIOS specification"
+ },
+ {
+ 0xFE80,
+ L" System and OEM specified"
+ },
+ {
+ 0xFF,
+ L" End-of-log"
+ },
+};
+
+TABLE_ITEM SELVarDataFormatTypeTable[] = {
+ {
+ 0x00,
+ L" None "
+ },
+ {
+ 0x01,
+ L" Handle "
+ },
+ {
+ 0x02,
+ L" Multiple-Event "
+ },
+ {
+ 0x03,
+ L" Multiple-Event Handle "
+ },
+ {
+ 0x04,
+ L" POST Results Bitmap "
+ },
+ //
+ // Defined below
+ //
+ {
+ 0x05,
+ L" System Management Type"
+ },
+ //
+ // Defined below
+ //
+ {
+ 0x06,
+ L" Multiple-Event System Management Type "
+ },
+ {
+ 0x7F07,
+ L" Unused "
+ },
+ {
+ 0xFF80,
+ L" OEM assigned "
+ },
+};
+
+TABLE_ITEM PostResultsBitmapDw1Table[] = {
+ {
+ 0,
+ L" Channel 2 Timer error "
+ },
+ {
+ 1,
+ L" Master PIC (8259 #1) error "
+ },
+ {
+ 2,
+ L" Slave PIC (8259 #2) error "
+ },
+ {
+ 3,
+ L" CMOS Battery Failure "
+ },
+ {
+ 4,
+ L" CMOS System Options Not Set "
+ },
+ {
+ 5,
+ L" CMOS Checksum Error "
+ },
+ {
+ 6,
+ L" CMOS Configuration Error "
+ },
+ {
+ 7,
+ L" Mouse and Keyboard Swapped "
+ },
+ {
+ 8,
+ L" Keyboard Locked "
+ },
+ {
+ 9,
+ L" Keyboard Not Functional "
+ },
+ {
+ 10,
+ L" Keyboard Controller Not Functional "
+ },
+ {
+ 11,
+ L" CMOS Memory Size Different "
+ },
+ {
+ 12,
+ L" Memory Decreased in Size "
+ },
+ {
+ 13,
+ L" Cache Memory Error "
+ },
+ {
+ 14,
+ L" Floppy Drive 0 Error "
+ },
+ {
+ 15,
+ L" Floppy Drive 1 Error "
+ },
+ {
+ 16,
+ L" Floppy Controller Failure "
+ },
+ {
+ 17,
+ L" Number of ATA Drives Reduced Error "
+ },
+ {
+ 18,
+ L" CMOS Time Not Set "
+ },
+ {
+ 19,
+ L" DDC Monitor Configuration Change "
+ },
+ {
+ 20,
+ L" Reserved, set to 0 "
+ },
+ {
+ 21,
+ L" Reserved, set to 0 "
+ },
+ {
+ 22,
+ L" Reserved, set to 0 "
+ },
+ {
+ 23,
+ L" Reserved, set to 0 "
+ },
+ {
+ 24,
+ L" Second DWORD has valid data "
+ },
+ {
+ 25,
+ L" Reserved, set to 0 "
+ },
+ {
+ 26,
+ L" Reserved, set to 0 "
+ },
+ {
+ 27,
+ L" Reserved, set to 0 "
+ },
+ {
+ 28,
+ L" Normally 0; available for OEM assignment "
+ },
+ {
+ 29,
+ L" Normally 0; available for OEM assignment "
+ },
+ {
+ 30,
+ L" Normally 0; available for OEM assignment "
+ },
+ {
+ 31,
+ L" Normally 0; available for OEM assignment "
+ },
+};
+
+TABLE_ITEM PostResultsBitmapDw2Table[] = {
+ {
+ 0,
+ L" Normally 0; available for OEM assignment "
+ },
+ {
+ 1,
+ L" Normally 0; available for OEM assignment "
+ },
+ {
+ 2,
+ L" Normally 0; available for OEM assignment "
+ },
+ {
+ 3,
+ L" Normally 0; available for OEM assignment "
+ },
+ {
+ 4,
+ L" Normally 0; available for OEM assignment "
+ },
+ {
+ 5,
+ L" Normally 0; available for OEM assignment "
+ },
+ {
+ 6,
+ L" Normally 0; available for OEM assignment "
+ },
+ {
+ 7,
+ L" PCI Memory Conflict "
+ },
+ {
+ 8,
+ L" PCI I/O Conflict "
+ },
+ {
+ 9,
+ L" PCI IRQ Conflict "
+ },
+ {
+ 10,
+ L" PNP Memory Conflict "
+ },
+ {
+ 11,
+ L" PNP 32 bit Memory Conflict "
+ },
+ {
+ 12,
+ L" PNP I/O Conflict "
+ },
+ {
+ 13,
+ L" PNP IRQ Conflict "
+ },
+ {
+ 14,
+ L" PNP DMA Conflict "
+ },
+ {
+ 15,
+ L" Bad PNP Serial ID Checksum "
+ },
+ {
+ 16,
+ L" Bad PNP Resource Data Checksum "
+ },
+ {
+ 17,
+ L" Static Resource Conflict "
+ },
+ {
+ 18,
+ L" NVRAM Checksum Error, NVRAM Cleared "
+ },
+ {
+ 19,
+ L" System Board Device Resource Conflict "
+ },
+ {
+ 20,
+ L" Primary Output Device Not Found "
+ },
+ {
+ 21,
+ L" Primary Input Device Not Found "
+ },
+ {
+ 22,
+ L" Primary Boot Device Not Found "
+ },
+ {
+ 23,
+ L" NVRAM Cleared By Jumper "
+ },
+ {
+ 24,
+ L" NVRAM Data Invalid, NVRAM Cleared "
+ },
+ {
+ 25,
+ L" FDC Resource Conflict "
+ },
+ {
+ 26,
+ L" Primary ATA Controller Resource Conflict "
+ },
+ {
+ 27,
+ L" Secondary ATA Controller Resource Conflict "
+ },
+ {
+ 28,
+ L" Parallel Port Resource Conflict "
+ },
+ {
+ 29,
+ L" Serial Port 1 Resource Conflict "
+ },
+ {
+ 30,
+ L" Serial Port 2 Resource Conflict "
+ },
+ {
+ 31,
+ L" Audio Resource Conflict "
+ },
+};
+
+TABLE_ITEM SELSysManagementTypesTable[] = {
+ {
+ 0x01,
+ L" +2.5V Out of range, #2 "
+ },
+ {
+ 0x02,
+ L" +3.3V Out of range "
+ },
+ {
+ 0x03,
+ L" +5V Out of range "
+ },
+ {
+ 0x04,
+ L" -5V Out of range "
+ },
+ {
+ 0x05,
+ L" +12V Out of range "
+ },
+ {
+ 0x06,
+ L" -12V Out of range "
+ },
+ {
+ 0x0F07,
+ L" Reserved for future out-of-range voltage levels "
+ },
+ {
+ 0x10,
+ L" System board temperature out of range "
+ },
+ {
+ 0x11,
+ L" Processor #1 temperature out of range "
+ },
+ {
+ 0x12,
+ L" Processor #2 temperature out of range "
+ },
+ {
+ 0x13,
+ L" Processor #3 temperature out of range "
+ },
+ {
+ 0x14,
+ L" Processor #4 temperature out of range "
+ },
+ {
+ 0x1F15,
+ L" Reserved for future out-of-range temperatures"
+ },
+ {
+ 0x2720,
+ L" Fan n (n = 0 to 7) Out of range "
+ },
+ {
+ 0x2F28,
+ L" Reserved for future assignment via this specification "
+ },
+ {
+ 0x30,
+ L" Chassis secure switch activated "
+ },
+};
+
+TABLE_ITEM PMALocationTable[] = {
+ {
+ 0x01,
+ L" Other"
+ },
+ {
+ 0x02,
+ L" Unknown"
+ },
+ {
+ 0x03,
+ L" System board or motherboard"
+ },
+ {
+ 0x04,
+ L" ISA add-on card"
+ },
+ {
+ 0x05,
+ L" EISA add-on card"
+ },
+ {
+ 0x06,
+ L" PCI add-on card"
+ },
+ {
+ 0x07,
+ L" MCA add-on card"
+ },
+ {
+ 0x08,
+ L" PCMCIA add-on card"
+ },
+ {
+ 0x09,
+ L" Proprietary add-on card"
+ },
+ {
+ 0x0A,
+ L" NuBus"
+ },
+ {
+ 0xA0,
+ L" PC-98/C20 add-on card"
+ },
+ {
+ 0xA1,
+ L" PC-98/C24 add-on card"
+ },
+ {
+ 0xA2,
+ L" PC-98/E add-on card"
+ },
+ {
+ 0xA3,
+ L" PC-98/Local bus add-on card"
+ }
+};
+
+TABLE_ITEM PMAUseTable[] = {
+ {
+ 0x01,
+ L" Other"
+ },
+ {
+ 0x02,
+ L" Unknown"
+ },
+ {
+ 0x03,
+ L" System memory"
+ },
+ {
+ 0x04,
+ L" Video memory"
+ },
+ {
+ 0x05,
+ L" Flash memory"
+ },
+ {
+ 0x06,
+ L" Non-volatile RAM"
+ },
+ {
+ 0x07,
+ L" Cache memory"
+ }
+};
+
+TABLE_ITEM PMAErrorCorrectionTypesTable[] = {
+ {
+ 0x01,
+ L" Other"
+ },
+ {
+ 0x02,
+ L" Unknown"
+ },
+ {
+ 0x03,
+ L" None"
+ },
+ {
+ 0x04,
+ L" Parity"
+ },
+ {
+ 0x05,
+ L" Single-bit ECC"
+ },
+ {
+ 0x06,
+ L" Multi-bit ECC"
+ },
+ {
+ 0x07,
+ L" CRC"
+ }
+};
+
+TABLE_ITEM MemoryDeviceFormFactorTable[] = {
+ {
+ 0x01,
+ L" Other"
+ },
+ {
+ 0x02,
+ L" Unknown"
+ },
+ {
+ 0x03,
+ L" SIMM"
+ },
+ {
+ 0x04,
+ L" SIP"
+ },
+ {
+ 0x05,
+ L" Chip"
+ },
+ {
+ 0x06,
+ L" DIP"
+ },
+ {
+ 0x07,
+ L" ZIP"
+ },
+ {
+ 0x08,
+ L" Proprietary Card"
+ },
+ {
+ 0x09,
+ L" DIMM"
+ },
+ {
+ 0x0A,
+ L" TSOP"
+ },
+ {
+ 0x0B,
+ L" Row of chips"
+ },
+ {
+ 0x0C,
+ L" RIMM"
+ },
+ {
+ 0x0D,
+ L" SODIMM"
+ },
+ {
+ 0x0E,
+ L" SRIMM"
+ },
+ {
+ 0x0F,
+ L" FB-DIMM"
+ }
+};
+
+TABLE_ITEM MemoryDeviceTypeTable[] = {
+ {
+ 0x01,
+ L" Other"
+ },
+ {
+ 0x02,
+ L" Unknown"
+ },
+ {
+ 0x03,
+ L" DRAM"
+ },
+ {
+ 0x04,
+ L" EDRAM"
+ },
+ {
+ 0x05,
+ L" VRAM"
+ },
+ {
+ 0x06,
+ L" SRAM"
+ },
+ {
+ 0x07,
+ L" RAM"
+ },
+ {
+ 0x08,
+ L" ROM"
+ },
+ {
+ 0x09,
+ L" FLASH"
+ },
+ {
+ 0x0A,
+ L" EEPROM"
+ },
+ {
+ 0x0B,
+ L" FEPROM"
+ },
+ {
+ 0x0C,
+ L" EPROM"
+ },
+ {
+ 0x0D,
+ L" CDRAM"
+ },
+ {
+ 0x0E,
+ L" 3DRAM"
+ },
+ {
+ 0x0F,
+ L" SDRAM"
+ },
+ {
+ 0x10,
+ L" SGRAM"
+ },
+ {
+ 0x11,
+ L" RDRAM"
+ },
+ {
+ 0x12,
+ L" DDR"
+ },
+ {
+ 0x13,
+ L" DDR2"
+ },
+ {
+ 0x14,
+ L" DDR2 FB-DIMM"
+ },
+ {
+ 0x18,
+ L" DDR3"
+ },
+ {
+ 0x19,
+ L" FBD2"
+ },
+ {
+ 0x1A,
+ L" DDR4"
+ },
+ {
+ 0x1B,
+ L" LPDDR"
+ },
+ {
+ 0x1C,
+ L" LPDDR2"
+ },
+ {
+ 0x1D,
+ L" LPDDR3"
+ },
+ {
+ 0x1E,
+ L" LPDDR4"
+ }
+};
+
+TABLE_ITEM MemoryDeviceTypeDetailTable[] = {
+ {
+ 1,
+ L" Other"
+ },
+ {
+ 2,
+ L" Unknown"
+ },
+ {
+ 3,
+ L" Fast-paged"
+ },
+ {
+ 4,
+ L" Static column"
+ },
+ {
+ 5,
+ L" Pseudo-STATIC"
+ },
+ {
+ 6,
+ L" RAMBUS "
+ },
+ {
+ 7,
+ L" Synchronous"
+ },
+ {
+ 8,
+ L" CMOS"
+ },
+ {
+ 9,
+ L" EDO"
+ },
+ {
+ 10,
+ L" Window DRAM"
+ },
+ {
+ 11,
+ L" Cache DRAM"
+ },
+ {
+ 12,
+ L" Non-volatile"
+ },
+ {
+ 13,
+ L" Registered(Buffered)"
+ },
+ {
+ 14,
+ L" Unbuffered(Unregistered)"
+ }
+};
+
+TABLE_ITEM MemoryErrorTypeTable[] = {
+ {
+ 0x01,
+ L" Other"
+ },
+ {
+ 0x02,
+ L" Unknown"
+ },
+ {
+ 0x03,
+ L" OK"
+ },
+ {
+ 0x04,
+ L" Bad read"
+ },
+ {
+ 0x05,
+ L" Parity error"
+ },
+ {
+ 0x06,
+ L" Single-bit error"
+ },
+ {
+ 0x07,
+ L" Double-bit error"
+ },
+ {
+ 0x08,
+ L" Multi-bit error"
+ },
+ {
+ 0x09,
+ L" Nibble error"
+ },
+ {
+ 0x0A,
+ L" Checksum error"
+ },
+ {
+ 0x0B,
+ L" CRC error"
+ },
+ {
+ 0x0C,
+ L" Corrected single-bit error"
+ },
+ {
+ 0x0D,
+ L" Corrected error"
+ },
+ {
+ 0x0E,
+ L" Uncorrectable error"
+ },
+};
+
+TABLE_ITEM MemoryErrorGranularityTable[] = {
+ {
+ 0x01,
+ L" Other"
+ },
+ {
+ 0x02,
+ L" Unknown"
+ },
+ {
+ 0x03,
+ L" Device level"
+ },
+ {
+ 0x04,
+ L" Memory partition level"
+ },
+};
+
+TABLE_ITEM MemoryErrorOperationTable[] = {
+ {
+ 0x01,
+ L" Other"
+ },
+ {
+ 0x02,
+ L" Unknown"
+ },
+ {
+ 0x03,
+ L" Read"
+ },
+ {
+ 0x04,
+ L" Write"
+ },
+ {
+ 0x05,
+ L" Partial Write"
+ },
+};
+
+TABLE_ITEM PointingDeviceTypeTable[] = {
+ {
+ 0x01,
+ L" Other"
+ },
+ {
+ 0x02,
+ L" Unknown"
+ },
+ {
+ 0x03,
+ L" Mouse"
+ },
+ {
+ 0x04,
+ L" Track Ball"
+ },
+ {
+ 0x05,
+ L" Track Point"
+ },
+ {
+ 0x06,
+ L" Glide Point"
+ },
+ {
+ 0x07,
+ L" Touch Pad"
+ },
+};
+
+TABLE_ITEM PointingDeviceInterfaceTable[] = {
+ {
+ 0x01,
+ L" Other"
+ },
+ {
+ 0x02,
+ L" Unknown"
+ },
+ {
+ 0x03,
+ L" Serial"
+ },
+ {
+ 0x04,
+ L" PS/2"
+ },
+ {
+ 0x05,
+ L" Infrared"
+ },
+ {
+ 0x06,
+ L" HP-HIL"
+ },
+ {
+ 0x07,
+ L" Bus mouse"
+ },
+ {
+ 0x08,
+ L" ADB(Apple Desktop Bus"
+ },
+ {
+ 0xA0,
+ L" Bus mouse DB-9"
+ },
+ {
+ 0xA1,
+ L" Bus mouse mirco-DIN"
+ },
+ {
+ 0xA2,
+ L" USB"
+ },
+};
+
+TABLE_ITEM PBDeviceChemistryTable[] = {
+ {
+ 0x01,
+ L" Other "
+ },
+ {
+ 0x02,
+ L" Unknown "
+ },
+ {
+ 0x03,
+ L" Lead Acid "
+ },
+ {
+ 0x04,
+ L" Nickel Cadmium "
+ },
+ {
+ 0x05,
+ L" Nickel metal hydride "
+ },
+ {
+ 0x06,
+ L" Lithium-ion "
+ },
+ {
+ 0x07,
+ L" Zinc air "
+ },
+ {
+ 0x08,
+ L" Lithium Polymer "
+ },
+};
+
+TABLE_ITEM VPLocationTable[] = {
+ {
+ 0x01,
+ L" Other "
+ },
+ {
+ 0x02,
+ L" Unknown "
+ },
+ {
+ 0x03,
+ L" OK "
+ },
+ {
+ 0x04,
+ L" Non-critical "
+ },
+ {
+ 0x05,
+ L" Critical "
+ },
+ {
+ 0x06,
+ L" Non-recoverable "
+ },
+};
+
+TABLE_ITEM VPStatusTable[] = {
+ {
+ 0x01,
+ L" Other "
+ },
+ {
+ 0x02,
+ L" Unknown "
+ },
+ {
+ 0x03,
+ L" Processor "
+ },
+ {
+ 0x04,
+ L" Disk "
+ },
+ {
+ 0x05,
+ L" Peripheral Bay "
+ },
+ {
+ 0x06,
+ L" System Management Module "
+ },
+ {
+ 0x07,
+ L" Motherboard "
+ },
+ {
+ 0x08,
+ L" Memory Module "
+ },
+ {
+ 0x09,
+ L" Processor Module "
+ },
+ {
+ 0x0A,
+ L" Power Unit "
+ },
+ {
+ 0x0B,
+ L" Add-in Card "
+ },
+};
+
+TABLE_ITEM CoolingDeviceStatusTable[] = {
+ {
+ 0x01,
+ L" Other "
+ },
+ {
+ 0x02,
+ L" Unknown "
+ },
+ {
+ 0x03,
+ L" OK "
+ },
+ {
+ 0x04,
+ L" Non-critical "
+ },
+ {
+ 0x05,
+ L" Critical "
+ },
+ {
+ 0x06,
+ L" Non-recoverable "
+ },
+};
+
+TABLE_ITEM CoolingDeviceTypeTable[] = {
+ {
+ 0x01,
+ L" Other "
+ },
+ {
+ 0x02,
+ L" Unknown "
+ },
+ {
+ 0x03,
+ L" Fan "
+ },
+ {
+ 0x04,
+ L" Centrifugal Blower "
+ },
+ {
+ 0x05,
+ L" Chip Fan "
+ },
+ {
+ 0x06,
+ L" Cabinet Fan "
+ },
+ {
+ 0x07,
+ L" Power Supply Fan "
+ },
+ {
+ 0x08,
+ L" Heat Pipe "
+ },
+ {
+ 0x09,
+ L" Integrated Refrigeration "
+ },
+ {
+ 0x10,
+ L" Active Cooling "
+ },
+ {
+ 0x11,
+ L" Passive Cooling "
+ },
+};
+
+TABLE_ITEM TemperatureProbeStatusTable[] = {
+ {
+ 0x01,
+ L" Other "
+ },
+ {
+ 0x02,
+ L" Unknown "
+ },
+ {
+ 0x03,
+ L" OK "
+ },
+ {
+ 0x04,
+ L" Non-critical "
+ },
+ {
+ 0x05,
+ L" Critical "
+ },
+ {
+ 0x06,
+ L" Non-recoverable "
+ },
+};
+
+TABLE_ITEM TemperatureProbeLocTable[] = {
+ {
+ 0x01,
+ L" Other "
+ },
+ {
+ 0x02,
+ L" Unknown "
+ },
+ {
+ 0x03,
+ L" Processor "
+ },
+ {
+ 0x04,
+ L" Disk "
+ },
+ {
+ 0x05,
+ L" Peripheral Bay "
+ },
+ {
+ 0x06,
+ L" System Management Module "
+ },
+ {
+ 0x07,
+ L" Motherboard "
+ },
+ {
+ 0x08,
+ L" Memory Module "
+ },
+ {
+ 0x09,
+ L" Processor Module "
+ },
+ {
+ 0x0A,
+ L" Power Unit "
+ },
+ {
+ 0x0B,
+ L" Add-in Card "
+ },
+};
+
+TABLE_ITEM ECPStatusTable[] = {
+ {
+ 0x01,
+ L" Other "
+ },
+ {
+ 0x02,
+ L" Unknown "
+ },
+ {
+ 0x03,
+ L" OK "
+ },
+ {
+ 0x04,
+ L" Non-critical "
+ },
+ {
+ 0x05,
+ L" Critical "
+ },
+ {
+ 0x06,
+ L" Non-recoverable "
+ },
+};
+
+TABLE_ITEM ECPLocTable[] = {
+ {
+ 0x01,
+ L" Other "
+ },
+ {
+ 0x02,
+ L" Unknown "
+ },
+ {
+ 0x03,
+ L" Processor "
+ },
+ {
+ 0x04,
+ L" Disk "
+ },
+ {
+ 0x05,
+ L" Peripheral Bay "
+ },
+ {
+ 0x06,
+ L" System Management Module "
+ },
+ {
+ 0x07,
+ L" Motherboard "
+ },
+ {
+ 0x08,
+ L" Memory Module "
+ },
+ {
+ 0x09,
+ L" Processor Module "
+ },
+ {
+ 0x0A,
+ L" Power Unit "
+ },
+ {
+ 0x0B,
+ L" Add-in Card "
+ },
+};
+
+TABLE_ITEM MDTypeTable[] = {
+ {
+ 0x01,
+ L" Other "
+ },
+ {
+ 0x02,
+ L" Unknown "
+ },
+ {
+ 0x03,
+ L" National Semiconductor LM75 "
+ },
+ {
+ 0x04,
+ L" National Semiconductor LM78 "
+ },
+ {
+ 0x05,
+ L" National Semiconductor LM79 "
+ },
+ {
+ 0x06,
+ L" National Semiconductor LM80 "
+ },
+ {
+ 0x07,
+ L" National Semiconductor LM81 "
+ },
+ {
+ 0x08,
+ L" Analog Devices ADM9240 "
+ },
+ {
+ 0x09,
+ L" Dallas Semiconductor DS1780 "
+ },
+ {
+ 0x0A,
+ L" Maxim 1617 "
+ },
+ {
+ 0x0B,
+ L" Genesys GL518SM "
+ },
+ {
+ 0x0C,
+ L" Winbond W83781D "
+ },
+ {
+ 0x0D,
+ L" Holtek HT82H791 "
+ },
+};
+
+TABLE_ITEM MDAddressTypeTable[] = {
+ {
+ 0x01,
+ L" Other "
+ },
+ {
+ 0x02,
+ L" Unknown "
+ },
+ {
+ 0x03,
+ L" I/O Port "
+ },
+ {
+ 0x04,
+ L" Memory "
+ },
+ {
+ 0x05,
+ L" SM Bus "
+ },
+};
+
+TABLE_ITEM MemoryChannelTypeTable[] = {
+ {
+ 0x01,
+ L" Other "
+ },
+ {
+ 0x02,
+ L" Unknown "
+ },
+ {
+ 0x03,
+ L" RamBus "
+ },
+ {
+ 0x04,
+ L" SyncLink "
+ },
+};
+
+TABLE_ITEM IPMIDIBMCInterfaceTypeTable[] = {
+ {
+ 0x00,
+ L" Unknown "
+ },
+ {
+ 0x01,
+ L" KCS: Keyboard Controller Style "
+ },
+ {
+ 0x02,
+ L" SMIC: Server Management Interface Chip "
+ },
+ {
+ 0x03,
+ L" BT: Block Transfer "
+ },
+ {
+ 0xFF04,
+ L" Reserved for future assignment by this specification "
+ },
+};
+
+TABLE_ITEM StructureTypeInfoTable[] = {
+ {
+ 0,
+ L" BIOS Information"
+ },
+ {
+ 1,
+ L" System Information"
+ },
+ {
+ 2,
+ L" Base Board Information"
+ },
+ {
+ 3,
+ L" System Enclosure"
+ },
+ {
+ 4,
+ L" Processor Information"
+ },
+ {
+ 5,
+ L" Memory Controller Information "
+ },
+ {
+ 6,
+ L" Memory Module Information "
+ },
+ {
+ 7,
+ L" Cache Information "
+ },
+ {
+ 8,
+ L" Port Connector Information "
+ },
+ {
+ 9,
+ L" System Slots "
+ },
+ {
+ 10,
+ L" On Board Devices Information "
+ },
+ {
+ 11,
+ L" OEM Strings"
+ },
+ {
+ 12,
+ L" System Configuration Options "
+ },
+ {
+ 13,
+ L" BIOS Language Information "
+ },
+ {
+ 14,
+ L" Group Associations "
+ },
+ {
+ 15,
+ L" System Event Log "
+ },
+ {
+ 16,
+ L" Physical Memory Array "
+ },
+ {
+ 17,
+ L" Memory Device "
+ },
+ {
+ 18,
+ L" 32-bit Memory Error Information "
+ },
+ {
+ 19,
+ L" Memory Array Mapped Address "
+ },
+ {
+ 20,
+ L" Memory Device Mapped Address "
+ },
+ {
+ 21,
+ L" Built-in Pointing Device "
+ },
+ {
+ 22,
+ L" Portable Battery "
+ },
+ {
+ 23,
+ L" System Reset "
+ },
+ {
+ 24,
+ L" Hardware Security "
+ },
+ {
+ 25,
+ L" System Power Controls "
+ },
+ {
+ 26,
+ L" Voltage Probe "
+ },
+ {
+ 27,
+ L" Cooling Device "
+ },
+ {
+ 28,
+ L" Temperature Probe "
+ },
+ {
+ 29,
+ L" Electrical Current Probe "
+ },
+ {
+ 30,
+ L" Out-of-Band Remote Access "
+ },
+ {
+ 31,
+ L" Boot Integrity Services (BIS) Entry Point"
+ },
+ {
+ 32,
+ L" System Boot Information "
+ },
+ {
+ 33,
+ L" 64-bit Memory Error Information "
+ },
+ {
+ 34,
+ L" Management Device "
+ },
+ {
+ 35,
+ L" Management Device Component "
+ },
+ {
+ 36,
+ L" Management Device Threshold Data "
+ },
+ {
+ 37,
+ L" Memory Channel "
+ },
+ {
+ 38,
+ L" IPMI Device Information "
+ },
+ {
+ 39,
+ L" System Power Supply"
+ },
+ {
+ 40,
+ L" Additional Information"
+ },
+ {
+ 41,
+ L" Onboard Devices Extended Information"
+ },
+ {
+ 42,
+ L" Management Controller Host Interface"
+ },
+ {
+ 0x7E,
+ L" Inactive"
+ },
+ {
+ 0x7F,
+ L" End-of-Table "
+ },
+};
+
+
+/**
+ Given a table and a Key, return the responding info.
+
+ Notes:
+ Table[Index].Key is change from UINT8 to UINT16,
+ in order to deal with "0xaa - 0xbb".
+
+ For example:
+ DisplaySELVariableDataFormatTypes(UINT8 Type, UINT8 Option)
+ has a item:
+ "0x07-0x7F, Unused"
+ Now define Key = 0x7F07, that is to say: High = 0x7F, Low = 0x07.
+ Then all the Key Value between Low and High gets the same string
+ L"Unused".
+
+ @param[in] Table The begin address of table.
+ @param[in] Number The number of table items.
+ @param[in] Key The query Key.
+ @param[in, out] Info Input as empty buffer; output as data buffer.
+ @param[in] InfoLen The max number of characters for Info.
+
+ @return the found Key and Info is valid.
+ @retval QUERY_TABLE_UNFOUND and Info should be NULL.
+**/
+UINT8
+QueryTable (
+ IN TABLE_ITEM *Table,
+ IN UINTN Number,
+ IN UINT8 Key,
+ IN OUT CHAR16 *Info,
+ IN UINTN InfoLen
+ )
+{
+ UINTN Index;
+ //
+ // High byte and Low byte of word
+ //
+ UINT8 High;
+ UINT8 Low;
+
+ for (Index = 0; Index < Number; Index++) {
+ High = (UINT8) (Table[Index].Key >> 8);
+ Low = (UINT8) (Table[Index].Key & 0x00FF);
+
+ //
+ // Check if Key is in the range
+ // or if Key == Value in the table
+ //
+ if ((High > Low && Key >= Low && Key <= High)
+ || (Table[Index].Key == Key)) {
+ StrnCpyS (Info, InfoLen, Table[Index].Info, InfoLen - 1);
+ StrnCatS (Info, InfoLen, L"\n", InfoLen - 1 - StrLen(Info));
+ return Key;
+ }
+ }
+
+ StrCpyS (Info, InfoLen, L"Undefined Value\n");
+ return QUERY_TABLE_UNFOUND;
+}
+
+/**
+ Given a table of bit info and a Key, return the responding info to the Key.
+
+ @param[in] Table Point to a table which maintains a map of 'bit' to 'message'.
+ @param[in] Number Number of table items.
+ @param[in] Bits The Key of query the bit map information.
+**/
+VOID
+PrintBitsInfo (
+ IN TABLE_ITEM *Table,
+ IN UINTN Number,
+ IN UINT32 Bits
+ )
+{
+ //
+ // Get certain bit of 'Value':
+ //
+#define BIT(Value, bit) ((Value) & ((UINT32) 1) << (bit))
+ //
+ // Clear certain bit of 'Value':
+ //
+#define CLR_BIT(Value, bit) ((Value) -= (BIT (Value, bit)))
+
+ UINTN Index;
+ UINT32 Value;
+ BOOLEAN NoInfo;
+
+ NoInfo = TRUE;
+ Value = Bits;
+ //
+ // query the table and print information
+ //
+ for (Index = 0; Index < Number; Index++) {
+ if (BIT (Value, Table[Index].Key) != 0) {
+ Print (Table[Index].Info);
+ Print (L" | ");
+
+ NoInfo = FALSE;
+ //
+ // clear the bit, for reserved bits test
+ //
+ CLR_BIT (Value, Table[Index].Key);
+ }
+ }
+
+ if (NoInfo) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_NO_INFO), gShellDebug1HiiHandle);
+ }
+
+ if (Value != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,
+ STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_RSVD_BITS_SET),
+ gShellDebug1HiiHandle,
+ Value
+ );
+ }
+
+ Print (L"\n");
+}
+//
+// //////////////////////////////////////////////////////////////////
+//
+// Following uses QueryTable functions to simplify the coding.
+// QueryTable(), PrintBitsInfo()
+//
+//
+#define PRINT_TABLE_ITEM(Table, Key) \
+ do { \
+ UINTN Num; \
+ CHAR16 Info[66]; \
+ Num = sizeof (Table) / sizeof (TABLE_ITEM); \
+ ZeroMem (Info, sizeof (Info)); \
+ QueryTable (Table, Num, Key, Info, sizeof(Info)/sizeof(Info[0])); \
+ Print (Info); \
+ } while (0);
+
+#define PRINT_BITS_INFO(Table, bits) \
+ do { \
+ UINTN Num; \
+ Num = sizeof (Table) / sizeof (TABLE_ITEM); \
+ PrintBitsInfo (Table, Num, (UINT32) bits); \
+ } while (0);
+
+/**
+ Display System Information (Type 1) Type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySystemWakeupType (
+ IN UINT8 Type,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_WAKEUP_TYPE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Type, Option);
+ PRINT_TABLE_ITEM (SystemWakeupTypeTable, Type);
+}
+
+/**
+ Display Base Board (Type 2) Feature Flags.
+
+ @param[in] FeatureFlags The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayBaseBoardFeatureFlags (
+ IN UINT8 FeatureFlags,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_BASE_BOARD_FEATURE_FLAGS), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (FeatureFlags, Option);
+ PRINT_BITS_INFO (BaseBoardFeatureFlagsTable, FeatureFlags);
+}
+
+/**
+ Display Base Board (Type 2) Board Type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayBaseBoardBoardType(
+ IN UINT8 Type,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_BASE_BOARD_BOARD_TYPE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Type, Option);
+ PRINT_TABLE_ITEM (BaseBoardBoardTypeTable, Type);
+}
+
+/**
+ Display System Enclosure (Type 3) Enclosure Type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySystemEnclosureType (
+ IN UINT8 Type,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_CHASSIS_TYPE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Type, Option);
+ //
+ // query table and print info
+ //
+ PRINT_TABLE_ITEM (SystemEnclosureTypeTable, Type);
+
+ if (BIT (Type, 7) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_CHASSIS_LOCK_PRESENT), gShellDebug1HiiHandle);
+ }
+}
+
+/**
+ Display System Enclosure (Type 3) Enclosure Status.
+
+ @param[in] Status The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySystemEnclosureStatus (
+ IN UINT8 Status,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_CHASSIS_STATUS), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Status, Option);
+ PRINT_TABLE_ITEM (SystemEnclosureStatusTable, Status);
+}
+
+/**
+ Display System Enclosure (Type 3) Security Status.
+
+ @param[in] Status The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySESecurityStatus (
+ IN UINT8 Status,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_CHASSIS_SECURITY), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Status, Option);
+ PRINT_TABLE_ITEM (SESecurityStatusTable, Status);
+}
+
+/**
+ Display Processor Information (Type 4) Type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayProcessorType (
+ IN UINT8 Type,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_PROC_TYPE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Type, Option);
+ PRINT_TABLE_ITEM (ProcessorTypeTable, Type);
+}
+
+/**
+ Display Processor Information (Type 4) Upgrade.
+
+ @param[in] Upgrade The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayProcessorUpgrade (
+ IN UINT8 Upgrade,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_PROC_UPDATE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Upgrade, Option);
+ PRINT_TABLE_ITEM (ProcessorUpgradeTable, Upgrade);
+}
+
+/**
+ Display Processor Information (Type 4) Characteristics.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayProcessorCharacteristics (
+ IN UINT16 Type,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_PROC_CHARACTERISTICS), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Type, Option);
+ PRINT_BITS_INFO (ProcessorCharacteristicsTable, Type);
+}
+
+/**
+ Display Memory Controller Information (Type 5) method.
+
+ @param[in] Method The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMcErrorDetectMethod (
+ IN UINT8 Method,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_DETECTMETHOD), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Method, Option);
+ PRINT_TABLE_ITEM (McErrorDetectMethodTable, Method);
+}
+
+/**
+ Display Memory Controller Information (Type 5) Capability.
+
+ @param[in] Capability The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMcErrorCorrectCapability (
+ IN UINT8 Capability,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_CORRECT_CAPABILITY), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Capability, Option);
+ PRINT_BITS_INFO (McErrorCorrectCapabilityTable, Capability);
+}
+
+/**
+ Display Memory Controller Information (Type 5) Support.
+
+ @param[in] Support The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMcInterleaveSupport (
+ IN UINT8 Support,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_INTERLEAVE_SUPPORT), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Support, Option);
+ PRINT_TABLE_ITEM (McInterleaveSupportTable, Support);
+}
+
+/**
+ Display Memory Controller Information (Type 5) speeds.
+
+ @param[in] Speed The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMcMemorySpeeds (
+ IN UINT16 Speed,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_MEMORY_SPEED), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Speed, Option);
+ PRINT_BITS_INFO (McMemorySpeedsTable, Speed);
+}
+
+/**
+ Display Memory Controller Information (Type 5) voltage.
+
+ @param[in] Voltage The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMemoryModuleVoltage (
+ IN UINT8 Voltage,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_REQUIRED_VOLTAGES), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Voltage, Option);
+ PRINT_BITS_INFO (MemoryModuleVoltageTable, Voltage);
+}
+
+/**
+ Display Memory Module Information (Type 6) type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMmMemoryType (
+ IN UINT16 Type,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_MODULE_TYPE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Type, Option);
+ PRINT_BITS_INFO (MmMemoryTypeTable, Type);
+}
+
+/**
+ Display Memory Module Information (Type 6) status.
+
+ @param[in] Status The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMmErrorStatus (
+ IN UINT8 Status,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_MODULE_ERROR_STATUS), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Status, Option);
+ PRINT_BITS_INFO (MmErrorStatusTable, Status);
+}
+
+/**
+ Display Cache Information (Type 7) SRAM Type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayCacheSRAMType (
+ IN UINT16 Type,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_CACHE_SRAM_TYPE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION ((UINT8) Type, Option);
+ PRINT_BITS_INFO (CacheSRAMTypeTable, (UINT8) Type);
+}
+
+/**
+ Display Cache Information (Type 7) correcting Type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayCacheErrCorrectingType (
+ IN UINT8 Type,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_CACHE_ERROR_CORRECTING), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Type, Option);
+ PRINT_TABLE_ITEM (CacheErrCorrectingTypeTable, Type);
+}
+
+/**
+ Display Cache Information (Type 7) Type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayCacheSystemCacheType (
+ IN UINT8 Type,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_CACHE_SYSTEM_TYPE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Type, Option);
+ PRINT_TABLE_ITEM (CacheSystemCacheTypeTable, Type);
+}
+
+/**
+ Display Cache Information (Type 7) Associativity.
+
+ @param[in] Associativity The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayCacheAssociativity (
+ IN UINT8 Associativity,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_CACHE_ASSOCIATIVITY), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Associativity, Option);
+ PRINT_TABLE_ITEM (CacheAssociativityTable, Associativity);
+}
+
+/**
+ Display Port Connector Information (Type 8) type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayPortConnectorType (
+ IN UINT8 Type,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_PORT_CONNECTOR_TYPE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Type, Option);
+ PRINT_TABLE_ITEM (PortConnectorTypeTable, Type);
+}
+
+/**
+ Display Port Connector Information (Type 8) port type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayPortType (
+ IN UINT8 Type,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_PORT_TYPE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Type, Option);
+ PRINT_TABLE_ITEM (PortTypeTable, Type);
+}
+
+/**
+ Display System Slots (Type 9) slot type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySystemSlotType (
+ IN UINT8 Type,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_SLOT_TYPE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Type, Option);
+ PRINT_TABLE_ITEM (SystemSlotTypeTable, Type);
+}
+
+/**
+ Display System Slots (Type 9) data bus width.
+
+ @param[in] Width The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySystemSlotDataBusWidth (
+ IN UINT8 Width,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_SLOT_DATA), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Width, Option);
+ PRINT_TABLE_ITEM (SystemSlotDataBusWidthTable, Width);
+}
+
+/**
+ Display System Slots (Type 9) usage information.
+
+ @param[in] Usage The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySystemSlotCurrentUsage (
+ IN UINT8 Usage,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_SLOT_CURRENT_USAGE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Usage, Option);
+ PRINT_TABLE_ITEM (SystemSlotCurrentUsageTable, Usage);
+}
+
+/**
+ Display System Slots (Type 9) slot length.
+
+ @param[in] Length The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySystemSlotLength (
+ IN UINT8 Length,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_SLOT_LENGTH), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Length, Option);
+ PRINT_TABLE_ITEM (SystemSlotLengthTable, Length);
+}
+
+/**
+ Display System Slots (Type 9) characteristics.
+
+ @param[in] Chara1 The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySlotCharacteristics1 (
+ IN UINT8 Chara1,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SLOT_CHARACTERISTICS), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Chara1, Option);
+ PRINT_BITS_INFO (SlotCharacteristics1Table, Chara1);
+}
+
+/**
+ Display System Slots (Type 9) characteristics.
+
+ @param[in] Chara2 The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySlotCharacteristics2 (
+ IN UINT8 Chara2,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SLOT_CHARACTERISTICS_2), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Chara2, Option);
+ PRINT_BITS_INFO (SlotCharacteristics2Table, Chara2);
+}
+
+/**
+ Display On Board Devices Information (Type 10) types.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayOnboardDeviceTypes (
+ IN UINT8 Type,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_ONBOARD_DEVICE_TYPE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Type, Option);
+ PRINT_TABLE_ITEM (OnboardDeviceTypesTable, Type);
+}
+
+/**
+ Display System Event Log (Type 15) types.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySELTypes (
+ IN UINT8 Type,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_EVENT_LOG_TYPE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Type, Option);
+ PRINT_TABLE_ITEM (SELTypesTable, Type);
+}
+
+/**
+ Display System Event Log (Type 15) format type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySELVarDataFormatType (
+ IN UINT8 Type,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_EVENT_LOG_VAR_DATA_FORMAT), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Type, Option);
+ PRINT_TABLE_ITEM (SELVarDataFormatTypeTable, Type);
+}
+
+/**
+ Display System Event Log (Type 15) dw1.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayPostResultsBitmapDw1 (
+ IN UINT32 Key,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_POST_RESULTS_BITMAP), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Key, Option);
+ PRINT_BITS_INFO (PostResultsBitmapDw1Table, Key);
+}
+
+/**
+ Display System Event Log (Type 15) dw2.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayPostResultsBitmapDw2 (
+ IN UINT32 Key,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_POST_RESULTS_SECOND_DWORD), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Key, Option);
+ PRINT_BITS_INFO (PostResultsBitmapDw2Table, Key);
+}
+
+/**
+ Display System Event Log (Type 15) type.
+
+ @param[in] SMType The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySELSysManagementTypes (
+ IN UINT32 SMType,
+ IN UINT8 Option
+ )
+{
+ UINT8 Temp;
+
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_MANAGEMENT_TYPES), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (SMType, Option);
+
+ //
+ // Deal with wide range Value
+ //
+ if (SMType >= 0x80000000) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_OEM_ASSIGNED), gShellDebug1HiiHandle);
+ } else if (SMType >= 0x00020000) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_RSVD_FOR_FUTURE_ASSIGN), gShellDebug1HiiHandle);
+ } else if (SMType >= 0x00010000) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_MANAGEMENT_PROBE), gShellDebug1HiiHandle);
+ } else if (SMType >= 0x31) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_RSVD_FOR_FUTURE_ASSIGN), gShellDebug1HiiHandle);
+ } else {
+ //
+ // Deal with One byte data
+ //
+ Temp = (UINT8) (SMType & 0x3F);
+ PRINT_TABLE_ITEM (SELSysManagementTypesTable, Temp);
+ }
+}
+
+/**
+ Display Physical Memory Array (Type 16) Location.
+
+ @param[in] Location The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayPMALocation (
+ IN UINT8 Location,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_PHYS_MEM_ARRAY_LOCATION), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Location, Option);
+ PRINT_TABLE_ITEM (PMALocationTable, Location);
+}
+
+/**
+ Display Physical Memory Array (Type 16) Use.
+
+ @param[in] Use The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayPMAUse (
+ IN UINT8 Use,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_PHYS_MEM_ARRAY_USE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Use, Option);
+ PRINT_TABLE_ITEM (PMAUseTable, Use);
+}
+
+/**
+ Display Physical Memory Array (Type 16) Types.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayPMAErrorCorrectionTypes (
+ IN UINT8 Type,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_PHYS_MEM_ARRAY_ERROR), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Type, Option);
+ PRINT_TABLE_ITEM (PMAErrorCorrectionTypesTable, Type);
+}
+
+/**
+ Display Memory Device (Type 17) form factor.
+
+ @param[in] FormFactor The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMemoryDeviceFormFactor (
+ IN UINT8 FormFactor,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_DEVICE_FORM_FACTOR), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (FormFactor, Option);
+ PRINT_TABLE_ITEM (MemoryDeviceFormFactorTable, FormFactor);
+}
+
+/**
+ Display Memory Device (Type 17) type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMemoryDeviceType (
+ IN UINT8 Type,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_DEVICE_TYPE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Type, Option);
+ PRINT_TABLE_ITEM (MemoryDeviceTypeTable, Type);
+}
+
+/**
+ Display Memory Device (Type 17) details.
+
+ @param[in] Para The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMemoryDeviceTypeDetail (
+ IN UINT16 Para,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_DEVICE_TYPE_DETAIL), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Para, Option);
+ PRINT_BITS_INFO (MemoryDeviceTypeDetailTable, Para);
+}
+
+/**
+ Display 32-bit Memory Error Information (Type 18) type.
+
+ @param[in] ErrorType The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMemoryErrorType (
+ IN UINT8 ErrorType,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_ERROR_INFO), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (ErrorType, Option);
+ PRINT_TABLE_ITEM (MemoryErrorTypeTable, ErrorType);
+}
+
+/**
+ Display 32-bit Memory Error Information (Type 18) error granularity.
+
+ @param[in] Granularity The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMemoryErrorGranularity (
+ IN UINT8 Granularity,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_ERROR_GRANULARITY), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Granularity, Option);
+ PRINT_TABLE_ITEM (MemoryErrorGranularityTable, Granularity);
+}
+
+/**
+ Display 32-bit Memory Error Information (Type 18) error information.
+
+ @param[in] Operation The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMemoryErrorOperation (
+ IN UINT8 Operation,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_ERROR_OP), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Operation, Option);
+ PRINT_TABLE_ITEM (MemoryErrorOperationTable, Operation);
+}
+
+/**
+ Display Built-in Pointing Device (Type 21) type information.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayPointingDeviceType (
+ IN UINT8 Type,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_POINTING_DEVICE_TYPE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Type, Option);
+ PRINT_TABLE_ITEM (PointingDeviceTypeTable, Type);
+}
+
+/**
+ Display Built-in Pointing Device (Type 21) information.
+
+ @param[in] Interface The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayPointingDeviceInterface (
+ IN UINT8 Interface,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_POINTING_DEVICE_INTERFACE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Interface, Option);
+ PRINT_TABLE_ITEM (PointingDeviceInterfaceTable, Interface);
+}
+
+/**
+ Display Portable Battery (Type 22) information.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayPBDeviceChemistry (
+ IN UINT8 Key,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_PORTABLE_BATT_DEV_CHEM), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Key, Option);
+ PRINT_TABLE_ITEM (PBDeviceChemistryTable, Key);
+}
+
+/**
+ Display Voltage Probe (Type 26) location information.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayVPLocation (
+ IN UINT8 Key,
+ IN UINT8 Option
+ )
+{
+ UINT8 Loc;
+
+ Loc = (UINT8) ((Key & 0xE0) >> 5);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_VOLTAGE_PROBE_LOC), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Loc, Option);
+ PRINT_TABLE_ITEM (VPLocationTable, Loc);
+}
+
+/**
+ Display Voltage Probe (Type 26) status ype information.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayVPStatus (
+ IN UINT8 Key,
+ IN UINT8 Option
+ )
+{
+ UINT8 Status;
+
+ Status = (UINT8) (Key & 0x1F);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_VOLTAGE_PROBE_STATUS), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Status, Option);
+ PRINT_TABLE_ITEM (VPStatusTable, Status);
+}
+
+/**
+ Display Cooling (Type 27) status information.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayCoolingDeviceStatus (
+ IN UINT8 Key,
+ IN UINT8 Option
+ )
+{
+ UINT8 Status;
+
+ Status = (UINT8) ((Key & 0xE0) >> 5);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_COOLING_DEV_STATUS), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Status, Option);
+ PRINT_TABLE_ITEM (CoolingDeviceStatusTable, Status);
+}
+
+/**
+ Display Cooling (Type 27) type information.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayCoolingDeviceType (
+ IN UINT8 Key,
+ IN UINT8 Option
+ )
+{
+ UINT8 Type;
+
+ Type = (UINT8) (Key & 0x1F);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_COOLING_DEV_TYPE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Type, Option);
+ PRINT_TABLE_ITEM (CoolingDeviceTypeTable, Type);
+}
+
+/**
+ Display Temperature Probe (Type 28) status information.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayTemperatureProbeStatus (
+ IN UINT8 Key,
+ IN UINT8 Option
+ )
+{
+ UINT8 Status;
+
+ Status = (UINT8) ((Key & 0xE0) >> 5);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_TEMP_PROBE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Status, Option);
+ PRINT_TABLE_ITEM (TemperatureProbeStatusTable, Status);
+}
+
+/**
+ Display Temperature Probe (Type 28) location information.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayTemperatureProbeLoc (
+ IN UINT8 Key,
+ IN UINT8 Option
+ )
+{
+ UINT8 Loc;
+
+ Loc = (UINT8) (Key & 0x1F);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_VOLTAGE_PROBE_LOC), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Loc, Option);
+ PRINT_TABLE_ITEM (TemperatureProbeLocTable, Loc);
+}
+
+/**
+ Display Electrical Current Probe (Type 29) status information.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayECPStatus (
+ IN UINT8 Key,
+ IN UINT8 Option
+ )
+{
+ UINT8 Status;
+
+ Status = (UINT8) ((Key & 0xE0) >> 5);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_ELEC_PROBE_STATUS), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Status, Option);
+ PRINT_TABLE_ITEM (ECPStatusTable, Status);
+}
+
+/**
+ Display Type 29 information.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayECPLoc (
+ IN UINT8 Key,
+ IN UINT8 Option
+ )
+{
+ UINT8 Loc;
+
+ Loc = (UINT8) (Key & 0x1F);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_ELEC_PROBE_LOC), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Loc, Option);
+ PRINT_TABLE_ITEM (ECPLocTable, Loc);
+}
+
+/**
+ Display Management Device (Type 34) Type.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMDType (
+ IN UINT8 Key,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MANAGEMENT_DEV_TYPE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Key, Option);
+ PRINT_TABLE_ITEM (MDTypeTable, Key);
+}
+
+/**
+ Display Management Device (Type 34) Address Type.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMDAddressType (
+ IN UINT8 Key,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MANAGEMENT_DEV_ADDR_TYPE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Key, Option);
+ PRINT_TABLE_ITEM (MDAddressTypeTable, Key);
+}
+
+/**
+ Display Memory Channel (Type 37) information.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMemoryChannelType (
+ IN UINT8 Key,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_MEM_CHANNEL_TYPE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Key, Option);
+ PRINT_TABLE_ITEM (MemoryChannelTypeTable, Key);
+}
+
+/**
+ Display IPMI Device Information (Type 38) information.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayIPMIDIBMCInterfaceType (
+ IN UINT8 Key,
+ IN UINT8 Option
+ )
+{
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_BMC_INTERFACE_TYPE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Key, Option);
+ PRINT_TABLE_ITEM (IPMIDIBMCInterfaceTypeTable, Key);
+}
+
+/**
+ Display the structure type information.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayStructureTypeInfo (
+ IN UINT8 Key,
+ IN UINT8 Option
+ )
+{
+ //
+ // display
+ //
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_QUERYTABLE_STRUCT_TYPE), gShellDebug1HiiHandle);
+ PRINT_INFO_OPTION (Key, Option);
+ PRINT_TABLE_ITEM (StructureTypeInfoTable, Key);
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/QueryTable.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/QueryTable.h
new file mode 100644
index 0000000000..9cae7094fb
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/QueryTable.h
@@ -0,0 +1,782 @@
+/** @file
+ Build a table, each item is (key, info) pair.
+ and give a interface of query a string out of a table.
+
+ Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SMBIOS_QUERY_TABLE_H_
+#define _SMBIOS_QUERY_TABLE_H_
+
+#define QUERY_TABLE_UNFOUND 0xFF
+
+typedef struct TABLE_ITEM {
+ UINT16 Key;
+ CHAR16 *Info;
+} TABLE_ITEM;
+
+//
+// Print info by option
+//
+#define PRINT_INFO_OPTION(Value, Option) \
+ do { \
+ if (Option == SHOW_NONE) { \
+ return ; \
+ } \
+ if (Option < SHOW_DETAIL) { \
+ Print (L"0x%x\n", Value); \
+ return ; \
+ } \
+ } while (0);
+
+/**
+ Given a table and a Key, return the responding info.
+
+ Notes:
+ Table[Index].Key is change from UINT8 to UINT16,
+ in order to deal with "0xaa - 0xbb".
+
+ For example:
+ DisplaySELVariableDataFormatTypes(UINT8 Type, UINT8 Option)
+ has a item:
+ "0x07-0x7F, Unused"
+ Now define Key = 0x7F07, that is to say: High = 0x7F, Low = 0x07.
+ Then all the Key Value between Low and High gets the same string
+ L"Unused".
+
+ @param[in] Table The begin address of table.
+ @param[in] Number The number of table items.
+ @param[in] Key The query Key.
+ @param[in, out] Info Input as empty buffer; output as data buffer.
+ @param[in] InfoLen The max number of characters for Info.
+
+ @return the found Key and Info is valid.
+ @retval QUERY_TABLE_UNFOUND and Info should be NULL.
+**/
+UINT8
+QueryTable (
+ IN TABLE_ITEM *Table,
+ IN UINTN Number,
+ IN UINT8 Key,
+ IN OUT CHAR16 *Info,
+ IN UINTN InfoLen
+ );
+
+/**
+ Display the structure type information.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayStructureTypeInfo (
+ IN UINT8 Key,
+ IN UINT8 Option
+ );
+
+/**
+ Display System Information (Type 1) Type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySystemWakeupType (
+ IN UINT8 Type,
+ IN UINT8 Option
+ );
+
+/**
+ Display Base Board (Type 2) Feature Flags.
+
+ @param[in] FeatureFlags The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayBaseBoardFeatureFlags (
+ IN UINT8 FeatureFlags,
+ IN UINT8 Option
+ );
+
+/**
+ Display Base Board (Type 2) Board Type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayBaseBoardBoardType(
+ IN UINT8 Type,
+ IN UINT8 Option
+ );
+
+/**
+ Display System Enclosure (Type 3) Enclosure Type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySystemEnclosureType (
+ IN UINT8 Type,
+ IN UINT8 Option
+ );
+
+/**
+ Display System Enclosure (Type 3) Enclosure Status.
+
+ @param[in] Status The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySystemEnclosureStatus (
+ IN UINT8 Status,
+ IN UINT8 Option
+ );
+
+/**
+ Display System Enclosure (Type 3) Security Status.
+
+ @param[in] Status The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySESecurityStatus (
+ IN UINT8 Status,
+ IN UINT8 Option
+ )
+;
+
+/**
+ Display Processor Information (Type 4) Type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayProcessorType (
+ IN UINT8 Type,
+ IN UINT8 Option
+ );
+
+/**
+ Display Processor Information (Type 4) Upgrade.
+
+ @param[in] Upgrade The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayProcessorUpgrade (
+ IN UINT8 Upgrade,
+ IN UINT8 Option
+ );
+
+/**
+ Display Processor Information (Type 4) Characteristics.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayProcessorCharacteristics (
+ IN UINT16 Type,
+ IN UINT8 Option
+ );
+
+/**
+ Display Memory Controller Information (Type 5) method.
+
+ @param[in] Method The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMcErrorDetectMethod (
+ IN UINT8 Method,
+ IN UINT8 Option
+ );
+
+/**
+ Display Memory Controller Information (Type 5) Capability.
+
+ @param[in] Capability The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMcErrorCorrectCapability (
+ IN UINT8 Capability,
+ IN UINT8 Option
+ );
+
+/**
+ Display Memory Controller Information (Type 5) Support.
+
+ @param[in] Support The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMcInterleaveSupport (
+ IN UINT8 Support,
+ IN UINT8 Option
+ );
+
+/**
+ Display Memory Controller Information (Type 5) speeds.
+
+ @param[in] Speed The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMcMemorySpeeds (
+ IN UINT16 Speed,
+ IN UINT8 Option
+ );
+
+/**
+ Display Memory Controller Information (Type 5) voltage.
+
+ @param[in] Voltage The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMemoryModuleVoltage (
+ IN UINT8 Voltage,
+ IN UINT8 Option
+ );
+
+/**
+ Display Memory Module Information (Type 6) type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMmMemoryType (
+ IN UINT16 Type,
+ IN UINT8 Option
+ );
+
+/**
+ Display Memory Module Information (Type 6) status.
+
+ @param[in] Status The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMmErrorStatus (
+ IN UINT8 Status,
+ IN UINT8 Option
+ );
+
+/**
+ Display Cache Information (Type 7) SRAM Type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayCacheSRAMType (
+ IN UINT16 Type,
+ IN UINT8 Option
+ );
+
+/**
+ Display Cache Information (Type 7) correcting Type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayCacheErrCorrectingType (
+ IN UINT8 Type,
+ IN UINT8 Option
+ );
+
+/**
+ Display Cache Information (Type 7) Type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayCacheSystemCacheType (
+ IN UINT8 Type,
+ IN UINT8 Option
+ );
+
+/**
+ Display Cache Information (Type 7) Associativity.
+
+ @param[in] Associativity The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayCacheAssociativity (
+ IN UINT8 Associativity,
+ IN UINT8 Option
+ );
+
+/**
+ Display Port Connector Information (Type 8) type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayPortConnectorType (
+ IN UINT8 Type,
+ IN UINT8 Option
+ );
+
+/**
+ Display Port Connector Information (Type 8) port type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayPortType (
+ IN UINT8 Type,
+ IN UINT8 Option
+ );
+
+/**
+ Display System Slots (Type 9) slot type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySystemSlotType (
+ IN UINT8 Type,
+ IN UINT8 Option
+ );
+
+/**
+ Display System Slots (Type 9) data bus width.
+
+ @param[in] Width The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySystemSlotDataBusWidth (
+ IN UINT8 Width,
+ IN UINT8 Option
+ );
+
+/**
+ Display System Slots (Type 9) usage information.
+
+ @param[in] Usage The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySystemSlotCurrentUsage (
+ IN UINT8 Usage,
+ IN UINT8 Option
+ );
+
+/**
+ Display System Slots (Type 9) slot length.
+
+ @param[in] Length The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySystemSlotLength (
+ IN UINT8 Length,
+ IN UINT8 Option
+ );
+
+/**
+ Display System Slots (Type 9) characteristics.
+
+ @param[in] Chara1 The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySlotCharacteristics1 (
+ IN UINT8 Chara1,
+ IN UINT8 Option
+ );
+
+/**
+ Display System Slots (Type 9) characteristics.
+
+ @param[in] Chara2 The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySlotCharacteristics2 (
+ IN UINT8 Chara2,
+ IN UINT8 Option
+ );
+
+/**
+ Display On Board Devices Information (Type 10) types.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayOnboardDeviceTypes (
+ IN UINT8 Type,
+ IN UINT8 Option
+ );
+
+/**
+ Display System Event Log (Type 15) types.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySELTypes (
+ IN UINT8 Type,
+ IN UINT8 Option
+ );
+
+/**
+ Display System Event Log (Type 15) format type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySELVarDataFormatType (
+ IN UINT8 Type,
+ IN UINT8 Option
+ );
+
+/**
+ Display System Event Log (Type 15) dw1.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayPostResultsBitmapDw1 (
+ IN UINT32 Key,
+ IN UINT8 Option
+ );
+
+/**
+ Display System Event Log (Type 15) dw2.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayPostResultsBitmapDw2 (
+ IN UINT32 Key,
+ IN UINT8 Option
+ );
+
+/**
+ Display System Event Log (Type 15) type.
+
+ @param[in] SMType The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplaySELSysManagementTypes (
+ IN UINT32 SMType,
+ IN UINT8 Option
+ );
+
+/**
+ Display Physical Memory Array (Type 16) Location.
+
+ @param[in] Location The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayPMALocation (
+ IN UINT8 Location,
+ IN UINT8 Option
+ );
+
+/**
+ Display Physical Memory Array (Type 16) Use.
+
+ @param[in] Use The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayPMAUse (
+ IN UINT8 Use,
+ IN UINT8 Option
+ );
+
+/**
+ Display Physical Memory Array (Type 16) Types.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayPMAErrorCorrectionTypes (
+ IN UINT8 Type,
+ IN UINT8 Option
+ );
+
+/**
+ Display Memory Device (Type 17) form factor.
+
+ @param[in] FormFactor The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMemoryDeviceFormFactor (
+ IN UINT8 FormFactor,
+ IN UINT8 Option
+ );
+
+/**
+ Display Memory Device (Type 17) type.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMemoryDeviceType (
+ IN UINT8 Type,
+ IN UINT8 Option
+ );
+
+/**
+ Display Memory Device (Type 17) details.
+
+ @param[in] Para The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMemoryDeviceTypeDetail (
+ IN UINT16 Para,
+ IN UINT8 Option
+ );
+
+/**
+ Display 32-bit Memory Error Information (Type 18) type.
+
+ @param[in] ErrorType The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMemoryErrorType (
+ IN UINT8 ErrorType,
+ IN UINT8 Option
+ );
+
+/**
+ Display 32-bit Memory Error Information (Type 18) error granularity.
+
+ @param[in] Granularity The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMemoryErrorGranularity (
+ IN UINT8 Granularity,
+ IN UINT8 Option
+ );
+
+/**
+ Display 32-bit Memory Error Information (Type 18) error information.
+
+ @param[in] Operation The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMemoryErrorOperation (
+ IN UINT8 Operation,
+ IN UINT8 Option
+ );
+
+/**
+ Display Built-in Pointing Device (Type 21) type information.
+
+ @param[in] Type The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayPointingDeviceType (
+ IN UINT8 Type,
+ IN UINT8 Option
+ );
+
+/**
+ Display Built-in Pointing Device (Type 21) information.
+
+ @param[in] Interface The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayPointingDeviceInterface (
+ IN UINT8 Interface,
+ IN UINT8 Option
+ );
+
+/**
+ Display Portable Battery (Type 22) information.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayPBDeviceChemistry (
+ IN UINT8 Key,
+ IN UINT8 Option
+ );
+
+/**
+ Display Voltage Probe (Type 26) location information.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayVPLocation (
+ IN UINT8 Key,
+ IN UINT8 Option
+ );
+
+/**
+ Display Voltage Probe (Type 26) status ype information.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayVPStatus (
+ IN UINT8 Key,
+ IN UINT8 Option
+ );
+
+/**
+ Display Cooling (Type 27) status information.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayCoolingDeviceStatus (
+ IN UINT8 Key,
+ IN UINT8 Option
+ );
+
+/**
+ Display Cooling (Type 27) type information.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayCoolingDeviceType (
+ IN UINT8 Key,
+ IN UINT8 Option
+ );
+
+/**
+ Display Temperature Probe (Type 28) status information.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayTemperatureProbeStatus (
+ IN UINT8 Key,
+ IN UINT8 Option
+ );
+
+/**
+ Display Temperature Probe (Type 28) location information.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayTemperatureProbeLoc (
+ IN UINT8 Key,
+ IN UINT8 Option
+ );
+
+/**
+ Display Electrical Current Probe (Type 29) status information.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayECPStatus (
+ IN UINT8 Key,
+ IN UINT8 Option
+ );
+
+/**
+ Display Electrical Current Probe (Type 29) location information.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayECPLoc (
+ IN UINT8 Key,
+ IN UINT8 Option
+ );
+
+/**
+ Display Management Device (Type 34) Type.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMDType (
+ IN UINT8 Key,
+ IN UINT8 Option
+ );
+
+/**
+ Display Management Device (Type 34) Address Type.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMDAddressType (
+ IN UINT8 Key,
+ IN UINT8 Option
+ );
+
+/**
+ Display Memory Channel (Type 37) information.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayMemoryChannelType (
+ IN UINT8 Key,
+ IN UINT8 Option
+ );
+
+/**
+ Display IPMI Device Information (Type 38) information.
+
+ @param[in] Key The key of the structure.
+ @param[in] Option The optional information.
+**/
+VOID
+DisplayIPMIDIBMCInterfaceType (
+ IN UINT8 Key,
+ IN UINT8 Option
+ );
+
+#endif
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosView.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosView.c
new file mode 100644
index 0000000000..a06339452a
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosView.c
@@ -0,0 +1,1013 @@
+/** @file
+ Tools of clarify the content of the smbios table.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "../UefiShellDebug1CommandsLib.h"
+#include "LibSmbiosView.h"
+#include "SmbiosView.h"
+#include "PrintInfo.h"
+#include "QueryTable.h"
+
+UINT8 gShowType = SHOW_DETAIL;
+STATIC STRUCTURE_STATISTICS *mStatisticsTable = NULL;
+STATIC STRUCTURE_STATISTICS *mSmbios64BitStatisticsTable = NULL;
+
+UINT8 SmbiosMajorVersion;
+UINT8 SmbiosMinorVersion;
+
+UINTN mNumberOfSmbios64BitStructures;
+UINTN mSmbios64BitTableLength;
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-t", TypeValue},
+ {L"-h", TypeValue},
+ {L"-s", TypeFlag},
+ {L"-a", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'smbiosview' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunSmbiosView (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ UINT8 StructType;
+ UINT16 StructHandle;
+ EFI_STATUS Status;
+ EFI_STATUS Status1;
+ EFI_STATUS Status2;
+ BOOLEAN RandomView;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ CONST CHAR16 *Temp;
+
+ mStatisticsTable = NULL;
+ mSmbios64BitStatisticsTable = NULL;
+ Package = NULL;
+ ShellStatus = SHELL_SUCCESS;
+
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDebug1HiiHandle, L"smbiosview", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetCount(Package) > 1) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"smbiosview");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetFlag(Package, L"-t") && ShellCommandLineGetValue(Package, L"-t") == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"smbiosview", L"-t");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetFlag(Package, L"-h") && ShellCommandLineGetValue(Package, L"-h") == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDebug1HiiHandle, L"smbiosview", L"-h");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (
+ (ShellCommandLineGetFlag(Package, L"-t") && ShellCommandLineGetFlag(Package, L"-h")) ||
+ (ShellCommandLineGetFlag(Package, L"-t") && ShellCommandLineGetFlag(Package, L"-s")) ||
+ (ShellCommandLineGetFlag(Package, L"-t") && ShellCommandLineGetFlag(Package, L"-a")) ||
+ (ShellCommandLineGetFlag(Package, L"-h") && ShellCommandLineGetFlag(Package, L"-s")) ||
+ (ShellCommandLineGetFlag(Package, L"-h") && ShellCommandLineGetFlag(Package, L"-a")) ||
+ (ShellCommandLineGetFlag(Package, L"-s") && ShellCommandLineGetFlag(Package, L"-a"))
+ ) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDebug1HiiHandle, L"smbiosview");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+
+ //
+ // Init Lib
+ //
+ Status1 = LibSmbiosInit ();
+ Status2 = LibSmbios64BitInit ();
+ if (EFI_ERROR (Status1) && EFI_ERROR (Status2)) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_LIBSMBIOSVIEW_CANNOT_GET_TABLE), gShellDebug1HiiHandle);
+ ShellStatus = SHELL_NOT_FOUND;
+ goto Done;
+ }
+
+ StructType = STRUCTURE_TYPE_RANDOM;
+ RandomView = TRUE;
+
+ Temp = ShellCommandLineGetValue(Package, L"-t");
+ if (Temp != NULL) {
+ StructType = (UINT8) ShellStrToUintn (Temp);
+ }
+
+ if (ShellCommandLineGetFlag(Package, L"-a")) {
+ gShowType = SHOW_ALL;
+ }
+
+ if (!EFI_ERROR (Status1)) {
+ //
+ // Initialize the StructHandle to be the first handle
+ //
+ StructHandle = INVALID_HANDLE;
+ LibGetSmbiosStructure (&StructHandle, NULL, NULL);
+
+ Temp = ShellCommandLineGetValue(Package, L"-h");
+ if (Temp != NULL) {
+ RandomView = FALSE;
+ StructHandle = (UINT16) ShellStrToUintn(Temp);
+ }
+ //
+ // build statistics table
+ //
+ Status = InitSmbiosTableStatistics ();
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_NOT_FOUND;
+ goto Done;
+ }
+
+ if (ShellCommandLineGetFlag(Package, L"-s")) {
+ Status = DisplayStatisticsTable (SHOW_DETAIL);
+ if (EFI_ERROR(Status)) {
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ goto Show64Bit;
+ }
+
+ //
+ // Show SMBIOS structure information
+ //
+ Status = SMBiosView (StructType, StructHandle, gShowType, RandomView);
+ if (EFI_ERROR(Status)) {
+ ShellStatus = SHELL_NOT_FOUND;
+ goto Done;
+ }
+ }
+
+Show64Bit:
+ if (!EFI_ERROR (Status2)) {
+ //
+ // build statistics table
+ //
+ Status = InitSmbios64BitTableStatistics ();
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_NOT_FOUND;
+ goto Done;
+ }
+ //
+ // Initialize the StructHandle to be the first handle
+ //
+ StructHandle = INVALID_HANDLE;
+ LibGetSmbios64BitStructure (&StructHandle, NULL, NULL);
+
+ Temp = ShellCommandLineGetValue(Package, L"-h");
+ if (Temp != NULL) {
+ RandomView = FALSE;
+ StructHandle = (UINT16) ShellStrToUintn(Temp);
+ }
+
+ if (ShellCommandLineGetFlag(Package, L"-s")) {
+ Status = DisplaySmbios64BitStatisticsTable (SHOW_DETAIL);
+ if (EFI_ERROR(Status)) {
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ goto Done;
+ }
+
+ //
+ // Show SMBIOS structure information
+ //
+ Status = SMBios64View (StructType, StructHandle, gShowType, RandomView);
+ if (EFI_ERROR(Status)) {
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ }
+ }
+ }
+Done:
+ //
+ // Release resources
+ //
+ if (mStatisticsTable != NULL) {
+ //
+ // Release statistics table
+ //
+ FreePool (mStatisticsTable);
+ mStatisticsTable = NULL;
+ }
+
+ if (mSmbios64BitStatisticsTable != NULL) {
+ //
+ // Release statistics table
+ //
+ FreePool (mSmbios64BitStatisticsTable);
+ mSmbios64BitStatisticsTable = NULL;
+ }
+
+ if (Package != NULL) {
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ LibSmbiosCleanup ();
+ LibSmbios64BitCleanup ();
+
+ return ShellStatus;
+}
+
+/**
+ Query all structures Data from SMBIOS table and Display
+ the information to users as required display option.
+
+ @param[in] QueryType Structure type to view.
+ @param[in] QueryHandle Structure handle to view.
+ @param[in] Option Display option: none,outline,normal,detail.
+ @param[in] RandomView Support for -h parameter.
+
+ @retval EFI_SUCCESS print is successful.
+ @retval EFI_BAD_BUFFER_SIZE structure is out of the range of SMBIOS table.
+**/
+EFI_STATUS
+EFIAPI
+SMBiosView (
+ IN UINT8 QueryType,
+ IN UINT16 QueryHandle,
+ IN UINT8 Option,
+ IN BOOLEAN RandomView
+ )
+{
+ UINT16 Handle;
+ UINT8 *Buffer;
+ UINT16 Length;
+ UINTN Index;
+
+ SMBIOS_STRUCTURE_POINTER SmbiosStruct;
+ SMBIOS_TABLE_ENTRY_POINT *SMBiosTable;
+
+ SMBiosTable = NULL;
+ LibSmbiosGetEPS (&SMBiosTable);
+ if (SMBiosTable == NULL) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_CANNOT_ACCESS_TABLE), gShellDebug1HiiHandle);
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ if (CompareMem (SMBiosTable->AnchorString, "_SM_", 4) == 0) {
+ //
+ // Have got SMBIOS table
+ //
+ SmbiosPrintEPSInfo (SMBiosTable, Option);
+
+ SmbiosMajorVersion = SMBiosTable->MajorVersion;
+ SmbiosMinorVersion = SMBiosTable->MinorVersion;
+
+ ShellPrintEx(-1,-1,L"=========================================================\n");
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_QUERY_STRUCT_COND), gShellDebug1HiiHandle);
+
+ if (QueryType == STRUCTURE_TYPE_RANDOM) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_QUERYTYPE_RANDOM), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_QUERYTYPE), gShellDebug1HiiHandle, QueryType);
+ }
+
+ if (RandomView) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_QUERYHANDLE_RANDOM), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_QUERYHANDLE), gShellDebug1HiiHandle, QueryHandle);
+ }
+
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_SHOWTYPE), gShellDebug1HiiHandle);
+ ShellPrintEx(-1,-1,GetShowTypeString (gShowType));
+ ShellPrintEx(-1,-1,L"\n\n");
+
+/*
+ //
+ // Get internal commands, such as change options.
+ //
+ Status = WaitEnter ();
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_ABORTED) {
+ return EFI_SUCCESS;
+ }
+
+ return Status;
+ }
+*/
+
+ //
+ // Searching and display structure info
+ //
+ Handle = QueryHandle;
+ for (Index = 0; Index < SMBiosTable->NumberOfSmbiosStructures; Index++) {
+ //
+ // if reach the end of table, break..
+ //
+ if (Handle == INVALID_HANDLE) {
+ break;
+ }
+ //
+ // handle then point to the next!
+ //
+ if (LibGetSmbiosStructure (&Handle, &Buffer, &Length) != DMI_SUCCESS) {
+ break;
+ }
+
+ SmbiosStruct.Raw = Buffer;
+
+ //
+ // if QueryType==Random, print this structure.
+ // if QueryType!=Random, but Hdr->Type==QueryType, also print it.
+ // only if QueryType != Random and Hdr->Type != QueryType, skiped it.
+ //
+ if (QueryType != STRUCTURE_TYPE_RANDOM && SmbiosStruct.Hdr->Type != QueryType) {
+ continue;
+ }
+
+ ShellPrintEx(-1,-1,L"\n=========================================================\n");
+ ShellPrintHiiEx(-1,-1,NULL,
+ STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_TYPE_HANDLE_DUMP_STRUCT),
+ gShellDebug1HiiHandle,
+ SmbiosStruct.Hdr->Type,
+ SmbiosStruct.Hdr->Handle
+ );
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_INDEX_LENGTH), gShellDebug1HiiHandle, Index, Length);
+ //
+ // Addr of structure in structure in table
+ //
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_ADDR), gShellDebug1HiiHandle, (UINTN) Buffer);
+ DumpHex (0, 0, Length, Buffer);
+
+/*
+ //
+ // Get internal commands, such as change options.
+ //
+ Status = WaitEnter ();
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_ABORTED) {
+ return EFI_SUCCESS;
+ }
+
+ return Status;
+ }
+*/
+
+ if (gShowType != SHOW_NONE) {
+ //
+ // Print structure information
+ //
+ SmbiosPrintStructure (&SmbiosStruct, gShowType);
+ ShellPrintEx(-1,-1,L"\n");
+
+/*
+ //
+ // Get internal commands, such as change options.
+ //
+ Status = WaitEnter ();
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_ABORTED) {
+ return EFI_SUCCESS;
+ }
+
+ return Status;
+ }
+*/
+ }
+ if (!RandomView) {
+ break;
+ }
+ //
+ // Support Execution Interrupt.
+ //
+ if (ShellGetExecutionBreakFlag ()) {
+ return EFI_ABORTED;
+ }
+ }
+
+ ShellPrintEx(-1,-1,L"\n=========================================================\n");
+ return EFI_SUCCESS;
+ }
+
+ return EFI_BAD_BUFFER_SIZE;
+}
+
+/**
+ Query all structures Data from SMBIOS table and Display
+ the information to users as required display option.
+
+ @param[in] QueryType Structure type to view.
+ @param[in] QueryHandle Structure handle to view.
+ @param[in] Option Display option: none,outline,normal,detail.
+ @param[in] RandomView Support for -h parameter.
+
+ @retval EFI_SUCCESS print is successful.
+ @retval EFI_BAD_BUFFER_SIZE structure is out of the range of SMBIOS table.
+**/
+EFI_STATUS
+EFIAPI
+SMBios64View (
+ IN UINT8 QueryType,
+ IN UINT16 QueryHandle,
+ IN UINT8 Option,
+ IN BOOLEAN RandomView
+ )
+{
+ UINT16 Handle;
+ UINT8 *Buffer;
+ UINT16 Length;
+ UINTN Index;
+ SMBIOS_STRUCTURE_POINTER SmbiosStruct;
+ SMBIOS_TABLE_3_0_ENTRY_POINT *SMBiosTable;
+
+ SMBiosTable = NULL;
+ LibSmbios64BitGetEPS (&SMBiosTable);
+ if (SMBiosTable == NULL) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_CANNOT_ACCESS_TABLE), gShellDebug1HiiHandle);
+ return EFI_BAD_BUFFER_SIZE;
+ }
+
+ if (CompareMem (SMBiosTable->AnchorString, "_SM3_", 5) == 0) {
+ //
+ // Have got SMBIOS table
+ //
+ Smbios64BitPrintEPSInfo (SMBiosTable, Option);
+
+ SmbiosMajorVersion = SMBiosTable->MajorVersion;
+ SmbiosMinorVersion = SMBiosTable->MinorVersion;
+
+ ShellPrintEx(-1,-1,L"=========================================================\n");
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_QUERY_STRUCT_COND), gShellDebug1HiiHandle);
+
+ if (QueryType == STRUCTURE_TYPE_RANDOM) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_QUERYTYPE_RANDOM), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_QUERYTYPE), gShellDebug1HiiHandle, QueryType);
+ }
+
+ if (RandomView) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_QUERYHANDLE_RANDOM), gShellDebug1HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_QUERYHANDLE), gShellDebug1HiiHandle, QueryHandle);
+ }
+
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_SHOWTYPE), gShellDebug1HiiHandle);
+ ShellPrintEx(-1,-1,GetShowTypeString (gShowType));
+ ShellPrintEx(-1,-1,L"\n\n");
+
+/*
+ //
+ // Get internal commands, such as change options.
+ //
+ Status = WaitEnter ();
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_ABORTED) {
+ return EFI_SUCCESS;
+ }
+
+ return Status;
+ }
+*/
+
+ //
+ // Searching and display structure info
+ //
+ Handle = QueryHandle;
+ for (Index = 0; Index < mNumberOfSmbios64BitStructures; Index++) {
+ //
+ // if reach the end of table, break..
+ //
+ if (Handle == INVALID_HANDLE) {
+ break;
+ }
+ //
+ // handle then point to the next!
+ //
+ if (LibGetSmbios64BitStructure (&Handle, &Buffer, &Length) != DMI_SUCCESS) {
+ break;
+ }
+
+ SmbiosStruct.Raw = Buffer;
+
+ //
+ // if QueryType==Random, print this structure.
+ // if QueryType!=Random, but Hdr->Type==QueryType, also print it.
+ // only if QueryType != Random and Hdr->Type != QueryType, skiped it.
+ //
+ if (QueryType != STRUCTURE_TYPE_RANDOM && SmbiosStruct.Hdr->Type != QueryType) {
+ continue;
+ }
+
+ ShellPrintEx(-1,-1,L"\n=========================================================\n");
+ ShellPrintHiiEx(-1,-1,NULL,
+ STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_TYPE_HANDLE_DUMP_STRUCT),
+ gShellDebug1HiiHandle,
+ SmbiosStruct.Hdr->Type,
+ SmbiosStruct.Hdr->Handle
+ );
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_INDEX_LENGTH), gShellDebug1HiiHandle, Index, Length);
+ //
+ // Addr of structure in structure in table
+ //
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_ADDR), gShellDebug1HiiHandle, (UINTN) Buffer);
+ DumpHex (0, 0, Length, Buffer);
+
+/*
+ //
+ // Get internal commands, such as change options.
+ //
+ Status = WaitEnter ();
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_ABORTED) {
+ return EFI_SUCCESS;
+ }
+
+ return Status;
+ }
+*/
+
+ if (gShowType != SHOW_NONE) {
+ //
+ // Print structure information
+ //
+ SmbiosPrintStructure (&SmbiosStruct, gShowType);
+ ShellPrintEx(-1,-1,L"\n");
+
+/*
+ //
+ // Get internal commands, such as change options.
+ //
+ Status = WaitEnter ();
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_ABORTED) {
+ return EFI_SUCCESS;
+ }
+
+ return Status;
+ }
+*/
+ }
+ if (!RandomView) {
+ break;
+ }
+ //
+ // Support Execution Interrupt.
+ //
+ if (ShellGetExecutionBreakFlag ()) {
+ return EFI_ABORTED;
+ }
+ }
+
+ ShellPrintEx(-1,-1,L"\n=========================================================\n");
+ return EFI_SUCCESS;
+ }
+
+ return EFI_BAD_BUFFER_SIZE;
+}
+
+/**
+ Function to initialize the global mStatisticsTable object.
+
+ @retval EFI_SUCCESS print is successful.
+**/
+EFI_STATUS
+EFIAPI
+InitSmbiosTableStatistics (
+ VOID
+ )
+{
+ UINT16 Handle;
+ UINT8 *Buffer;
+ UINT16 Length;
+ UINT16 Offset;
+ UINT16 Index;
+
+ SMBIOS_STRUCTURE_POINTER SmbiosStruct;
+ SMBIOS_TABLE_ENTRY_POINT *SMBiosTable;
+ STRUCTURE_STATISTICS *StatisticsPointer;
+
+ SMBiosTable = NULL;
+ LibSmbiosGetEPS (&SMBiosTable);
+ if (SMBiosTable == NULL) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_CANNOT_ACCESS_TABLE), gShellDebug1HiiHandle);
+ return EFI_NOT_FOUND;
+ }
+
+ if (CompareMem (SMBiosTable->AnchorString, "_SM_", 4) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_SMBIOS_TABLE), gShellDebug1HiiHandle);
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Allocate memory to mStatisticsTable
+ //
+ if (mStatisticsTable != NULL) {
+ FreePool (mStatisticsTable);
+ mStatisticsTable = NULL;
+ }
+
+ mStatisticsTable = (STRUCTURE_STATISTICS *) AllocateZeroPool (SMBiosTable->NumberOfSmbiosStructures * sizeof (STRUCTURE_STATISTICS));
+
+ if (mStatisticsTable == NULL) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_OUT_OF_MEM), gShellDebug1HiiHandle);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Offset = 0;
+ StatisticsPointer = mStatisticsTable;
+
+ //
+ // search from the first one
+ //
+ Handle = INVALID_HANDLE;
+ LibGetSmbiosStructure (&Handle, NULL, NULL);
+ for (Index = 1; Index <= SMBiosTable->NumberOfSmbiosStructures; Index++) {
+ //
+ // If reach the end of table, break..
+ //
+ if (Handle == INVALID_HANDLE) {
+ break;
+ }
+ //
+ // After LibGetSmbiosStructure(), handle then point to the next!
+ //
+ if (LibGetSmbiosStructure (&Handle, &Buffer, &Length) != DMI_SUCCESS) {
+ break;
+ }
+
+ SmbiosStruct.Raw = Buffer;
+
+ //
+ // general statistics
+ //
+ StatisticsPointer->Index = Index;
+ StatisticsPointer->Type = SmbiosStruct.Hdr->Type;
+ StatisticsPointer->Handle = SmbiosStruct.Hdr->Handle;
+ StatisticsPointer->Length = Length;
+ StatisticsPointer->Addr = Offset;
+
+ Offset = (UINT16) (Offset + Length);
+
+ StatisticsPointer = &mStatisticsTable[Index];
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ @param[in] Smbios64EntryPoint SMBIOS 64-bit entry point.
+ @param[out] NumberOfSmbios64Structures The number of structures in 64-bit SMBIOS table.
+ @param[out] Smbios64TableLength The total length of 64-bit SMBIOS table.
+
+ @retval EFI_SUCCESS Calculation was successful.
+**/
+EFI_STATUS
+EFIAPI
+CalculateSmbios64BitStructureCountAndLength (
+ SMBIOS_TABLE_3_0_ENTRY_POINT *Smbios64EntryPoint,
+ UINTN *NumberOfSmbios64Structures,
+ UINTN *Smbios64TableLength
+)
+{
+ SMBIOS_STRUCTURE_POINTER Smbios;
+ UINT8 *Raw;
+
+ *Smbios64TableLength = 0;
+ *NumberOfSmbios64Structures = 0;
+
+ Smbios.Raw = (UINT8 *)(UINTN)(Smbios64EntryPoint->TableAddress);
+ while (TRUE) {
+ if (Smbios.Hdr->Type == 127) {
+ //
+ // Reach the end of table type 127
+ //
+ (*NumberOfSmbios64Structures)++;
+ (*Smbios64TableLength) += sizeof (SMBIOS_STRUCTURE);
+ return EFI_SUCCESS;
+ }
+
+ Raw = Smbios.Raw;
+ //
+ // Walk to next structure
+ //
+ LibGetSmbiosString (&Smbios, (UINT16) (-1));
+ //
+ // Length = Next structure head - this structure head
+ //
+ (*Smbios64TableLength) += (UINTN) (Smbios.Raw - Raw);
+ if ((*Smbios64TableLength) > Smbios64EntryPoint->TableMaximumSize) {
+ //
+ // The actual table length exceeds maximum table size,
+ // There should be something wrong with SMBIOS table.
+ //
+ return EFI_INVALID_PARAMETER;
+ }
+ (*NumberOfSmbios64Structures)++;
+ }
+}
+
+/**
+ Function to initialize the global mSmbios64BitStatisticsTable object.
+
+ @retval EFI_SUCCESS print is successful.
+**/
+EFI_STATUS
+EFIAPI
+InitSmbios64BitTableStatistics (
+ VOID
+ )
+{
+ UINT16 Handle;
+ UINT8 *Buffer;
+ UINT16 Length;
+ UINT16 Offset;
+ UINT16 Index;
+ EFI_STATUS Status;
+ SMBIOS_STRUCTURE_POINTER SmbiosStruct;
+ SMBIOS_TABLE_3_0_ENTRY_POINT *SMBiosTable;
+ STRUCTURE_STATISTICS *StatisticsPointer;
+
+ SMBiosTable = NULL;
+ LibSmbios64BitGetEPS (&SMBiosTable);
+ if (SMBiosTable == NULL) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_CANNOT_ACCESS_TABLE), gShellDebug1HiiHandle);
+ return EFI_NOT_FOUND;
+ }
+
+ if (CompareMem (SMBiosTable->AnchorString, "_SM3_", 5) != 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_SMBIOS_TABLE), gShellDebug1HiiHandle);
+ return EFI_INVALID_PARAMETER;
+ }
+ //
+ // Allocate memory to mSmbios64BitStatisticsTable
+ //
+ if (mSmbios64BitStatisticsTable != NULL) {
+ FreePool (mSmbios64BitStatisticsTable);
+ mSmbios64BitStatisticsTable = NULL;
+ }
+ //
+ // Calculate number of smbios structures
+ //
+ Status = CalculateSmbios64BitStructureCountAndLength (SMBiosTable, &mNumberOfSmbios64BitStructures, &mSmbios64BitTableLength);
+ if ((EFI_ERROR (Status)) || (mSmbios64BitTableLength > SMBiosTable->TableMaximumSize)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ mSmbios64BitStatisticsTable = (STRUCTURE_STATISTICS *) AllocateZeroPool (mNumberOfSmbios64BitStructures * sizeof (STRUCTURE_STATISTICS));
+
+ if (mSmbios64BitStatisticsTable == NULL) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_OUT_OF_MEM), gShellDebug1HiiHandle);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Offset = 0;
+ StatisticsPointer = mSmbios64BitStatisticsTable;
+
+ //
+ // search from the first one
+ //
+ Handle = INVALID_HANDLE;
+ LibGetSmbios64BitStructure (&Handle, NULL, NULL);
+ for (Index = 1; Index <= mNumberOfSmbios64BitStructures; Index++) {
+ //
+ // If reach the end of table, break..
+ //
+ if (Handle == INVALID_HANDLE) {
+ break;
+ }
+ //
+ // After LibGetSmbios64BitStructure(), handle then point to the next!
+ //
+ if (LibGetSmbios64BitStructure (&Handle, &Buffer, &Length) != DMI_SUCCESS) {
+ break;
+ }
+
+ SmbiosStruct.Raw = Buffer;
+
+ //
+ // general statistics
+ //
+ StatisticsPointer->Index = Index;
+ StatisticsPointer->Type = SmbiosStruct.Hdr->Type;
+ StatisticsPointer->Handle = SmbiosStruct.Hdr->Handle;
+ StatisticsPointer->Length = Length;
+ StatisticsPointer->Addr = Offset;
+
+ Offset = (UINT16) (Offset + Length);
+
+ StatisticsPointer = &mSmbios64BitStatisticsTable[Index];
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Function to display the global mStatisticsTable object.
+
+ @param[in] Option ECHO, NORMAL, or DETAIL control the amount of detail displayed.
+
+ @retval EFI_SUCCESS print is successful.
+**/
+EFI_STATUS
+EFIAPI
+DisplayStatisticsTable (
+ IN UINT8 Option
+ )
+{
+ UINTN Index;
+ UINTN Num;
+ STRUCTURE_STATISTICS *StatisticsPointer;
+ SMBIOS_TABLE_ENTRY_POINT *SMBiosTable;
+
+ SMBiosTable = NULL;
+ if (Option < SHOW_OUTLINE) {
+ return EFI_SUCCESS;
+ }
+ //
+ // display EPS information firstly
+ //
+ LibSmbiosGetEPS (&SMBiosTable);
+ if (SMBiosTable == NULL) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_CANNOT_ACCESS_TABLE), gShellDebug1HiiHandle);
+ return EFI_UNSUPPORTED;
+ }
+
+ ShellPrintEx(-1,-1,L"\n============================================================\n");
+ SmbiosPrintEPSInfo (SMBiosTable, Option);
+
+ if (Option < SHOW_NORMAL) {
+ return EFI_SUCCESS;
+ }
+
+ if (mStatisticsTable == NULL) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_CANNOT_ACCESS_STATS), gShellDebug1HiiHandle);
+ return EFI_NOT_FOUND;
+ }
+
+ ShellPrintEx(-1,-1,L"============================================================\n");
+ StatisticsPointer = &mStatisticsTable[0];
+ Num = SMBiosTable->NumberOfSmbiosStructures;
+ //
+ // display statistics table content
+ //
+ for (Index = 1; Index <= Num; Index++) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_INDEX), gShellDebug1HiiHandle, StatisticsPointer->Index);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_TYPE), gShellDebug1HiiHandle, StatisticsPointer->Type);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_HANDLE), gShellDebug1HiiHandle, StatisticsPointer->Handle);
+ if (Option >= SHOW_DETAIL) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_OFFSET), gShellDebug1HiiHandle, StatisticsPointer->Addr);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_LENGTH), gShellDebug1HiiHandle, StatisticsPointer->Length);
+ }
+
+ ShellPrintEx(-1,-1,L"\n");
+ StatisticsPointer = &mStatisticsTable[Index];
+/*
+ //
+ // Display 20 lines and wait for a page break
+ //
+ if (Index % 20 == 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_ENTER_CONTINUE), gShellDebug1HiiHandle);
+ Status = WaitEnter ();
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_ABORTED) {
+ return EFI_SUCCESS;
+ }
+
+ return Status;
+ }
+ }
+*/
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Function to display the global mSmbios64BitStatisticsTable object.
+
+ @param[in] Option ECHO, NORMAL, or DETAIL control the amount of detail displayed.
+
+ @retval EFI_SUCCESS print is successful.
+**/
+EFI_STATUS
+EFIAPI
+DisplaySmbios64BitStatisticsTable (
+ IN UINT8 Option
+ )
+{
+ UINTN Index;
+ UINTN Num;
+ STRUCTURE_STATISTICS *StatisticsPointer;
+ SMBIOS_TABLE_3_0_ENTRY_POINT *SMBiosTable;
+
+ SMBiosTable = NULL;
+ if (Option < SHOW_OUTLINE) {
+ return EFI_SUCCESS;
+ }
+ //
+ // display EPS information firstly
+ //
+ LibSmbios64BitGetEPS (&SMBiosTable);
+ if (SMBiosTable == NULL) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_CANNOT_ACCESS_TABLE), gShellDebug1HiiHandle);
+ return EFI_UNSUPPORTED;
+ }
+
+ ShellPrintEx(-1,-1,L"\n============================================================\n");
+ Smbios64BitPrintEPSInfo (SMBiosTable, Option);
+
+ if (Option < SHOW_NORMAL) {
+ return EFI_SUCCESS;
+ }
+
+ if (mSmbios64BitStatisticsTable == NULL) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_CANNOT_ACCESS_STATS), gShellDebug1HiiHandle);
+ return EFI_NOT_FOUND;
+ }
+
+ ShellPrintEx(-1,-1,L"============================================================\n");
+ StatisticsPointer = &mSmbios64BitStatisticsTable[0];
+ Num = mNumberOfSmbios64BitStructures;
+ //
+ // display statistics table content
+ //
+ for (Index = 1; Index <= Num; Index++) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_INDEX), gShellDebug1HiiHandle, StatisticsPointer->Index);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_TYPE), gShellDebug1HiiHandle, StatisticsPointer->Type);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_HANDLE), gShellDebug1HiiHandle, StatisticsPointer->Handle);
+ if (Option >= SHOW_DETAIL) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_OFFSET), gShellDebug1HiiHandle, StatisticsPointer->Addr);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_LENGTH), gShellDebug1HiiHandle, StatisticsPointer->Length);
+ }
+
+ ShellPrintEx(-1,-1,L"\n");
+ StatisticsPointer = &mSmbios64BitStatisticsTable[Index];
+/*
+ //
+ // Display 20 lines and wait for a page break
+ //
+ if (Index % 20 == 0) {
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_SMBIOSVIEW_SMBIOSVIEW_ENTER_CONTINUE), gShellDebug1HiiHandle);
+ Status = WaitEnter ();
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_ABORTED) {
+ return EFI_SUCCESS;
+ }
+
+ return Status;
+ }
+ }
+*/
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ function to return a string of the detail level.
+
+ @param[in] ShowType The detail level whose name is desired in clear text.
+
+ @return A pointer to a string representing the ShowType (or 'undefined type' if not known).
+**/
+CHAR16 *
+EFIAPI
+GetShowTypeString (
+ UINT8 ShowType
+ )
+{
+ //
+ // show type
+ //
+ switch (ShowType) {
+
+ case SHOW_NONE:
+ return L"SHOW_NONE";
+
+ case SHOW_OUTLINE:
+ return L"SHOW_OUTLINE";
+
+ case SHOW_NORMAL:
+ return L"SHOW_NORMAL";
+
+ case SHOW_DETAIL:
+ return L"SHOW_DETAIL";
+
+ case SHOW_ALL:
+ return L"SHOW_ALL";
+
+ default:
+ return L"Undefined type";
+ }
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosView.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosView.h
new file mode 100644
index 0000000000..647fd5fe26
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosView.h
@@ -0,0 +1,136 @@
+/** @file
+ Tools of clarify the content of the smbios table.
+
+ Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _SMBIOS_VIEW_H_
+#define _SMBIOS_VIEW_H_
+
+#define STRUCTURE_TYPE_RANDOM (UINT8) 0xFE
+#define STRUCTURE_TYPE_INVALID (UINT8) 0xFF
+
+typedef struct {
+ UINT16 Index;
+ UINT8 Type;
+ UINT16 Handle;
+ UINT16 Addr; // offset from table head
+ UINT16 Length; // total structure length
+} STRUCTURE_STATISTICS;
+
+/**
+ Query all structures Data from SMBIOS table and Display
+ the information to users as required display option.
+
+ @param[in] QueryType Structure type to view.
+ @param[in] QueryHandle Structure handle to view.
+ @param[in] Option Display option: none,outline,normal,detail.
+ @param[in] RandomView Support for -h parameter.
+
+ @retval EFI_SUCCESS print is successful.
+ @retval EFI_BAD_BUFFER_SIZE structure is out of the range of SMBIOS table.
+**/
+EFI_STATUS
+EFIAPI
+SMBiosView (
+ IN UINT8 QueryType,
+ IN UINT16 QueryHandle,
+ IN UINT8 Option,
+ IN BOOLEAN RandomView
+ );
+
+/**
+ Query all structures Data from SMBIOS table and Display
+ the information to users as required display option.
+
+ @param[in] QueryType Structure type to view.
+ @param[in] QueryHandle Structure handle to view.
+ @param[in] Option Display option: none,outline,normal,detail.
+ @param[in] RandomView Support for -h parameter.
+
+ @retval EFI_SUCCESS print is successful.
+ @retval EFI_BAD_BUFFER_SIZE structure is out of the range of SMBIOS table.
+**/
+EFI_STATUS
+EFIAPI
+SMBios64View (
+ IN UINT8 QueryType,
+ IN UINT16 QueryHandle,
+ IN UINT8 Option,
+ IN BOOLEAN RandomView
+ );
+
+/**
+ Function to initialize the global mStatisticsTable object.
+
+ @retval EFI_SUCCESS print is successful.
+**/
+EFI_STATUS
+EFIAPI
+InitSmbiosTableStatistics (
+ VOID
+ );
+
+/**
+ Function to initialize the global mSmbios64BitStatisticsTable object.
+
+ @retval EFI_SUCCESS print is successful.
+**/
+EFI_STATUS
+EFIAPI
+InitSmbios64BitTableStatistics (
+ VOID
+ );
+
+/**
+ Function to display the global mStatisticsTable object.
+
+ @param[in] Option ECHO, NORMAL, or DETAIL control the amount of detail displayed.
+
+ @retval EFI_SUCCESS print is successful.
+**/
+EFI_STATUS
+EFIAPI
+DisplayStatisticsTable (
+ IN UINT8 Option
+ );
+
+/**
+ Function to display the global mSmbios64BitStatisticsTable object.
+
+ @param[in] Option ECHO, NORMAL, or DETAIL control the amount of detail displayed.
+
+ @retval EFI_SUCCESS print is successful.
+**/
+EFI_STATUS
+EFIAPI
+DisplaySmbios64BitStatisticsTable (
+ IN UINT8 Option
+ );
+
+/**
+ function to return a string of the detail level.
+
+ @param[in] ShowType The detail level whose name is desired in clear text.
+
+ @return A pointer to a string representing the ShowType (or 'undefined type' if not known).
+**/
+CHAR16*
+EFIAPI
+GetShowTypeString (
+ UINT8 ShowType
+ );
+
+extern UINT8 gShowType;
+
+extern UINTN mSmbios64BitTableLength;
+
+#endif
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosViewStrings.uni b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosViewStrings.uni
new file mode 100644
index 0000000000..9811542013
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/SmbiosView/SmbiosViewStrings.uni
@@ -0,0 +1,491 @@
+// /**
+//
+// Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>
+// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.<BR>
+// (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// Module Name:
+//
+// UefiShellDebug1CommandsLib.uni
+//
+// Abstract:
+//
+// String definitions for UEFI Shell 2.0 Debug1 profile SmBiosView command
+//
+//
+// **/
+/=#
+#langdef en-US "english"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_ACCESS_METHOD #language en-US "Access method: "
+#string STR_SMBIOSVIEW_EVENTLOGINFO_ONE_EIGHT_BIT #language en-US "Indexed I/O: 1 8-bit index port, 1 8-bit data port\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_TWO_EIGHT_BITS #language en-US "Indexed I/O: 2 8-bit index ports, 1 8-bit data port\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_ONE_SIXTEEN_BIT #language en-US "Indexed I/O: 1 16-bit index port, 1 8-bit data port\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_MEM_MAPPED_PHYS #language en-US "Memory-mapped physical 32-bit address\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_AVAIL_VIA_GENERAL #language en-US "Available via General-Purpose NonVolatile Data functions\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_AVAIL_FOR_FUTURE_ASSIGN #language en-US "Available for future assignment via this specification\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_BIOS_VENDOR_OEM #language en-US "BIOS Vendor/OEM-specific \r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_LOG_STATUS #language en-US "Log Status: "
+#string STR_SMBIOSVIEW_EVENTLOGINFO_LOG_AREA_VALID #language en-US "Log area valid\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_LOG_AREA_FULL #language en-US "Log area full\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_LOG_AREA_NOT_FULL #language en-US "Log area not full\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_RES_BITS_NOT_ZERO #language en-US "Reserved bits not zero - 0x%x\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_LOG_HEADER_FORMAT #language en-US "Log Header Format: \r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_NO_HEADER #language en-US "No Header\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_TYPE_LOG_HEADER #language en-US "Type 1 log header\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_AVAIL_FOR_FUTURE #language en-US "Available for future\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_BIOS_VENDOR #language en-US "BIOS Vendor/OEM-specific format\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_LOG_HEADER_LEN #language en-US "Log Header Len: "
+#string STR_SMBIOSVIEW_EVENTLOGINFO_ONE_VAR_D #language en-US " %d\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_THIS_RECORD_READ #language en-US "This record has been read\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_THIS_RECORD_NOT_READ #language en-US "This record has not been read\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_SYSTEM_EVENT_LOG #language en-US "System Event Log Header Type1 Format:\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_OEM_RESERVED #language en-US "OEM Reserved:\r\n0x%x 0x%x 0x%x 0x%x 0x%x\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_MULTIPLE_EVENT_TIME #language en-US "Multiple Event Time Window: 0x%x\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_MULTIPLE_EVENT_COUNT #language en-US "Multiple Event Count Increment: 0x%x\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_PREBOOT_ADDRESS #language en-US "Pre-boot Event Log Reset - CMOS Address: 0x%x\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_PREBOOT_INDEX #language en-US "Pre-boot Event Log Reset - CMOS Bit Index: 0x%x\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_CHECKSUM_STARTING_OFF #language en-US "CMOS Checksum - Starting Offset: 0x%x\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_CHECKSUN_BYTE_COUNT #language en-US "CMOS Checksum - Byte Count: 0x%x\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_RESERVED #language en-US "Reserved: 0x%x 0x%x 0x%x\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_HEADER_REVISION #language en-US "HeaderRevision: 0x%x\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_LOG_HEADER #language en-US "\r\nLog Header: "
+#string STR_SMBIOSVIEW_EVENTLOGINFO_AVAIL_FUTURE_ASSIGN #language en-US "Available for future assignment via this specification\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_NO_STD_FORMAT #language en-US "No standard format data is available\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_SMBIOS_STRUCT_ASSOC #language en-US "SMBIOS structure associated with the hardware element that failed\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_STRUCT_HANDLE #language en-US "Structure handle = 0x%x\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_MULT_EVENT_COUNTER #language en-US "multiple-event counter: 0x%x\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_UNUSED_AVAIL_FOR_ASSIGN #language en-US "Unused, available for assignment by this specification\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_AVAIL_FOR_SYSTEM #language en-US "Available for system- and OEM-specific assignments\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_SYSTEM_EVENT_LOG_2 #language en-US "\r\nSystem Event Log records:\r\n"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_DATE #language en-US "Date/Time: "
+#string STR_SMBIOSVIEW_EVENTLOGINFO_ERROR #language en-US "error"
+#string STR_SMBIOSVIEW_EVENTLOGINFO_TIME_SIX_VARS #language en-US "%02x/%02x/%02x, %x:%x:%x\r\n"
+#string STR_SMBIOSVIEW_LIBSMBIOSVIEW_CANNOT_GET_TABLE #language en-US "Cannot get SMBIOS Table\r\n"
+#string STR_SMBIOSVIEW_LIBSMBIOSVIEW_GET_TABLE_ERROR #language en-US "Get SMBIOS Table error - %r\r\n"
+#string STR_SMBIOSVIEW_LIBSMBIOSVIEW_NO_BUFF_LEN_SPEC #language en-US " Get SMBIOS Structure, no buffer or length specified!\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_DUMP #language en-US "Dump "
+#string STR_SMBIOSVIEW_PRINTINFO_SIZE #language en-US "\r\nsize=%d:\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_SMBIOSTABLE_NULL #language en-US "SMBiosTable is NULL!\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_ENTRY_POINT_SIGN #language en-US "%HSMBIOS Entry Point Structure:%N\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_64_BIT_ENTRY_POINT_SIGN #language en-US "%HSMBIOS 3.0 (64-bit) Entry Point Structure:%N\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BCD_REVISION #language en-US "SMBIOS BCD Revision: 0x%x\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_DOCREV #language en-US "SMBIOS Docrev: 0x%x\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_NUMBER_STRUCT #language en-US "Number of Structures: %d\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_MAX_STRUCT_SIZE #language en-US "Max Struct size: %d\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_TABLE_ADDR #language en-US "Table Address: 0x%p\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_TABLE_LENGTH #language en-US "Table Length: %d\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_TABLE_MAX_SIZE #language en-US "Table Max Size: %d\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_ANCHOR_STR #language en-US "Anchor String: %a\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_EPS_CHECKSUM #language en-US "EPS Checksum: 0x%x\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_ENTRY_POINT_LEN #language en-US "Entry Point Len: %d\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_VERSION #language en-US "Version: %d.%d\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_MAJOR_VERSION #language en-US "Major version: %d\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_MINOR_VERSION #language en-US "Minor version: %d\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_ENTRY_POINT_REVISION #language en-US "Entry Point revision: 0x%x\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_FORMATTED_AREA_NONE #language en-US "Formatted Area: None\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_FORMATTED_AREA #language en-US "Formatted Area: \r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTER_ACHOR #language en-US "Inter Anchor: %a\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTER_CHECKSUM #language en-US "Inter Checksum: 0x%x\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_FORMAT_PART_LEN #language en-US "Format part Len : %d\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_STRUCT_HANDLE #language en-US "Structure Handle: %d\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BOOTUP_STATE #language en-US "Bootup state "
+#string STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_STATE #language en-US "Power Supply State "
+#string STR_SMBIOSVIEW_PRINTINFO_THERMAL_STATE #language en-US "Thermal state "
+#string STR_SMBIOSVIEW_PRINTINFO_SECURITY_STATUS #language en-US "Security Status "
+#string STR_SMBIOSVIEW_PRINTINFO_SUPOPRT #language en-US "Support "
+#string STR_SMBIOSVIEW_PRINTINFO_CURRENT #language en-US "Current "
+#string STR_SMBIOSVIEW_PRINTINFO_INSTALLED #language en-US "Installed "
+#string STR_SMBIOSVIEW_PRINTINFO_ENABLED #language en-US "Enabled "
+#string STR_SMBIOSVIEW_PRINTINFO_EXTERNAL #language en-US "External "
+#string STR_SMBIOSVIEW_PRINTINFO_DESC_STRING #language en-US "Description String: "
+#string STR_SMBIOSVIEW_PRINTINFO_SUPOPRTED_EVENT #language en-US "Supported Event Log Type Descriptors %d:\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_ACCESS_METHOD_NOT_SUPOPRTED #language en-US "Access Method %d has not supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_STRUCT_TYPE31 #language en-US "This structure is Type31, reserved by BIS (Boot Integrity Services)\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_MEM_DEVICE #language en-US "Memory Device %d:\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_DEV_LOAD #language en-US "Device Load: 0x%02x,"
+#string STR_SMBIOSVIEW_PRINTINFO_DEV_HANDLE #language en-US "Device Handle: 0x%04x\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INACTIVE_STRUCT #language en-US "Inactive structure --- Needn't interpret it.\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_THIS_STRUCT_END_TABLE #language en-US "This structure indicates the End-of-table!\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_STRUCT_TYPE_UNDEFINED #language en-US "Structure Type undefined!\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BIOS_CHAR #language en-US "BIOS Characteristics: \r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_RESERVED_BIT #language en-US "Reserved bit\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_UNKNOWN_BIT #language en-US "Unknown bit\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BIOS_CHAR_NOT_SUPPORTED #language en-US "BIOS Characteristics Not Supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_ISA_SUPPORTED #language en-US "ISA is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_MSA_SUPPORTED #language en-US "MSA is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_EISA_SUPPORTED #language en-US "EISA is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_PCI_SUPPORTED #language en-US "PCI is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_PC_CARD_SUPPORTED #language en-US "PC Card(PCMCIA) is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_PLUG_PLAY_SUPPORTED #language en-US "Plug and play is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_APM_SUPPORTED #language en-US "APM is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BIOS_UPGRADEABLE #language en-US "BIOS is Upgradeable(FLASH)\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BIOS_SHADOWING #language en-US "BIOS shadowing is allowed\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_VESA_SUPPORTED #language en-US "VL-VESA is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_ECSD_SUPPORT #language en-US "ESCD support is available\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BOOT_FORM_CD_SUPPORTED #language en-US "Boot form CD is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_SELECTED_BOOT_SUPPORTED #language en-US "Selectable Boot is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BIOS_ROM_SOCKETED #language en-US "BIOS ROM is socketed\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BOOT_FROM_PC_CARD #language en-US "Boot From PC Card(PCMCIA)is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_EDD_ENHANCED_DRIVER #language en-US "EDD Enhanced Disk Driver) Specification is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_JAPANESE_FLOPPY_NEC #language en-US "Int 13h - Japanese Floppy for NEC 9800 1.2mb (3.5\",1k Bytes/Sector, 360 RPM) is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_JAPANESE_FLOPPY_TOSHIBA #language en-US "Int 13h - Japanese Floppy for Toshiba 1.2mn (3.5\", 360 RPM) is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_FLOPPY_SERVICES_SUPPORTED #language en-US "Int 13h - 5.25\"/360KB Floppy Services are supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_ONE_POINT_TWO_MB #language en-US "Int 13h - 5.25\"/1.2MB Floppy services are supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_720_KB #language en-US "Int 13h - 3.5\"/720KB Floppy services are supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_TWO_POINT_EIGHT_EIGHT_MB #language en-US "Int 13h - 3.5\"/2.88MB Floppy services are supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_PRINT_SCREEN_SUPPORT #language en-US "Int 5h, Print screen Services is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_KEYBOARD_SERV_SUPPORT #language en-US "Int 9h, 8042 Keyboard services are supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_SERIAL_SERVICES_SUPPORT #language en-US "Int 14h, Serial Services are supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_PRINTER_SERVICES_SUPPORT #language en-US "Int 17h, Printer services are supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_MONO_VIDEO_SUPPORT #language en-US "Int 10h, CGA/Mono Video services are supported2\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_NEC_PC_98 #language en-US "NEC PC-98\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BITS_32_47 #language en-US " Bits 32:47 are reserved for BIOS Vendor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BITS_48_64 #language en-US " Bits 48:64 are reserved for System Vendor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BIOS_CHAR_EXTENSION #language en-US "BIOS Characteristics Extension Byte1:\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_ACPI_SUPPORTED #language en-US "ACPI supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_USB_LEGACY_SUPPORTED #language en-US "USB Legacy is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_AGP_SUPPORTED #language en-US "AGP is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_I2O_BOOT_SUPPORTED #language en-US "I2O boot is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_LS_120_BOOT_SUPPORTED #language en-US "LS-120 boot is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_ATAPI_ZIP_DRIVE #language en-US "ATAPI ZIP Drive boot is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_1394_BOOT_SUPPORTED #language en-US "1394 boot is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_SMART_BATTERY_SUPPORTED #language en-US "Smart battery supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BIOS_CHAR_EXTENSION_2 #language en-US "BIOS Characteristics Extension Byte2:\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BIOS_BOOT_SPEC_SUPP #language en-US "BIOS Boot Specification supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_FUNCTION_KEY_INIT #language en-US "Function key-initiated Network Service boot supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_ENABLE_TAR_CONT_DIST #language en-US "Enable Targeted Content Distribution\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_UEFI_SPEC_SUPPORT #language en-US "UEFI Specification is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_VIRTUAL_MACHINE #language en-US "The SMBIOS table describes a virtual machine\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BITS_RSVD_FOR_FUTURE #language en-US " Bits %d:7 are reserved for future assignment\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_PROCESSOR_FAMILY #language en-US "Processor Family: "
+#string STR_SMBIOSVIEW_PRINTINFO_OTHER #language en-US "Other\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_UNKNOWN #language en-US "Unknown\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL386_PROCESSOR #language en-US "Intel386(TM) Processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL486_PROCESSOR #language en-US "Intel486(TM) Processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_PENTIUM_PROC_FAMILY #language en-US "Pentium(R) Processor Family\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_PENTIUM_PRO_PROC #language en-US "Pentium(R) Pro processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_PENTIUM_II_PROC #language en-US "Pentium(R) II processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_PENTIUM_PROC_MMX #language en-US "Pentium(R) processor with MMX(TM) technology\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_CELERON_PROC #language en-US "Celeron(TM) processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_PENTIUM_XEON_PROC #language en-US "Pentium(R) II Xeon(TM) processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_PENTIUM_III_PROC #language en-US "Pentium(R) III Processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_M1_FAMILY #language en-US "M1 Family\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_K5_FAMILY #language en-US "K5 Family\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_POWER_PC_FAMILY #language en-US "Power PC Family\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_POWER_PC_601 #language en-US "Power PC 601\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_POWER_PC_603 #language en-US "Power PC 603\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_POWER_PC_603_PLUS #language en-US "Power PC 603+\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_POWER_PC_604 #language en-US "Power PC 604\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_ALPHA_FAMILY_2 #language en-US "Alpha Family 2\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE_DUO #language en-US "Intel(R) Core(TM) Duo processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE_DUO_MOBILE #language en-US "Intel(R) Core(TM) Duo mobile processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE_SOLO_MOBILE #language en-US "Intel(R) Core(TM) Solo mobile processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_ATOM #language en-US "Intel(R) Atom(TM) processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_QUAD_CORE #language en-US "Quad-Core AMD Opteron(TM) Processor Family\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_THIRD_GENERATION #language en-US "Third-Generation AMD Opteron(TM) Processor Family\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_AMD_PHENOM_FX_QUAD_CORE #language en-US "AMD Phenom(TM) FX Quad-Core Processor Family\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_AMD_PHENOM_X4_QUAD_CORE #language en-US "AMD Phenom(TM) X4 Quad-Core Processor Family\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_AMD_PHENOM_X2_DUAL_CORE #language en-US "AMD Phenom(TM) X2 Dual-Core Processor Family\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_AMD_ATHLON_X2_DUAL_CORE #language en-US "AMD Athlon(TM) X2 Dual-Core Processor Family\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_3200_SERIES_QUAD_CORE #language en-US "Quad-Core Intel(R) Xeon(R) processor 3200 Series\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_3000_SERIES_DUAL_CORE #language en-US "Dual-Core Intel(R) Xeon(R) processor 3000 Series\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5300_SERIES_QUAD_CORE #language en-US "Quad-Core Intel(R) Xeon(R) processor 5300 Series\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5100_SERIES_DUAL_CORE #language en-US "Dual-Core Intel(R) Xeon(R) processor 5100 Series\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5000_SERIES_DUAL_CORE #language en-US "Dual-Core Intel(R) Xeon(R) processor 5000 Series\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_LV_DUAL_CORE #language en-US "Dual-Core Intel(R) Xeon(R) processor LV\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_ULV_DUAL_CORE #language en-US "Dual-Core Intel(R) Xeon(R) processor ULV\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7100_SERIES_DUAL_CORE #language en-US "Dual-Core Intel(R) Xeon(R) processor 7100 Series\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5400_SERIES_QUAD_CORE #language en-US "Quad-Core Intel(R) Xeon(R) processor 5400 Series\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_QUAD_CORE #language en-US "Quad-Core Intel(R) Xeon(R) processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5200_SERIES_DUAL_CORE #language en-US "Dual-Core Intel(R) Xeon(R) processor 5200 Series\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7200_SERIES_DUAL_CORE #language en-US "Dual-Core Intel(R) Xeon(R) processor 7200 Series\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7300_SERIES_QUAD_CORE #language en-US "Quad-Core Intel(R) Xeon(R) processor 7300 Series\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7400_SERIES_QUAD_CORE #language en-US "Quad-Core Intel(R) Xeon(R) processor 7400 Series\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7400_SERIES_MULTI_CORE #language en-US "Multi-Core Intel(R) Xeon(R) processor 7400 Series\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE2_SOLO #language en-US "Intel(R) Core(TM)2 Solo processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE2_EXTREME #language en-US "Intel(R) Core(TM)2 Extreme processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE2_QUAD #language en-US "Intel(R) Core(TM)2 Quad processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE2_EXTREME_MOBILE #language en-US "Intel(R) Core(TM)2 Extreme mobile processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE2_DUO_MOBILE #language en-US "Intel(R) Core(TM)2 Duo mobile processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE2_SOLO_MOBILE #language en-US "Intel(R) Core(TM)2 Solo mobile processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_CORE_I7 #language en-US "Intel(R) Core(TM) i7 processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_CELERON_DUAL_CORE #language en-US "Dual-Core Intel(R) Celeron(R) processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_MULTI_CORE #language en-US "Multi-Core Intel(R) Xeon(R) processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_3_SERIES_DUAL_CORE #language en-US "Dual-Core Intel(R) Xeon(R) processor 3xxx Series\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_3_SERIES_QUAD_CORE #language en-US "Quad-Core Intel(R) Xeon(R) processor 3xxx Series\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5_SERIES_DUAL_CORE #language en-US "Dual-Core Intel(R) Xeon(R) processor 5xxx Series\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_5_SERIES_QUAD_CORE #language en-US "Quad-Core Intel(R) Xeon(R) processor 5xxx Series\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7_SERIES_DUAL_CORE #language en-US "Dual-Core Intel(R) Xeon(R) processor 7xxx Series\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7_SERIES_QUAD_CORE #language en-US "Quad-Core Intel(R) Xeon(R) processor 7xxx Series\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INTEL_XEON_7_SERIES_MULTI_CORE #language en-US "Multi-Core Intel(R) Xeon(R) processor 7xxx Series\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_3000_SERIES #language en-US "AMD Opteron(TM) 3000 Series Processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_AMD_SEMPRON_II #language en-US "AMD Sempron(TM) II Processor Family\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_AMD_FX_SERIES #language en-US "AMD FX(TM) Series Processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_AMD_Z_SERIES #language en-US "AMD Z-Series Processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_AMD_R_SERIES #language en-US "AMD R-Series Processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_4300_SERIES #language en-US "AMD Opteron(TM) 4300 Series Processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_6300_SERIES #language en-US "AMD Opteron(TM) 6300 Series Processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_3300_SERIES #language en-US "AMD Opteron(TM) 3300 Series Processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_AMD_OPTERON_FIREPRO_SERIES #language en-US "AMD FirePro(TM) Series Processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_AMD_EMBEDDED_OPTERON_QUAD_CORE #language en-US "Embedded AMD Opteron(TM) Quad-Core Processor Family\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_AMD_PHENOM_TRIPLE_CORE #language en-US "AMD Phenom(TM) Triple-Core Processor Family\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_AMD_TURION_ULTRA_DUAL_CORE_MOBILE #language en-US "AMD Turion(TM) Ultra Dual-Core Mobile Processor Family\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_AMD_TURION_DUAL_CORE_MOBILE #language en-US "AMD Turion(TM) Dual-Core Mobile Processor Family\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_AMD_ATHLON_DUAL_CORE #language en-US "AMD Athlon(TM) Dual-Core Processor Family\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_AMD_SEMPRON_SI #language en-US "AMD Sempron(TM) SI Processor Family\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_MIPS_FAMILY #language en-US "MIPS Family\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_SPARC_FAMILY #language en-US "SPARC Family\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_68040_FAMILY #language en-US "68040 Family\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_HOBBIT_FAMILY #language en-US "Hobbit Family\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_WEITEK #language en-US "Weitek\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_PA_RISC_FAMILY #language en-US "PA-RISC Family\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_V30_FAMILY #language en-US "V30 Family\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_PENTIUM_III_XEON #language en-US "Pentium(R) III Xeon(TM) Processor\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_RSVD_FOR_SPEC_M1 #language en-US "Reserved for specific M1 versions\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_RSVD_FOR_SPEC_K5 #language en-US "Reserved for specific K5 versions\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_RSVD_FOR_SPEC_PENTIUM #language en-US "Reserved for specific Pentium(R) Processor versions\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_UNDEFINED_PROC_FAMILY #language en-US "Undefined processor family and type\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_PROC_INFO #language en-US "Processor Information - Voltage:\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_PROC_CURRENT_VOLTAGE #language en-US "Processor current voltage = (%d/10)V\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_5V_SUPOPRTED #language en-US " 5V is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_33V_SUPPORTED #language en-US " 3.3V is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_29V_SUPPORTED #language en-US " 2.9V is supported\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BIT3_NOT_ZERO #language en-US "Error, reserved BIT 3 must be zero\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BIT4_NOT_ZERO #language en-US "Error, reserved BIT 4 must be zero\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BIT5_NOT_ZERO #language en-US "Error, reserved BIT 5 must be zero\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BIT6_NOT_ZERO #language en-US "Error, reserved BIT 6 must be zero\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BIT7_NOT_ZERO #language en-US "Error, reserved BIT 7 must be zero\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BIT10_NOT_ZERO #language en-US "Error, reserved BIT 10 must be zero\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BIT11_NOT_ZERO #language en-US "Error, reserved BIT 11 must be zero\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BIT12_NOT_ZERO #language en-US "Error, reserved BIT 12 must be zero\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BIT13_NOT_ZERO #language en-US "Error, reserved BIT 13 must be zero\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BIT14_NOT_ZERO #language en-US "Error, reserved BIT 14 must be zero\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BIT15_NOT_ZERO #language en-US "Error, reserved BIT 15 must be zero\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_PROC_STATUS #language en-US "Processor Status:\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_CPU_SOCKET_POPULATED #language en-US "CPU Socket Populated\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_CPU_SOCKET_UNPOPULATED #language en-US "CPU Socket Unpopulated Bits\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_CPU_ENABLED #language en-US "CPU Enabled\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_CPU_DISABLED_BY_USER #language en-US "CPU Disabled by User via BIOS Setup\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_CPU_DIABLED_BY_BIOS #language en-US "CPU Disabled By BIOS (POST Error)\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_CPU_IDLE #language en-US "CPU is Idle, waiting to be enabled\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_OTHERS #language en-US "Others\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_RESERVED #language en-US "Reserved\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_SIZE_LARGEST_MEM #language en-US "The size of the largest memory module supported (per slot): "
+#string STR_SMBIOSVIEW_PRINTINFO_ONE_VAR_MB #language en-US "%d * %d = %d MB\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_MAX_AMOUNT_MEM #language en-US "The maximum amount of memory supported by this controller: "
+#string STR_SMBIOSVIEW_PRINTINFO_HANDLES_CONTROLLED #language en-US "There are %d Handles controlled by this controller\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_HANDLES_LIST_CONTROLLED #language en-US "Handles' List controlled by this controller:\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_HANDLE #language en-US "Handle%d: 0x%04x\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BANK_CONNECTIONS #language en-US "Bank Connections:"
+#string STR_SMBIOSVIEW_PRINTINFO_BANK_RAS #language en-US "Banks %d & %d(RAS# %d & %d)\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BANK_RAS_2 #language en-US "Bank %d(RAS# %d)\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_NO_BANKS_CONNECTED #language en-US "No banks connected\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_MEMORY_SIZE #language en-US "Memory Size:"
+#string STR_SMBIOSVIEW_PRINTINFO_MEM_SIZE_NOT_DETERMINABLE #language en-US " Memory Size Not determinable (Installed Size only)\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_MODULE_INSTALLED #language en-US " Module is installed, but no memory has been enabled\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_NOT_INSTALLED #language en-US " Not installed\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_MEM_SIZE #language en-US " Memory Size: %d MB\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_MEM_MODULE_DOUBLE_BANK #language en-US "The memory module has a Double-bank connection\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_MEM_MODULE_SINGLE_BANK #language en-US "The memory module has a Single-bank connection\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_SLOT_ID #language en-US " Slot Id:"
+#string STR_SMBIOSVIEW_PRINTINFO_LOGICAL_MICRO_CHAN #language en-US " the logical Micro Channel slot number is:"
+#string STR_SMBIOSVIEW_PRINTINFO_ONE_VAR_D #language en-US " %d\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_ERROR_NOT_1_15 #language en-US " error, not 1-15.\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_LOGICAL_EISA_NUM #language en-US " the logical EISA slot number is:"
+#string STR_SMBIOSVIEW_PRINTINFO_IDENTIFIES_ADAPTER_NUM #language en-US " Identifies the Adapter Number is: %d\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_VALUE_PRESENT #language en-US " the value present in the Slot Number field of the PCI Interrupt Routing table entry that is associated with this slot is: %d\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_UNDEFINED_SLOT_ID #language en-US " undefined Slot Id\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_CACHE_CONFIGURATION #language en-US "Cache Configuration:\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_CACHE_WRITE_THROUGH #language en-US "Write Through\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_CACHE_WRITE_BACK #language en-US "Write Back\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_CACHE_VARIES_WITH_MEM_ADDR #language en-US "Varies with Memory Address\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_CACHE_INTERNAL #language en-US "Internal\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_CACHE_EXTERNAL #language en-US "External\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_CACHE_SOCKETED #language en-US "Socketed\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_CACHE_NOT_SOCKETED #language en-US "Not Socketed\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_CACHE_LEVEL #language en-US "Level %d\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_SYSTEM_BOOT_STATUS #language en-US "System Boot Status: "
+#string STR_SMBIOSVIEW_PRINTINFO_NO_ERRORS_DETECTED #language en-US " No errors detected"
+#string STR_SMBIOSVIEW_PRINTINFO_NO_BOOTABLE_MEDIA #language en-US " No bootable media"
+#string STR_SMBIOSVIEW_PRINTINFO_NORMAL_OP_SYSTEM #language en-US " The \"normal\" unable to load operating system."
+#string STR_SMBIOSVIEW_PRINTINFO_FIRMWARE_DETECTED #language en-US " Firmware-detected hardware problem, including \"unknown\" failure types."
+#string STR_SMBIOSVIEW_PRINTINFO_OP_SYSTEM #language en-US " Operating system-detected hardware failure."
+#string STR_SMBIOSVIEW_PRINTINFO_USER_REQUESTED_BOOT #language en-US " User-requested boot, usually via a keystroke"
+#string STR_SMBIOSVIEW_PRINTINFO_SYSTEM_SECURITY_VIOLATION #language en-US " System security violation"
+#string STR_SMBIOSVIEW_PRINTINFO_PREV_REQ_IMAGE #language en-US " Previously-requested image. "
+#string STR_SMBIOSVIEW_PRINTINFO_WATCHDOG_TIMER #language en-US " A system watchdog timer expired, causing the system to reboot."
+#string STR_SMBIOSVIEW_PRINTINFO_RSVD_FUTURE_ASSIGNMENT #language en-US " Reserved for future assignment via this specification. "
+#string STR_SMBIOSVIEW_PRINTINFO_VENDOR_OEM_SPECIFIC #language en-US " Vendor/OEM-specific implementations. The Vendor/OEM identifier is the \"Manufacturer\" string found in the System Identification structure."
+#string STR_SMBIOSVIEW_PRINTINFO_PRODUCT_SPEC_IMPLMENTATION #language en-US "Product-specific implementations. The product identifier is formed by the concatenation of the \"Manufacturer\" and \"Product Name\" strings found in the System Information structure."
+#string STR_SMBIOSVIEW_PRINTINFO_ERROR_VALUE #language en-US "Error value\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_SBDS_MANUFACTURE_DATE #language en-US "SBDS Manufacture Date: "
+#string STR_SMBIOSVIEW_PRINTINFO_MONTH_DAY_YEAR #language en-US "%02d/%02d/%4d\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_SYSTEM_RESET_CAPABILITIES #language en-US "System Reset Capabilities: "
+#string STR_SMBIOSVIEW_PRINTINFO_BITS_RESERVED_ZERO #language en-US "Bits 7:6 are reserved bits, must be zero\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_WATCHDOG_TIMER_2 #language en-US "System contains a watchdog timer\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_SYSTEM_NOT_CONTAIN_TIMER #language en-US "System does not contain a watchdog timer\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BOOT_OPTION_LIMIT #language en-US "Boot Option on Limit: "
+#string STR_SMBIOSVIEW_PRINTINFO_OP_SYSTEM_2 #language en-US "Operating system\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_SYSTEM_UTIL #language en-US "System utilities\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_DO_NOT_REBOOT_BITS #language en-US "Do not reboot Bits\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BOOT_OPTION #language en-US "Boot Option :"
+#string STR_SMBIOSVIEW_PRINTINFO_DO_NOT_REBOOT #language en-US "Do not reboot\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_HARDWARE_SECURITY_SET #language en-US "Hardware Security Settings: \r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_POWER_ON_PASSWORD #language en-US "Power-on Password Status: "
+#string STR_SMBIOSVIEW_PRINTINFO_DISABLED #language en-US "Disabled\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_ENABLED_NEWLINE #language en-US "Enabled\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_NOT_IMPLEMENTED #language en-US "Not Implemented\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_KEYBOARD_PASSWORD #language en-US "Keyboard Password Status: "
+#string STR_SMBIOSVIEW_PRINTINFO_ADMIN_PASSWORD_STATUS #language en-US "Administrator Password Status: "
+#string STR_SMBIOSVIEW_PRINTINFO_FRONT_PANEL_RESET #language en-US "Front Panel Reset Status: "
+#string STR_SMBIOSVIEW_PRINTINFO_CONNECTIONS #language en-US "Connections: "
+#string STR_SMBIOSVIEW_PRINTINFO_BITS_RESERVED_ZERO_2 #language en-US "Bits 7:2 are reserved bits, must be zero\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_OUTBOUND_CONN_ENABLED #language en-US "Outbound Connection Enabled\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_OTUBOUND_CONN_DISABLED #language en-US "Outbound Connection Disabled\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INBOIUND_CONN_ENABLED #language en-US "Inbound Connection Enabled\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INBOUND_CONN_DISABLED #language en-US "Inbound Connection Disabled\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_CHAR #language en-US "Power Supply Characteristics: \r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BITS_15_14_RSVD #language en-US "Bits 15:14 are reserved bits, must be zero\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_TYPE #language en-US "Type - "
+#string STR_SMBIOSVIEW_PRINTINFO_OTHER_SPACE #language en-US " Other\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_LINEAR #language en-US " Linear\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_SWITCHING #language en-US " Switching\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BATTERY #language en-US " Battery\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_UPS #language en-US " UPS\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_CONVERTER #language en-US " Converter\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_REGULATOR #language en-US " Regulator\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_RESERVED_2 #language en-US " Reserved \r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_STATUS_DASH #language en-US " Status - "
+#string STR_SMBIOSVIEW_PRINTINFO_OK #language en-US " OK\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_NON_CRITICAL #language en-US " Non-critical\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_CRITICAL_POWER_SUPPLY #language en-US " Critical, power supply has failed and has been taken off-line\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_UNDEFINED #language en-US " Undefined \r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_INPUT_VOLTAGE_RANGE #language en-US "Input Voltage Range Switching - "
+#string STR_SMBIOSVIEW_PRINTINFO_MANUAL #language en-US " Manual\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_AUTO_SWITCH #language en-US " Auto-switch\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_WIDE_RANGE #language en-US " Wide range\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_NOT_APPLICABLE #language en-US " Not applicable\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_RESERVED_3 #language en-US " Reserved \r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_UNPLUGGED #language en-US "Power supply is unplugged from the wall\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_PLUGGED #language en-US "Power supply is plugged from the wall\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_PRESENT #language en-US "Power supply is present\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_NOT_PRESENT #language en-US "Power supply is not present\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_REPLACE #language en-US "Power supply is hot replaceable\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_POWER_SUPPLY_NOT_REPLACE #language en-US "Power supply is not hot replaceable\r\n"
+#string STR_SMBIOSVIEW_PRINTINFO_BIOS_SIZE #language en-US "BiosSize: %d KB\r\n"
+#string STR_SMBIOSVIEW_QUERYTABLE_NO_INFO #language en-US "No Info"
+#string STR_SMBIOSVIEW_QUERYTABLE_RSVD_BITS_SET #language en-US "\r\nIt also has reserved bits set 1 --- reserved bits: 0x%x"
+#string STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_WAKEUP_TYPE #language en-US "System Wakeup Type:"
+#string STR_SMBIOSVIEW_QUERYTABLE_BASE_BOARD_FEATURE_FLAGS #language en-US "Base Board Feature Flags:"
+#string STR_SMBIOSVIEW_QUERYTABLE_BASE_BOARD_BOARD_TYPE #language en-US "Base Board Board Type:"
+#string STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_CHASSIS_TYPE #language en-US "System Enclosure or Chassis Types:"
+#string STR_SMBIOSVIEW_QUERYTABLE_CHASSIS_LOCK_PRESENT #language en-US "Chassis Lock present\r\n"
+#string STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_CHASSIS_STATUS #language en-US "System Enclosure or Chassis Status: "
+#string STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_CHASSIS_SECURITY #language en-US "System Enclosure or Chassis Security Status: "
+#string STR_SMBIOSVIEW_QUERYTABLE_PROC_TYPE #language en-US "Processor Type: "
+#string STR_SMBIOSVIEW_QUERYTABLE_PROC_UPDATE #language en-US "Processor Upgrade: "
+#string STR_SMBIOSVIEW_QUERYTABLE_PROC_CHARACTERISTICS #language en-US "Processor Characteristics: "
+#string STR_SMBIOSVIEW_QUERYTABLE_MEM_DETECTMETHOD #language en-US "Memory Controller Error DetectMethod:"
+#string STR_SMBIOSVIEW_QUERYTABLE_MEM_CORRECT_CAPABILITY #language en-US "Memory Controller Error Correct Capability:\r\n"
+#string STR_SMBIOSVIEW_QUERYTABLE_MEM_INTERLEAVE_SUPPORT #language en-US "Memory Controller Interleave Support:"
+#string STR_SMBIOSVIEW_QUERYTABLE_MEM_MEMORY_SPEED #language en-US "Memory Controller Memory Speed:"
+#string STR_SMBIOSVIEW_QUERYTABLE_REQUIRED_VOLTAGES #language en-US "The required voltages for each memory module sockets:\r\n"
+#string STR_SMBIOSVIEW_QUERYTABLE_MEM_MODULE_TYPE #language en-US "Memory Module Memory Type: "
+#string STR_SMBIOSVIEW_QUERYTABLE_MEM_MODULE_ERROR_STATUS #language en-US "Memory Module Error Status: "
+#string STR_SMBIOSVIEW_QUERYTABLE_CACHE_SRAM_TYPE #language en-US "Cache SRAM Type: "
+#string STR_SMBIOSVIEW_QUERYTABLE_CACHE_ERROR_CORRECTING #language en-US "Cache Error Correcting Type: "
+#string STR_SMBIOSVIEW_QUERYTABLE_CACHE_SYSTEM_TYPE #language en-US "Cache System Cache Type:"
+#string STR_SMBIOSVIEW_QUERYTABLE_CACHE_ASSOCIATIVITY #language en-US "Cache Associativity:"
+#string STR_SMBIOSVIEW_QUERYTABLE_PORT_CONNECTOR_TYPE #language en-US "Port Connector Type: "
+#string STR_SMBIOSVIEW_QUERYTABLE_PORT_TYPE #language en-US "Port Type: "
+#string STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_SLOT_TYPE #language en-US "System Slot Type: "
+#string STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_SLOT_DATA #language en-US "System Slot Data Bus Width: "
+#string STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_SLOT_CURRENT_USAGE #language en-US "System Slot Current Usage: "
+#string STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_SLOT_LENGTH #language en-US "System Slot Length: "
+#string STR_SMBIOSVIEW_QUERYTABLE_SLOT_CHARACTERISTICS #language en-US "Slot characteristics 1: "
+#string STR_SMBIOSVIEW_QUERYTABLE_SLOT_CHARACTERISTICS_2 #language en-US "Slot characteristics 2: "
+#string STR_SMBIOSVIEW_QUERYTABLE_ONBOARD_DEVICE_TYPE #language en-US "Onboard Device Type: "
+#string STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_EVENT_LOG_TYPE #language en-US "System Event Log Type: "
+#string STR_SMBIOSVIEW_QUERYTABLE_EVENT_LOG_VAR_DATA_FORMAT #language en-US "Event Log Variable Data Format Types: "
+#string STR_SMBIOSVIEW_QUERYTABLE_POST_RESULTS_BITMAP #language en-US "POST Results Bitmap - First DWORD:\r\n"
+#string STR_SMBIOSVIEW_QUERYTABLE_POST_RESULTS_SECOND_DWORD #language en-US "POST Results Bitmap - Second DWORD:\r\n"
+#string STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_MANAGEMENT_TYPES #language en-US "System Management Types: "
+#string STR_SMBIOSVIEW_QUERYTABLE_OEM_ASSIGNED #language en-US "OEM assigned\r\n"
+#string STR_SMBIOSVIEW_QUERYTABLE_RSVD_FOR_FUTURE_ASSIGN #language en-US "Reserved for future assignment via this specification\r\n"
+#string STR_SMBIOSVIEW_QUERYTABLE_SYSTEM_MANAGEMENT_PROBE #language en-US "A system-management probe or cooling device is out-of-range\r\n"
+#string STR_SMBIOSVIEW_QUERYTABLE_PHYS_MEM_ARRAY_LOCATION #language en-US "Physical Memory Array Location: "
+#string STR_SMBIOSVIEW_QUERYTABLE_PHYS_MEM_ARRAY_USE #language en-US "Physical Memory Array Use: "
+#string STR_SMBIOSVIEW_QUERYTABLE_PHYS_MEM_ARRAY_ERROR #language en-US "Physical Memory Array Error Correction Types: "
+#string STR_SMBIOSVIEW_QUERYTABLE_MEM_DEVICE_FORM_FACTOR #language en-US "Memory Device - Form Factor: "
+#string STR_SMBIOSVIEW_QUERYTABLE_MEM_DEVICE_TYPE #language en-US "Memory Device - Type: "
+#string STR_SMBIOSVIEW_QUERYTABLE_MEM_DEVICE_TYPE_DETAIL #language en-US "Memory Device - Type Detail: "
+#string STR_SMBIOSVIEW_QUERYTABLE_MEM_ERROR_INFO #language en-US "32-bit Memory Error Information - Type: "
+#string STR_SMBIOSVIEW_QUERYTABLE_MEM_ERROR_GRANULARITY #language en-US "Memory Error - Error granularity: "
+#string STR_SMBIOSVIEW_QUERYTABLE_MEM_ERROR_OP #language en-US "Memory Error - Error Operation: "
+#string STR_SMBIOSVIEW_QUERYTABLE_POINTING_DEVICE_TYPE #language en-US "Pointing Device - Type: "
+#string STR_SMBIOSVIEW_QUERYTABLE_POINTING_DEVICE_INTERFACE #language en-US "Pointing Device - Interface:"
+#string STR_SMBIOSVIEW_QUERYTABLE_PORTABLE_BATT_DEV_CHEM #language en-US "Portable Battery - Device Chemistry:"
+#string STR_SMBIOSVIEW_QUERYTABLE_VOLTAGE_PROBE_LOC #language en-US "Voltage Probe - Location:"
+#string STR_SMBIOSVIEW_QUERYTABLE_VOLTAGE_PROBE_STATUS #language en-US "Voltage Probe - Status:"
+#string STR_SMBIOSVIEW_QUERYTABLE_COOLING_DEV_STATUS #language en-US "Cooling Device - Status: "
+#string STR_SMBIOSVIEW_QUERYTABLE_COOLING_DEV_TYPE #language en-US "Cooling Device - Type: "
+#string STR_SMBIOSVIEW_QUERYTABLE_TEMP_PROBE #language en-US "Temperature Probe - Status:"
+#string STR_SMBIOSVIEW_QUERYTABLE_ELEC_PROBE_STATUS #language en-US "Electrical Current Probe - Status:"
+#string STR_SMBIOSVIEW_QUERYTABLE_ELEC_PROBE_LOC #language en-US "Electrical Current Probe - Location:"
+#string STR_SMBIOSVIEW_QUERYTABLE_MANAGEMENT_DEV_TYPE #language en-US "Management Device Type:"
+#string STR_SMBIOSVIEW_QUERYTABLE_MANAGEMENT_DEV_ADDR_TYPE #language en-US "Management Device - Address Type:"
+#string STR_SMBIOSVIEW_QUERYTABLE_MEM_CHANNEL_TYPE #language en-US "Memory Channel Type:"
+#string STR_SMBIOSVIEW_QUERYTABLE_BMC_INTERFACE_TYPE #language en-US "BMC Interface Type:"
+#string STR_SMBIOSVIEW_QUERYTABLE_STRUCT_TYPE #language en-US "Structure Type:"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_ONE_VAR_ARGV #language en-US "%s "
+#string STR_SMBIOSVIEW_SMBIOSVIEW_QUERY_STRUCT_COND #language en-US "Query Structure, conditions are:\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_QUERYTYPE_RANDOM #language en-US "QueryType = Random \r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_QUERYTYPE #language en-US "QueryType = %d\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_QUERYHANDLE_RANDOM #language en-US "QueryHandle = Random\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_QUERYHANDLE #language en-US "QueryHandle = 0x%x\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_SHOWTYPE #language en-US "ShowType = "
+#string STR_SMBIOSVIEW_SMBIOSVIEW_TYPE_HANDLE_DUMP_STRUCT #language en-US "Type=%d, Handle=0x%x\r\nDump Structure as:\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_INDEX_LENGTH #language en-US "Index=%d,Length=0x%x,"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_ADDR #language en-US "Addr=0x%p\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_ENTRYLEN #language en-US "Entry Length: 0x%x\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_REFERENCEDHANDLE #language en-US "Referenced Handle: 0x%x\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_REFERENCEDOFFSET #language en-US "Referenced Offset: 0x%x\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_ENTER_Q #language en-US "\r\n%HEnter%N to continue, %H:q%N to exit, %H:[0-3]%N to change mode, %H/?%N for help\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_SMBIOS_UTILITY #language en-US " SMBIOS Utility ---- smbiosview HELP Information\r\n\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_USAGE #language en-US "Usage:\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_HSMBIOSVIEW #language en-US "%Hsmbiosview [-t type] | [-h handle] | [-s] | [-a]%N\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_EXAMPLES #language en-US "Examples:\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_SHOW_STAT_INFO #language en-US "%H>smbiosview -s %N - Show statistics information\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_SHOW_ALL_STRUCT_TYPE #language en-US "%H>smbiosview -t 8 %N - Show all structures of type=8\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_SHOW_STRUCT_HANDLE #language en-US "%H>smbiosview -h 25 %N - Show structure of handle=0x25\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_SHOW_ALL_OUTPUT_TO_FILE #language en-US "%H>smbiosview -a > 1.log%N - Show all and output to file 1.log\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_INTERNAL_COMMANDS #language en-US "Internal commands:\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_QUIT_SMBIOSVIEW #language en-US "%H:q%N -------- quit smbiosview\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_CHANGE_DISPLAY_NONE #language en-US "%H:0%N -------- Change smbiosview display NONE info\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_CHANGE_DISPLAY_OUTLINE #language en-US "%H:1%N -------- Change smbiosview display OUTLINE info\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_CHANGE_DISPLAY_NORMAL #language en-US "%H:2%N -------- Change smbiosview display NORMAL info\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_CHANGE_DISPLAY_DETAIL #language en-US "%H:3%N -------- Change smbiosview display DETAIL info\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_SHOW_HELP #language en-US "%H/?%N -------- Show help\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_INDEX #language en-US "Index=%04d "
+#string STR_SMBIOSVIEW_SMBIOSVIEW_TYPE #language en-US "Type=%03d "
+#string STR_SMBIOSVIEW_SMBIOSVIEW_HANDLE #language en-US "Handle=0x%04x "
+#string STR_SMBIOSVIEW_SMBIOSVIEW_OFFSET #language en-US "Offset=0x%04x "
+#string STR_SMBIOSVIEW_SMBIOSVIEW_LENGTH #language en-US "Length=0x%04x"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_ENTER_CONTINUE #language en-US "Press Enter to continue..\r\n"
+#string STR_SMBIOSVIEW_LIBSMBIOSVIEW_NO_BUF_SPEC_WHEN_STRUCT #language en-US "smbiosview: No buffer specified when get structure\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_NOT_SPEC #language en-US "SmbiosView: Type # not specified\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_HANDLE_NOT_SPEC #language en-US "SmbiosView: Handle # not specified\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_UNKNOWN_FLAG #language en-US "\r\nSmbiosView: Unknown flag\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_CANNOT_ACCESS_TABLE #language en-US "SmbiosView: Cannot access SMBIOS table\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_UNKNOWN_INTERNAL_COMMAND #language en-US "\r\nSmbiosView: Unknown internal command\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_SMBIOS_TABLE #language en-US "SmbiosView: SMBIOS table damaged\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_OUT_OF_MEM #language en-US "SmbiosView: Out of memory\r\n"
+#string STR_SMBIOSVIEW_SMBIOSVIEW_CANNOT_ACCESS_STATS #language en-US "SmbiosView: Cannot access statistics table\r\n"
+
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.c b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.c
new file mode 100644
index 0000000000..1814564c12
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.c
@@ -0,0 +1,574 @@
+/** @file
+ Main file for NULL named library for debug1 profile shell command functions.
+
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDebug1CommandsLib.h"
+#include <Library/BcfgCommandLib.h>
+
+STATIC CONST CHAR16 mFileName[] = L"Debug1Commands";
+EFI_HANDLE gShellDebug1HiiHandle = NULL;
+
+/**
+ Gets the debug file name. This will be used if HII is not working.
+
+ @retval NULL No file is available.
+ @return The NULL-terminated filename to get help from.
+**/
+CONST CHAR16*
+EFIAPI
+ShellCommandGetManFileNameDebug1 (
+ VOID
+ )
+{
+ return (mFileName);
+}
+
+/**
+ Constructor for the Shell Debug1 Commands library.
+
+ @param ImageHandle the image handle of the process
+ @param SystemTable the EFI System Table pointer
+
+ @retval EFI_SUCCESS the shell command handlers were installed sucessfully
+ @retval EFI_UNSUPPORTED the shell level required was not found.
+**/
+EFI_STATUS
+EFIAPI
+UefiShellDebug1CommandsLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ //
+ // check our bit of the profiles mask
+ //
+ if ((PcdGet8(PcdShellProfileMask) & BIT1) == 0) {
+ return (EFI_SUCCESS);
+ }
+
+ //
+ // install the HII stuff.
+ //
+ gShellDebug1HiiHandle = HiiAddPackages (&gShellDebug1HiiGuid, gImageHandle, UefiShellDebug1CommandsLibStrings, NULL);
+ if (gShellDebug1HiiHandle == NULL) {
+ return (EFI_DEVICE_ERROR);
+ }
+
+ //
+ // install our shell command handlers that are always installed
+ //
+ ShellCommandRegisterCommandName(L"setsize", ShellCommandRunSetSize , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_SETSIZE) );
+ ShellCommandRegisterCommandName(L"comp", ShellCommandRunComp , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_COMP) );
+ ShellCommandRegisterCommandName(L"mode", ShellCommandRunMode , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_MODE) );
+ ShellCommandRegisterCommandName(L"memmap", ShellCommandRunMemMap , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_MEMMAP) );
+ ShellCommandRegisterCommandName(L"eficompress", ShellCommandRunEfiCompress , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_EFICOMPRESS) );
+ ShellCommandRegisterCommandName(L"efidecompress", ShellCommandRunEfiDecompress , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_EFIDCOMPRESS) );
+ ShellCommandRegisterCommandName(L"dmem", ShellCommandRunDmem , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_DMEM) );
+ ShellCommandRegisterCommandName(L"loadpcirom", ShellCommandRunLoadPciRom , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_LOAD_PCI_ROM) );
+ ShellCommandRegisterCommandName(L"mm", ShellCommandRunMm , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_MM) );
+ ShellCommandRegisterCommandName(L"setvar", ShellCommandRunSetVar , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_SETVAR) );
+ ShellCommandRegisterCommandName(L"sermode", ShellCommandRunSerMode , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_SERMODE) );
+ ShellCommandRegisterCommandName(L"pci", ShellCommandRunPci , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_PCI) );
+ ShellCommandRegisterCommandName(L"smbiosview", ShellCommandRunSmbiosView , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_SMBIOSVIEW) );
+ ShellCommandRegisterCommandName(L"dmpstore", ShellCommandRunDmpStore , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_DMPSTORE) );
+ ShellCommandRegisterCommandName(L"dblk", ShellCommandRunDblk , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_DBLK) );
+ ShellCommandRegisterCommandName(L"edit", ShellCommandRunEdit , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_EDIT) );
+ ShellCommandRegisterCommandName(L"hexedit", ShellCommandRunHexEdit , ShellCommandGetManFileNameDebug1, 0, L"Debug1", TRUE, gShellDebug1HiiHandle, STRING_TOKEN(STR_GET_HELP_HEXEDIT) );
+
+ ShellCommandRegisterAlias(L"dmem", L"mem");
+
+ BcfgLibraryRegisterBcfgCommand(ImageHandle, SystemTable, L"Debug1");
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Destructor for the library. free any resources.
+
+ @param ImageHandle The image handle of the process.
+ @param SystemTable The EFI System Table pointer.
+**/
+EFI_STATUS
+EFIAPI
+UefiShellDebug1CommandsLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ if (gShellDebug1HiiHandle != NULL) {
+ HiiRemovePackages(gShellDebug1HiiHandle);
+ }
+
+ BcfgLibraryUnregisterBcfgCommand(ImageHandle, SystemTable);
+ return (EFI_SUCCESS);
+}
+
+/**
+ Convert a Unicode character to upper case only if
+ it maps to a valid small-case ASCII character.
+
+ This internal function only deal with Unicode character
+ which maps to a valid small-case ASCII character, i.e.
+ L'a' to L'z'. For other Unicode character, the input character
+ is returned directly.
+
+ @param Char The character to convert.
+
+ @retval LowerCharacter If the Char is with range L'a' to L'z'.
+ @retval Unchanged Otherwise.
+
+
+ //Stolen from MdePkg Baselib
+**/
+CHAR16
+EFIAPI
+CharToUpper (
+ IN CHAR16 Char
+ )
+{
+ if (Char >= L'a' && Char <= L'z') {
+ return (CHAR16) (Char - (L'a' - L'A'));
+ }
+
+ return Char;
+}
+
+/**
+ Function returns a system configuration table that is stored in the
+ EFI System Table based on the provided GUID.
+
+ @param[in] TableGuid A pointer to the table's GUID type.
+ @param[in, out] Table On exit, a pointer to a system configuration table.
+
+ @retval EFI_SUCCESS A configuration table matching TableGuid was found.
+ @retval EFI_NOT_FOUND A configuration table matching TableGuid was not found.
+**/
+EFI_STATUS
+EFIAPI
+GetSystemConfigurationTable (
+ IN EFI_GUID *TableGuid,
+ IN OUT VOID **Table
+ )
+{
+ UINTN Index;
+ ASSERT (Table != NULL);
+
+ for (Index = 0; Index < gST->NumberOfTableEntries; Index++) {
+ if (CompareGuid (TableGuid, &(gST->ConfigurationTable[Index].VendorGuid))) {
+ *Table = gST->ConfigurationTable[Index].VendorTable;
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Convert a Unicode character to numerical value.
+
+ This internal function only deal with Unicode character
+ which maps to a valid hexadecimal ASII character, i.e.
+ L'0' to L'9', L'a' to L'f' or L'A' to L'F'. For other
+ Unicode character, the value returned does not make sense.
+
+ @param Char The character to convert.
+
+ @return The numerical value converted.
+
+**/
+UINTN
+EFIAPI
+HexCharToUintn (
+ IN CHAR16 Char
+ )
+{
+ if (Char >= L'0' && Char <= L'9') {
+ return Char - L'0';
+ }
+
+ return (UINTN) (10 + CharToUpper (Char) - L'A');
+}
+
+/**
+ Convert a string representation of a guid to a Guid value.
+
+ @param[in] StringGuid The pointer to the string of a guid.
+ @param[in, out] Guid The pointer to the GUID structure to populate.
+
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.
+ @retval EFI_SUCCESS The conversion was successful.
+**/
+EFI_STATUS
+EFIAPI
+ConvertStringToGuid (
+ IN CONST CHAR16 *StringGuid,
+ IN OUT EFI_GUID *Guid
+ )
+{
+ CHAR16 *TempCopy;
+ CHAR16 *TempSpot;
+ CHAR16 *Walker;
+ UINT64 TempVal;
+ EFI_STATUS Status;
+
+ if (StringGuid == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ } else if (StrLen(StringGuid) != 36) {
+ return (EFI_INVALID_PARAMETER);
+ }
+ TempCopy = NULL;
+ TempCopy = StrnCatGrow(&TempCopy, NULL, StringGuid, 0);
+ if (TempCopy == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ Walker = TempCopy;
+ TempSpot = StrStr(Walker, L"-");
+ if (TempSpot != NULL) {
+ *TempSpot = CHAR_NULL;
+ }
+ Status = ShellConvertStringToUint64(Walker, &TempVal, TRUE, FALSE);
+ if (EFI_ERROR(Status)) {
+ FreePool(TempCopy);
+ return (Status);
+ }
+ Guid->Data1 = (UINT32)TempVal;
+ Walker += 9;
+ TempSpot = StrStr(Walker, L"-");
+ if (TempSpot != NULL) {
+ *TempSpot = CHAR_NULL;
+ }
+ Status = ShellConvertStringToUint64(Walker, &TempVal, TRUE, FALSE);
+ if (EFI_ERROR(Status)) {
+ FreePool(TempCopy);
+ return (Status);
+ }
+ Guid->Data2 = (UINT16)TempVal;
+ Walker += 5;
+ TempSpot = StrStr(Walker, L"-");
+ if (TempSpot != NULL) {
+ *TempSpot = CHAR_NULL;
+ }
+ Status = ShellConvertStringToUint64(Walker, &TempVal, TRUE, FALSE);
+ if (EFI_ERROR(Status)) {
+ FreePool(TempCopy);
+ return (Status);
+ }
+ Guid->Data3 = (UINT16)TempVal;
+ Walker += 5;
+ Guid->Data4[0] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
+ Guid->Data4[0] = (UINT8)(Guid->Data4[0]+ (UINT8)HexCharToUintn(Walker[1]));
+ Walker += 2;
+ Guid->Data4[1] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
+ Guid->Data4[1] = (UINT8)(Guid->Data4[1] + (UINT8)HexCharToUintn(Walker[1]));
+ Walker += 3;
+ Guid->Data4[2] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
+ Guid->Data4[2] = (UINT8)(Guid->Data4[2] + (UINT8)HexCharToUintn(Walker[1]));
+ Walker += 2;
+ Guid->Data4[3] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
+ Guid->Data4[3] = (UINT8)(Guid->Data4[3] + (UINT8)HexCharToUintn(Walker[1]));
+ Walker += 2;
+ Guid->Data4[4] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
+ Guid->Data4[4] = (UINT8)(Guid->Data4[4] + (UINT8)HexCharToUintn(Walker[1]));
+ Walker += 2;
+ Guid->Data4[5] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
+ Guid->Data4[5] = (UINT8)(Guid->Data4[5] + (UINT8)HexCharToUintn(Walker[1]));
+ Walker += 2;
+ Guid->Data4[6] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
+ Guid->Data4[6] = (UINT8)(Guid->Data4[6] + (UINT8)HexCharToUintn(Walker[1]));
+ Walker += 2;
+ Guid->Data4[7] = (UINT8)(HexCharToUintn(Walker[0]) * 16);
+ Guid->Data4[7] = (UINT8)(Guid->Data4[7] + (UINT8)HexCharToUintn(Walker[1]));
+ FreePool(TempCopy);
+ return (EFI_SUCCESS);
+}
+
+/**
+ Clear the line at the specified Row.
+
+ @param[in] Row The row number to be cleared ( start from 1 )
+ @param[in] LastCol The last printable column.
+ @param[in] LastRow The last printable row.
+**/
+VOID
+EFIAPI
+EditorClearLine (
+ IN UINTN Row,
+ IN UINTN LastCol,
+ IN UINTN LastRow
+ )
+{
+ CHAR16 Line[200];
+
+ if (Row == 0) {
+ Row = 1;
+ }
+
+ //
+ // prepare a blank line
+ //
+ SetMem16(Line, LastCol*sizeof(CHAR16), L' ');
+
+ if (Row == LastRow) {
+ //
+ // if CHAR_NULL is still at position 80, it will cause first line error
+ //
+ Line[LastCol - 1] = CHAR_NULL;
+ } else {
+ Line[LastCol] = CHAR_NULL;
+ }
+
+ //
+ // print out the blank line
+ //
+ ShellPrintEx (0, ((INT32)Row) - 1, Line);
+}
+
+/**
+ Determine if the character is valid for a filename.
+
+ @param[in] Ch The character to test.
+
+ @retval TRUE The character is valid.
+ @retval FALSE The character is not valid.
+**/
+BOOLEAN
+EFIAPI
+IsValidFileNameChar (
+ IN CONST CHAR16 Ch
+ )
+{
+ //
+ // See if there are any illegal characters within the name
+ //
+ if (Ch < 0x20 || Ch == L'\"' || Ch == L'*' || Ch == L'/' || Ch == L'<' || Ch == L'>' || Ch == L'?' || Ch == L'|') {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ Check if file name has illegal characters.
+
+ @param Name The filename to check.
+
+ @retval TRUE The filename is ok.
+ @retval FALSE The filename is not ok.
+**/
+BOOLEAN
+EFIAPI
+IsValidFileName (
+ IN CONST CHAR16 *Name
+ )
+{
+
+ UINTN Index;
+ UINTN Len;
+
+ //
+ // check the length of Name
+ //
+ for (Len = 0, Index = StrLen (Name) - 1; Index + 1 != 0; Index--, Len++) {
+ if (Name[Index] == '\\' || Name[Index] == ':') {
+ break;
+ }
+ }
+
+ if (Len == 0 || Len > 255) {
+ return FALSE;
+ }
+ //
+ // check whether any char in Name not appears in valid file name char
+ //
+ for (Index = 0; Index < StrLen (Name); Index++) {
+ if (!IsValidFileNameChar (Name[Index])) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/**
+ Find a filename that is valid (not taken) with the given extension.
+
+ @param[in] Extension The file extension.
+
+ @retval NULL Something went wrong.
+ @return the valid filename.
+**/
+CHAR16 *
+EFIAPI
+EditGetDefaultFileName (
+ IN CONST CHAR16 *Extension
+ )
+{
+ EFI_STATUS Status;
+ UINTN Suffix;
+ CHAR16 *FileNameTmp;
+
+ Suffix = 0;
+
+ do {
+ FileNameTmp = CatSPrint (NULL, L"NewFile%d.%s", Suffix, Extension);
+
+ //
+ // after that filename changed to path
+ //
+ Status = ShellFileExists (FileNameTmp);
+
+ if (Status == EFI_NOT_FOUND) {
+ return FileNameTmp;
+ }
+
+ FreePool (FileNameTmp);
+ FileNameTmp = NULL;
+ Suffix++;
+ } while (Suffix != 0);
+
+ FreePool (FileNameTmp);
+ return NULL;
+}
+
+/**
+ Read a file into an allocated buffer. The buffer is the responsibility
+ of the caller to free.
+
+ @param[in] FileName The filename of the file to open.
+ @param[out] Buffer Upon successful return, the pointer to the
+ address of the allocated buffer.
+ @param[out] BufferSize If not NULL, then the pointer to the size
+ of the allocated buffer.
+ @param[out] ReadOnly Upon successful return TRUE if the file is
+ read only. FALSE otherwise.
+
+ @retval EFI_NOT_FOUND The filename did not represent a file in the
+ file system.
+ @retval EFI_SUCCESS The file was read into the buffer.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR The file read operation failed.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.
+ @retval EFI_INVALID_PARAMETER FileName was NULL.
+ @retval EFI_INVALID_PARAMETER FileName was a directory.
+**/
+EFI_STATUS
+EFIAPI
+ReadFileIntoBuffer (
+ IN CONST CHAR16 *FileName,
+ OUT VOID **Buffer,
+ OUT UINTN *BufferSize OPTIONAL,
+ OUT BOOLEAN *ReadOnly
+ )
+{
+ VOID *InternalBuffer;
+ UINTN FileSize;
+ SHELL_FILE_HANDLE FileHandle;
+ BOOLEAN CreateFile;
+ EFI_STATUS Status;
+ EFI_FILE_INFO *Info;
+
+ InternalBuffer = NULL;
+ FileSize = 0;
+ FileHandle = NULL;
+ CreateFile = FALSE;
+ Status = EFI_SUCCESS;
+ Info = NULL;
+
+ if (FileName == NULL || Buffer == NULL || ReadOnly == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ //
+ // try to open the file
+ //
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0);
+
+ if (!EFI_ERROR(Status)) {
+ ASSERT(CreateFile == FALSE);
+ if (FileHandle == NULL) {
+ return EFI_LOAD_ERROR;
+ }
+
+ Info = ShellGetFileInfo(FileHandle);
+
+ if (Info->Attribute & EFI_FILE_DIRECTORY) {
+ FreePool (Info);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Info->Attribute & EFI_FILE_READ_ONLY) {
+ *ReadOnly = TRUE;
+ } else {
+ *ReadOnly = FALSE;
+ }
+ //
+ // get file size
+ //
+ FileSize = (UINTN) Info->FileSize;
+
+ FreePool (Info);
+ } else if (Status == EFI_NOT_FOUND) {
+ //
+ // file not exists. add create and try again
+ //
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ } else {
+ //
+ // it worked. now delete it and move on with the name (now validated)
+ //
+ Status = ShellDeleteFile (&FileHandle);
+ if (Status == EFI_WARN_DELETE_FAILURE) {
+ Status = EFI_ACCESS_DENIED;
+ }
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ }
+ //
+ // file doesn't exist, so set CreateFile to TRUE and can't be read-only
+ //
+ CreateFile = TRUE;
+ *ReadOnly = FALSE;
+ }
+
+ //
+ // the file exists
+ //
+ if (!CreateFile) {
+ //
+ // allocate buffer to read file
+ //
+ InternalBuffer = AllocateZeroPool (FileSize);
+ if (InternalBuffer == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ //
+ // read file into InternalBuffer
+ //
+ Status = ShellReadFile (FileHandle, &FileSize, InternalBuffer);
+ ShellCloseFile(&FileHandle);
+ FileHandle = NULL;
+ if (EFI_ERROR (Status)) {
+ SHELL_FREE_NON_NULL (InternalBuffer);
+ return EFI_LOAD_ERROR;
+ }
+ }
+ *Buffer = InternalBuffer;
+ if (BufferSize != NULL) {
+ *BufferSize = FileSize;
+ }
+ return (EFI_SUCCESS);
+
+}
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.h b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.h
new file mode 100644
index 0000000000..6e018a6a81
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.h
@@ -0,0 +1,421 @@
+/** @file
+ Main file for NULL named library for Profile1 shell command functions.
+
+ Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _UEFI_SHELL_DEBUG1_COMMANDS_LIB_H_
+#define _UEFI_SHELL_DEBUG1_COMMANDS_LIB_H_
+
+#include <Uefi.h>
+#include <ShellBase.h>
+
+#include <Guid/GlobalVariable.h>
+#include <Guid/ConsoleInDevice.h>
+#include <Guid/ConsoleOutDevice.h>
+#include <Guid/FileSystemInfo.h>
+#include <Guid/ShellLibHiiGuid.h>
+
+#include <Protocol/EfiShell.h>
+#include <Protocol/EfiShellParameters.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/UnicodeCollation.h>
+#include <Protocol/DriverDiagnostics2.h>
+#include <Protocol/DriverDiagnostics.h>
+#include <Protocol/PlatformDriverOverride.h>
+#include <Protocol/BusSpecificDriverOverride.h>
+#include <Protocol/PlatformToDriverConfiguration.h>
+#include <Protocol/DriverSupportedEfiVersion.h>
+#include <Protocol/DriverFamilyOverride.h>
+#include <Protocol/DriverHealth.h>
+#include <Protocol/SimplePointer.h>
+#include <Protocol/CpuIo2.h>
+#include <Protocol/PciRootBridgeIo.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/ShellCommandLib.h>
+#include <Library/ShellLib.h>
+#include <Library/SortLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HiiLib.h>
+#include <Library/FileHandleLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PrintLib.h>
+#include <Library/HandleParsingLib.h>
+
+
+extern EFI_HANDLE gShellDebug1HiiHandle;
+
+/**
+ Function returns a system configuration table that is stored in the
+ EFI System Table based on the provided GUID.
+
+ @param[in] TableGuid A pointer to the table's GUID type.
+ @param[in, out] Table On exit, a pointer to a system configuration table.
+
+ @retval EFI_SUCCESS A configuration table matching TableGuid was found.
+ @retval EFI_NOT_FOUND A configuration table matching TableGuid was not found.
+**/
+EFI_STATUS
+EFIAPI
+GetSystemConfigurationTable (
+ IN EFI_GUID *TableGuid,
+ IN OUT VOID **Table
+ );
+
+/**
+ Convert a string representation of a GUID to the GUID value.
+
+ @param[in] StringGuid The pointer to the string containing a GUID printed.
+ @param[in, out] Guid The pointer to the buffer to get the GUID value.
+**/
+EFI_STATUS
+EFIAPI
+ConvertStringToGuid (
+ IN CONST CHAR16 *StringGuid,
+ IN OUT EFI_GUID *Guid
+ );
+
+/**
+ Convert a Unicode character to numerical value.
+
+ This internal function only deal with Unicode character
+ which maps to a valid hexadecimal ASII character, i.e.
+ L'0' to L'9', L'a' to L'f' or L'A' to L'F'. For other
+ Unicode character, the value returned does not make sense.
+
+ @param Char The character to convert.
+
+ @return The numerical value converted.
+
+**/
+UINTN
+EFIAPI
+HexCharToUintn (
+ IN CHAR16 Char
+ );
+
+/**
+ Function for 'setsize' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunSetSize (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'comp' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunComp (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'mode' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunMode (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'memmap' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunMemMap (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'compress' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunEfiCompress (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'decompress' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunEfiDecompress (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'dmem' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDmem (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'loadpcirom' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunLoadPciRom (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'mm' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunMm (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'setvar' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunSetVar (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'sermode' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunSerMode (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'bcfg' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunBcfg (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'pci' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunPci (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'smbiosview' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunSmbiosView (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'dmpstore' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDmpStore (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'dblk' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDblk (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'edit' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunEdit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'hexedit' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunHexEdit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Clear the line at the specified Row.
+
+ @param[in] Row The row number to be cleared ( start from 1 )
+ @param[in] LastCol The last printable column.
+ @param[in] LastRow The last printable row.
+**/
+VOID
+EFIAPI
+EditorClearLine (
+ IN UINTN Row,
+ IN UINTN LastCol,
+ IN UINTN LastRow
+ );
+
+/**
+ Check if file name has illegal characters.
+
+ @param Name The filename to check.
+
+ @retval TRUE The filename is ok.
+ @retval FALSE The filename is not ok.
+**/
+BOOLEAN
+EFIAPI
+IsValidFileName (
+ IN CONST CHAR16 *Name
+ );
+
+/**
+ Find a filename that is valid (not taken) with the given extension.
+
+ @param[in] Extension The file extension.
+
+ @retval NULL Something went wrong.
+ @return the valid filename.
+**/
+CHAR16 *
+EFIAPI
+EditGetDefaultFileName (
+ IN CONST CHAR16 *Extension
+ );
+
+/**
+ Read a file into an allocated buffer. The buffer is the responsibility
+ of the caller to free.
+
+ @param[in] FileName The filename of the file to open.
+ @param[out] Buffer Upon successful return, the pointer to the
+ address of the allocated buffer.
+ @param[out] BufferSize If not NULL, then the pointer to the size
+ of the allocated buffer.
+ @param[out] ReadOnly Upon successful return TRUE if the file is
+ read only. FALSE otherwise.
+
+ @retval EFI_NOT_FOUND The filename did not represent a file in the
+ file system. Directories cannot be read with
+ this method.
+ @retval EFI_SUCCESS The file was read into the buffer.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_LOAD_ERROR The file read operation failed.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.
+ @retval EFI_INVALID_PARAMETER FileName was NULL.
+ @retval EFI_INVALID_PARAMETER FileName was a directory.
+**/
+EFI_STATUS
+EFIAPI
+ReadFileIntoBuffer (
+ IN CONST CHAR16 *FileName,
+ OUT VOID **Buffer,
+ OUT UINTN *BufferSize OPTIONAL,
+ OUT BOOLEAN *ReadOnly
+ );
+
+#endif
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf
new file mode 100644
index 0000000000..6b837b5faa
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf
@@ -0,0 +1,139 @@
+## @file
+# Provides shell Debug1 profile functions
+#
+# Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = UefiShellDebug1CommandsLib
+ FILE_GUID = 90330D51-A99B-4cc8-A2EB-AE22542A3F45
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.2
+ LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER
+ CONSTRUCTOR = UefiShellDebug1CommandsLibConstructor
+ DESTRUCTOR = UefiShellDebug1CommandsLibDestructor
+
+[Sources]
+ SetSize.c
+ Comp.c
+ Mode.c
+ MemMap.c
+ Compress.h
+ Compress.c
+ EfiCompress.c
+ EfiDecompress.c
+ Dmem.c
+ LoadPciRom.c
+ Mm.c
+ SetVar.c
+ SerMode.c
+ Pci.c
+ Pci.h
+ DmpStore.c
+ Dblk.c
+ SmbiosView/EventLogInfo.c
+ SmbiosView/EventLogInfo.h
+ SmbiosView/PrintInfo.c
+ SmbiosView/QueryTable.c
+ SmbiosView/SmbiosView.c
+ SmbiosView/SmbiosViewStrings.uni
+ SmbiosView/LibSmbiosView.c
+ SmbiosView/PrintInfo.h
+ SmbiosView/LibSmbiosView.h
+ SmbiosView/QueryTable.h
+ SmbiosView/SmbiosView.h
+ UefiShellDebug1CommandsLib.c
+ UefiShellDebug1CommandsLib.h
+ UefiShellDebug1CommandsLib.uni
+
+## Files shared by both editors
+ EditTitleBar.h
+ EditTitleBar.c
+ EditInputBar.h
+ EditInputBar.c
+ EditStatusBar.h
+ EditStatusBar.c
+ EditMenuBar.h
+ EditMenuBar.c
+
+## Files specific to the text editor
+ Edit/Edit.c
+ Edit/TextEditor.h
+ Edit/TextEditorTypes.h
+ Edit/FileBuffer.h
+ Edit/FileBuffer.c
+ Edit/MainTextEditor.h
+ Edit/MainTextEditor.c
+ Edit/Misc.h
+ Edit/Misc.c
+ Edit/TextEditStrings.uni
+
+## Files specific to the HEX editor
+ HexEdit/BufferImage.h
+ HexEdit/BufferImage.c
+ HexEdit/Clipboard.h
+ HexEdit/Clipboard.c
+ HexEdit/DiskImage.h
+ HexEdit/DiskImage.c
+ HexEdit/FileImage.h
+ HexEdit/FileImage.c
+ HexEdit/HexEdit.c
+ HexEdit/HexEditor.h
+ HexEdit/HexEditorTypes.h
+ HexEdit/HexeditStrings.uni
+ HexEdit/MainHexEditor.h
+ HexEdit/MainHexEditor.c
+ HexEdit/MemImage.h
+ HexEdit/MemImage.c
+ HexEdit/Misc.h
+ HexEdit/Misc.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ BaseMemoryLib
+ IoLib
+ DebugLib
+ ShellCommandLib
+ ShellLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ SortLib
+ PrintLib
+ BcfgCommandLib
+
+[Pcd]
+ gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask ## CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdShellFileOperationSize ## CONSUMES
+ gEfiMdePkgTokenSpaceGuid.PcdMaximumUnicodeStringLength ## CONSUMES
+
+[Protocols]
+ gEfiPciRootBridgeIoProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiBlockIoProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiSimplePointerProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiCpuIo2ProtocolGuid ## SOMETIMES_CONSUMES
+
+[Guids]
+ gEfiGlobalVariableGuid ## SOMETIMES_CONSUMES ## GUID
+ gEfiSmbiosTableGuid ## SOMETIMES_CONSUMES ## SystemTable
+ gEfiSmbios3TableGuid ## SOMETIMES_CONSUMES ## SystemTable
+ gEfiMpsTableGuid ## SOMETIMES_CONSUMES ## SystemTable
+ gEfiSalSystemTableGuid ## SOMETIMES_CONSUMES ## SystemTable
+ gEfiAcpi10TableGuid ## SOMETIMES_CONSUMES ## SystemTable
+ gEfiAcpi20TableGuid ## SOMETIMES_CONSUMES ## SystemTable
+ gShellDebug1HiiGuid ## SOMETIMES_CONSUMES ## HII
diff --git a/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.uni b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.uni
new file mode 100644
index 0000000000..c6c7ba9e2f
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.uni
@@ -0,0 +1,1188 @@
+// /**
+//
+// Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
+// (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
+// (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// Module Name:
+//
+// UefiShellDebug1CommandsLib.uni
+//
+// Abstract:
+//
+// String definitions for UEFI Shell 2.0 Debug1 profile commands
+//
+//
+// **/
+
+/=#
+
+#langdef en-US "english"
+
+#string STR_GEN_NO_MEM #language en-US "%H%s%N: Memory is not available.\r\n"
+#string STR_GEN_BOOT_ONLY #language en-US "%H%s%N: Boot must be selected for hot key options.\r\n"
+#string STR_GEN_FIND_FAIL #language en-US "%H%s%N: File not found - '%H%s%N'\r\n"
+
+#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n"
+#string STR_GEN_PROBLEM_VAL #language en-US "%H%s%N: Bad value - '%H%s%N' for flag - '%H%s%N'\r\n"
+#string STR_GEN_NO_VALUE #language en-US "%H%s%N: Missing argument for flag - '%H%s%N'\r\n"
+#string STR_GEN_TOO_FEW #language en-US "%H%s%N: Too few arguments.\r\n"
+#string STR_GEN_TOO_MANY #language en-US "%H%s%N: Too many arguments.\r\n"
+#string STR_GEN_NO_DRIVER_BOOT #language en-US "%H%s%N: Driver or Boot must be selected.\r\n"
+#string STR_GEN_PCIRBIO_NF #language en-US "%H%s%N: Protocol - PciRootBridgeIo not found.\r\n"
+#string STR_GEN_PCIRBIO_ER #language en-US "%H%s%N: Problem accessing the data using Protocol - PciRootBridgeIo\r\n"
+#string STR_GEN_PARAM_INV #language en-US "%H%s%N: Invalid argument - '%H%s%N'\r\n"
+#string STR_GEN_PARAM_INV_HEX #language en-US "%H%s%N: Invalid parameter - '%H%s%N:'. Must be hexadecimal.\r\n"
+#string STR_GEN_PARAM_CONFLICT #language en-US "%H%s%N: Flags conflict with - '%H%s%N' and '%H%s%N'\r\n"
+#string STR_GEN_OUT_MEM #language en-US "%H%s%N: Memory allocation was not successful.\r\n"
+#string STR_GEN_MAP_PROTOCOL #language en-US "%H%s%N: Mapped device '%B%s%N' does not have protocol %B%s%N\r\n"
+#string STR_GEN_FILE_OPEN_FAIL #language en-US "%H%s%N: Cannot open file - '%H%s%N'\r\n"
+#string STR_GEN_FILE_DELETE_FAIL #language en-US "%H%s%N: Cannot delete file - '%H%s%N'\r\n"
+#string STR_GEN_NO_CWD #language en-US "%H%s%N: Current directory not specified.\r\n"
+#string STR_GEN_FILE_IS_DIRECTORY #language en-US "%H%s%N: The file '%H%s%N' is a directory.\r\n"
+#string STR_GEN_SFO_HEADER #language en-US "ShellCommand,"%s"\r\n"
+
+
+#string STR_FILE_OPEN_FAIL #language en-US "Unable to open file on '%B%s%N' with: %r.\r\n"
+#string STR_FILE_FIND_FAIL #language en-US "%H%s%N: File not found - '%H%s%N'\r\n"
+#string STR_FILE_NOT_DIR #language en-US "%H%s%N: Directories are not permitted - '%H%s%N'\r\n"
+#string STR_SIZE_NOT_SPEC #language en-US "%H%s%N: A valid size must be specified\r\n"
+#string STR_FILE_NOT_SPEC #language en-US "%H%s%N: File not specified\r\n"
+#string STR_FILE_WRITE_FAIL #language en-US "%H%s%N: Write file error - '%H%s%N'\r\n"
+#string STR_FILE_READ_FAIL #language en-US "%H%s%N: Read file error - '%H%s%N'\r\n"
+#string STR_VOLUME_FULL #language en-US "%H%s%N: The volume is full\r\n"
+
+#string STR_SET_SIZE_FAIL #language en-US "%H%s%N: Unable to change size on '%B%s%N'\r\n"
+#string STR_SET_SIZE_DONE #language en-US "Size changed on '%B%s%N'.\r\n"
+
+#string STR_DBLK_HEADER #language en-US "LBA %016LX Size %08x bytes BlkIo %0x\r\n"
+
+#string STR_COMP_HEADER #language en-US "Compare %s to %s.\r\n"
+#string STR_COMP_SIZE_FAIL #language en-US "Difference # 1: File size mismatch.\r\n"
+#string STR_COMP_SPOT_FAIL1 #language en-US ""
+ "Difference #% 2d:\r\n"
+ "File1: %s\r\n"
+ " %08x: %02x *%c*\r\n"
+ "File2: %s\r\n"
+ " %08x: %02x *%c*\r\n"
+#string STR_COMP_SPOT_FAIL2 #language en-US ""
+ "Difference #% 2d:\r\n"
+ "File1: %s\r\n"
+ " %08x: %02x %02x *%c%c*\r\n"
+ "File2: %s\r\n"
+ " %08x: %02x %02x *%c%c*\r\n"
+#string STR_COMP_SPOT_FAIL3 #language en-US ""
+ "Difference #% 2d:\r\n"
+ "File1: %s\r\n"
+ " %08x: %02x %02x %02x *%c%c%c*\r\n"
+ "File2: %s\r\n"
+ " %08x: %02x %02x %02x *%c%c%c*\r\n"
+#string STR_COMP_SPOT_FAIL4 #language en-US ""
+ "Difference #% 2d:\r\n"
+ "File1: %s\r\n"
+ " %08x: %02x %02x %02x %02x *%c%c%c%c*\r\n"
+ "File2: %s\r\n"
+ " %08x: %02x %02x %02x %02x *%c%c%c%c*\r\n"
+
+#string STR_COMP_FOOTER_FAIL #language en-US "[difference(s) encountered] \r\n"
+#string STR_COMP_FOOTER_PASS #language en-US "[no differences encountered]\r\n"
+
+#string STR_MODE_SET_FAIL #language en-US "%H%s%N: Unable to change the mode.\r\n"
+#string STR_MODE_NO_MATCH #language en-US "%H%s%N: No matching mode found to set\r\n"
+#string STR_MODE_LIST_HEAD #language en-US "Available modes for console output device.\r\n"
+#string STR_MODE_LIST_ITEM #language en-US " Col % 5d Row % 5d %c\r\n"
+
+#string STR_MEMMAP_GET_FAILED #language en-US "%H%s%N: Unable to get memory map\r\n"
+#string STR_MEMMAP_LIST_HEAD #language en-US "Type Start End # Pages Attributes\r\n"
+#string STR_MEMMAP_LIST_ITEM #language en-US "% -10s %016LX-%016LX %016LX %016LX\r\n"
+#string STR_MEMMAP_LIST_SUMM #language en-US " \r\n"
+ " Reserved : %,14ld Pages (%,ld Bytes)\r\n"
+ " LoaderCode: %,14ld Pages (%,ld Bytes)\r\n"
+ " LoaderData: %,14ld Pages (%,ld Bytes)\r\n"
+ " BS_Code : %,14ld Pages (%,ld Bytes)\r\n"
+ " BS_Data : %,14ld Pages (%,ld Bytes)\r\n"
+ " RT_Code : %,14ld Pages (%,ld Bytes)\r\n"
+ " RT_Data : %,14ld Pages (%,ld Bytes)\r\n"
+ " ACPI_Recl : %,14ld Pages (%,ld Bytes)\r\n"
+ " ACPI_NVS : %,14ld Pages (%,ld Bytes)\r\n"
+ " MMIO : %,14ld Pages (%,ld Bytes)\r\n"
+ " MMIO_Port : %,14ld Pages (%,ld Bytes)\r\n"
+ " PalCode : %,14ld Pages (%,ld Bytes)\r\n"
+ " Available : %,14ld Pages (%,ld Bytes)\r\n"
+ " -------------- \r\n"
+ "Total Memory: %,14ld MB (%,ld Bytes)\r\n"
+#string STR_MEMMAP_LIST_ITEM_SFO #language en-US "MemoryMap,"%s","%LX","%LX","%LX","%LX"\r\n"
+#string STR_MEMMAP_LIST_SUMM_SFO #language en-US "MemoryMapSummary,"%Ld","%Ld","%Ld","%Ld","%Ld","%Ld","%Ld","%Ld","%Ld","%Ld","%Ld","%Ld","%Ld","%Ld","%Ld"\r\n"
+
+#string STR_EFI_COMPRESS_FAIL #language en-US "Unable to compress: %r.\r\n"
+#string STR_EFI_DECOMPRESS_FAIL #language en-US "Unable to decompress: %r.\r\n"
+#string STR_EFI_DECOMPRESS_NOPE #language en-US "The file does not appear to be a compressed file. Cannot continue. \"%H%s%N\"\r\n"
+
+#string STR_DMEM_HEADER_ROW #language en-US "Memory Address %016LX %X Bytes\r\n"
+#string STR_DMEM_MMIO_HEADER_ROW #language en-US "Memory Mapped IO Address %016LX %X Bytes\r\n"
+#string STR_DMEM_DATA_ROW #language en-US "%08X: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x *%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c*\r\n"
+#string STR_DMEM_SYSTEM_TABLE #language en-US "\r\nValid EFI Header at Address %016Lx\r\n"
+ "---------------------------------------------\r\n"
+ "System: Table Structure size %08x revision %08x\r\n"
+ "ConIn (%016LX) ConOut (%016LX) StdErr (%016LX)\r\n"
+ "Runtime Services %016LX\r\n"
+ "Boot Services %016LX\r\n"
+ "SAL System Table %016LX\r\n"
+ "ACPI Table %016LX\r\n"
+ "ACPI 2.0 Table %016LX\r\n"
+ "MPS Table %016LX\r\n"
+ "SMBIOS Table %016LX\r\n"
+
+#string STR_LOAD_PCI_ROM_RES #language en-US "Image '%B%s%N' load result: %r\r\n"
+#string STR_LOADPCIROM_CORRUPT #language en-US "%H%s%N: File '%B%s%N' Image %d is corrupt.\r\n"
+#string STR_LOADPCIROM_LOAD_FAIL #language en-US "%H%s%N: File '%B%s%N' Image %d unable to load.\r\n"
+#string STR_LOADPCIROM_START_FAIL #language en-US "%H%s%N: File '%B%s%N' Image %d unable to start.\r\n"
+
+#string STR_MM_NOT_ALIGNED #language en-US "%H%s%N: Address parameter %016LX is not aligned.\r\n"
+#string STR_MM_PCIE_ADDRESS_RANGE #language en-US "%H%s%N: Address parameter %016LX is not a valid PCI/PCIE address.\r\n"
+#string STR_MM_IO_ADDRESS_RANGE #language en-US "%H%s%N: IO address out of range 0 - 0xFFFF\r\n"
+#string STR_MM_MMIO #language en-US "%HMMIO%N"
+#string STR_MM_IO #language en-US "%HIO%N"
+#string STR_MM_PCI #language en-US "%HPCI%N"
+#string STR_MM_MEM #language en-US "%HMEM%N"
+#string STR_MM_PCIE #language en-US "%HPCIE%N"
+#string STR_MM_ADDRESS #language en-US " 0x%016lx : "
+#string STR_MM_BUF #language en-US "0x%0*lx"
+#string STR_MM_ADDRESS_RANGE2 #language en-US "%H%s%N: IO address out of range\r\n"
+#string STR_MM_ERROR #language en-US "%H%s%N: Input had incorrect format\r\n"
+
+#string STR_SETVAR_PRINT #language en-US "%g - %s - %04x Bytes\r\n"
+#string STR_SETVAR_ERROR_SET #language en-US "%H%s%N: Unable to set - %H%g%N - %H%s%N\r\n"
+#string STR_SETVAR_ERROR_GET #language en-US "%H%s%N: Unable to get - %H%g%N - %H%s%N\r\n"
+#string STR_SETVAR_ERROR_DPFT #language en-US "%H%s%N: DevicePathFromText conversion was not successful.\r\n"
+
+#string STR_SERMODE_NO_FOUND #language en-US "%H%s%N: No serial ports found.\r\n"
+#string STR_SERMODE_NOT_FOUND #language en-US "%H%s%N: No serial port or specified serial port found.\r\n"
+#string STR_SERMODE_BAD_HANDLE #language en-US "%H%s%N: Handle %H%02x%N is not a serial device handle.\r\n"
+#string STR_SERMODE_SET_HANDLE #language en-US "Mode set on handle %H%02x%N successfully.\r\n"
+#string STR_SERMODE_SET_FAIL #language en-US "%H%s%N: Mode change on handle %H%02x%N was not successful.\r\n"
+#string STR_SERMODE_DISPLAY #language en-US "%x(%08x) - (%ld, %c, %d, %s)\r\n"
+#string STR_SERMODE_SET_UNSUPPORTED #language en-US "%H%s%N: One or more of the new settings is not supported on handle %H%02x%N.\r\n"
+#string STR_SERMODE_SET_DEV_ERROR #language en-US "%H%s%N: The serial device on handle %H%02x%N is not functioning correctly.\r\n"
+
+#string STR_PCI_HANDLE_CFG_ERR #language en-US "%H%s%N: Handle protocol or configuration error.\r\n"
+#string STR_PCI_BUS_RANGE_ERR #language en-US "%H%s%N: Get next bus range error.\r\n"
+#string STR_PCI_NO_FIND #language en-US "%H%s%N: Cannot find protocol interface for segment %x, bus %x.\r\n"
+#string STR_PCI_NO_CFG #language en-US "%H%s%N: Cannot read configuration data.\r\n"
+#string STR_PCI_INFO #language en-US "%H PCI Segment %02x Bus %02x Device %02x Func %02x%N [EFI %02x%02x%02x%02x00]\r\n"
+#string STR_PCI_TITLE #language en-US " Seg Bus Dev Func\r\n"
+ " --- --- --- ----\r\n"
+#string STR_PCI_LINE_P1 #language en-US " %E%02x %02x %02x %02x ==> %N"
+#string STR_PCI_LINE_P2 #language en-US "\r\n Vendor %04x Device %04x Prog Interface %x\r\n"
+#string STR_PCIEX_CAPABILITY_CAPID #language en-US "CapID(%2x): %E%02x%N"
+#string STR_PCIEX_NEXTCAP_PTR #language en-US " NextCap Ptr(%2x): %E%02x%N\r\n"
+#string STR_PCIEX_CAP_REGISTER #language en-US "Cap Register(%2x): %E%04x%N\r\n"
+#string STR_PCIEX_DEVICE_CAP #language en-US "Device Capabilities(%2x): %E%08x%N\r\n"
+#string STR_PCIEX_DEVICE_CONTROL #language en-US "Device Control(%2x): %E%04x%N\r\n"
+#string STR_PCIEX_DEVICE_STATUS #language en-US "Device Status(%2x): %E%04x%N\r\n"
+#string STR_PCIEX_LINK_CAPABILITIES #language en-US "Link Capabilities(%2x): %E%08x%N\r\n"
+#string STR_PCIEX_LINK_CONTROL #language en-US "Link Control(%2x): %E%04x%N\r\n"
+#string STR_PCIEX_LINK_STATUS #language en-US "Link Status(%2x): %E%04x%N\r\n"
+#string STR_PCIEX_SLOT_CAPABILITIES #language en-US "Slot Capabilities(%2x): %E%08x%N\r\n"
+#string STR_PCIEX_SLOT_CONTROL #language en-US "Slot Control(%2x): %E%04x%N\r\n"
+#string STR_PCIEX_SLOT_STATUS #language en-US "Slot Status(%2x): %E%04x%N\r\n"
+#string STR_PCIEX_ROOT_CONTROL #language en-US "Root Control(%2x): %E%04x%N\r\n"
+#string STR_PCIEX_RSVDP #language en-US "Root Capabilities(%2x): %E%04x%N\r\n"
+#string STR_PCIEX_ROOT_STATUS #language en-US "Root Status(%2x): %E%08x%N\r\n"
+#string STR_PCI_LINE_VID_DID #language en-US "Vendor ID(%x): %E%04x%N Device ID(%x): %E%04x%N\r\n"
+#string STR_PCI_LINE_RID #language en-US "Revision ID(%x): %E%02x%N "
+#string STR_PCI_LINE_BIST #language en-US "BIST(%02x): "
+#string STR_PCI_LINE_CAP #language en-US "Capable,Return: %E%02x%N\r\n"
+#string STR_PCI_LINE_CAP_NO #language en-US " Incapable\r\n"
+#string STR_PCI2_CACHE_LINE_SIZE #language en-US "Cache Line Size(%x): %E%02x%N "
+#string STR_PCI2_LATENCY_TIMER #language en-US "Latency Timer(%x): %E%02x%N\r\n"
+#string STR_PCI2_HEADER_TYPE #language en-US "Header Type(%02x): %E%02x%N, "
+#string STR_PCI2_MULTI_FUNCTION #language en-US "Multi-function, "
+#string STR_PCI2_SINGLE_FUNCTION #language en-US "Single function, "
+#string STR_PCI2_PCI_DEVICE #language en-US "PCI device\r\n"
+#string STR_PCI2_P2P_BRIDGE #language en-US "P2P bridge\r\n"
+#string STR_PCI2_CARDBUS_BRIDGE #language en-US "CardBus bridge\r\n"
+#string STR_PCI2_RESERVED #language en-US "Reserved\r\n"
+#string STR_PCI2_CLASS #language en-US "Class: "
+#string STR_PCI2_BASE_ADDR #language en-US "Base Address Registers(%x):\r\n"
+#string STR_PCI2_START_TYPE #language en-US " Start_Address Type Space Prefetchable? Size Limit\r\n"
+#string STR_PCI2_NONE #language en-US " (None)"
+#string STR_PCI2_EXPANSION_ROM_DISABLED #language en-US "\r\nExpansion ROM Disabled(%x)\r\n\r\n"
+#string STR_PCI2_EXPANSION_ROM_BASE #language en-US "\r\nExpansion ROM Base Address(%x): %E%08x%N\r\n\r\n"
+#string STR_PCI2_CARDBUS_CIS #language en-US "Cardbus CIS ptr(%x): %E%08x%N\r\n"
+#string STR_PCI2_SUB_VENDOR_ID #language en-US "Sub VendorID(%x): %E%04x%N "
+#string STR_PCI2_SUBSYSTEM_ID #language en-US "Subsystem ID(%x): %E%04x%N\r\n"
+#string STR_PCI2_CAPABILITIES_PTR #language en-US "Capabilities Ptr(%x): %E%02x%N\r\n"
+#string STR_PCI2_INTERRUPT_LINE #language en-US "Interrupt Line(%x): %E%02x%N "
+#string STR_PCI2_INTERRUPT_PIN #language en-US "Interrupt Pin(%x): %E%02x%N\r\n"
+#string STR_PCI2_MIN_GNT #language en-US "Min_Gnt(%x): %E%02x%N "
+#string STR_PCI2_MAX_LAT #language en-US "Max_Lat(%x): %E%02x%N\r\n"
+#string STR_PCI2_BASE_ADDRESS #language en-US "Base Address Registers(%x):"
+#string STR_PCI2_START_TYPE_2 #language en-US " Start_Address Type Space Prefetchable? Size Limit\r\n"
+#string STR_PCI2_NO_EXPANSION_ROM #language en-US "\r\nNo Expansion ROM(%x) "
+#string STR_PCI2_EXPANSION_ROM_BASE_2 #language en-US "\r\nExpansion ROM Base Address(%x): %E%08x%N\r\n"
+#string STR_PCI2_BUS_NUMBERS #language en-US "\r\n\r\n(Bus Numbers) Primary(%x) Secondary(%x) Subordinate(%x)\r\n"
+#string STR_PCI2_BRIDGE #language en-US " %E%02x%N"
+#string STR_PCI2_SECONDARY_TIMER #language en-US "\r\nSecondary Latency Timer(%x): %E%02x%N\n\n"
+#string STR_PCI2_CARDBUS_LATENCY #language en-US "\r\nCardBus Latency Timer(%x): %E%02x%N\r\n"
+#string STR_PCI2_RESOURCE_TYPE_2 #language en-US "\r\nResource Type Type Base Limit\r\n"
+#string STR_PCI2_MEM_3 #language en-US "Mem(%x) %s %E%08x%N %E%08x%N\r\n"
+#string STR_PCI2_IO_2 #language en-US "I/O(%x) %s %E%08x%N %E%08x%N\r\n"
+#string STR_PCI2_INTERRUPT_LINE_3 #language en-US "\r\nInterrupt Line(%x): %E%02x%N Interrupt Pin(%x): %E%02x%N\r\n"
+#string STR_PCI2_SUB_VENDOR_ID_2 #language en-US "\r\nSub VendorID(%x): %E%04x%N Subsystem ID(%x): %E%04x%N\r\n"
+#string STR_PCI2_OPTIONAL #language en-US "Optional 16-Bit PC Card legacy Mode Base Address(%x): %E%08x%N\r\n"
+#string STR_PCI2_STATUS #language en-US "Status(%x): %E%04x%N\r\n"
+#string STR_PCI2_SECONDARY_STATUS #language en-US "Secondary Status(%2x): %E%4x%N\r\n"
+#string STR_PCI2_NEW_CAPABILITIES #language en-US " (04)New Capabilities linked list: %E%d%N"
+#string STR_PCI2_66_CAPABLE #language en-US " (05)66MHz Capable: %EN/A%N\r\n"
+#string STR_PCI2_66_CAPABLE_2 #language en-US " (05)66MHz Capable: %E%d%N\r\n"
+#string STR_PCI2_FAST_BACK #language en-US " (07)Fast Back-to-Back Capable: %E%d%N"
+#string STR_PCI2_NO #language en-US "No "
+#string STR_PCI2_YES #language en-US "YES "
+#string STR_PCI2_ONE_VAR_4 #language en-US "\r\n %E%04x%N "
+#string STR_PCI2_NEWBAR_32 #language en-US " %08x "
+#string STR_PCI2_NEWBAR_32_2 #language en-US " %08x"
+#string STR_PCI2_RSHIFT #language en-US "%08x"
+#string STR_PCI2_NEWBAR_32_3 #language en-US "%04x "
+#string STR_PCI2_NEWBAR_32_4 #language en-US "%04x"
+#string STR_PCI2_CARDBUS_SOCKET #language en-US "\r\nCardBus Socket Registers/ExCA Base Address Register(%x): %E%8x%N\r\n\r\n"
+#string STR_PCI2_BUS_NUMBERS_2 #language en-US "\r\n(Bus Numbers) Pci(%x) CardBus(%x) Subordinate(%x)\r\n"
+#string STR_PCI2_CARDBUS #language en-US " %E%02x%N"
+#string STR_PCI2_CARDBUS_2 #language en-US " %E%02x%N"
+#string STR_PCI2_CARDBUS_3 #language en-US " %E%02x%N\r\n"
+#string STR_PCI2_MASTER_DATA #language en-US " (08)Master Data Parity Error: %E%d%N\r\n"
+#string STR_PCI2_DEVSEL_TIMING #language en-US " (09)DEVSEL timing: "
+#string STR_PCI2_FAST #language en-US "%E Fast%N"
+#string STR_PCI2_MEDIUM #language en-US "%E Medium%N"
+#string STR_PCI2_SLOW #language en-US "%E Slow%N"
+#string STR_PCI2_RESERVED_2 #language en-US "%EReserved%N"
+#string STR_PCI2_SIGNALED_TARGET #language en-US " (11)Signaled Target Abort: %E%d%N\r\n"
+#string STR_PCI2_RECEIVED_TARGET #language en-US " (12)Received Target Abort: %E%d%N"
+#string STR_PCI2_RECEIVED_MASTER #language en-US " (13)Received Master Abort: %E%d%N\r\n"
+#string STR_PCI2_SIGNALED_ERROR #language en-US " (14)Signaled System Error: %E%d%N"
+#string STR_PCI2_RECEIVED_ERROR #language en-US " (14)Received System Error: %E%d%N"
+#string STR_PCI2_DETECTED_ERROR #language en-US " (15)Detected Parity Error: %E%d%N\r\n"
+#string STR_PCI2_COMMAND #language en-US "Command(%x): %E%04x%N\r\n"
+#string STR_PCI2_SPACE_ACCESS_DENIED #language en-US " (00)I/O space access enabled: %E%d%N"
+#string STR_PCI2_MEMORY_SPACE #language en-US " (01)Memory space access enabled: %E%d%N\r\n"
+#string STR_PCI2_BEHAVE_BUS_MASTER #language en-US " (02)Behave as bus master: %E%d%N"
+#string STR_PCI2_MONITOR_SPECIAL_CYCLE #language en-US " (03)Monitor special cycle enabled: %E%d%N\r\n"
+#string STR_PCI2_MEM_WRITE_INVALIDATE #language en-US " (04)Mem Write & Invalidate enabled: %E%d%N"
+#string STR_PCI2_PALETTE_SNOOPING #language en-US " (05)Palette snooping is enabled: %E%d%N\r\n"
+#string STR_PCI2_ASSERT_PERR #language en-US " (06)Assert PERR# when parity error: %E%d%N"
+#string STR_PCI2_DO_ADDR_STEPPING #language en-US " (07)Do address/data stepping: %E%d%N\r\n"
+#string STR_PCI2_SERR_DRIVER #language en-US " (08)SERR# driver enabled: %E%d%N"
+#string STR_PCI2_FAST_BACK_2 #language en-US " (09)Fast back-to-back transact...: %E%d%N\r\n\r\n"
+#string STR_PCI2_BRIDGE_CONTROL #language en-US "Bridge Control(%x) %E%04x%N\r\n"
+#string STR_PCI2_PARITY_ERROR #language en-US " (00)Parity Error Response: %E%d%N"
+#string STR_PCI2_SERR_ENABLE #language en-US " (01)SERR# Enable: %E%d%N\r\n"
+#string STR_PCI2_ISA_ENABLE #language en-US " (02)ISA Enable: %E%d%N"
+#string STR_PCI2_RESOURCE_TYPE #language en-US "\r\nResource Type Base Limit\r\n"
+#string STR_PCI2_TWO_VARS #language en-US "I/O(%x) %E%08x%N"
+#string STR_PCI2_ONE_VAR #language en-US " %E%08x%N\r\n"
+#string STR_PCI2_MEMORY #language en-US "Memory(%x) %E%08x%N"
+#string STR_PCI2_PREFETCHABLE #language en-US "Prefetchable Memory(%x) %E%08x%08x%N"
+#string STR_PCI2_TWO_VARS_2 #language en-US " %E%08x%08x%N\r\n"
+#string STR_PCI2_CAPABILITIES_PTR_2 #language en-US "\r\nCapabilities Ptr(%x): %E%02x%N \r\n\r\n"
+#string STR_PCI2_INTERRUPT_LINE_2 #language en-US "\r\nInterrupt Line(%x) %E%02x%N "
+#string STR_PCI2_BAR #language en-US "\r\n %E%08x%N "
+#string STR_PCI2_MEM #language en-US "Mem "
+#string STR_PCI2_32_BITS #language en-US "32 bits "
+#string STR_PCI2_ONE_VAR_2 #language en-US "\r\n %E%08x"
+#string STR_PCI2_ONE_VAR_3 #language en-US "%08x%N "
+#string STR_PCI2_64_BITS #language en-US "64 bits "
+#string STR_PCI2_MEM_2 #language en-US "Mem "
+#string STR_PCI2_VGA_ENABLE #language en-US " (03)VGA Enable: %E%d%N\r\n"
+#string STR_PCI2_MASTER_ABORT #language en-US " (05)Master Abort Mode: %E%d%N"
+#string STR_PCI2_SECONDARY_BUS_RESET #language en-US " (06)Secondary Bus Reset: %E%d%N\r\n"
+#string STR_PCI2_FAST_ENABLE #language en-US " (07)Fast Back-to-Back Enable: %E%d%N"
+#string STR_PCI2_PRIMARY_DISCARD_TIMER #language en-US " (08)Primary Discard Timer: %E%s%N\r\n"
+#string STR_PCI2_SECONDARY_DISCARD_TIMER #language en-US " (09)Secondary Discard Timer: %E%s%N"
+#string STR_PCI2_DISCARD_TIMER_STATUS #language en-US " (10)Discard Timer Status: %E%d%N\r\n"
+#string STR_PCI2_DISCARD_TIMER_SERR #language en-US " (11)Discard Timer SERR# Enable: %E%d%N\r\n"
+#string STR_PCI2_CARDBUS_RESET #language en-US " (06)CardBus Reset: %E%d%N\r\n"
+#string STR_PCI2_IREQ_ENABLE #language en-US " (07)IREQ/INT Enable: %E%d%N"
+#string STR_PCI2_WRITE_POSTING_ENABLE #language en-US " (10)Write Posting Enable: %E%d%N\r\n"
+#string STR_PCI_EXT_CAP_AER #language en-US " Advanced Error Reporting\r\n"
+ " UncorrectableErrorStatus %08x\r\n"
+ " UncorrectableErrorMask %08x\r\n"
+ " UncorrectableErrorSeverity %08x\r\n"
+ " CorrectableErrorStatus %08x\r\n"
+ " CorrectableErrorMask %08x\r\n"
+ " AdvancedErrorCapAndControl %08x\r\n"
+ " HeaderLog1 %08x\r\n"
+ " HeaderLog2 %08x\r\n"
+ " HeaderLog3 %08x\r\n"
+ " HeaderLog4 %08x\r\n"
+ " RootErrorCommand %08x\r\n"
+ " RootErrorStatus %08x\r\n"
+ " ErrorSourceIdentification %04x\r\n"
+ " CorrectableErrorSourceIden %04x\r\n"
+ " TlpPrefixLog1 %08x\r\n"
+ " TlpPrefixLog2 %08x\r\n"
+ " TlpPrefixLog3 %08x\r\n"
+ " TlpPrefixLog4 %08x\r\n"
+#string STR_PCI_EXT_CAP_LINK_CONTROL #language en-US " Link Control\r\n"
+ " RootComplexLinkCapabilities %08x\r\n"
+ " RootComplexLinkControl %04x\r\n"
+ " RootComplexLinkStatus %04x\r\n"
+#string STR_PCI_EXT_CAP_LINK_DECLAR #language en-US " Link Declaration\r\n"
+ " ElementSelfDescription %08x\r\n"
+#string STR_PCI_EXT_CAP_LINK_DECLAR2 #language en-US " LinkEntry[%x] %08x\r\n"
+#string STR_PCI_EXT_CAP_SN #language en-US " Serial Number\r\n"
+ " SerialNumber %L16x\r\n"
+#string STR_PCI_EXT_CAP_POWER #language en-US " Power Budgeting\r\n"
+ " DataSelect %02x\r\n"
+ " Data %08x\r\n"
+ " PowerBudgetCapability %02x\r\n"
+#string STR_PCI_EXT_CAP_ACS #language en-US " ACS\r\n"
+ " CapabilityRegister %04x\r\n"
+ " ControlRegister %04x\r\n"
+#string STR_PCI_EXT_CAP_ACS2 #language en-US " EgressControlVectorByte[%x] %02x\r\n"
+#string STR_PCI_EXT_CAP_LAT #language en-US " Latency Tolerance Reporting\r\n"
+ " MaxSnoopLatency %04x\r\n"
+ " MaxNoSnoopLatency %04x\r\n"
+#string STR_PCI_EXT_CAP_ARI #language en-US " ARI\r\n"
+ " AriCapability %04x\r\n"
+ " AriControl %04x\r\n"
+#string STR_PCI_EXT_CAP_RCRB #language en-US " RCRB\r\n"
+ " VendorId %04x\r\n"
+ " DeviceId %04x\r\n"
+ " RcrbCapabilities %04x\r\n"
+ " RcrbControl %04x\r\n"
+#string STR_PCI_EXT_CAP_VEN #language en-US " VendorSpecific\r\n"
+ " VendorSpecificHeader %04x\r\n"
+#string STR_PCI_EXT_CAP_DPA #language en-US " DPA\r\n"
+ " DpaCapability %04x\r\n"
+ " DpaLatencyIndicator %04x\r\n"
+ " DpaStatus %04x\r\n"
+ " DpaControl %04x\r\n"
+#string STR_PCI_EXT_CAP_DPA2 #language en-US " DpaPowerAllocationArray[%x] %02x\r\n"
+#string STR_PCI_EXT_CAP_ECEA #language en-US " Event Collector Endpoint Association\r\n"
+ " AssociationBitmap %04x\r\n"
+#string STR_PCI_EXT_CAP_VC_BASE #language en-US " Virtual (Multi) Channel Capability\r\n"
+ " ExtendedVcCount %08x\r\n"
+ " PortCapability1 %08x\r\n"
+ " PortCapability2 %08x\r\n"
+ " ArbitrationTableOffset %08x\r\n"
+ " PortVcControl %04x\r\n"
+ " PortVcStatus %04x\r\n"
+#string STR_PCI_EXT_CAP_VC_ITEM #language en-US " Virtual Channel Capability Extended Item[%x]\r\n"
+ " ResourceCapability %08x\r\n"
+ " ArbitrationTableOffset %08x\r\n"
+ " ResourceControl %08x\r\n"
+ " ResourceStatus %04x\r\n"
+#string STR_PCI_EXT_CAP_MULTICAST #language en-US " MultiCast Capability\r\n"
+ " MultiCastCapability %04x\r\n"
+ " MulticastControl %04x\r\n"
+ " McBaseAddress %L16x\r\n"
+ " McReceiveAddress %L16x\r\n"
+ " McBlockAll %L16x\r\n"
+ " McBlockUntranslated %L16x\r\n"
+ " McOverlayBar %L16x\r\n"
+#string STR_PCI_EXT_CAP_RESIZE_BAR #language en-US " Resizeable Bar Capability [%x]\r\n"
+ " ResizableBarCapability %08x\r\n"
+ " ResizableBarControl %04x\r\n"
+#string STR_PCI_EXT_CAP_TPH #language en-US " TPH\r\n"
+ " TphRequesterCapability %08x\r\n"
+ " TphRequesterControl %04x\r\n"
+ " TphTable (optional):\r\n"
+#string STR_PCI_EXT_CAP_SECONDARY #language en-US " Secondary PCI Express Extended Capability\r\n"
+ " LinkControl3 %08x\r\n"
+ " LaneErrorStatus %08x\r\n"
+ " EqualizationControl:\r\n"
+
+#string STR_DMPSTORE_SAVE #language en-US "Save variable to file: %H%s%N.\r\n"
+#string STR_DMPSTORE_LOAD #language en-US "Load and set variables from file: %H%s%N.\r\n"
+#string STR_DMPSTORE_LOAD_GEN_FAIL #language en-US "%H%s%N: Failed to set variable %H%s%N: %r.\r\n"
+#string STR_DMPSTORE_LOAD_BAD_FILE #language en-US "%H%s%N: Incorrect file format.\r\n"
+#string STR_DMPSTORE_HEADER_LINE #language en-US "Variable %H%s%N '%H%g%N:%H%s%N' DataSize = 0x%02x\r\n"
+#string STR_DMPSTORE_DELETE_LINE #language en-US "Delete variable '%H%g%N:%H%s%N': %r\r\n"
+#string STR_DMPSTORE_NO_VAR_FOUND #language en-US "%H%s%N: No matching variables found.\r\n"
+#string STR_DMPSTORE_NO_VAR_FOUND_GN #language en-US "%H%s%N: No matching variables found. Guid %g, Name %s\r\n"
+#string STR_DMPSTORE_NO_VAR_FOUND_N #language en-US "%H%s%N: No matching variables found. Name %s\r\n"
+#string STR_DMPSTORE_NO_VAR_FOUND_G #language en-US "%H%s%N: No matching variables found. Guid %g\r\n"
+
+#string STR_GET_HELP_COMP #language en-US ""
+".TH comp 0 "Compare 2 files"\r\n"
+".SH NAME\r\n"
+"Compares the contents of two files on a byte-for-byte basis.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"COMP [-b] file1 file2\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -b - Displays one screen at a time.\r\n"
+" file1 - Specifies a first file name (directory name or wildcards not permitted).\r\n"
+" file2 - Specifies a second file name (directory name or wildcards not permitted).\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command compares the contents of two files in binary mode.\r\n"
+" 2. It displays up to 10 differences between the two files. For each\r\n"
+" difference, up to 32 bytes from the location where the difference starts\r\n"
+" is dumped.\r\n"
+" 3. It will exit immediately if the lengths of the compared files are\r\n"
+" different.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To compare two files with the same length but different contents:\r\n"
+" fs0:\> comp bios.inf bios2.inf\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The function operated as expected.\r\n"
+" SHELL_NOT_EQUAL The files were not identical.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_NOT_FOUND The requested file was not found.\r\n"
+
+#string STR_GET_HELP_SETSIZE #language en-US ""
+".TH setsize 0 "Set file size"\r\n"
+".SH NAME\r\n"
+"Adjusts the size of a file.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"SETSIZE size file [file...]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" size - Specifies the size of the file after it is adjusted.\r\n"
+" file - Specifies the file or files to be adjusted.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. Setting the size smaller than the actual data contained in this file will\r\n"
+" truncate its data.\r\n"
+" 2. This command adjusts the size of a particular target file.\r\n"
+" 3. This command automatically truncates or extends the size of a file based on the passed-in\r\n"
+" parameters. If the file does not exist, it is created.\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_VOLUME_FULL The media has insufficient space to complete the\r\n"
+" request.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+
+#string STR_GET_HELP_MODE #language en-US ""
+".TH mode 0 "Shows or changes ConOut mode."\r\n"
+".SH NAME\r\n"
+"Displays or changes the console output device mode.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"MODE [col row]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" col - Specifies the number of columns.\r\n"
+" row - Specifies the number of rows.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command changes the display mode for the console output\r\n"
+" device.\r\n"
+" 2. When this command is used without any parameters, it shows the list of\r\n"
+" modes that the standard output device currently supports.\r\n"
+" 3. When used with the row and col parameter, this command\r\n"
+" changes the number of rows and columns on the standard output device.\r\n"
+" 4. The current selected mode is indicated by a '*'. \r\n"
+" 5. The display is cleared every time this command is used to change the\r\n"
+" currently selected display mode.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display all available modes on standard output:\r\n"
+" Shell> mode\r\n"
+" \r\n"
+" * To change the current mode setting:\r\n"
+" Shell> mode 80 50\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+
+#string STR_GET_HELP_MEMMAP #language en-US ""
+".TH memmap 0 "Displays the memory map."\r\n"
+".SH NAME\r\n"
+"Displays the memory map maintained by the UEFI environment.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"MEMMAP [-b] [-sfo]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -b - Displays one screen at a time\r\n"
+" -sfo - Displays information as described in Standard-Format Output.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. The UEFI environment keeps track of all the physical memory in the system\r\n"
+" and how it is currently being used.\r\n"
+" 2. Total Memory is the physical memory size excluding Reserved, Unusable,\r\n"
+" MemoryMappedIO, and MemoryMappedIOPortSpace memory types.\r\n"
+" 3. Refer to the UEFI specification for memory type definitions.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display the system memory map:\r\n"
+" Shell> memmap\r\n"
+" \r\n"
+
+#string STR_GET_HELP_EFICOMPRESS #language en-US ""
+".TH eficompress 0 "compresses a file."\r\n"
+".SH NAME\r\n"
+"Compresses a file using UEFI Compression Algorithm.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"EFICOMPRESS infile outfile\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" infile - Specifies the file name of the uncompressed input file.\r\n"
+" outfile - Specifies the file name of the compressed output file.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command compresses a file using UEFI Compression Algorithm\r\n"
+" and writes the compressed form out to a new file.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To compress a file named 'uncompressed' to a file named 'compressed':\r\n"
+" fs0:\> eficompress uncompressed compressed\r\n"
+
+#string STR_GET_HELP_EFIDCOMPRESS #language en-US ""
+".TH efidecompress 0 "Decompresses a file."\r\n"
+".SH NAME\r\n"
+"Decompresses a file using UEFI Decompression Algorithm.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"EFIDECOMPRESS infile outfile\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" infile - Specifies the file name of the compressed input file.\r\n"
+" outfile - Specifies the file name of the decompressed output file.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This decompresses a file using UEFI Decompression\r\n"
+" Algorithm and writes the decompressed form out to a new file.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To decompress a file named 'compressed' to a file named 'uncompressed':\r\n"
+" fs0:\> efidecompress compressed uncompressed\r\n"
+
+#string STR_GET_HELP_DMEM #language en-US ""
+".TH dmem 0 "Displays memory."\r\n"
+".SH NAME\r\n"
+"Displays the contents of system or device memory.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"DMEM [-b] [address] [size] [-MMIO]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -b - Displays one screen at a time.\r\n"
+" -MMIO - Forces address cycles to the PCI bus.\r\n"
+" address - Specifies a starting address in hexadecimal format.\r\n"
+" size - Specifies the number of bytes to display in hexadecimal format.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command displays the contents of system memory or device memory.\r\n"
+" 2. Enter address and size in hexadecimal format.\r\n"
+" 3. If address is not specified, the contents of the UEFI System Table\r\n"
+" are displayed. Otherwise, memory starting at the specified address is displayed.\r\n"
+" 4. Size specifies the number of bytes to display. If size is not specified,\r\n"
+" 512 bytes are displayed.\r\n"
+" 5. If MMIO is not specified, main system memory is displayed. Otherwise,\r\n"
+" device memory is displayed through the use of the\r\n"
+" EFI_PCI_ROOT_BRIDGE_IO_PROTOCOL.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display the UEFI system table pointer entries:\r\n"
+" fs0:\> dmem\r\n"
+" \r\n"
+" * To display memory contents from 1af3088 with size of 16 bytes:\r\n"
+" Shell> dmem 1af3088 16\r\n"
+" \r\n"
+" * To display memory mapped IO contents from 1af3088 with a size of 16 bytes:\r\n"
+" Shell> dmem 1af3088 16 -MMIO\r\n"
+
+#string STR_GET_HELP_MM #language en-US ""
+".TH mm 0 "Displays or modifies address space memory."\r\n"
+".SH NAME\r\n"
+"Displays or modifies MEM/MMIO/IO/PCI/PCIE address space.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"MM Address [Value] [-w 1|2|4|8] [-MEM | -MMIO | -IO | -PCI | -PCIE] [-n]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" Address - Specifies a starting address.\r\n"
+" Value - Specifies the value to write.\r\n"
+" -MEM - Memory Address type\r\n"
+" -MMIO - Memory Mapped IO Address type\r\n"
+" -IO - IO Address type\r\n"
+" -PCI - PCI Configuration Space Address type:\r\n"
+" Address format: 0x000000ssbbddffrr\r\n"
+" ss - Segment\r\n"
+" bb - Bus\r\n"
+" dd - Device\r\n"
+" ff - Function\r\n"
+" rr - Register\r\n"
+" -PCIE - PCIE Configuration Space Address type:\r\n"
+" Address format: 0x00000ssbbddffrrr\r\n"
+" ss - Segment\r\n"
+" bb - Bus\r\n"
+" dd - Device\r\n"
+" ff - Function\r\n"
+" rrr - Register\r\n"
+" -w - Unit size accessed in bytes:\r\n"
+" 1 - 1 byte\r\n"
+" 2 - 2 bytes\r\n"
+" 4 - 4 bytes\r\n"
+" 8 - 8 bytes\r\n"
+" -n - Non-interactive mode\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. If the address type parameter is not specified, address type defaults\r\n"
+" to the 'MEM' type.\r\n"
+" 2. If the 'Value' parameter is specified, the '-n' option is used and\r\n"
+" the command writes the value to the\r\n"
+" specified address in non-interactive mode. If the 'Value' parameter is\r\n"
+" not specified, only the current contents in the address are displayed.\r\n"
+" 3. If the '-w' option is not specified, unit size defaults to 1 byte.\r\n"
+" 4. If the PCI address type is specified, the 'Address' parameter must\r\n"
+" follow the PCI Configuration Space Address format above. The 'PCI'\r\n"
+" command can be used to determine the address for a specified device.\r\n"
+" It is listed in the PCI configuration space dump information in the\r\n"
+" following format: "[EFI 0x000000ssbbddffxx]".\r\n"
+" 5. If the PCIE address type is specified, the 'Address' parameter must\r\n"
+" follow the PCIE Configuration Space Address format above.\r\n"
+" 6. In interactive mode, type a hex value to modify, 'q' or '.' to exit.\r\n"
+" If the '-n' option is specified, it runs in non-interactive mode,\r\n"
+" which supports batch file operation without user intervention.\r\n"
+" 7. Not all PCI configuration register locations are writable.\r\n"
+" 8. MM will only write the specified value. Read-modify-write operations\r\n"
+" are not supported.\r\n"
+" 9. The 'Address' parameter must be aligned on a boundary of the\r\n"
+" specified width.\r\n"
+" 10. Not all addresses are safe to access. Access to any improper address\r\n"
+" can bring unexpected results.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display or modify memory:\r\n"
+" Address 0x1b07288, default width=1 byte:\r\n"
+" fs0:\> mm 1b07288\r\n"
+" MEM 0x0000000001B07288 : 0x6D >\r\n"
+" MEM 0x0000000001B07289 : 0x6D >\r\n"
+" MEM 0x0000000001B0728A : 0x61 > 80\r\n"
+" MEM 0x0000000001B0728B : 0x70 > q\r\n"
+" fs0:\> mm 1b07288\r\n"
+" MEM 0x0000000001B07288 : 0x6D >\r\n"
+" MEM 0x0000000001B07289 : 0x6D >\r\n"
+" MEM 0x0000000001B0728A : 0x80 > *Modified\r\n"
+" MEM 0x0000000001B0728B : 0x70 > q\r\n"
+" \r\n"
+" * To modify memory: Address 0x1b07288, width = 2 bytes:\r\n"
+" Shell> mm 1b07288 -w 2\r\n"
+" MEM 0x0000000001B07288 : 0x6D6D >\r\n"
+" MEM 0x0000000001B0728A : 0x7061 > 55aa\r\n"
+" MEM 0x0000000001B0728C : 0x358C > q\r\n"
+" Shell> mm 1b07288 -w 2\r\n"
+" MEM 0x0000000001B07288 : 0x6D6D >\r\n"
+" MEM 0x0000000001B0728A : 0x55AA > *Modified\r\n"
+" MEM 0x0000000001B0728C : 0x358C > q\r\n"
+" \r\n"
+" * To display IO space: Address 80h, width = 4 bytes:\r\n"
+" Shell> mm 80 -w 4 -IO\r\n"
+" IO 0x0000000000000080 : 0x000000FE >\r\n"
+" IO 0x0000000000000084 : 0x00FF5E6D > q\r\n"
+" \r\n"
+" * To modify IO space using non-interactive mode:\r\n"
+" Shell> mm 80 52 -w 1 -IO\r\n"
+" Shell> mm 80 -w 1 -IO\r\n"
+" IO 0x0000000000000080 : 0x52 > FE *Modified\r\n"
+" IO 0x0000000000000081 : 0xFF >\r\n"
+" IO 0x0000000000000082 : 0x00 >\r\n"
+" IO 0x0000000000000083 : 0x00 >\r\n"
+" IO 0x0000000000000084 : 0x6D >\r\n"
+" IO 0x0000000000000085 : 0x5E >\r\n"
+" IO 0x0000000000000086 : 0xFF >\r\n"
+" IO 0x0000000000000087 : 0x00 > q\r\n"
+" \r\n"
+" * To display PCI configuration space, ss=00, bb=00, dd=00, ff=00, rr=00:\r\n"
+" Shell> mm 0000000000 -PCI\r\n"
+" PCI 0x0000000000000000 : 0x86 >\r\n"
+" PCI 0x0000000000000001 : 0x80 >\r\n"
+" PCI 0x0000000000000002 : 0x30 >\r\n"
+" PCI 0x0000000000000003 : 0x11 >\r\n"
+" PCI 0x0000000000000004 : 0x06 >\r\n"
+" PCI 0x0000000000000005 : 0x00 > q\r\n"
+" These contents can also be displayed by 'PCI 00 00 00'.\r\n"
+" \r\n"
+" * To display PCIE configuration space, ss=00, bb=06, dd=00, ff=00, rrr=000:\r\n"
+" Shell> mm 00060000000 -PCIE\r\n"
+" PCIE 0x0000000060000000 : 0xAB >\r\n"
+" PCIE 0x0000000060000001 : 0x11 >\r\n"
+" PCIE 0x0000000060000002 : 0x61 >\r\n"
+" PCIE 0x0000000060000003 : 0x43 >\r\n"
+" \r\n"
+
+#string STR_GET_HELP_LOAD_PCI_ROM #language en-US ""
+".TH loadpcirom 0 "Loads a PCI option ROM file."\r\n"
+".SH NAME\r\n"
+"Loads a PCI Option ROM.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"LoadPciRom [-nc] romfile [romfile...]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -nc - Loads the ROM image(s) but does not connect drivers.\r\n"
+" romfile - Specifies the PCI option ROM image file (wildcards are permitted).\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command loads PCI option ROM images into memory for\r\n"
+" execution.\r\n"
+" 2. The file can contain legacy images and multiple PE32 images, in which case\r\n"
+" all PE32 images are loaded.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To load a rom file 'rom.bin':\r\n"
+" fs0:\> LoadPciRom rom.bin\r\n"
+" \r\n"
+" * To load '*.bin' files without connecting drivers:\r\n"
+" fs0:\> LoadPciRom -nc *.bin\r\n"
+
+#string STR_GET_HELP_SETVAR #language en-US ""
+".TH setvar 0 "Displays or modifies a UEFI variable."\r\n"
+".SH NAME\r\n"
+"Displays or modifies a UEFI variable.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"SETVAR variable-name [-guid guid][-bs][-rt][-nv] [=data]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" variable-name - Specifies the name of the UEFI variable to modify or display.\r\n"
+" -guid - Specifies the GUID of the UEFI variable to modify or display.\r\n"
+" If not present, GUID EFI_GLOBAL_VARIABLE is assumed.\r\n"
+" -bs - Indicates that the variable is a boot variable. Applies to a new variable;\r\n"
+" otherwise, it is ignored. \r\n"
+" -rt - Indicates that the variable is a runtime variable. Applies to a new variable;\r\n"
+" otherwise, it is ignored. \r\n"
+" -nv - Indicates that the variable is non-volatile. If not present,\r\n"
+" then the variable is assumed to be volatile. Applies to a new variable;\r\n"
+" otherwise, it is ignored. \r\n"
+" =data - Specifies there is new data for the variable. If there is nothing after the '='\r\n"
+" then the variable is deleted. If '=' is not present, then the\r\n"
+" current value of the variable is dumped as hex bytes.\r\n"
+" The data can consist of zero or more of the following:\r\n"
+" xx[xx] - Hexadecimal bytes\r\n"
+" ^"ascii-string^" - ASCII-string with no null-terminator\r\n"
+" L^"UCS2-string^" - UCS-2 encoded string with no\r\n"
+" null-terminator\r\n"
+" --device - Device path text format\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command changes the UEFI variable specified by name and GUID.\r\n"
+" 2. If = is specified, but data is not, the variable is deleted, if it exists.\r\n"
+" 3. If = is not specified, then the current variable contents are displayed.\r\n"
+" 4. If =data is specified, then the variable's value is changed to the value\r\n"
+" specified by data.\r\n"
+" 5. -bs, -rt and -nv are only useful if the variable already exists.\r\n"
+" 6. If the variable already exists and the attributes cannot be changed,\r\n"
+" then -1 is returned. \r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The shell has stored the variable and its data with\r\n"
+" the defined attributes.\r\n"
+" SHELL_INVALID_PARAMETER Incorrect attributes were used.\r\n"
+" SHELL_OUT_OF_RESOURCES Insufficient resources were available for storing\r\n"
+" the variable and its data.\r\n"
+" SHELL_DEVICE_ERROR The Variable could not be saved due to a hardware\r\n"
+" error.\r\n"
+" SHELL_WRITE_PROTECTED The variable in question is read-only.\r\n"
+" SHELL_WRITE_PROTECTED The variable in question cannot be deleted.\r\n"
+" SHELL_NOT_FOUND The variable could not be found.\r\n"
+
+#string STR_GET_HELP_SERMODE #language en-US ""
+".TH sermode 0 "configure serial port"\r\n"
+".SH NAME\r\n"
+"Sets serial port attributes.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"SERMODE [handle [baudrate parity databits stopbits]]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" handle - Specifies a device handle for a serial port in hexadecimal format.\r\n"
+" baudrate - Specifies a baud rate for specified serial port.\r\n"
+" parity - Sets parity bit settings for specified serial port. Valid values\r\n"
+" are:\r\n"
+" d - Default parity\r\n"
+" n - No parity\r\n"
+" e - Even parity\r\n"
+" o - Odd parity\r\n"
+" m - Mark parity\r\n"
+" s - Space parity\r\n"
+" databits - Sets the data bits for the specified serial port.\r\n"
+" stopbits - Sets the stop bits for the specified serial port.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. The 'handle' parameter is the device handle of the desired serial port.\r\n"
+" The 'DH' command can be used to retrieve this information.\r\n"
+" 2. The 'stopbits' parameter supports the following settings:\r\n"
+" 0 (0 stop bits - default setting)\r\n"
+" 1 (1 stop bit)\r\n"
+" 2 (2 stop bits)\r\n"
+" 15 (1.5 stop bits)\r\n"
+" All other settings are invalid.\r\n"
+" 3. The 'baudrate' parameter supports the following settings:\r\n"
+" 50, 75, 110, 150, 300, 600, 1200, 1800, 2000, 2400, 3600, 4800,\r\n"
+" 7200, 9600(default), 19200, 38400, 57600, 115200, 230400, 460800\r\n"
+" All other values will be converted to the next highest setting.\r\n"
+" 4. The 'databits' parameter supports the following settings:\r\n"
+" 4\r\n"
+" 7\r\n"
+" 8 (default)\r\n"
+" All other settings are invalid.\r\n"
+" 5. Parity attributes are mutually exclusive.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display the settings for all serial port devices:\r\n"
+" Shell> sermode\r\n"
+" \r\n"
+" * To display the settings for the serial port device whose handle is 0x6B:\r\n"
+" Shell> sermode 6B\r\n"
+" \r\n"
+" * To configure the serial port settings for handle 0x6B to 9600bps, even\r\n"
+" parity, 8 data bits, and 1 stop bit:\r\n"
+" Shell> sermode 6B 9600 e 8 1\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The new attributes were set on the serial device.\r\n"
+" SHELL_INVALID_PARAMETER One or more of the attributes has an unsupported\r\n"
+" value.\r\n"
+" SHELL_DEVICE_ERROR The serial device is not functioning correctly.\r\n"
+
+#string STR_GET_HELP_PCI #language en-US ""
+".TH pci 0 "Displays PCI device information."\r\n"
+".SH NAME\r\n"
+"Displays a PCI device list or PCI function configuration space of a device.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"PCI [Bus Dev [Func] [-s Seg] [-i]]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -s - Specifies optional segment number.\r\n"
+" -i - Displays interpreted information.\r\n"
+" Bus - Specifies a bus number.\r\n"
+" Dev - Specifies a device number.\r\n"
+" Func - Specifies a function number.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command displays a list of all the PCI devices found in the system. It\r\n"
+" also displays the configuration space of a PCI device according to the\r\n"
+" specified bus (Bus), device (Dev), and function (Func) addresses. If the\r\n"
+" function address is not specified, it defaults to 0.\r\n"
+" 2. The -i option displays verbose information for the specified PCI\r\n"
+" device. The PCI configuration space for the device is displayed with\r\n"
+" a detailed interpretation.\r\n"
+" 3. If no parameters are specified, all PCI devices are listed.\r\n"
+" 4. If the 'Bus' and 'Dev' parameters are specified but the 'Func' or\r\n"
+" 'Seg' parameters are not, Function or Seg are set to the default value of 0.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display all PCI devices in the system:\r\n"
+" Shell> pci\r\n"
+" \r\n"
+" * To display the configuration space of Bus 0, Device 0, Function 0:\r\n"
+" Shell> pci 00 00 00 -i\r\n"
+" \r\n"
+" * To display configuration space of Segment 0, Bus 0, Device 0, Function 0:\r\n"
+" Shell> pci 00 00 00 -s 0\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS Data was displayed as requested.\r\n"
+" SHELL_DEVICE_ERROR The specified device parameters did not match a physical\r\n"
+" device in the system.\r\n"
+
+#string STR_GET_HELP_SMBIOSVIEW #language en-US ""
+".TH smbiosview 0 "Displays SMBIOS information."\r\n"
+".SH NAME\r\n"
+"Displays SMBIOS information.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"SMBIOSVIEW [-t SmbiosType]|[-h SmbiosHandle]|[-s]|[-a]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -t - Displays all structures of SmbiosType.\r\n"
+" -h - Displays structure of SmbiosHandle.\r\n"
+" -s - Displays a statistics table.\r\n"
+" -a - Displays all information.\r\n"
+" SmbiosType - Specifies a SMBIOS structure type.\r\n"
+" SmbiosHandle - Specifies a SMBIOS structure unique 16-bit handle.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. The SmbiosType parameter supports the following types:\n"
+" 0 - BIOS Information\r\n"
+" 1 - System Information\r\n"
+" 2 - Baseboard Information\r\n"
+" 3 - System Enclosure\r\n"
+" 4 - Processor Information\r\n"
+" 5 - Memory Controller Information\r\n"
+" 6 - Memory Module Information\r\n"
+" 7 - Cache Information\r\n"
+" 8 - Port Connector Information\r\n"
+" 9 - System Slots\r\n"
+" 10 - On Board Devices Information\r\n"
+" 11 - OEM Strings\r\n"
+" 12 - System Configuration Options\r\n"
+" 13 - BIOS Language Information\r\n"
+" 14 - Group Associations\r\n"
+" 15 - System Event Log\r\n"
+" 16 - Physical Memory Array\r\n"
+" 17 - Memory Device\r\n"
+" 18 - 32-bit Memory Error Information\r\n"
+" 19 - Memory Array Mapped Address\r\n"
+" 20 - Memory Device Mapped Address\r\n"
+" 21 - Built-in Pointing Device\r\n"
+" 22 - Portable Battery\r\n"
+" 23 - System Reset\r\n"
+" 24 - Hardware Security\r\n"
+" 25 - System Power Controls\r\n"
+" 26 - Voltage Probe\r\n"
+" 27 - Cooling Device\r\n"
+" 28 - Temperature Probe\r\n"
+" 29 - Electrical Current Probe\r\n"
+" 30 - Out-Of-Band Remote Access\r\n"
+" 31 - Boot Integrity Services (BIS) Entry Point\r\n"
+" 32 - System Boot Information\r\n"
+" 33 - 64-Bit Memory Error Information\r\n"
+" 34 - Management Device\r\n"
+" 35 - Management Device Component\r\n"
+" 36 - Management Device Threshold Data\r\n"
+" 37 - Memory Channel\r\n"
+" 38 - IPMI Device Information\r\n"
+" 39 - System Power Supply\r\n"
+" 40 - Additional Information\r\n"
+" 41 - Onboard Devices Extended Information\r\n"
+" 42 - Management Controller Host Interface\r\n"
+" 2. Enter the SmbiosHandle parameter in hexadecimal format.\r\n"
+" Do not use the '0x' prefix format for hexadecimal values.\r\n"
+" 3. Internal commands:\r\n"
+" :q -------- quit smbiosview\r\n"
+" :0 -------- Change smbiosview display NONE info\r\n"
+" :1 -------- Change smbiosview display OUTLINE info\r\n"
+" :2 -------- Change smbiosview display NORMAL info\r\n"
+" :3 -------- Change smbiosview display DETAIL info\r\n"
+" /? -------- Show help\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS Data was displayed as requested.\r\n"
+" SHELL_DEVICE_ERROR The requested structure was not found.\r\n"
+
+#string STR_GET_HELP_DMPSTORE #language en-US ""
+".TH dmpstore 0 "Manages all UEFI variables."\r\n"
+".SH NAME\r\n"
+"Manages all UEFI variables.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"DMPSTORE [-b] [-d] [-all | ([variable] [-guid guid])]\r\n"
+"DMPSTORE [-all | ([variable] [-guid guid])] [-s file]\r\n"
+"DMPSTORE [-all | ([variable] [-guid guid])] [-l file]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -b - Displays one screen at a time.\r\n"
+" -guid - Specifies the GUID of the variables to be displayed in\r\n"
+" standard text format. If not specified and -all is not\r\n"
+" specified, the EFI_GLOBAL_VARIABLE GUID is assumed.\r\n"
+" -all - Dumps all variables, including those\r\n"
+" with a different GUID than EFI_GLOBAL_VARIABLE.\r\n"
+" -d - Delete variables.\r\n"
+" -s - Saves variables to a file.\r\n"
+" -l - Loads and sets variables from a file.\r\n"
+" variable - Specifies a variable name. This can be a literal name or\r\n"
+" a pattern as specified in the MetaiMatch() function of the\r\n"
+" EFI_UNICODE_COLLATION2_PROCOOL.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command manages the UEFI variables. The variables\r\n"
+" displayed or deleted depend on the command line options, as specified in\r\n"
+" the following table:\r\n"
+" Variable GUID -all Description\r\n"
+" --- --- --- All variables with the GUID EFI_GLOBAL_VARIABLE will\r\n"
+" be operated on.\r\n"
+" --- --- X All variables (regardless of GUID or name) will be\r\n"
+" operated on.\r\n"
+" --- X --- All variables with the specified GUID will be\r\n"
+" operated on.\r\n"
+" X --- --- The variable with the GUID EFI_GLOBAL_VARIABLE and\r\n"
+" the name Variable will be operated on.\r\n"
+" X X --- The variable with the specified GUID and name\r\n"
+" Variable will be operated on.\r\n"
+" 2. The variable value is printed as a hexadecimal dump.\r\n"
+" 3. Option -d is used to delete variables. Option -s and -l are used to save\r\n"
+" and load variables to and from a file. The variable name can be specified\r\n"
+" when using these flags so that the operation only takes effect on\r\n"
+" that variable.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To dump all variables with the GUID EFI_GLOBAL_VARIABLE:\r\n"
+" Shell> dmpstore\r\n"
+" \r\n"
+" * To dump all variables (regardless of GUID or name):\r\n"
+" Shell> dmpstore -all\r\n"
+" \r\n"
+" * To dump the 'path' variable with the GUID '158DEF5A-F656-419C-B027-\r\n"
+" 7A3192C079D2':\r\n"
+" Shell> dmpstore path -guid 158DEF5A-F656-419C-B027-7A3192C079D2\r\n"
+" \r\n"
+" * To save all variables (regardless of GUID or name) to a file 'VarDump.txt':\r\n"
+" fs0:\> dmpstore -all -s VarDump.txt\r\n"
+" \r\n"
+" * To delete the 'BootOrder' variable with the GUID EFI_GLOBAL_VARIABLE:\r\n"
+" Shell> dmpstore -d BootOrder\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+
+#string STR_GET_HELP_DBLK #language en-US ""
+".TH dblk 0 "Displays one or more blocks from a block device."\r\n"
+".SH NAME\r\n"
+"Displays one or more blocks from a block device.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"DBLK device [lba] [blocks] [-b]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -b - Displays one screen at a time.\r\n"
+" device - Blocks the device name.\r\n"
+" lba - Specifies the index of the first block to be displayed (a hexadecimal number).\r\n"
+" The default is 0.\r\n"
+" blocks - Specifies the number of blocks to display (a hexadecimal number). The default\r\n"
+" is 1. If larger than 0x10, then only 0x10 are displayed.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command displays the contents of one or more blocks from a block\r\n"
+" device. Enter a hexidecimal value for the lba and blocks variables. If lba is not\r\n"
+" specified, block #0 is assumed. If blocks is not specified, on1y one\r\n"
+" block is displayed. The maximum number of blocks that can be\r\n"
+" displayed at one time is 0x10.\r\n"
+" 2. If an MBR is found on the block, the partition information is displayed\r\n"
+" after all the block contents are displayed.\r\n"
+" 3. If the block is a FAT partition, some FAT parameters are displayed\r\n"
+" (label, systemid, oemid, sectorsize, clustersize, media, and so forth) after all the\r\n"
+" blocks are displayed.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display one block of blk0, beginning from block 0:\r\n"
+" Shell> dblk blk0\r\n"
+" \r\n"
+" * To display one block of fs0, beginning from block 0x2:\r\n"
+" Shell> dblk fs0 2\r\n"
+" \r\n"
+" * To display 0x5 blocks of fs0, beginning from block 0x12:\r\n"
+" Shell> dblk fs0 12 5\r\n"
+" \r\n"
+" * To display 0x10 blocks of fs0, beginning from block 0x12:\r\n"
+" Shell> dblk fs0 12 10\r\n"
+" \r\n"
+" * To attempt to display more than 0x10 blocks, resulting in only 0x10\r\n"
+" blocks being displayed:\r\n"
+" Shell> dblk fs0 12 20\r\n"
+" \r\n"
+" * To display one block of blk2, beginning from the first block (blk0):\r\n"
+" fs1:\tmps1> dblk blk2 0 1\r\n"
+" \r\n"
+
+#string STR_GET_HELP_EDIT #language en-US ""
+".TH edit 0 "Provides a full screen text editor for ASCII or UCS-2 files."\r\n"
+".SH NAME\r\n"
+"Provides a full screen text editor for ASCII or UCS-2 files.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"EDIT [file]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" file - Specifies the name of file to be edited. If none is specified, an empty file\r\n"
+" is created with a default file name.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command enables full screen file editing.\r\n"
+" 2. The editor supports both UCS-2 and ASCII file types.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To edit the 'shell.log' file:\r\n"
+" fs0:\> edit shell.log\r\n"
+
+#string STR_GET_HELP_HEXEDIT #language en-US ""
+".TH hexedit 0 "Provides a full screen hex editor for files, block devices, or memory."\r\n"
+".SH NAME\r\n"
+"Provides a full screen hex editor for files, block devices, or memory.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"HEXEDIT [[-f] filename| [-d diskname offset size] | [-m address size]]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -f - Specifies the name of the file to edit.\r\n"
+" -d - Specifies the disk block to edit:\r\n"
+" DiskName - Name of the disk to edit (for example fs0)\r\n"
+" Offset - Starting block number (beginning from 0)\r\n"
+" Size - Number of blocks to edit\r\n"
+" -m - Specifies the memory region to edit:\r\n"
+" Address - Starting 32-bit memory address (beginning from 0)\r\n"
+" Size - Size of memory region to edit in bytes\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command enables you to edit a file, block device, or memory region.\r\n"
+" 2. The region being edited is displayed as hexadecimal bytes. The\r\n"
+" contents can be modified and saved.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To edit a file in hex mode:\r\n"
+" fs0:\> hexedit test.bin\r\n"
+" \r\n"
+" * To edit block device fs0 starting at block 0 with size of 2 blocks:\r\n"
+" fs0:\> hexedit -d fs0 0 2\r\n"
+" \r\n"
+" * To edit memory region starting at address 0x00000000 with size of 2 bytes:\r\n"
+" fs0:\> hexedit -m 0 2\r\n"
+
diff --git a/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Connect.c b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Connect.c
new file mode 100644
index 0000000000..dd3d4a6a27
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Connect.c
@@ -0,0 +1,552 @@
+/** @file
+ Main file for connect shell Driver1 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDriver1CommandsLib.h"
+
+/**
+ Create all handles associate with every device path node.
+
+ @param DevicePathToConnect The device path which will be connected.
+
+ @retval EFI_SUCCESS All handles associate with every device path node
+ have been created.
+ @retval EFI_INVALID_PARAMETER DevicePathToConnect is NULL.
+ @retval EFI_NOT_FOUND Create the handle associate with one device path
+ node failed
+
+**/
+EFI_STATUS
+ShellConnectDevicePath (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePathToConnect
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;
+ EFI_STATUS Status;
+ EFI_HANDLE Handle;
+ EFI_HANDLE PreviousHandle;
+
+ if (DevicePathToConnect == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ PreviousHandle = NULL;
+ do{
+ RemainingDevicePath = DevicePathToConnect;
+ Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &Handle);
+
+ if (!EFI_ERROR (Status) && (Handle != NULL)) {
+ if (PreviousHandle == Handle) {
+ Status = EFI_NOT_FOUND;
+ } else {
+ PreviousHandle = Handle;
+ Status = gBS->ConnectController (Handle, NULL, RemainingDevicePath, FALSE);
+ }
+ }
+
+ } while (!EFI_ERROR (Status) && !IsDevicePathEnd (RemainingDevicePath) );
+
+ return Status;
+
+}
+
+/**
+ Connect drivers for PCI root bridge.
+
+ @retval EFI_SUCCESS Connect drivers successfully.
+ @retval EFI_NOT_FOUND Cannot find PCI root bridge device.
+
+**/
+EFI_STATUS
+ShellConnectPciRootBridge (
+ VOID
+ )
+{
+ UINTN RootBridgeHandleCount;
+ EFI_HANDLE *RootBridgeHandleBuffer;
+ UINTN RootBridgeIndex;
+ EFI_STATUS Status;
+
+ RootBridgeHandleCount = 0;
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciRootBridgeIoProtocolGuid,
+ NULL,
+ &RootBridgeHandleCount,
+ &RootBridgeHandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ for (RootBridgeIndex = 0; RootBridgeIndex < RootBridgeHandleCount; RootBridgeIndex++) {
+ gBS->ConnectController (RootBridgeHandleBuffer[RootBridgeIndex], NULL, NULL, FALSE);
+ }
+
+ FreePool (RootBridgeHandleBuffer);
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Connect controller(s) and driver(s).
+
+ @param[in] ControllerHandle The handle to the controller. Should have driver binding on it.
+ @param[in] DriverHandle The handle to the driver. Should have driver binding.
+ @param[in] Recursive TRUE to connect recursively, FALSE otherwise.
+ @param[in] Output TRUE to have info on the screen, FALSE otherwise.
+ @param[in] AlwaysOutput Override Output for errors.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+ConnectControllers (
+ IN CONST EFI_HANDLE ControllerHandle OPTIONAL,
+ IN CONST EFI_HANDLE DriverHandle OPTIONAL,
+ IN CONST BOOLEAN Recursive,
+ IN CONST BOOLEAN Output,
+ IN CONST BOOLEAN AlwaysOutput
+ )
+{
+ EFI_STATUS Status;
+ EFI_STATUS Status2;
+ EFI_HANDLE *ControllerHandleList;
+ EFI_HANDLE *DriverHandleList;
+ EFI_HANDLE *HandleWalker;
+
+ ControllerHandleList = NULL;
+ Status = EFI_NOT_FOUND;
+ Status2 = EFI_NOT_FOUND;
+
+ //
+ // If we have a single handle to connect make that a 'list'
+ //
+ if (DriverHandle == NULL) {
+ DriverHandleList = NULL;
+ } else {
+ DriverHandleList = AllocateZeroPool(2*sizeof(EFI_HANDLE));
+ if (DriverHandleList == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ DriverHandleList[0] = DriverHandle;
+ DriverHandleList[1] = NULL;
+ }
+
+ //
+ // do we connect all controllers (with a loop) or a single one...
+ // This is where we call the gBS->ConnectController function.
+ //
+ if (ControllerHandle == NULL) {
+ ControllerHandleList = GetHandleListByProtocol(&gEfiDevicePathProtocolGuid);
+ for (HandleWalker = ControllerHandleList
+ ; HandleWalker != NULL && *HandleWalker != NULL
+ ; HandleWalker++
+ ){
+ Status = gBS->ConnectController(*HandleWalker, DriverHandleList, NULL, Recursive);
+ if (!EFI_ERROR(Status)) {
+ Status2 = EFI_SUCCESS;
+ }
+ if ((Output && !EFI_ERROR(Status)) || AlwaysOutput) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_HANDLE_RESULT), gShellDriver1HiiHandle, L"Connect", ConvertHandleToHandleIndex(*HandleWalker), Status);
+ }
+ }
+ } else {
+ Status = gBS->ConnectController(ControllerHandle, DriverHandleList, NULL, Recursive);
+ if (!EFI_ERROR(Status)) {
+ Status2 = EFI_SUCCESS;
+ }
+ if ((Output && !EFI_ERROR(Status)) || AlwaysOutput) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_HANDLE_RESULT), gShellDriver1HiiHandle, L"Connect", ConvertHandleToHandleIndex(ControllerHandle), Status);
+ }
+ }
+
+ //
+ // Free any memory we allocated.
+ //
+ if (ControllerHandleList != NULL) {
+ FreePool(ControllerHandleList);
+ }
+ if (DriverHandleList != NULL) {
+ FreePool(DriverHandleList);
+ }
+ return (Status2);
+}
+
+/**
+ Do a connect from an EFI variable via it's key name.
+
+ @param[in] Key The name of the EFI Variable.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+ShellConnectFromDevPaths (
+ IN CONST CHAR16 *Key
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+ EFI_DEVICE_PATH_PROTOCOL *CopyOfDevPath;
+ EFI_DEVICE_PATH_PROTOCOL *Instance;
+ EFI_DEVICE_PATH_PROTOCOL *Next;
+ UINTN Length;
+ UINTN Index;
+ UINTN HandleArrayCount;
+ UINTN Size;
+ EFI_HANDLE *HandleArray;
+ EFI_STATUS Status;
+ BOOLEAN AtLeastOneConnected;
+ EFI_PCI_IO_PROTOCOL *PciIo;
+ UINT8 Class[3];
+
+ DevPath = NULL;
+ Length = 0;
+ AtLeastOneConnected = FALSE;
+
+ //
+ // Get the DevicePath buffer from the variable...
+ //
+ Status = gRT->GetVariable((CHAR16*)Key, (EFI_GUID*)&gEfiGlobalVariableGuid, NULL, &Length, DevPath);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ DevPath = AllocateZeroPool(Length);
+ if (DevPath == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Status = gRT->GetVariable((CHAR16*)Key, (EFI_GUID*)&gEfiGlobalVariableGuid, NULL, &Length, DevPath);
+ if (EFI_ERROR (Status)) {
+ if (DevPath != NULL) {
+ FreePool (DevPath);
+ }
+ return Status;
+ }
+ } else if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = EFI_NOT_FOUND;
+
+ CopyOfDevPath = DevPath;
+ //
+ // walk the list of devices and connect them
+ //
+ do {
+ //
+ // Check every instance of the console variable
+ //
+ Instance = GetNextDevicePathInstance (&CopyOfDevPath, &Size);
+ if (Instance == NULL) {
+ if (DevPath != NULL) {
+ FreePool (DevPath);
+ }
+ return EFI_UNSUPPORTED;
+ }
+
+ Next = Instance;
+ while (!IsDevicePathEndType (Next)) {
+ Next = NextDevicePathNode (Next);
+ }
+
+ SetDevicePathEndNode (Next);
+ //
+ // connect short form device path
+ //
+ if ((DevicePathType (Instance) == MESSAGING_DEVICE_PATH) &&
+ ((DevicePathSubType (Instance) == MSG_USB_CLASS_DP)
+ || (DevicePathSubType (Instance) == MSG_USB_WWID_DP)
+ )) {
+
+ Status = ShellConnectPciRootBridge ();
+ if (EFI_ERROR(Status)) {
+ FreePool(Instance);
+ FreePool(DevPath);
+ return Status;
+ }
+
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiPciIoProtocolGuid,
+ NULL,
+ &HandleArrayCount,
+ &HandleArray
+ );
+
+ if (!EFI_ERROR (Status)) {
+ for (Index = 0; Index < HandleArrayCount; Index++) {
+ Status = gBS->HandleProtocol (
+ HandleArray[Index],
+ &gEfiPciIoProtocolGuid,
+ (VOID **)&PciIo
+ );
+
+ if (!EFI_ERROR (Status)) {
+ Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint8, 0x09, 3, &Class);
+ if (!EFI_ERROR (Status)) {
+ if ((PCI_CLASS_SERIAL == Class[2]) &&
+ (PCI_CLASS_SERIAL_USB == Class[1])) {
+ Status = gBS->ConnectController (
+ HandleArray[Index],
+ NULL,
+ Instance,
+ FALSE
+ );
+ if (!EFI_ERROR(Status)) {
+ AtLeastOneConnected = TRUE;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (HandleArray != NULL) {
+ FreePool (HandleArray);
+ }
+ } else {
+ //
+ // connect the entire device path
+ //
+ Status = ShellConnectDevicePath (Instance);
+ if (!EFI_ERROR (Status)) {
+ AtLeastOneConnected = TRUE;
+ }
+ }
+ FreePool (Instance);
+
+ } while (CopyOfDevPath != NULL);
+
+ if (DevPath != NULL) {
+ FreePool(DevPath);
+ }
+
+ if (AtLeastOneConnected) {
+ return EFI_SUCCESS;
+ } else {
+ return EFI_NOT_FOUND;
+ }
+
+}
+
+/**
+ Convert the handle identifiers from strings and then connect them.
+
+ One of them should have driver binding and either can be NULL.
+
+ @param[in] Handle1 The first handle.
+ @param[in] Handle2 The second handle.
+ @param[in] Recursive TRUE to do connect recursively. FALSE otherwise.
+ @param[in] Output TRUE to have output to screen. FALSE otherwise.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+ConvertAndConnectControllers (
+ IN EFI_HANDLE *Handle1 OPTIONAL,
+ IN EFI_HANDLE *Handle2 OPTIONAL,
+ IN CONST BOOLEAN Recursive,
+ IN CONST BOOLEAN Output
+ )
+{
+ //
+ // if only one is NULL verify it's the proper one...
+ //
+ if ( (Handle1 == NULL && Handle2 != NULL)
+ || (Handle1 != NULL && Handle2 == NULL)
+ ){
+ //
+ // Figure out which one should be NULL and move the handle to the right place.
+ // If Handle1 is NULL then test Handle2 and vise versa.
+ // The one that DOES has driver binding must be Handle2
+ //
+ if (Handle1 == NULL) {
+ if (EFI_ERROR(gBS->OpenProtocol(Handle2, &gEfiDriverBindingProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {
+ // swap
+ Handle1 = Handle2;
+ Handle2 = NULL;
+ } else {
+ // We're all good...
+ }
+ } else {
+ if (EFI_ERROR(gBS->OpenProtocol(Handle1, &gEfiDriverBindingProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {
+ // We're all good...
+ } else {
+ // swap
+ Handle2 = Handle1;
+ Handle1 = NULL;
+ }
+ }
+ }
+
+ return (ConnectControllers(Handle1, Handle2, Recursive, Output, (BOOLEAN)(Handle2 != NULL && Handle1 != NULL)));
+}
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-c", TypeFlag},
+ {L"-r", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'connect' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunConnect (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ CONST CHAR16 *Param1;
+ CONST CHAR16 *Param2;
+ UINTN Count;
+ EFI_HANDLE Handle1;
+ EFI_HANDLE Handle2;
+ UINT64 Intermediate;
+
+ ShellStatus = SHELL_SUCCESS;
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"connect", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // if more than 2 'value' parameters (plus the name one) or either -r or -c with any value parameters we have too many parameters
+ //
+ Count = (gInReconnect?0x4:0x3);
+ if ((ShellCommandLineGetCount(Package) > Count)
+ ||(ShellCommandLineGetFlag(Package, L"-c") && ShellCommandLineGetCount(Package)>1)
+ ||(ShellCommandLineGetFlag(Package, L"-r") && ShellCommandLineGetCount(Package)>2)
+ ||(ShellCommandLineGetFlag(Package, L"-r") && ShellCommandLineGetFlag(Package, L"-c") )
+ ){
+ //
+ // error for too many parameters
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"connect");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetFlag(Package, L"-c")) {
+ //
+ // do the conin and conout from EFI variables
+ // if the first fails dont 'loose' the error
+ //
+ Status = ShellConnectFromDevPaths(L"ConInDev");
+ if (EFI_ERROR(Status)) {
+ ShellConnectFromDevPaths(L"ConOutDev");
+ } else {
+ Status = ShellConnectFromDevPaths(L"ConOutDev");
+ }
+ if (EFI_ERROR(Status)) {
+ ShellConnectFromDevPaths(L"ErrOutDev");
+ } else {
+ Status = ShellConnectFromDevPaths(L"ErrOutDev");
+ }
+ if (EFI_ERROR(Status)) {
+ ShellConnectFromDevPaths(L"ErrOut");
+ } else {
+ Status = ShellConnectFromDevPaths(L"ErrOut");
+ }
+ if (EFI_ERROR(Status)) {
+ ShellConnectFromDevPaths(L"ConIn");
+ } else {
+ Status = ShellConnectFromDevPaths(L"ConIn");
+ }
+ if (EFI_ERROR(Status)) {
+ ShellConnectFromDevPaths(L"ConOut");
+ } else {
+ Status = ShellConnectFromDevPaths(L"ConOut");
+ }
+ if (EFI_ERROR(Status)) {
+ ShellStatus = SHELL_DEVICE_ERROR;
+ }
+ } else {
+ //
+ // 0, 1, or 2 specific handles and possibly recursive
+ //
+ Param1 = ShellCommandLineGetRawValue(Package, 1);
+ Param2 = ShellCommandLineGetRawValue(Package, 2);
+ Count = ShellCommandLineGetCount(Package);
+
+ if (Param1 != NULL) {
+ Status = ShellConvertStringToUint64(Param1, &Intermediate, TRUE, FALSE);
+ Handle1 = ConvertHandleIndexToHandle((UINTN)Intermediate);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"connect", Param1);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ } else {
+ Handle1 = NULL;
+ }
+
+ if (Param2 != NULL) {
+ Status = ShellConvertStringToUint64(Param2, &Intermediate, TRUE, FALSE);
+ Handle2 = ConvertHandleIndexToHandle((UINTN)Intermediate);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"connect", Param2);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ } else {
+ Handle2 = NULL;
+ }
+
+ if (ShellStatus == SHELL_SUCCESS) {
+ if (Param1 != NULL && Handle1 == NULL){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"connect", Param1);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (Param2 != NULL && Handle2 == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"connect", Param2);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (Handle2 != NULL && Handle1 != NULL && EFI_ERROR(gBS->OpenProtocol(Handle2, &gEfiDriverBindingProtocolGuid, NULL, gImageHandle, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"connect", Param2);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Status = ConvertAndConnectControllers(Handle1, Handle2, ShellCommandLineGetFlag(Package, L"-r"), (BOOLEAN)(Count!=0));
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CONNECT_NONE), gShellDriver1HiiHandle);
+ ShellStatus = SHELL_DEVICE_ERROR;
+ }
+ }
+ }
+ }
+
+ ShellCommandLineFreeVarList (Package);
+ }
+ return (ShellStatus);
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/DevTree.c b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/DevTree.c
new file mode 100644
index 0000000000..237cb85f94
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/DevTree.c
@@ -0,0 +1,278 @@
+/** @file
+ Main file for DevTree shell Driver1 function.
+
+ (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDriver1CommandsLib.h"
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-d", TypeFlag},
+ {L"-l", TypeValue},
+ {NULL, TypeMax}
+ };
+
+/**
+ Display a tree starting from this handle.
+
+ @param[in] TheHandle The handle to start with.
+ @param[in] Lang Optionally, a UEFI defined language code.
+ @param[in] UseDevPaths TRUE to display info from DevPath as identifiers.
+ FALSE will use component name protocol instead.
+ @param[in] IndentCharCount How many characters to indent (allows for recursion).
+ @param[in] HiiString The string from HII to use for output.
+
+ @retval SHELL_SUCCESS The operation was successful.
+**/
+SHELL_STATUS
+EFIAPI
+DoDevTreeForHandle(
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST CHAR8 *Lang OPTIONAL,
+ IN CONST BOOLEAN UseDevPaths,
+ IN CONST UINTN IndentCharCount,
+ IN CONST CHAR16 *HiiString
+ )
+{
+ SHELL_STATUS ShellStatus;
+ EFI_STATUS Status;
+ CHAR16 *FormatString;
+ CHAR16 *Name;
+ EFI_HANDLE *ChildHandleBuffer;
+ UINTN ChildCount;
+ UINTN LoopVar;
+
+ Status = EFI_SUCCESS;
+ ShellStatus = SHELL_SUCCESS;
+ Name = NULL;
+ ChildHandleBuffer = NULL;
+ ChildCount = 0;
+
+ ASSERT (TheHandle != NULL);
+ ASSERT (HiiString != NULL);
+
+ if (ShellGetExecutionBreakFlag()) {
+ ShellStatus = SHELL_ABORTED;
+ return ShellStatus;
+ }
+
+ //
+ // We want controller handles. they will not have LoadedImage or DriverBinding (or others...)
+ //
+ Status = gBS->OpenProtocol (
+ TheHandle,
+ &gEfiDriverBindingProtocolGuid,
+ NULL,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ return SHELL_SUCCESS;
+ }
+
+ Status = gBS->OpenProtocol (
+ TheHandle,
+ &gEfiLoadedImageProtocolGuid,
+ NULL,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ return SHELL_SUCCESS;
+ }
+
+ FormatString = AllocateZeroPool(StrSize(HiiString) + (10)*sizeof(FormatString[0]));
+ if (FormatString == NULL) {
+ return SHELL_OUT_OF_RESOURCES;
+ }
+
+ //
+ // we generate the format string on the fly so that we can control the
+ // number of space characters that the first (empty) string has. this
+ // handles the indenting.
+ //
+
+ UnicodeSPrint(FormatString, StrSize(HiiString) + (10)*sizeof(FormatString[0]), L"%%%ds %s", IndentCharCount, HiiString);
+ gEfiShellProtocol->GetDeviceName((EFI_HANDLE)TheHandle, !UseDevPaths?EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH:EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Lang, &Name);
+ //
+ // print out the information for ourselves
+ //
+ ShellPrintEx(
+ -1,
+ -1,
+ FormatString,
+ L"",
+ ConvertHandleToHandleIndex(TheHandle),
+ Name==NULL?L"Unknown":Name);
+
+ FreePool(FormatString);
+ if (Name != NULL) {
+ FreePool(Name);
+ }
+
+ //
+ // recurse on each child handle with IndentCharCount + 2
+ //
+ ParseHandleDatabaseForChildControllers(TheHandle, &ChildCount, &ChildHandleBuffer);
+ for (LoopVar = 0 ; LoopVar < ChildCount && ShellStatus == SHELL_SUCCESS; LoopVar++){
+ ShellStatus = DoDevTreeForHandle(ChildHandleBuffer[LoopVar], Lang, UseDevPaths, IndentCharCount+2, HiiString);
+ if (ShellStatus == SHELL_ABORTED) {
+ break;
+ }
+ }
+
+ if (ChildHandleBuffer != NULL) {
+ FreePool(ChildHandleBuffer);
+ }
+
+ return (ShellStatus);
+}
+
+/**
+ Function for 'devtree' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDevTree (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ CHAR8 *Language;
+ CONST CHAR16 *Lang;
+ CHAR16 *HiiString;
+ UINTN LoopVar;
+ EFI_HANDLE TheHandle;
+ BOOLEAN FlagD;
+ UINT64 Intermediate;
+ UINTN ParentControllerHandleCount;
+ EFI_HANDLE *ParentControllerHandleBuffer;
+
+ ShellStatus = SHELL_SUCCESS;
+ Status = EFI_SUCCESS;
+ Language = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"devtree", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetCount(Package) > 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"devtree");
+ ShellCommandLineFreeVarList (Package);
+ return (SHELL_INVALID_PARAMETER);
+ }
+ Lang = ShellCommandLineGetValue(Package, L"-l");
+ if (Lang != NULL) {
+ Language = AllocateZeroPool(StrSize(Lang));
+ AsciiSPrint(Language, StrSize(Lang), "%S", Lang);
+ } else if (!ShellCommandLineGetFlag(Package, L"-l")){
+ ASSERT(Language == NULL);
+// Language = AllocateZeroPool(10);
+// AsciiSPrint(Language, 10, "en-us");
+ } else {
+ ASSERT(Language == NULL);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"devtree", L"-l");
+ ShellCommandLineFreeVarList (Package);
+ return (SHELL_INVALID_PARAMETER);
+ }
+ FlagD = ShellCommandLineGetFlag(Package, L"-d");
+
+ Lang = ShellCommandLineGetRawValue(Package, 1);
+ HiiString = HiiGetString(gShellDriver1HiiHandle, STRING_TOKEN (STR_DEV_TREE_OUTPUT), Language);
+
+ if (Lang == NULL) {
+ for (LoopVar = 1 ; ; LoopVar++){
+ TheHandle = ConvertHandleIndexToHandle(LoopVar);
+ if (TheHandle == NULL){
+ break;
+ }
+
+ //
+ // Skip handles that do not have device path protocol
+ //
+ Status = gBS->OpenProtocol (
+ TheHandle,
+ &gEfiDevicePathProtocolGuid,
+ NULL,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ //
+ // Skip handles that do have parents
+ //
+ ParentControllerHandleBuffer = NULL;
+ Status = PARSE_HANDLE_DATABASE_PARENTS (
+ TheHandle,
+ &ParentControllerHandleCount,
+ &ParentControllerHandleBuffer
+ );
+ SHELL_FREE_NON_NULL (ParentControllerHandleBuffer);
+ if (ParentControllerHandleCount > 0) {
+ continue;
+ }
+
+ //
+ // Start a devtree from TheHandle that has a device path and no parents
+ //
+ ShellStatus = DoDevTreeForHandle(TheHandle, Language, FlagD, 0, HiiString);
+ }
+ } else {
+ Status = ShellConvertStringToUint64(Lang, &Intermediate, TRUE, FALSE);
+ if (EFI_ERROR(Status) || ConvertHandleIndexToHandle((UINTN)Intermediate) == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"devtree", Lang);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ShellStatus = DoDevTreeForHandle(ConvertHandleIndexToHandle((UINTN)Intermediate), Language, FlagD, 0, HiiString);
+ }
+ }
+
+ if (HiiString != NULL) {
+ FreePool(HiiString);
+ }
+ SHELL_FREE_NON_NULL(Language);
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ return (ShellStatus);
+}
diff --git a/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Devices.c b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Devices.c
new file mode 100644
index 0000000000..d229b352c8
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Devices.c
@@ -0,0 +1,270 @@
+/** @file
+ Main file for devices shell Driver1 function.
+
+ (C) Copyright 2012-2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDriver1CommandsLib.h"
+
+/**
+ Get lots of info about a device from its handle.
+
+ @param[in] TheHandle The device handle to get info on.
+ @param[in, out] Type On successful return R, B, or D (root, bus, or
+ device) will be placed in this buffer.
+ @param[in, out] Cfg On successful return this buffer will be
+ TRUE if the handle has configuration, FALSE
+ otherwise.
+ @param[in, out] Diag On successful return this buffer will be
+ TRUE if the handle has disgnostics, FALSE
+ otherwise.
+ @param[in, out] Parents On successful return this buffer will be
+ contain the number of parent handles.
+ @param[in, out] Devices On successful return this buffer will be
+ contain the number of devices controlled.
+ @param[in, out] Children On successful return this buffer will be
+ contain the number of child handles.
+ @param[out] Name The pointer to a buffer that will be allocated
+ and contain the string name of the handle.
+ The caller must free this memory.
+ @param[in] Language The language code as defined by the UEFI spec.
+
+ @retval EFI_SUCCESS The info is there.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.
+**/
+EFI_STATUS
+EFIAPI
+GetDeviceHandleInfo (
+ IN EFI_HANDLE TheHandle,
+ IN OUT CHAR16 *Type,
+ IN OUT BOOLEAN *Cfg,
+ IN OUT BOOLEAN *Diag,
+ IN OUT UINTN *Parents,
+ IN OUT UINTN *Devices,
+ IN OUT UINTN *Children,
+ OUT CHAR16 **Name,
+ IN CONST CHAR8 *Language
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Count;
+
+ if (TheHandle == NULL
+ || Type == NULL
+ || Cfg == NULL
+ || Diag == NULL
+ || Parents == NULL
+ || Devices == NULL
+ || Children == NULL
+ || Name == NULL ) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ *Cfg = FALSE;
+ *Diag = FALSE;
+ *Children = 0;
+ *Parents = 0;
+ *Devices = 0;
+ *Type = L' ';
+ *Name = CHAR_NULL;
+ HandleBuffer = NULL;
+ Status = EFI_SUCCESS;
+
+ gEfiShellProtocol->GetDeviceName(TheHandle, EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Language, Name);
+
+ Status = ParseHandleDatabaseForChildControllers(TheHandle, Children, NULL);
+// if (!EFI_ERROR(Status)) {
+ Status = PARSE_HANDLE_DATABASE_PARENTS(TheHandle, Parents, NULL);
+ if (/*!EFI_ERROR(Status) && */Parents != NULL && Children != NULL) {
+ if (*Parents == 0) {
+ *Type = L'R';
+ } else if (*Children > 0) {
+ *Type = L'B';
+ } else {
+ *Type = L'D';
+ }
+ }
+// }
+ Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS(TheHandle, Devices, &HandleBuffer);
+ if (!EFI_ERROR(Status) && Devices != NULL && HandleBuffer != NULL) {
+ for (Count = 0 ; Count < *Devices ; Count++) {
+ if (!EFI_ERROR(gBS->OpenProtocol(HandleBuffer[Count], &gEfiDriverConfigurationProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {
+ *Cfg = TRUE;
+ }
+ if (!EFI_ERROR(gBS->OpenProtocol(HandleBuffer[Count], &gEfiDriverDiagnosticsProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {
+ *Diag = TRUE;
+ }
+ if (!EFI_ERROR(gBS->OpenProtocol(HandleBuffer[Count], &gEfiDriverDiagnostics2ProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {
+ *Diag = TRUE;
+ }
+ }
+ SHELL_FREE_NON_NULL(HandleBuffer);
+ }
+
+ return (Status);
+}
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-sfo", TypeFlag},
+ {L"-l", TypeValue},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'devices' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDevices (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ CHAR8 *Language;
+ EFI_HANDLE *HandleList;
+ EFI_HANDLE *HandleListWalker;
+ CHAR16 Type;
+ BOOLEAN Cfg;
+ BOOLEAN Diag;
+ UINTN Parents;
+ UINTN Devices;
+ UINTN Children;
+ CHAR16 *Name;
+ CONST CHAR16 *Lang;
+ BOOLEAN SfoFlag;
+
+ ShellStatus = SHELL_SUCCESS;
+ Language = NULL;
+ SfoFlag = FALSE;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"devices", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // if more than 0 'value' parameters we have too many parameters
+ //
+ if (ShellCommandLineGetRawValue(Package, 1) != NULL){
+ //
+ // error for too many parameters
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"devices");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // get the language if necessary
+ //
+ Lang = ShellCommandLineGetValue(Package, L"-l");
+ if (Lang != NULL) {
+ Language = AllocateZeroPool(StrSize(Lang));
+ AsciiSPrint(Language, StrSize(Lang), "%S", Lang);
+ } else if (!ShellCommandLineGetFlag(Package, L"-l")){
+ ASSERT(Language == NULL);
+// Language = AllocateZeroPool(10);
+// AsciiSPrint(Language, 10, "en-us");
+ } else {
+ ASSERT(Language == NULL);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"devices", L"-l");
+ ShellCommandLineFreeVarList (Package);
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+
+ //
+ // Print Header
+
+ //
+ if (ShellCommandLineGetFlag (Package, L"-sfo")) {
+ ShellPrintHiiEx (-1, -1, Language, STRING_TOKEN (STR_GEN_SFO_HEADER), gShellDriver1HiiHandle, L"devices");
+ SfoFlag = TRUE;
+ } else {
+ ShellPrintHiiEx (-1, -1, Language, STRING_TOKEN (STR_DEVICES_HEADER_LINES), gShellDriver1HiiHandle);
+ }
+
+ //
+ // loop through each handle
+ //
+ HandleList = GetHandleListByProtocol(NULL);
+ ASSERT(HandleList != NULL);
+ for (HandleListWalker = HandleList
+ ; HandleListWalker != NULL && *HandleListWalker != NULL /*&& !EFI_ERROR(Status)*/
+ ; HandleListWalker++
+ ){
+
+ //
+ // get all the info on each handle
+ //
+ Name = NULL;
+ Status = GetDeviceHandleInfo(*HandleListWalker, &Type, &Cfg, &Diag, &Parents, &Devices, &Children, &Name, Language);
+ if (Name != NULL && (Parents != 0 || Devices != 0 || Children != 0)) {
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ Language,
+ SfoFlag?STRING_TOKEN (STR_DEVICES_ITEM_LINE_SFO):STRING_TOKEN (STR_DEVICES_ITEM_LINE),
+ gShellDriver1HiiHandle,
+ ConvertHandleToHandleIndex (*HandleListWalker),
+ Type,
+ Cfg?(SfoFlag?L'Y':L'X'):(SfoFlag?L'N':L'-'),
+ Diag?(SfoFlag?L'Y':L'X'):(SfoFlag?L'N':L'-'),
+ Parents,
+ Devices,
+ Children,
+ Name!=NULL?Name:L"<UNKNOWN>");
+ }
+ if (Name != NULL) {
+ FreePool(Name);
+ }
+ if (ShellGetExecutionBreakFlag ()) {
+ ShellStatus = SHELL_ABORTED;
+ break;
+ }
+
+ }
+
+ if (HandleList != NULL) {
+ FreePool(HandleList);
+ }
+
+ }
+ SHELL_FREE_NON_NULL(Language);
+ ShellCommandLineFreeVarList (Package);
+ }
+ return (ShellStatus);
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Dh.c b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Dh.c
new file mode 100644
index 0000000000..0a1b9a9206
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Dh.c
@@ -0,0 +1,984 @@
+/** @file
+ Main file for Dh shell Driver1 function.
+
+ (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDriver1CommandsLib.h"
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-p", TypeValue},
+ {L"-d", TypeFlag},
+ {L"-v", TypeFlag},
+ {L"-verbose", TypeFlag},
+ {L"-sfo", TypeFlag},
+ {L"-l", TypeValue},
+ {NULL, TypeMax}
+ };
+
+STATIC CONST EFI_GUID *UefiDriverModelProtocolsGuidArray[] = {
+ &gEfiDriverBindingProtocolGuid,
+ &gEfiPlatformDriverOverrideProtocolGuid,
+ &gEfiBusSpecificDriverOverrideProtocolGuid,
+ &gEfiDriverDiagnosticsProtocolGuid,
+ &gEfiDriverDiagnostics2ProtocolGuid,
+ &gEfiComponentNameProtocolGuid,
+ &gEfiComponentName2ProtocolGuid,
+ &gEfiPlatformToDriverConfigurationProtocolGuid,
+ &gEfiDriverSupportedEfiVersionProtocolGuid,
+ &gEfiDriverFamilyOverrideProtocolGuid,
+ &gEfiDriverHealthProtocolGuid,
+ &gEfiLoadedImageProtocolGuid,
+ NULL
+};
+
+/**
+ Get the name of a driver by it's handle.
+
+ If a name is found the memory must be callee freed.
+
+ @param[in] TheHandle The driver's handle.
+ @param[in] Language The language to use.
+ @param[in] NameFound Upon a successful return the name found.
+
+ @retval EFI_SUCCESS The name was found.
+**/
+EFI_STATUS
+EFIAPI
+GetDriverName (
+ IN EFI_HANDLE TheHandle,
+ IN CONST CHAR8 *Language,
+ IN CHAR16 **NameFound
+ )
+{
+ CHAR8 *Lang;
+ EFI_STATUS Status;
+ EFI_COMPONENT_NAME2_PROTOCOL *CompName2;
+ CHAR16 *NameToReturn;
+ //
+ // Go through those handles until we get one that passes for GetComponentName
+ //
+ Status = gBS->OpenProtocol(
+ TheHandle,
+ &gEfiComponentName2ProtocolGuid,
+ (VOID**)&CompName2,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR(Status)) {
+ Status = gBS->OpenProtocol(
+ TheHandle,
+ &gEfiComponentNameProtocolGuid,
+ (VOID**)&CompName2,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ }
+
+ if (EFI_ERROR(Status)) {
+ return (EFI_NOT_FOUND);
+ }
+ Lang = GetBestLanguageForDriver (CompName2->SupportedLanguages, Language, FALSE);
+ Status = CompName2->GetDriverName(CompName2, Lang, &NameToReturn);
+ FreePool(Lang);
+
+ if (!EFI_ERROR(Status) && NameToReturn != NULL) {
+ *NameFound = NULL;
+ StrnCatGrow(NameFound, NULL, NameToReturn, 0);
+ }
+ return (Status);
+}
+
+/**
+ Discover if a protocol guid is one of the UEFI Driver Model Protocols.
+
+ @param[in] Guid The guid to test.
+
+ @retval TRUE The guid does represent a driver model protocol.
+ @retval FALSE The guid does not represent a driver model protocol.
+**/
+BOOLEAN
+EFIAPI
+IsDriverProt (
+ IN CONST EFI_GUID *Guid
+ )
+{
+ CONST EFI_GUID **GuidWalker;
+ BOOLEAN GuidFound;
+ GuidFound = FALSE;
+ for (GuidWalker = UefiDriverModelProtocolsGuidArray
+ ; GuidWalker != NULL && *GuidWalker != NULL
+ ; GuidWalker++
+ ){
+ if (CompareGuid(*GuidWalker, Guid)) {
+ GuidFound = TRUE;
+ break;
+ }
+ }
+ return (GuidFound);
+}
+
+/**
+ Get information for a handle.
+
+ @param[in] TheHandle The handles to show info on.
+ @param[in] Language Language string per UEFI specification.
+ @param[in] Seperator Separator string between information blocks.
+ @param[in] Verbose TRUE for extra info, FALSE otherwise.
+ @param[in] ExtraInfo TRUE for extra info, FALSE otherwise.
+
+ @retval SHELL_SUCCESS The operation was successful.
+ @retval SHELL_INVALID_PARAMETER ProtocolName was NULL or invalid.
+**/
+CHAR16*
+EFIAPI
+GetProtocolInfoString(
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST CHAR8 *Language,
+ IN CONST CHAR16 *Seperator,
+ IN CONST BOOLEAN Verbose,
+ IN CONST BOOLEAN ExtraInfo
+ )
+{
+ EFI_GUID **ProtocolGuidArray;
+ UINTN ArrayCount;
+ UINTN ProtocolIndex;
+ EFI_STATUS Status;
+ CHAR16 *RetVal;
+ UINTN Size;
+ CHAR16 *Temp;
+
+ ProtocolGuidArray = NULL;
+ RetVal = NULL;
+ Size = 0;
+
+ Status = gBS->ProtocolsPerHandle (
+ TheHandle,
+ &ProtocolGuidArray,
+ &ArrayCount
+ );
+ if (!EFI_ERROR (Status)) {
+ for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {
+ Temp = GetStringNameFromGuid(ProtocolGuidArray[ProtocolIndex], Language);
+ if (Temp != NULL) {
+ ASSERT((RetVal == NULL && Size == 0) || (RetVal != NULL));
+ if (Size != 0) {
+ StrnCatGrow(&RetVal, &Size, Seperator, 0);
+ }
+ StrnCatGrow(&RetVal, &Size, L"%H", 0);
+ StrnCatGrow(&RetVal, &Size, Temp, 0);
+ StrnCatGrow(&RetVal, &Size, L"%N", 0);
+ FreePool(Temp);
+ }
+ if (ExtraInfo) {
+ Temp = GetProtocolInformationDump(TheHandle, ProtocolGuidArray[ProtocolIndex], Verbose);
+ if (Temp != NULL) {
+ ASSERT((RetVal == NULL && Size == 0) || (RetVal != NULL));
+ if (!Verbose) {
+ StrnCatGrow(&RetVal, &Size, L"(", 0);
+ StrnCatGrow(&RetVal, &Size, Temp, 0);
+ StrnCatGrow(&RetVal, &Size, L")\r\n", 0);
+ } else {
+ StrnCatGrow(&RetVal, &Size, Seperator, 0);
+ StrnCatGrow(&RetVal, &Size, Temp, 0);
+ }
+ FreePool(Temp);
+ }
+ }
+ }
+ }
+
+ SHELL_FREE_NON_NULL(ProtocolGuidArray);
+
+ if (RetVal == NULL) {
+ return (NULL);
+ }
+
+ ASSERT((RetVal == NULL && Size == 0) || (RetVal != NULL));
+ StrnCatGrow(&RetVal, &Size, Seperator, 0);
+ return (RetVal);
+}
+
+/**
+ Gets the name of the loaded image.
+
+ @param[in] TheHandle The handle of the driver to get info on.
+ @param[out] Name The pointer to the pointer. Valid upon a successful return.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+GetDriverImageName (
+ IN EFI_HANDLE TheHandle,
+ OUT CHAR16 **Name
+ )
+{
+ // get loaded image and devicepathtotext on image->Filepath
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+
+ if (TheHandle == NULL || Name == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ Status = gBS->OpenProtocol (
+ TheHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **) &LoadedImage,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR(Status)) {
+ return (Status);
+ }
+ DevicePath = LoadedImage->FilePath;
+ *Name = ConvertDevicePathToText(DevicePath, TRUE, TRUE);
+ return (EFI_SUCCESS);
+}
+
+/**
+ Display driver model information for a given handle.
+
+ @param[in] Handle The handle to display info on.
+ @param[in] BestName Use the best name?
+ @param[in] Language The language to output in.
+**/
+EFI_STATUS
+EFIAPI
+DisplayDriverModelHandle (
+ IN EFI_HANDLE Handle,
+ IN BOOLEAN BestName,
+ IN CONST CHAR8 *Language OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN ConfigurationStatus;
+ BOOLEAN DiagnosticsStatus;
+ UINTN DriverBindingHandleCount;
+ EFI_HANDLE *DriverBindingHandleBuffer;
+ UINTN ParentControllerHandleCount;
+ EFI_HANDLE *ParentControllerHandleBuffer;
+ UINTN ChildControllerHandleCount;
+ EFI_HANDLE *ChildControllerHandleBuffer;
+ CHAR16 *TempStringPointer;
+ EFI_DEVICE_PATH_PROTOCOL *DevicePath;
+ UINTN Index;
+ CHAR16 *DriverName;
+ EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
+ UINTN NumberOfChildren;
+ UINTN HandleIndex;
+ UINTN ControllerHandleCount;
+ EFI_HANDLE *ControllerHandleBuffer;
+ UINTN ChildIndex;
+ BOOLEAN Image;
+
+ DriverName = NULL;
+
+ //
+ // See if Handle is a device handle and display its details.
+ //
+ DriverBindingHandleBuffer = NULL;
+ Status = PARSE_HANDLE_DATABASE_UEFI_DRIVERS (
+ Handle,
+ &DriverBindingHandleCount,
+ &DriverBindingHandleBuffer
+ );
+
+ ParentControllerHandleBuffer = NULL;
+ Status = PARSE_HANDLE_DATABASE_PARENTS (
+ Handle,
+ &ParentControllerHandleCount,
+ &ParentControllerHandleBuffer
+ );
+
+ ChildControllerHandleBuffer = NULL;
+ Status = ParseHandleDatabaseForChildControllers (
+ Handle,
+ &ChildControllerHandleCount,
+ &ChildControllerHandleBuffer
+ );
+
+ DiagnosticsStatus = FALSE;
+ ConfigurationStatus = FALSE;
+
+ if (!EFI_ERROR(gBS->OpenProtocol(Handle, &gEfiDriverConfigurationProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {
+ ConfigurationStatus = TRUE;
+ }
+ if (!EFI_ERROR(gBS->OpenProtocol(Handle, &gEfiDriverConfiguration2ProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {
+ ConfigurationStatus = TRUE;
+ }
+ if (!EFI_ERROR(gBS->OpenProtocol(Handle, &gEfiDriverDiagnosticsProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {
+ DiagnosticsStatus = TRUE;
+ }
+ if (!EFI_ERROR(gBS->OpenProtocol(Handle, &gEfiDriverDiagnostics2ProtocolGuid, NULL, NULL, gImageHandle, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {
+ DiagnosticsStatus = TRUE;
+ }
+
+ Status = EFI_SUCCESS;
+
+ if (DriverBindingHandleCount > 0 || ParentControllerHandleCount > 0 || ChildControllerHandleCount > 0) {
+
+
+
+ DevicePath = NULL;
+ TempStringPointer = NULL;
+ Status = gBS->HandleProtocol (Handle, &gEfiDevicePathProtocolGuid, (VOID**)&DevicePath);
+
+ Status = gEfiShellProtocol->GetDeviceName(Handle, EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Language, &TempStringPointer);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DH_OUTPUT_DRIVER1), gShellDriver1HiiHandle, TempStringPointer!=NULL?TempStringPointer:L"<Unknown>");
+ SHELL_FREE_NON_NULL(TempStringPointer);
+
+ TempStringPointer = ConvertDevicePathToText(DevicePath, TRUE, FALSE);
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DH_OUTPUT_DRIVER2),
+ gShellDriver1HiiHandle,
+ TempStringPointer!=NULL?TempStringPointer:L"<None>",
+ ParentControllerHandleCount == 0?L"ROOT":(ChildControllerHandleCount > 0)?L"BUS":L"DEVICE",
+ ConfigurationStatus?L"YES":L"NO",
+ DiagnosticsStatus?L"YES":L"NO"
+ );
+
+ SHELL_FREE_NON_NULL(TempStringPointer);
+
+ if (DriverBindingHandleCount == 0) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DH_OUTPUT_DRIVER3),
+ gShellDriver1HiiHandle,
+ L"<None>"
+ );
+ } else {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DH_OUTPUT_DRIVER3),
+ gShellDriver1HiiHandle,
+ L""
+ );
+ for (Index = 0; Index < DriverBindingHandleCount; Index++) {
+ Image = FALSE;
+ Status = GetDriverName (
+ DriverBindingHandleBuffer[Index],
+ Language,
+ &DriverName
+ );
+ if (EFI_ERROR (Status)) {
+ Status = GetDriverImageName (
+ DriverBindingHandleBuffer[Index],
+ &DriverName
+ );
+ if (EFI_ERROR (Status)) {
+ DriverName = NULL;
+ }
+ }
+
+ if (Image) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DH_OUTPUT_DRIVER4A),
+ gShellDriver1HiiHandle,
+ ConvertHandleToHandleIndex (DriverBindingHandleBuffer[Index]),
+ DriverName!=NULL?DriverName:L"<Unknown>"
+ );
+ } else {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DH_OUTPUT_DRIVER4B),
+ gShellDriver1HiiHandle,
+ ConvertHandleToHandleIndex (DriverBindingHandleBuffer[Index]),
+ DriverName!=NULL?DriverName:L"<Unknown>"
+ );
+ }
+ SHELL_FREE_NON_NULL(DriverName);
+ }
+ }
+
+ if (ParentControllerHandleCount == 0) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DH_OUTPUT_DRIVER5),
+ gShellDriver1HiiHandle,
+ L"<None>"
+ );
+ } else {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DH_OUTPUT_DRIVER5),
+ gShellDriver1HiiHandle,
+ L""
+ );
+ for (Index = 0; Index < ParentControllerHandleCount; Index++) {
+ Status = gEfiShellProtocol->GetDeviceName(ParentControllerHandleBuffer[Index], EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Language, &TempStringPointer);
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DH_OUTPUT_DRIVER5B),
+ gShellDriver1HiiHandle,
+ ConvertHandleToHandleIndex (ParentControllerHandleBuffer[Index]),
+ TempStringPointer!=NULL?TempStringPointer:L"<Unknown>"
+ );
+ SHELL_FREE_NON_NULL(TempStringPointer);
+ }
+ }
+
+ if (ChildControllerHandleCount == 0) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DH_OUTPUT_DRIVER6),
+ gShellDriver1HiiHandle,
+ L"<None>"
+ );
+ } else {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DH_OUTPUT_DRIVER6),
+ gShellDriver1HiiHandle,
+ L""
+ );
+ for (Index = 0; Index < ChildControllerHandleCount; Index++) {
+ Status = gEfiShellProtocol->GetDeviceName(ChildControllerHandleBuffer[Index], EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Language, &TempStringPointer);
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DH_OUTPUT_DRIVER6B),
+ gShellDriver1HiiHandle,
+ ConvertHandleToHandleIndex (ChildControllerHandleBuffer[Index]),
+ TempStringPointer!=NULL?TempStringPointer:L"<Unknown>"
+ );
+ SHELL_FREE_NON_NULL(TempStringPointer);
+ }
+ }
+ }
+
+ SHELL_FREE_NON_NULL(DriverBindingHandleBuffer);
+
+ SHELL_FREE_NON_NULL(ParentControllerHandleBuffer);
+
+ SHELL_FREE_NON_NULL(ChildControllerHandleBuffer);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ //
+ // See if Handle is a driver binding handle and display its details.
+ //
+ Status = gBS->OpenProtocol (
+ Handle,
+ &gEfiDriverBindingProtocolGuid,
+ (VOID **) &DriverBinding,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ return EFI_SUCCESS;
+ }
+
+ NumberOfChildren = 0;
+ ControllerHandleBuffer = NULL;
+ Status = PARSE_HANDLE_DATABASE_DEVICES (
+ Handle,
+ &ControllerHandleCount,
+ &ControllerHandleBuffer
+ );
+ if (ControllerHandleCount > 0) {
+ for (HandleIndex = 0; HandleIndex < ControllerHandleCount; HandleIndex++) {
+ Status = PARSE_HANDLE_DATABASE_MANAGED_CHILDREN (
+ Handle,
+ ControllerHandleBuffer[HandleIndex],
+ &ChildControllerHandleCount,
+ NULL
+ );
+ NumberOfChildren += ChildControllerHandleCount;
+ }
+ }
+
+ Status = GetDriverName (Handle, Language, &DriverName);
+ if (EFI_ERROR (Status)) {
+ DriverName = NULL;
+ }
+
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DH_OUTPUT_DRIVER6B),
+ gShellDriver1HiiHandle,
+ ConvertHandleToHandleIndex(Handle),
+ DriverName!=NULL?DriverName:L"<Unknown>"
+ );
+ SHELL_FREE_NON_NULL(DriverName);
+ Status = GetDriverImageName (
+ Handle,
+ &DriverName
+ );
+ if (EFI_ERROR (Status)) {
+ DriverName = NULL;
+ }
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DH_OUTPUT_DRIVER7B),
+ gShellDriver1HiiHandle,
+ DriverName!=NULL?DriverName:L"<Unknown>"
+ );
+ SHELL_FREE_NON_NULL(DriverName);
+
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DH_OUTPUT_DRIVER8),
+ gShellDriver1HiiHandle,
+ DriverBinding->Version,
+ NumberOfChildren > 0?L"Bus":ControllerHandleCount > 0?L"Device":L"<Unknown>",
+ ConfigurationStatus?L"YES":L"NO",
+ DiagnosticsStatus?L"YES":L"NO"
+ );
+
+ if (ControllerHandleCount == 0) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DH_OUTPUT_DRIVER6),
+ gShellDriver1HiiHandle,
+ L"None"
+ );
+ } else {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DH_OUTPUT_DRIVER6),
+ gShellDriver1HiiHandle,
+ L""
+ );
+ for (HandleIndex = 0; HandleIndex < ControllerHandleCount; HandleIndex++) {
+ Status = gEfiShellProtocol->GetDeviceName(ControllerHandleBuffer[HandleIndex], EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Language, &TempStringPointer);
+
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DH_OUTPUT_DRIVER9B),
+ gShellDriver1HiiHandle,
+ ConvertHandleToHandleIndex(ControllerHandleBuffer[HandleIndex]),
+ TempStringPointer!=NULL?TempStringPointer:L"<Unknown>"
+ );
+ SHELL_FREE_NON_NULL(TempStringPointer);
+
+ Status = PARSE_HANDLE_DATABASE_MANAGED_CHILDREN (
+ Handle,
+ ControllerHandleBuffer[HandleIndex],
+ &ChildControllerHandleCount,
+ &ChildControllerHandleBuffer
+ );
+ if (!EFI_ERROR (Status)) {
+ for (ChildIndex = 0; ChildIndex < ChildControllerHandleCount; ChildIndex++) {
+ Status = gEfiShellProtocol->GetDeviceName(ChildControllerHandleBuffer[ChildIndex], EFI_DEVICE_NAME_USE_COMPONENT_NAME|EFI_DEVICE_NAME_USE_DEVICE_PATH, (CHAR8*)Language, &TempStringPointer);
+
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DH_OUTPUT_DRIVER6B),
+ gShellDriver1HiiHandle,
+ ConvertHandleToHandleIndex(ChildControllerHandleBuffer[ChildIndex]),
+ TempStringPointer!=NULL?TempStringPointer:L"<Unknown>"
+ );
+ SHELL_FREE_NON_NULL(TempStringPointer);
+ }
+
+ SHELL_FREE_NON_NULL (ChildControllerHandleBuffer);
+ }
+ }
+
+ SHELL_FREE_NON_NULL (ControllerHandleBuffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Display information for a handle.
+
+ @param[in] TheHandle The handles to show info on.
+ @param[in] Verbose TRUE for extra info, FALSE otherwise.
+ @param[in] Sfo TRUE to output in standard format output (spec).
+ @param[in] Language Language string per UEFI specification.
+ @param[in] DriverInfo TRUE to show all info about the handle.
+ @param[in] Multiple TRUE indicates more than will be output,
+ FALSE for a single one.
+
+ @retval SHELL_SUCCESS The operation was successful.
+ @retval SHELL_INVALID_PARAMETER ProtocolName was NULL or invalid.
+**/
+SHELL_STATUS
+EFIAPI
+DoDhByHandle(
+ IN CONST EFI_HANDLE TheHandle,
+ IN CONST BOOLEAN Verbose,
+ IN CONST BOOLEAN Sfo,
+ IN CONST CHAR8 *Language,
+ IN CONST BOOLEAN DriverInfo,
+ IN CONST BOOLEAN Multiple
+ )
+{
+ CHAR16 *ProtocolInfoString;
+ SHELL_STATUS ShellStatus;
+
+ ShellStatus = SHELL_SUCCESS;
+ ProtocolInfoString = NULL;
+
+ if (!Sfo) {
+ if (Multiple) {
+ ProtocolInfoString = GetProtocolInfoString(TheHandle, Language, L" ", Verbose, TRUE);
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DH_OUTPUT),
+ gShellDriver1HiiHandle,
+ ConvertHandleToHandleIndex(TheHandle),
+ ProtocolInfoString==NULL?L"":ProtocolInfoString);
+ } else {
+ ProtocolInfoString = GetProtocolInfoString(TheHandle, Language, L"\r\n", Verbose, TRUE);
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DH_OUTPUT_SINGLE),
+ gShellDriver1HiiHandle,
+ ConvertHandleToHandleIndex(TheHandle),
+ TheHandle,
+ ProtocolInfoString==NULL?L"":ProtocolInfoString);
+ }
+
+ if (DriverInfo) {
+ DisplayDriverModelHandle ((EFI_HANDLE)TheHandle, TRUE, Language);
+ }
+ } else {
+ ProtocolInfoString = GetProtocolInfoString(TheHandle, Language, L";", FALSE, FALSE);
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DH_OUTPUT_SFO),
+ gShellDriver1HiiHandle,
+ Multiple ?L"HandlesInfo":L"HandleInfo",
+ L"DriverName",
+ L"ControllerName",
+ ConvertHandleToHandleIndex(TheHandle),
+ L"DevPath",
+ ProtocolInfoString==NULL?L"":ProtocolInfoString);
+
+
+ }
+
+
+ if (ProtocolInfoString != NULL) {
+ FreePool(ProtocolInfoString);
+ }
+ return (ShellStatus);
+}
+
+/**
+ Display information for all handles on a list.
+
+ @param[in] HandleList The NULL-terminated list of handles.
+ @param[in] Verbose TRUE for extra info, FALSE otherwise.
+ @param[in] Sfo TRUE to output in standard format output (spec).
+ @param[in] Language Language string per UEFI specification.
+ @param[in] DriverInfo TRUE to show all info about the handle.
+
+ @retval SHELL_SUCCESS The operation was successful.
+ @retval SHELL_INVALID_PARAMETER ProtocolName was NULL or invalid.
+**/
+SHELL_STATUS
+EFIAPI
+DoDhForHandleList(
+ IN CONST EFI_HANDLE *HandleList,
+ IN CONST BOOLEAN Verbose,
+ IN CONST BOOLEAN Sfo,
+ IN CONST CHAR8 *Language,
+ IN CONST BOOLEAN DriverInfo
+ )
+{
+ CONST EFI_HANDLE *HandleWalker;
+ SHELL_STATUS ShellStatus;
+
+ ShellStatus = SHELL_SUCCESS;
+
+ for (HandleWalker = HandleList ; HandleWalker != NULL && *HandleWalker != NULL && ShellStatus == SHELL_SUCCESS; HandleWalker++) {
+ ShellStatus = DoDhByHandle(
+ *HandleWalker,
+ Verbose,
+ Sfo,
+ Language,
+ DriverInfo,
+ TRUE
+ );
+ if (ShellGetExecutionBreakFlag ()) {
+ ShellStatus = SHELL_ABORTED;
+ break;
+ }
+ }
+ return (ShellStatus);
+}
+
+/**
+ Display information for all handles.
+
+ @param[in] Sfo TRUE to output in standard format output (spec).
+ @param[in] Verbose TRUE for extra info, FALSE otherwise.
+ @param[in] Language Language string per UEFI specification.
+ @param[in] DriverInfo TRUE to show all info about the handle.
+
+ @retval SHELL_SUCCESS The operation was successful.
+ @retval SHELL_INVALID_PARAMETER ProtocolName was NULL or invalid.
+**/
+SHELL_STATUS
+EFIAPI
+DoDhForAll(
+ IN CONST BOOLEAN Sfo,
+ IN CONST BOOLEAN Verbose,
+ IN CONST CHAR8 *Language,
+ IN CONST BOOLEAN DriverInfo
+ )
+{
+ EFI_HANDLE *HandleList;
+ SHELL_STATUS ShellStatus;
+
+ HandleList = GetHandleListByProtocol(NULL);
+
+ ShellStatus = DoDhForHandleList(
+ HandleList,
+ Verbose,
+ Sfo,
+ Language,
+ DriverInfo);
+
+ FreePool(HandleList);
+
+ return (ShellStatus);
+}
+
+/**
+ Display information for all handles which have a specific protocol.
+
+ @param[in] ProtocolName The pointer to the name of the protocol.
+ @param[in] Verbose TRUE for extra info, FALSE otherwise.
+ @param[in] Sfo TRUE to output in standard format output (spec).
+ @param[in] Language Language string per UEFI specification.
+ @param[in] DriverInfo TRUE to show all info about the handle.
+
+ @retval SHELL_SUCCESS The operation was successful.
+ @retval SHELL_INVALID_PARAMETER ProtocolName was NULL or invalid.
+**/
+SHELL_STATUS
+EFIAPI
+DoDhByProtocol(
+ IN CONST CHAR16 *ProtocolName,
+ IN CONST BOOLEAN Verbose,
+ IN CONST BOOLEAN Sfo,
+ IN CONST CHAR8 *Language,
+ IN CONST BOOLEAN DriverInfo
+ )
+{
+ EFI_GUID *Guid;
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleList;
+ SHELL_STATUS ShellStatus;
+
+ if (ProtocolName == NULL) {
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ Status = GetGuidFromStringName(ProtocolName, Language, &Guid);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DH_NO_GUID_FOUND), gShellDriver1HiiHandle, ProtocolName);
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ HandleList = GetHandleListByProtocol(Guid);
+
+ ShellStatus = DoDhForHandleList(
+ HandleList,
+ Verbose,
+ Sfo,
+ Language,
+ DriverInfo);
+
+ SHELL_FREE_NON_NULL(HandleList);
+
+ return (ShellStatus);
+}
+
+/**
+ Function for 'dh' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDh (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ CHAR8 *Language;
+ CONST CHAR16 *Lang;
+ CONST CHAR16 *Temp2;
+ BOOLEAN SfoMode;
+ BOOLEAN FlagD;
+ BOOLEAN Verbose;
+ UINT64 Intermediate;
+
+ ShellStatus = SHELL_SUCCESS;
+ Status = EFI_SUCCESS;
+ Language = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"dh", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetCount(Package) > 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"dh");
+ ShellCommandLineFreeVarList (Package);
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ Lang = ShellCommandLineGetValue(Package, L"-l");
+ if (Lang != NULL) {
+ Language = AllocateZeroPool(StrSize(Lang));
+ AsciiSPrint(Language, StrSize(Lang), "%S", Lang);
+ } else if (!ShellCommandLineGetFlag(Package, L"-l")){
+ Language = AllocateZeroPool(10);
+ AsciiSPrint(Language, 10, "en-us");
+ } else {
+ ASSERT(Language == NULL);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"dh", L"-l");
+ ShellCommandLineFreeVarList (Package);
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ SfoMode = ShellCommandLineGetFlag(Package, L"-sfo");
+ FlagD = ShellCommandLineGetFlag(Package, L"-d");
+ Verbose = (BOOLEAN)(ShellCommandLineGetFlag(Package, L"-v") || ShellCommandLineGetFlag(Package, L"-verbose"));
+
+ if (ShellCommandLineGetFlag(Package, L"-p")) {
+ if (ShellCommandLineGetCount(Package) > 1) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"dh");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetValue(Package, L"-p") == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"dh", L"-p");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // print by protocol
+ //
+ ShellStatus = DoDhByProtocol(
+ ShellCommandLineGetValue(Package, L"-p"),
+ Verbose,
+ SfoMode,
+ Lang==NULL?NULL:Language,
+ FlagD
+ );
+ }
+ } else {
+ Temp2 = ShellCommandLineGetRawValue(Package, 1);
+ if (Temp2 == NULL) {
+ //
+ // Print everything
+ //
+ ShellStatus = DoDhForAll(
+ SfoMode,
+ Verbose,
+ Lang==NULL?NULL:Language,
+ FlagD
+ );
+ } else {
+ Status = ShellConvertStringToUint64(Temp2, &Intermediate, TRUE, FALSE);
+ if (EFI_ERROR(Status) || ConvertHandleIndexToHandle((UINTN)Intermediate) == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"dh", Temp2);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // print 1 handle
+ //
+ ShellStatus = DoDhByHandle(
+ ConvertHandleIndexToHandle((UINTN)Intermediate),
+ Verbose,
+ SfoMode,
+ Lang==NULL?NULL:Language,
+ FlagD,
+ FALSE
+ );
+ }
+ }
+ }
+
+
+ ShellCommandLineFreeVarList (Package);
+ SHELL_FREE_NON_NULL(Language);
+ }
+
+ return (ShellStatus);
+}
diff --git a/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Disconnect.c b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Disconnect.c
new file mode 100644
index 0000000000..9afbf07329
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Disconnect.c
@@ -0,0 +1,189 @@
+/** @file
+ Main file for Disconnect shell Driver1 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2010 - 2012, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDriver1CommandsLib.h"
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-r", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Disconnect everything.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+DisconnectAll(
+ VOID
+ )
+{
+ //
+ // Stolen from UEFI 2.3 spec (May 2009 version)
+ // Pages 171/172
+ // Removed gBS local definition
+ //
+
+ //
+ // Disconnect All Handles Example
+ // The following example recusively disconnects all drivers from all
+ // controllers in a platform.
+ //
+ EFI_STATUS Status;
+// EFI_BOOT_SERVICES *gBS;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN HandleIndex;
+ //
+ // Retrieve the list of all handles from the handle database
+ //
+ Status = gBS->LocateHandleBuffer (
+ AllHandles,
+ NULL,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (!EFI_ERROR (Status)) {
+ for (HandleIndex = 0; HandleIndex < HandleCount; HandleIndex++) {
+ Status = gBS->DisconnectController (
+ HandleBuffer[HandleIndex],
+ NULL,
+ NULL
+ );
+ }
+ gBS->FreePool(HandleBuffer);
+ //
+ // end of stealing
+ //
+ }
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function for 'disconnect' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDisconnect (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ CONST CHAR16 *Param1;
+ CONST CHAR16 *Param2;
+ CONST CHAR16 *Param3;
+ EFI_HANDLE Handle1;
+ EFI_HANDLE Handle2;
+ EFI_HANDLE Handle3;
+ UINT64 Intermediate1;
+ UINT64 Intermediate2;
+ UINT64 Intermediate3;
+
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"disconnect", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetFlag(Package, L"-r")){
+ if (ShellCommandLineGetCount(Package) > 1){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"disconnect");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetCount(Package) < 1) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDriver1HiiHandle, L"disconnect");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Status = DisconnectAll();
+ }
+ } else {
+ if (ShellCommandLineGetCount(Package) > 4){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"disconnect");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetCount(Package) < 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDriver1HiiHandle, L"disconnect");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // must have between 1 and 3 handles passed in ...
+ //
+ Param1 = ShellCommandLineGetRawValue(Package, 1);
+ Param2 = ShellCommandLineGetRawValue(Package, 2);
+ Param3 = ShellCommandLineGetRawValue(Package, 3);
+ ShellConvertStringToUint64(Param1, &Intermediate1, TRUE, FALSE);
+ Handle1 = Param1!=NULL?ConvertHandleIndexToHandle((UINTN)Intermediate1):NULL;
+ ShellConvertStringToUint64(Param2, &Intermediate2, TRUE, FALSE);
+ Handle2 = Param2!=NULL?ConvertHandleIndexToHandle((UINTN)Intermediate2):NULL;
+ ShellConvertStringToUint64(Param3, &Intermediate3, TRUE, FALSE);
+ Handle3 = Param3!=NULL?ConvertHandleIndexToHandle((UINTN)Intermediate3):NULL;
+
+ if (Param1 != NULL && Handle1 == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"disconnect", Param1);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (Param2 != NULL && Handle2 == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"disconnect", Param2);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (Param3 != NULL && Handle3 == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"disconnect", Param3);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (Handle2 != NULL && EFI_ERROR(gBS->OpenProtocol(Handle2, &gEfiDriverBindingProtocolGuid, NULL, gImageHandle, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {
+ ASSERT(Param2 != NULL);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_HANDLE_NOT), gShellDriver1HiiHandle, L"disconnect", ShellStrToUintn(Param2), L"driver handle");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(Param1 != NULL);
+ Status = gBS->DisconnectController(Handle1, Handle2, Handle3);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_3P_RESULT), gShellDriver1HiiHandle, L"Disconnect", (UINTN)Intermediate1, (UINTN)Intermediate2, (UINTN)Intermediate3, Status);
+ }
+ }
+ }
+ }
+ if (ShellStatus == SHELL_SUCCESS) {
+ if (Status == EFI_SECURITY_VIOLATION) {
+ ShellStatus = SHELL_SECURITY_VIOLATION;
+ } else if (Status == EFI_INVALID_PARAMETER) {
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (EFI_ERROR(Status)) {
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ }
+ return (ShellStatus);
+}
diff --git a/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Drivers.c b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Drivers.c
new file mode 100644
index 0000000000..d6d75f0625
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Drivers.c
@@ -0,0 +1,321 @@
+/** @file
+ Main file for Drivers shell Driver1 function.
+
+ (C) Copyright 2012-2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDriver1CommandsLib.h"
+
+#define MAX_LEN_DRIVER_NAME 35
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-sfo", TypeFlag},
+ {L"-l", TypeValue},
+ {NULL, TypeMax}
+ };
+
+/**
+ Get a device path (in text format) for a given handle.
+
+ @param[in] TheHandle The handle to get the device path for.
+
+ @retval NULL An error occured.
+ @return A pointer to the driver path as a string. The callee must
+ free this memory.
+**/
+CHAR16*
+EFIAPI
+GetDevicePathTextForHandle(
+ IN EFI_HANDLE TheHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath;
+ EFI_DEVICE_PATH_PROTOCOL *FinalPath;
+ CHAR16 *RetVal;
+
+ FinalPath = NULL;
+
+ Status = gBS->OpenProtocol (
+ TheHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID**)&LoadedImage,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->OpenProtocol (
+ LoadedImage->DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID**)&ImageDevicePath,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (!EFI_ERROR (Status)) {
+ FinalPath = AppendDevicePath (ImageDevicePath, LoadedImage->FilePath);
+ gBS->CloseProtocol(
+ LoadedImage->DeviceHandle,
+ &gEfiDevicePathProtocolGuid,
+ gImageHandle,
+ NULL);
+ }
+ gBS->CloseProtocol(
+ TheHandle,
+ &gEfiLoadedImageProtocolGuid,
+ gImageHandle,
+ NULL);
+ }
+
+ if (FinalPath == NULL) {
+ return (NULL);
+ }
+ RetVal = gEfiShellProtocol->GetFilePathFromDevicePath(FinalPath);
+ if (RetVal == NULL) {
+ RetVal = ConvertDevicePathToText(FinalPath, TRUE, TRUE);
+ }
+ FreePool(FinalPath);
+ return (RetVal);
+}
+
+/**
+ Determine if the given handle has Driver Configuration protocol.
+
+ @param[in] TheHandle The handle to the driver to test.
+
+ @retval TRUE The driver does have Driver Configuration.
+ @retval FALSE The driver does not have Driver Configuration.
+**/
+BOOLEAN
+EFIAPI
+ReturnDriverConfig(
+ IN CONST EFI_HANDLE TheHandle
+ )
+{
+ EFI_STATUS Status;
+ Status = gBS->OpenProtocol((EFI_HANDLE)TheHandle, &gEfiDriverConfigurationProtocolGuid, NULL, gImageHandle, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
+ if (EFI_ERROR(Status)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+/**
+ Determine if the given handle has DriverDiagnostics protocol.
+
+ @param[in] TheHandle The handle to the driver to test.
+
+ @retval TRUE The driver does have Driver Diasgnostics.
+ @retval FALSE The driver does not have Driver Diagnostics.
+**/
+BOOLEAN
+EFIAPI
+ReturnDriverDiag(
+ IN CONST EFI_HANDLE TheHandle
+ )
+{
+ EFI_STATUS Status;
+ Status = gBS->OpenProtocol((EFI_HANDLE)TheHandle, &gEfiDriverDiagnostics2ProtocolGuid, NULL, gImageHandle, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
+ if (EFI_ERROR(Status)) {
+ Status = gBS->OpenProtocol((EFI_HANDLE)TheHandle, &gEfiDriverDiagnosticsProtocolGuid, NULL, gImageHandle, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL);
+ if (EFI_ERROR(Status)) {
+ return (FALSE);
+ }
+ }
+ return (TRUE);
+}
+
+/**
+ Finds and returns the version of the driver specified by TheHandle.
+
+ @param[in] TheHandle The driver handle to get the version of.
+
+ @return The version of the driver.
+ @retval 0xFFFFFFFF An error ocurred.
+**/
+UINT32
+EFIAPI
+ReturnDriverVersion(
+ IN CONST EFI_HANDLE TheHandle
+ )
+{
+ EFI_DRIVER_BINDING_PROTOCOL *DriverBinding;
+ EFI_STATUS Status;
+ UINT32 RetVal;
+
+ RetVal = (UINT32)-1;
+
+ Status = gBS->OpenProtocol((EFI_HANDLE)TheHandle, &gEfiDriverBindingProtocolGuid, (VOID**)&DriverBinding, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (!EFI_ERROR(Status)) {
+ RetVal = DriverBinding->Version;
+ gBS->CloseProtocol(TheHandle, &gEfiDriverBindingProtocolGuid, gImageHandle, NULL);
+ }
+ return (RetVal);
+}
+
+/**
+ Function for 'drivers' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDrivers (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ CHAR8 *Language;
+ CONST CHAR16 *Lang;
+ EFI_HANDLE *HandleList;
+ EFI_HANDLE *HandleWalker;
+ UINTN ChildCount;
+ UINTN DeviceCount;
+ CHAR16 *Temp2;
+ CONST CHAR16 *FullDriverName;
+ CHAR16 *TruncatedDriverName;
+ CHAR16 *FormatString;
+ UINT32 DriverVersion;
+ BOOLEAN DriverConfig;
+ BOOLEAN DriverDiag;
+ BOOLEAN SfoFlag;
+
+ ShellStatus = SHELL_SUCCESS;
+ Status = EFI_SUCCESS;
+ Language = NULL;
+ FormatString = NULL;
+ SfoFlag = FALSE;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"drivers", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetCount(Package) > 1) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"drivers");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ if (ShellCommandLineGetFlag(Package, L"-l")){
+ Lang = ShellCommandLineGetValue(Package, L"-l");
+ if (Lang != NULL) {
+ Language = AllocateZeroPool(StrSize(Lang));
+ AsciiSPrint(Language, StrSize(Lang), "%S", Lang);
+ } else {
+ ASSERT(Language == NULL);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"drivers", L"-l");
+ ShellCommandLineFreeVarList (Package);
+ return (SHELL_INVALID_PARAMETER);
+ }
+ }
+
+ if (ShellCommandLineGetFlag (Package, L"-sfo")) {
+ SfoFlag = TRUE;
+ FormatString = HiiGetString (gShellDriver1HiiHandle, STRING_TOKEN (STR_DRIVERS_ITEM_LINE_SFO), Language);
+ //
+ // print the SFO header
+ //
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ Language,
+ STRING_TOKEN (STR_GEN_SFO_HEADER),
+ gShellDriver1HiiHandle,
+ L"drivers");
+ } else {
+ FormatString = HiiGetString (gShellDriver1HiiHandle, STRING_TOKEN (STR_DRIVERS_ITEM_LINE), Language);
+ //
+ // print the header row
+ //
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ Language,
+ STRING_TOKEN (STR_DRIVERS_HEADER_LINES),
+ gShellDriver1HiiHandle);
+ }
+
+ HandleList = GetHandleListByProtocol(&gEfiDriverBindingProtocolGuid);
+ for (HandleWalker = HandleList ; HandleWalker != NULL && *HandleWalker != NULL ; HandleWalker++){
+ ChildCount = 0;
+ DeviceCount = 0;
+ Status = ParseHandleDatabaseForChildDevices (*HandleWalker, &ChildCount , NULL);
+ Status = PARSE_HANDLE_DATABASE_DEVICES (*HandleWalker, &DeviceCount, NULL);
+ Temp2 = GetDevicePathTextForHandle(*HandleWalker);
+ DriverVersion = ReturnDriverVersion(*HandleWalker);
+ DriverConfig = ReturnDriverConfig(*HandleWalker);
+ DriverDiag = ReturnDriverDiag (*HandleWalker);
+ FullDriverName = GetStringNameFromHandle(*HandleWalker, Language);
+
+ TruncatedDriverName = NULL;
+ if (!SfoFlag && (FullDriverName != NULL)) {
+ TruncatedDriverName = AllocateZeroPool ((MAX_LEN_DRIVER_NAME + 1) * sizeof (CHAR16));
+ StrnCpyS (TruncatedDriverName, MAX_LEN_DRIVER_NAME + 1, FullDriverName, MAX_LEN_DRIVER_NAME);
+ }
+
+ ShellPrintEx(
+ -1,
+ -1,
+ FormatString,
+ ConvertHandleToHandleIndex(*HandleWalker),
+ DriverVersion,
+ ChildCount > 0?L'B':(DeviceCount > 0?L'D':L'?'),
+ DriverConfig?L'Y':L'N',
+ DriverDiag?L'Y':L'N',
+ DeviceCount,
+ ChildCount,
+ SfoFlag?FullDriverName:TruncatedDriverName,
+ Temp2==NULL?L"":Temp2
+ );
+ if (TruncatedDriverName != NULL) {
+ FreePool (TruncatedDriverName);
+ }
+ if (Temp2 != NULL) {
+ FreePool(Temp2);
+ }
+
+ if (ShellGetExecutionBreakFlag ()) {
+ ShellStatus = SHELL_ABORTED;
+ break;
+ }
+ }
+ }
+ SHELL_FREE_NON_NULL(Language);
+ ShellCommandLineFreeVarList (Package);
+ SHELL_FREE_NON_NULL(FormatString);
+ }
+
+ return (ShellStatus);
+}
diff --git a/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/DrvCfg.c b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/DrvCfg.c
new file mode 100644
index 0000000000..0d12f01199
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/DrvCfg.c
@@ -0,0 +1,1414 @@
+/** @file
+ Main file for DrvCfg shell Driver1 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDriver1CommandsLib.h"
+#include <Protocol/HiiConfigAccess.h>
+#include <Protocol/HiiDatabase.h>
+
+STATIC CONST EFI_GUID *CfgGuidList[] = {&gEfiDriverConfigurationProtocolGuid, &gEfiDriverConfiguration2ProtocolGuid, NULL};
+
+/**
+ Find the EFI_HII_HANDLE by device path.
+
+ @param[in] DevPath1 The Device Path to match.
+ @param[out] HiiHandle The EFI_HII_HANDLE after the converstion.
+ @param[in] HiiDb The Hii database protocol
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_NOT_FOUND There was no EFI_HII_HANDLE found for that deviec path.
+**/
+EFI_STATUS
+EFIAPI
+FindHiiHandleViaDevPath(
+ IN CONST EFI_DEVICE_PATH_PROTOCOL *DevPath1,
+ OUT EFI_HII_HANDLE *HiiHandle,
+ IN EFI_HII_DATABASE_PROTOCOL *HiiDb
+ )
+{
+ EFI_HII_HANDLE *HandleBuffer;
+ UINTN HandleBufferSize;
+ VOID *MainBuffer;
+ UINTN MainBufferSize;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;
+ EFI_HII_PACKAGE_HEADER *PackageHeader;
+ UINTN LoopVariable;
+ EFI_DEVICE_PATH_PROTOCOL *DevPath2;
+ EFI_STATUS Status;
+
+ ASSERT(DevPath1 != NULL);
+ ASSERT(HiiHandle != NULL);
+ ASSERT(*HiiHandle == NULL);
+ ASSERT(HiiDb != NULL);
+
+ HandleBufferSize = 0;
+ HandleBuffer = NULL;
+ Status = HiiDb->ListPackageLists(HiiDb, EFI_HII_PACKAGE_DEVICE_PATH, NULL, &HandleBufferSize, HandleBuffer);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HandleBuffer = AllocateZeroPool(HandleBufferSize);
+ if (HandleBuffer == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ Status = HiiDb->ListPackageLists (HiiDb, EFI_HII_PACKAGE_DEVICE_PATH, NULL, &HandleBufferSize, HandleBuffer);
+ }
+ }
+ if (EFI_ERROR(Status)) {
+ SHELL_FREE_NON_NULL(HandleBuffer);
+ return (Status);
+ }
+
+ if (HandleBuffer == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ for (LoopVariable = 0 ; LoopVariable < (HandleBufferSize/sizeof(HandleBuffer[0])) && *HiiHandle == NULL ; LoopVariable++) {
+ MainBufferSize = 0;
+ MainBuffer = NULL;
+ Status = HiiDb->ExportPackageLists(HiiDb, HandleBuffer[LoopVariable], &MainBufferSize, MainBuffer);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ MainBuffer = AllocateZeroPool(MainBufferSize);
+ if (MainBuffer != NULL) {
+ Status = HiiDb->ExportPackageLists (HiiDb, HandleBuffer[LoopVariable], &MainBufferSize, MainBuffer);
+ }
+ }
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+ //
+ // Enumerate through the block of returned memory.
+ // This should actually be a small block, but we need to be sure.
+ //
+ for (PackageListHeader = (EFI_HII_PACKAGE_LIST_HEADER*)MainBuffer
+ ; PackageListHeader != NULL && ((CHAR8*)PackageListHeader) < (((CHAR8*)MainBuffer)+MainBufferSize) && *HiiHandle == NULL
+ ; PackageListHeader = (EFI_HII_PACKAGE_LIST_HEADER*)(((CHAR8*)(PackageListHeader)) + PackageListHeader->PackageLength )) {
+ for (PackageHeader = (EFI_HII_PACKAGE_HEADER*)(((CHAR8*)(PackageListHeader))+sizeof(EFI_HII_PACKAGE_LIST_HEADER))
+ ; PackageHeader != NULL && ((CHAR8*)PackageHeader) < (((CHAR8*)MainBuffer)+MainBufferSize) && PackageHeader->Type != EFI_HII_PACKAGE_END && *HiiHandle == NULL
+ ; PackageHeader = (EFI_HII_PACKAGE_HEADER*)(((CHAR8*)(PackageHeader))+PackageHeader->Length)) {
+ if (PackageHeader->Type == EFI_HII_PACKAGE_DEVICE_PATH) {
+ DevPath2 = (EFI_DEVICE_PATH_PROTOCOL*)(((CHAR8*)PackageHeader) + sizeof(EFI_HII_PACKAGE_HEADER));
+ if (DevicePathCompare(&DevPath1, &DevPath2) == 0) {
+ *HiiHandle = HandleBuffer[LoopVariable];
+ break;
+ }
+ }
+ }
+ }
+ SHELL_FREE_NON_NULL(MainBuffer);
+ }
+ SHELL_FREE_NON_NULL(HandleBuffer);
+
+ if (*HiiHandle == NULL) {
+ return (EFI_NOT_FOUND);
+ }
+ return (EFI_SUCCESS);
+}
+
+/**
+ Convert a EFI_HANDLE to a EFI_HII_HANDLE.
+
+ @param[in] Handle The EFI_HANDLE to convert.
+ @param[out] HiiHandle The EFI_HII_HANDLE after the converstion.
+ @param[in] HiiDb The Hii database protocol
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+ConvertHandleToHiiHandle(
+ IN CONST EFI_HANDLE Handle,
+ OUT EFI_HII_HANDLE *HiiHandle,
+ IN EFI_HII_DATABASE_PROTOCOL *HiiDb
+ )
+{
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *DevPath1;
+
+ if (HiiHandle == NULL || HiiDb == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+ *HiiHandle = NULL;
+
+ if (Handle == NULL) {
+ return (EFI_SUCCESS);
+ }
+
+ DevPath1 = NULL;
+ Status = gBS->OpenProtocol(Handle, &gEfiDevicePathProtocolGuid, (VOID**)&DevPath1, gImageHandle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR(Status) || DevPath1 == NULL) {
+ return (EFI_NOT_FOUND);
+ }
+
+ return (FindHiiHandleViaDevPath(DevPath1, HiiHandle, HiiDb));
+}
+
+/**
+ Function to print out all HII configuration information to a file.
+
+ @param[in] Handle The handle to get info on. NULL to do all handles.
+ @param[in] FileName The filename to rwite the info to.
+**/
+SHELL_STATUS
+EFIAPI
+ConfigToFile(
+ IN CONST EFI_HANDLE Handle,
+ IN CONST CHAR16 *FileName
+ )
+{
+ EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
+ EFI_STATUS Status;
+ VOID *MainBuffer;
+ UINTN MainBufferSize;
+ EFI_HII_HANDLE HiiHandle;
+ SHELL_FILE_HANDLE FileHandle;
+
+ HiiDatabase = NULL;
+ MainBufferSize = 0;
+ MainBuffer = NULL;
+ FileHandle = NULL;
+
+ Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_GEN_FILE_OPEN_FAIL),
+ gShellDriver1HiiHandle,
+ L"drvcfg",
+ FileName,
+ Status);
+ return (SHELL_DEVICE_ERROR);
+ }
+
+ //
+ // Locate HII Database protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiHiiDatabaseProtocolGuid,
+ NULL,
+ (VOID **) &HiiDatabase
+ );
+
+ if (EFI_ERROR(Status) || HiiDatabase == NULL) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_GEN_PROTOCOL_NF),
+ gShellDriver1HiiHandle,
+ L"drvcfg",
+ L"EfiHiiDatabaseProtocol",
+ &gEfiHiiDatabaseProtocolGuid);
+ ShellCloseFile(&FileHandle);
+ return (SHELL_NOT_FOUND);
+ }
+
+ HiiHandle = NULL;
+ Status = ConvertHandleToHiiHandle(Handle, &HiiHandle, HiiDatabase);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_GEN_HANDLE_NOT),
+ gShellDriver1HiiHandle,
+ L"drvcfg",
+ ConvertHandleToHandleIndex(Handle),
+ L"Device");
+ ShellCloseFile(&FileHandle);
+ return (SHELL_DEVICE_ERROR);
+ }
+
+ Status = HiiDatabase->ExportPackageLists(HiiDatabase, HiiHandle, &MainBufferSize, MainBuffer);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ MainBuffer = AllocateZeroPool(MainBufferSize);
+ Status = HiiDatabase->ExportPackageLists(HiiDatabase, HiiHandle, &MainBufferSize, MainBuffer);
+ }
+
+ Status = ShellWriteFile(FileHandle, &MainBufferSize, MainBuffer);
+
+ ShellCloseFile(&FileHandle);
+ SHELL_FREE_NON_NULL(MainBuffer);
+
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_FILE_WRITE_FAIL),
+ gShellDriver1HiiHandle,
+ L"drvcfg",
+ FileName);
+ return (SHELL_DEVICE_ERROR);
+ }
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_DRVCFG_COMP),
+ gShellDriver1HiiHandle);
+
+ return (SHELL_SUCCESS);
+}
+
+/**
+ Function to read in HII configuration information from a file.
+
+ @param[in] Handle The handle to get info for.
+ @param[in] FileName The filename to read the info from.
+**/
+SHELL_STATUS
+EFIAPI
+ConfigFromFile(
+ IN EFI_HANDLE Handle,
+ IN CONST CHAR16 *FileName
+ )
+{
+ EFI_HII_DATABASE_PROTOCOL *HiiDatabase;
+ EFI_STATUS Status;
+ VOID *MainBuffer;
+ UINT64 Temp;
+ UINTN MainBufferSize;
+ EFI_HII_HANDLE HiiHandle;
+ SHELL_FILE_HANDLE FileHandle;
+ CHAR16 *TempDevPathString;
+ EFI_HII_PACKAGE_LIST_HEADER *PackageListHeader;
+ EFI_HII_PACKAGE_HEADER *PackageHeader;
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+ UINTN HandleIndex;
+
+ HiiDatabase = NULL;
+ MainBufferSize = 0;
+ MainBuffer = NULL;
+ FileHandle = NULL;
+
+ Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_READ, 0);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_GEN_FILE_OPEN_FAIL),
+ gShellDriver1HiiHandle,
+ L"drvcfg",
+ FileName,
+ Status);
+ return (SHELL_DEVICE_ERROR);
+ }
+
+ //
+ // Locate HII Database protocol
+ //
+ Status = gBS->LocateProtocol (
+ &gEfiHiiDatabaseProtocolGuid,
+ NULL,
+ (VOID **) &HiiDatabase
+ );
+
+ if (EFI_ERROR(Status) || HiiDatabase == NULL) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_GEN_PROTOCOL_NF),
+ gShellDriver1HiiHandle,
+ L"drvcfg",
+ L"EfiHiiDatabaseProtocol",
+ &gEfiHiiDatabaseProtocolGuid);
+ ShellCloseFile(&FileHandle);
+ return (SHELL_NOT_FOUND);
+ }
+
+ Status = ShellGetFileSize(FileHandle, &Temp);
+ MainBufferSize = (UINTN)Temp;
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_FILE_READ_FAIL),
+ gShellDriver1HiiHandle,
+ L"drvcfg",
+ FileName);
+
+ ShellCloseFile(&FileHandle);
+ return (SHELL_DEVICE_ERROR);
+ }
+ MainBuffer = AllocateZeroPool((UINTN)MainBufferSize);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_GEN_OUT_MEM),
+ gShellDriver1HiiHandle, L"drvcfg");
+ ShellCloseFile(&FileHandle);
+ return (SHELL_DEVICE_ERROR);
+ }
+ Status = ShellReadFile(FileHandle, &MainBufferSize, MainBuffer);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_FILE_READ_FAIL),
+ gShellDriver1HiiHandle,
+ L"drvcfg",
+ FileName);
+
+ ShellCloseFile(&FileHandle);
+ SHELL_FREE_NON_NULL(MainBuffer);
+ return (SHELL_DEVICE_ERROR);
+ }
+
+ ShellCloseFile(&FileHandle);
+
+ if (Handle != NULL) {
+ //
+ // User override in place. Just do it.
+ //
+ HiiHandle = NULL;
+ Status = ConvertHandleToHiiHandle(Handle, &HiiHandle, HiiDatabase);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_GEN_HANDLE_NOT),
+ gShellDriver1HiiHandle, L"drvcfg",
+ ConvertHandleToHandleIndex(Handle),
+ L"Device");
+ ShellCloseFile(&FileHandle);
+ return (SHELL_DEVICE_ERROR);
+ }
+ Status = HiiDatabase->UpdatePackageList(HiiDatabase, HiiHandle, MainBuffer);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_GEN_UEFI_FUNC_WARN),
+ gShellDriver1HiiHandle,
+ L"drvcfg",
+ L"HiiDatabase->UpdatePackageList",
+ Status);
+ return (SHELL_DEVICE_ERROR);
+ }
+ } else {
+ //
+ // we need to parse the buffer and try to match the device paths for each item to try to find it's device path.
+ //
+
+ for (PackageListHeader = (EFI_HII_PACKAGE_LIST_HEADER*)MainBuffer
+ ; PackageListHeader != NULL && ((CHAR8*)PackageListHeader) < (((CHAR8*)MainBuffer)+MainBufferSize)
+ ; PackageListHeader = (EFI_HII_PACKAGE_LIST_HEADER*)(((CHAR8*)(PackageListHeader)) + PackageListHeader->PackageLength )) {
+ for (PackageHeader = (EFI_HII_PACKAGE_HEADER*)(((CHAR8*)(PackageListHeader))+sizeof(EFI_HII_PACKAGE_LIST_HEADER))
+ ; PackageHeader != NULL && ((CHAR8*)PackageHeader) < (((CHAR8*)MainBuffer)+MainBufferSize) && PackageHeader->Type != EFI_HII_PACKAGE_END
+ ; PackageHeader = (EFI_HII_PACKAGE_HEADER*)(((CHAR8*)(PackageHeader))+PackageHeader->Length)) {
+ if (PackageHeader->Type == EFI_HII_PACKAGE_DEVICE_PATH) {
+ HiiHandle = NULL;
+ Status = FindHiiHandleViaDevPath((EFI_DEVICE_PATH_PROTOCOL*)(((CHAR8*)PackageHeader) + sizeof(EFI_HII_PACKAGE_HEADER)), &HiiHandle, HiiDatabase);
+ if (EFI_ERROR(Status)) {
+ //
+ // print out an error.
+ //
+ TempDevPathString = ConvertDevicePathToText((EFI_DEVICE_PATH_PROTOCOL*)(((CHAR8*)PackageHeader) + sizeof(EFI_HII_PACKAGE_HEADER)), TRUE, TRUE);
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_DRVCFG_IN_FILE_NF),
+ gShellDriver1HiiHandle,
+ TempDevPathString);
+ SHELL_FREE_NON_NULL(TempDevPathString);
+ } else {
+ Status = HiiDatabase->UpdatePackageList(HiiDatabase, HiiHandle, PackageListHeader);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_GEN_UEFI_FUNC_WARN),
+ gShellDriver1HiiHandle,
+ L"drvcfg",
+ L"HiiDatabase->UpdatePackageList",
+ Status);
+ return (SHELL_DEVICE_ERROR);
+ } else {
+ DevPath = (EFI_DEVICE_PATH_PROTOCOL*)(((CHAR8*)PackageHeader) + sizeof(EFI_HII_PACKAGE_HEADER));
+ gBS->LocateDevicePath(&gEfiHiiConfigAccessProtocolGuid, &DevPath, &Handle);
+ HandleIndex = ConvertHandleToHandleIndex(Handle);
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_DRVCFG_DONE_HII),
+ gShellDriver1HiiHandle,
+ HandleIndex);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ SHELL_FREE_NON_NULL(MainBuffer);
+
+
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_DRVCFG_COMP),
+ gShellDriver1HiiHandle);
+ return (SHELL_SUCCESS);
+}
+
+/**
+ Present a requested action to the user.
+
+ @param[in] DriverImageHandle The handle for the driver to configure.
+ @param[in] ControllerHandle The handle of the device being managed by the Driver specified.
+ @param[in] ChildHandle The handle of a child device of the specified device.
+ @param[in] ActionRequired The required HII action.
+
+ @retval SHELL_INVALID_PARAMETER A parameter has a invalid value.
+**/
+EFI_STATUS
+EFIAPI
+ShellCmdDriverConfigurationProcessActionRequired (
+ EFI_HANDLE DriverImageHandle,
+ EFI_HANDLE ControllerHandle,
+ EFI_HANDLE ChildHandle,
+ EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED ActionRequired
+ )
+{
+ EFI_HANDLE ConnectControllerContextOverride[2];
+
+ switch (ActionRequired) {
+ case EfiDriverConfigurationActionNone:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_DRVCFG_NONE), gShellDriver1HiiHandle);
+ break;
+
+ case EfiDriverConfigurationActionStopController:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_DRVCFG_STOP), gShellDriver1HiiHandle);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_DRVCFG_ENTER_S), gShellDriver1HiiHandle, L"stop controller");
+ ShellPromptForResponse(ShellPromptResponseTypeEnterContinue, NULL, NULL);
+
+ gBS->DisconnectController (ControllerHandle, DriverImageHandle, ChildHandle);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_DRVCFG_CTLR_S), gShellDriver1HiiHandle, L"stopped");
+ break;
+
+ case EfiDriverConfigurationActionRestartController:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_DRVCFG_RESTART_S), gShellDriver1HiiHandle, L"controller");
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_DRVCFG_ENTER_S), gShellDriver1HiiHandle, L"restart controller");
+ ShellPromptForResponse(ShellPromptResponseTypeEnterContinue, NULL, NULL);
+
+ gBS->DisconnectController (ControllerHandle, DriverImageHandle, ChildHandle);
+ ConnectControllerContextOverride[0] = DriverImageHandle;
+ ConnectControllerContextOverride[1] = NULL;
+ gBS->ConnectController (ControllerHandle, ConnectControllerContextOverride, NULL, TRUE);
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_DRVCFG_CTLR_S), gShellDriver1HiiHandle, L"restarted");
+ break;
+
+ case EfiDriverConfigurationActionRestartPlatform:
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_DRVCFG_RESTART_S), gShellDriver1HiiHandle, L"platform");
+ ShellPrintHiiEx(-1,-1,NULL,STRING_TOKEN (STR_DRVCFG_ENTER_S), gShellDriver1HiiHandle, L"restart platform");
+ ShellPromptForResponse(ShellPromptResponseTypeEnterContinue, NULL, NULL);
+
+ gRT->ResetSystem (EfiResetCold, EFI_SUCCESS, 0, NULL);
+ break;
+
+ default:
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Do the configuration in an environment without HII.
+
+ @param[in] Language The language code.
+ @param[in] ForceDefaults TRUE to force defaults, FALSE otherwise.
+ @param[in] DefaultType If ForceDefaults is TRUE, specifies the default type.
+ @param[in] AllChildren TRUE to configure all children, FALSE otherwise.
+ @param[in] ValidateOptions TRUE to validate existing options, FALSE otherwise.
+ @param[in] SetOptions TRUE to set options, FALSE otherwise.
+ @param[in] DriverImageHandle The handle for the driver to configure.
+ @param[in] DeviceHandle The handle of the device being managed by the Driver specified.
+ @param[in] ChildHandle The handle of a child device of the specified device.
+
+ @retval SHELL_NOT_FOUND A specified handle could not be found.
+ @retval SHELL_INVALID_PARAMETER A parameter has a invalid value.
+**/
+SHELL_STATUS
+EFIAPI
+PreHiiDrvCfg (
+ IN CONST CHAR8 *Language,
+ IN BOOLEAN ForceDefaults,
+ IN UINT32 DefaultType,
+ IN BOOLEAN AllChildren,
+ IN BOOLEAN ValidateOptions,
+ IN BOOLEAN SetOptions,
+ IN EFI_HANDLE DriverImageHandle,
+ IN EFI_HANDLE DeviceHandle,
+ IN EFI_HANDLE ChildHandle
+ )
+{
+ EFI_STATUS Status;
+ SHELL_STATUS ShellStatus;
+ UINTN OuterLoopCounter;
+ CHAR8 *BestLanguage;
+ UINTN DriverImageHandleCount;
+ EFI_HANDLE *DriverImageHandleBuffer;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN *HandleType;
+ UINTN LoopCounter;
+ UINTN ChildIndex;
+ UINTN ChildHandleCount;
+ EFI_HANDLE *ChildHandleBuffer;
+ UINTN *ChildHandleType;
+ EFI_DRIVER_CONFIGURATION_ACTION_REQUIRED ActionRequired;
+ EFI_DRIVER_CONFIGURATION_PROTOCOL *DriverConfiguration;
+ BOOLEAN Iso639Language;
+ UINTN HandleIndex1;
+ UINTN HandleIndex2;
+ UINTN HandleIndex3;
+
+ ShellStatus = SHELL_SUCCESS;
+
+ if (ChildHandle == NULL && AllChildren) {
+ SetOptions = FALSE;
+ }
+
+ if (ForceDefaults) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRVCFG_FORCE_D),
+ gShellDriver1HiiHandle,
+ DefaultType);
+ } else if (ValidateOptions) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRVCFG_VALIDATE),
+ gShellDriver1HiiHandle);
+ } else if (SetOptions) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRVCFG_SET),
+ gShellDriver1HiiHandle);
+ }
+
+ if (DriverImageHandle == 0) {
+ DriverImageHandleBuffer = GetHandleListByProtocolList(CfgGuidList);
+ if (DriverImageHandleBuffer == NULL) {
+ ShellStatus = SHELL_NOT_FOUND;
+ goto Done;
+ }
+ for (
+ HandleBuffer = DriverImageHandleBuffer, DriverImageHandleCount = 0
+ ; HandleBuffer != NULL && *HandleBuffer != NULL
+ ; HandleBuffer++,DriverImageHandleCount++);
+ } else {
+ DriverImageHandleCount = 1;
+ //
+ // Allocate buffer to hold the image handle so as to
+ // keep consistent with the above clause
+ //
+ DriverImageHandleBuffer = AllocatePool (sizeof (EFI_HANDLE));
+ ASSERT (DriverImageHandleBuffer);
+ DriverImageHandleBuffer[0] = DriverImageHandle;
+ }
+
+ for (OuterLoopCounter = 0; OuterLoopCounter < DriverImageHandleCount; OuterLoopCounter++) {
+ Iso639Language = FALSE;
+ Status = gBS->OpenProtocol (
+ DriverImageHandleBuffer[OuterLoopCounter],
+ &gEfiDriverConfiguration2ProtocolGuid,
+ (VOID **) &DriverConfiguration,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ Iso639Language = TRUE;
+ Status = gBS->OpenProtocol (
+ DriverImageHandleBuffer[OuterLoopCounter],
+ &gEfiDriverConfigurationProtocolGuid,
+ (VOID **) &DriverConfiguration,
+ NULL,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ }
+ if (EFI_ERROR (Status)) {
+// ShellPrintHiiEx(
+// -1,
+// -1,
+// NULL,
+// STRING_TOKEN (STR_DRVCFG_NOT_SUPPORT),
+// gShellDriver1HiiHandle,
+// ConvertHandleToHandleIndex (DriverImageHandleBuffer[OuterLoopCounter])
+// );
+ ShellStatus = SHELL_UNSUPPORTED;
+ continue;
+ }
+
+ BestLanguage = GetBestLanguage (
+ DriverConfiguration->SupportedLanguages,
+ Iso639Language,
+ Language!=NULL?Language:"",
+ DriverConfiguration->SupportedLanguages,
+ NULL
+ );
+ if (BestLanguage == NULL) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_GEN_NO_VALUE),
+ gShellDriver1HiiHandle,
+ L"drvcfg",
+ L"-l"
+ );
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ continue;
+ }
+
+ Status = ParseHandleDatabaseByRelationshipWithType (
+ DriverImageHandleBuffer[OuterLoopCounter],
+ NULL,
+ &HandleCount,
+ &HandleBuffer,
+ &HandleType
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ if (SetOptions && DeviceHandle == NULL) {
+
+ gST->ConOut->ClearScreen (gST->ConOut);
+ Status = DriverConfiguration->SetOptions (
+ DriverConfiguration,
+ NULL,
+ NULL,
+ BestLanguage,
+ &ActionRequired
+ );
+ gST->ConOut->ClearScreen (gST->ConOut);
+
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRVCFG_ALL_LANG),
+ gShellDriver1HiiHandle,
+ ConvertHandleToHandleIndex (DriverImageHandleBuffer[OuterLoopCounter]),
+ DriverConfiguration->SupportedLanguages
+ );
+ if (!EFI_ERROR (Status)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRVCFG_OPTIONS_SET),
+ gShellDriver1HiiHandle);
+ for (LoopCounter = 0; LoopCounter < HandleCount; LoopCounter++) {
+ if ((HandleType[LoopCounter] & HR_CONTROLLER_HANDLE) == HR_CONTROLLER_HANDLE) {
+ ShellCmdDriverConfigurationProcessActionRequired (
+ DriverImageHandleBuffer[OuterLoopCounter],
+ HandleBuffer[LoopCounter],
+ NULL,
+ ActionRequired
+ );
+ }
+ }
+ } else {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRVCFG_NOT_SET),
+ gShellDriver1HiiHandle,
+ Status);
+ }
+ continue;
+ }
+
+ for (LoopCounter = 0; LoopCounter < HandleCount; LoopCounter++) {
+ if ((HandleType[LoopCounter] & HR_CONTROLLER_HANDLE) != HR_CONTROLLER_HANDLE) {
+ continue;
+ }
+ if (DeviceHandle != NULL && DeviceHandle != HandleBuffer[LoopCounter]) {
+ continue;
+ }
+ if (ChildHandle == NULL) {
+ HandleIndex1 = ConvertHandleToHandleIndex (DriverImageHandleBuffer[OuterLoopCounter]);
+ HandleIndex2 = ConvertHandleToHandleIndex (HandleBuffer[LoopCounter]);
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRVCFG_CTRL_LANG),
+ gShellDriver1HiiHandle,
+ HandleIndex1,
+ HandleIndex2,
+ DriverConfiguration->SupportedLanguages
+ );
+
+ if (ForceDefaults) {
+ Status = DriverConfiguration->ForceDefaults (
+ DriverConfiguration,
+ HandleBuffer[LoopCounter],
+ NULL,
+ DefaultType,
+ &ActionRequired
+ );
+
+ if (!EFI_ERROR (Status)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRVCFG_DEF_FORCED),
+ gShellDriver1HiiHandle);
+ ShellCmdDriverConfigurationProcessActionRequired (
+ DriverImageHandleBuffer[OuterLoopCounter],
+ HandleBuffer[LoopCounter],
+ NULL,
+ ActionRequired
+ );
+ } else {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRVCFG_FORCE_FAILED),
+ gShellDriver1HiiHandle,
+ Status);
+ ShellStatus = SHELL_DEVICE_ERROR;
+ }
+ } else if (ValidateOptions) {
+ Status = DriverConfiguration->OptionsValid (
+ DriverConfiguration,
+ HandleBuffer[LoopCounter],
+ NULL
+ );
+
+ if (!EFI_ERROR (Status)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRVCFG_OPTIONS_VALID),
+ gShellDriver1HiiHandle);
+ } else {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRVCFG_OPTIONS_INV),
+ gShellDriver1HiiHandle,
+ Status);
+ ShellStatus = SHELL_DEVICE_ERROR;
+ }
+ } else if (SetOptions) {
+ gST->ConOut->ClearScreen (gST->ConOut);
+ Status = DriverConfiguration->SetOptions (
+ DriverConfiguration,
+ HandleBuffer[LoopCounter],
+ NULL,
+ BestLanguage,
+ &ActionRequired
+ );
+ gST->ConOut->ClearScreen (gST->ConOut);
+ HandleIndex1 = ConvertHandleToHandleIndex (DriverImageHandleBuffer[OuterLoopCounter]);
+ HandleIndex2 = ConvertHandleToHandleIndex (HandleBuffer[LoopCounter]);
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRVCFG_CTRL_LANG),
+ gShellDriver1HiiHandle,
+ HandleIndex1,
+ HandleIndex2,
+ DriverConfiguration->SupportedLanguages
+ );
+ if (!EFI_ERROR (Status)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRVCFG_OPTIONS_SET),
+ gShellDriver1HiiHandle);
+
+ ShellCmdDriverConfigurationProcessActionRequired (
+ DriverImageHandleBuffer[OuterLoopCounter],
+ HandleBuffer[LoopCounter],
+ NULL,
+ ActionRequired
+ );
+
+ } else {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRVCFG_NOT_SET),
+ gShellDriver1HiiHandle,
+ Status);
+ ShellStatus = SHELL_DEVICE_ERROR;
+ }
+ } else {
+ Print (L"\n");
+ }
+ }
+
+ if (ChildHandle == NULL && !AllChildren) {
+ continue;
+ }
+
+ Status = ParseHandleDatabaseByRelationshipWithType (
+ DriverImageHandleBuffer[OuterLoopCounter],
+ HandleBuffer[LoopCounter],
+ &ChildHandleCount,
+ &ChildHandleBuffer,
+ &ChildHandleType
+ );
+ if (EFI_ERROR (Status)) {
+ continue;
+ }
+
+ for (ChildIndex = 0; ChildIndex < ChildHandleCount; ChildIndex++) {
+
+ if ((ChildHandleType[ChildIndex] & HR_CHILD_HANDLE) != HR_CHILD_HANDLE) {
+ continue;
+ }
+
+ if (ChildHandle != NULL && ChildHandle != ChildHandleBuffer[ChildIndex]) {
+ continue;
+ }
+
+ HandleIndex1 = ConvertHandleToHandleIndex (DriverImageHandleBuffer[OuterLoopCounter]);
+ HandleIndex2 = ConvertHandleToHandleIndex (HandleBuffer[LoopCounter]);
+ HandleIndex3 = ConvertHandleToHandleIndex (ChildHandleBuffer[ChildIndex]);
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRVCFG_CHILD_LANG),
+ gShellDriver1HiiHandle,
+ HandleIndex1,
+ HandleIndex2,
+ HandleIndex3,
+ DriverConfiguration->SupportedLanguages);
+
+ if (ForceDefaults) {
+ Status = DriverConfiguration->ForceDefaults (
+ DriverConfiguration,
+ HandleBuffer[LoopCounter],
+ ChildHandleBuffer[ChildIndex],
+ DefaultType,
+ &ActionRequired
+ );
+
+ if (!EFI_ERROR (Status)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRVCFG_DEF_FORCED),
+ gShellDriver1HiiHandle);
+
+ ShellCmdDriverConfigurationProcessActionRequired (
+ DriverImageHandleBuffer[OuterLoopCounter],
+ HandleBuffer[LoopCounter],
+ ChildHandleBuffer[ChildIndex],
+ ActionRequired
+ );
+
+ } else {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRVCFG_FORCE_FAILED),
+ gShellDriver1HiiHandle,
+ Status);
+ ShellStatus = SHELL_DEVICE_ERROR;
+ }
+ } else if (ValidateOptions) {
+ Status = DriverConfiguration->OptionsValid (
+ DriverConfiguration,
+ HandleBuffer[LoopCounter],
+ ChildHandleBuffer[ChildIndex]
+ );
+
+ if (!EFI_ERROR (Status)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRVCFG_OPTIONS_VALID),
+ gShellDriver1HiiHandle);
+ } else {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRVCFG_OPTIONS_INV),
+ gShellDriver1HiiHandle,
+ Status);
+ ShellStatus = SHELL_DEVICE_ERROR;
+ }
+ } else if (SetOptions) {
+ gST->ConOut->ClearScreen (gST->ConOut);
+ Status = DriverConfiguration->SetOptions (
+ DriverConfiguration,
+ HandleBuffer[LoopCounter],
+ ChildHandleBuffer[ChildIndex],
+ BestLanguage,
+ &ActionRequired
+ );
+ gST->ConOut->ClearScreen (gST->ConOut);
+ HandleIndex1 = ConvertHandleToHandleIndex (DriverImageHandleBuffer[OuterLoopCounter]);
+ HandleIndex2 = ConvertHandleToHandleIndex (HandleBuffer[LoopCounter]);
+ HandleIndex3 = ConvertHandleToHandleIndex (ChildHandleBuffer[ChildIndex]);
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRVCFG_CHILD_LANG),
+ gShellDriver1HiiHandle,
+ HandleIndex1,
+ HandleIndex2,
+ HandleIndex3,
+ DriverConfiguration->SupportedLanguages
+ );
+ if (!EFI_ERROR (Status)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRVCFG_OPTIONS_SET),
+ gShellDriver1HiiHandle);
+
+ ShellCmdDriverConfigurationProcessActionRequired (
+ DriverImageHandleBuffer[OuterLoopCounter],
+ HandleBuffer[LoopCounter],
+ ChildHandleBuffer[ChildIndex],
+ ActionRequired
+ );
+
+ } else {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRVCFG_NOT_SET),
+ gShellDriver1HiiHandle,
+ Status);
+ ShellStatus = SHELL_DEVICE_ERROR;
+ }
+ } else {
+ Print (L"\n");
+ }
+ }
+
+ FreePool (ChildHandleBuffer);
+ FreePool (ChildHandleType);
+ }
+
+ FreePool (BestLanguage);
+ FreePool (HandleBuffer);
+ FreePool (HandleType);
+ }
+
+ if (DriverImageHandle != NULL && DriverImageHandleCount != 0) {
+ FreePool (DriverImageHandleBuffer);
+ }
+
+Done:
+ return ShellStatus;
+}
+
+/**
+ Function to print out configuration information on all configurable handles.
+
+ @param[in] ChildrenToo TRUE to tewst for children.
+ @param[in] Language ASCII string for language code.
+ @param[in] UseHii TRUE to check for Hii and DPC, FALSE for DCP only.
+
+ @retval SHELL_SUCCESS The operation was successful.
+**/
+SHELL_STATUS
+EFIAPI
+PrintConfigInfoOnAll(
+ IN CONST BOOLEAN ChildrenToo,
+ IN CONST CHAR8 *Language,
+ IN CONST BOOLEAN UseHii
+ )
+{
+ EFI_HANDLE *HandleList;
+ EFI_HANDLE *CurrentHandle;
+ BOOLEAN Found;
+ UINTN Index2;
+
+
+ Found = FALSE;
+ HandleList = NULL;
+ CurrentHandle = NULL;
+
+ if (UseHii) {
+ //
+ // HII method
+ //
+ HandleList = GetHandleListByProtocol(&gEfiHiiConfigAccessProtocolGuid);
+ for (CurrentHandle = HandleList ; CurrentHandle != NULL && *CurrentHandle != NULL; CurrentHandle++){
+ Found = TRUE;
+ Index2 = *CurrentHandle == NULL ? 0 : ConvertHandleToHandleIndex(*CurrentHandle);
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRVCFG_LINE_HII),
+ gShellDriver1HiiHandle,
+ Index2
+ );
+ }
+ SHELL_FREE_NON_NULL(HandleList);
+ }
+
+ if (PreHiiDrvCfg (
+ Language,
+ FALSE,
+ 0,
+ ChildrenToo,
+ FALSE,
+ FALSE,
+ 0,
+ 0,
+ 0) == SHELL_SUCCESS) {
+ Found = TRUE;
+ }
+
+ if (!Found) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DRVCFG_NONE_FOUND), gShellDriver1HiiHandle);
+ return (SHELL_SUCCESS);
+ }
+
+ return (SHELL_SUCCESS);
+}
+
+STATIC CONST SHELL_PARAM_ITEM ParamListHii[] = {
+ {L"-s", TypeFlag},
+ {L"-l", TypeValue},
+ {L"-f", TypeValue},
+ {L"-o", TypeValue},
+ {L"-i", TypeValue},
+ {NULL, TypeMax}
+ };
+STATIC CONST SHELL_PARAM_ITEM ParamListPreHii[] = {
+ {L"-c", TypeFlag},
+ {L"-s", TypeFlag},
+ {L"-v", TypeFlag},
+ {L"-l", TypeValue},
+ {L"-f", TypeValue},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'drvcfg' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDrvCfg (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ CHAR8 *Language;
+ CONST CHAR16 *Lang;
+ CONST CHAR16 *HandleIndex1;
+ CONST CHAR16 *HandleIndex2;
+ CONST CHAR16 *HandleIndex3;
+ CONST CHAR16 *ForceTypeString;
+ BOOLEAN Force;
+ BOOLEAN Set;
+ BOOLEAN Validate;
+ BOOLEAN InFromFile;
+ BOOLEAN OutToFile;
+ BOOLEAN AllChildren;
+ BOOLEAN UseHii;
+ UINT32 ForceType;
+ UINT64 Intermediate;
+ EFI_HANDLE Handle1;
+ EFI_HANDLE Handle2;
+ EFI_HANDLE Handle3;
+ CONST CHAR16 *FileName;
+
+ ShellStatus = SHELL_SUCCESS;
+ Status = EFI_SUCCESS;
+ Language = NULL;
+ UseHii = TRUE;
+ ProblemParam = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamListHii, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status) || ShellCommandLineGetCount(Package) > 2) {
+ UseHii = FALSE;
+ if (Package != NULL) {
+ ShellCommandLineFreeVarList (Package);
+ }
+ SHELL_FREE_NON_NULL(ProblemParam);
+ Status = ShellCommandLineParse (ParamListPreHii, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"drvcfg", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ } else {
+ ASSERT(FALSE);
+ }
+ }
+ }
+ if (ShellStatus == SHELL_SUCCESS) {
+ Lang = ShellCommandLineGetValue(Package, L"-l");
+ if (Lang != NULL) {
+ Language = AllocateZeroPool(StrSize(Lang));
+ AsciiSPrint(Language, StrSize(Lang), "%S", Lang);
+ } else if (ShellCommandLineGetFlag(Package, L"-l")){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"drvcfg", L"-l");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ Set = ShellCommandLineGetFlag (Package, L"-s");
+ Validate = ShellCommandLineGetFlag (Package, L"-v");
+ InFromFile = ShellCommandLineGetFlag (Package, L"-i");
+ OutToFile = ShellCommandLineGetFlag (Package, L"-o");
+ AllChildren = ShellCommandLineGetFlag (Package, L"-c");
+ Force = ShellCommandLineGetFlag (Package, L"-f");
+ ForceTypeString = ShellCommandLineGetValue(Package, L"-f");
+
+ if (OutToFile) {
+ FileName = ShellCommandLineGetValue(Package, L"-o");
+ } else if (InFromFile) {
+ FileName = ShellCommandLineGetValue(Package, L"-i");
+ } else {
+ FileName = NULL;
+ }
+
+ if (InFromFile && EFI_ERROR(ShellFileExists(FileName))) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FIND_FAIL), gShellDriver1HiiHandle, L"drvcfg", FileName);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ if (OutToFile && !EFI_ERROR(ShellFileExists(FileName))) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_EXIST), gShellDriver1HiiHandle, L"drvcfg", FileName);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ if (Force && ForceTypeString == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"drvcfg", L"-f");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ if (Force) {
+ Status = ShellConvertStringToUint64(ForceTypeString, &Intermediate, FALSE, FALSE);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellDriver1HiiHandle, L"drvcfg", ForceTypeString, L"-f");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ ForceType = (UINT32)Intermediate;
+ } else {
+ ForceType = 0;
+ }
+ HandleIndex1 = ShellCommandLineGetRawValue(Package, 1);
+ Handle1 = NULL;
+ if (HandleIndex1 != NULL && !EFI_ERROR(ShellConvertStringToUint64(HandleIndex1, &Intermediate, TRUE, FALSE))) {
+ Handle1 = ConvertHandleIndexToHandle((UINTN)Intermediate);
+ if (Handle1 == NULL || (UINT64)(UINTN)Intermediate != Intermediate) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"drvcfg", HandleIndex1);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ }
+ HandleIndex2 = ShellCommandLineGetRawValue(Package, 2);
+ Handle2 = NULL;
+ if (HandleIndex2 != NULL && !EFI_ERROR(ShellConvertStringToUint64(HandleIndex2, &Intermediate, TRUE, FALSE))) {
+ Handle2 = ConvertHandleIndexToHandle((UINTN)Intermediate);
+ if (Handle2 == NULL || (UINT64)(UINTN)Intermediate != Intermediate) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"drvcfg", HandleIndex2);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ }
+ HandleIndex3 = ShellCommandLineGetRawValue(Package, 3);
+ Handle3 = NULL;
+ if (HandleIndex3 != NULL && !EFI_ERROR(ShellConvertStringToUint64(HandleIndex3, &Intermediate, TRUE, FALSE))) {
+ Handle3 = ConvertHandleIndexToHandle((UINTN)Intermediate);
+ if (Handle3 == NULL || (UINT64)(UINTN)Intermediate != Intermediate) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"drvcfg", HandleIndex3);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ }
+
+ if ((InFromFile || OutToFile) && (FileName == NULL)) {
+ if (FileName == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"drvcfg", InFromFile?L"-i":L"-o");
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_HANDLE_REQ), gShellDriver1HiiHandle, L"drvcfg");
+ }
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ if (!UseHii && (InFromFile || OutToFile)) {
+ if (InFromFile) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDriver1HiiHandle, L"drvcfg", L"-i");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ if (OutToFile) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellDriver1HiiHandle, L"drvcfg", L"-o");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ }
+ if (Validate && Force) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDriver1HiiHandle, L"drvcfg", L"-v", L"-f");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ if (Validate && Set) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDriver1HiiHandle, L"drvcfg", L"-v", L"-s");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ if (Set && Force) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDriver1HiiHandle, L"drvcfg", L"-s", L"-f");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+ if (OutToFile && InFromFile) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellDriver1HiiHandle, L"drvcfg", L"-i", L"-o");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ //
+ // We do HII first.
+ //
+ if (UseHii) {
+ if (Handle1 != NULL && EFI_ERROR(gBS->OpenProtocol(Handle1, &gEfiHiiConfigAccessProtocolGuid, NULL, gImageHandle, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {
+ //
+ // no HII on this handle.
+ //
+ ShellStatus = SHELL_UNSUPPORTED;
+ } else if (Validate) {
+ } else if (Force) {
+ } else if (Set) {
+ } else if (InFromFile) {
+ ShellStatus = ConfigFromFile(Handle1, FileName);
+ if (Handle1 != NULL && ShellStatus == SHELL_SUCCESS) {
+ goto Done;
+ }
+ } else if (OutToFile) {
+ ShellStatus = ConfigToFile(Handle1, FileName);
+ if (Handle1 != NULL && ShellStatus == SHELL_SUCCESS) {
+ goto Done;
+ }
+ } else if (HandleIndex1 == NULL) {
+ //
+ // display all that are configurable
+ //
+ ShellStatus = PrintConfigInfoOnAll(AllChildren, Language, UseHii);
+ goto Done;
+ } else {
+ if (!EFI_ERROR(gBS->OpenProtocol(Handle1, &gEfiHiiConfigAccessProtocolGuid, NULL, gImageHandle, NULL, EFI_OPEN_PROTOCOL_TEST_PROTOCOL))) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRVCFG_LINE_HII),
+ gShellDriver1HiiHandle,
+ ConvertHandleToHandleIndex(Handle1)
+ );
+ goto Done;
+ }
+ }
+ }
+
+ //
+ // We allways need to do this one since it does both by default.
+ //
+ if (!InFromFile && !OutToFile) {
+ ShellStatus = PreHiiDrvCfg (
+ Language,
+ Force,
+ ForceType,
+ AllChildren,
+ Validate,
+ Set,
+ Handle1,
+ Handle2,
+ Handle3);
+ }
+
+ if (ShellStatus == SHELL_UNSUPPORTED) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRVCFG_NOT_SUPPORT),
+ gShellDriver1HiiHandle,
+ ConvertHandleToHandleIndex(Handle1)
+ );
+ }
+ }
+
+Done:
+ ShellCommandLineFreeVarList (Package);
+ SHELL_FREE_NON_NULL(Language);
+ return (ShellStatus);
+}
diff --git a/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/DrvDiag.c b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/DrvDiag.c
new file mode 100644
index 0000000000..04f6a58c3d
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/DrvDiag.c
@@ -0,0 +1,464 @@
+/** @file
+ Main file for DrvDiag shell Driver1 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDriver1CommandsLib.h"
+
+STATIC CONST EFI_GUID *DiagGuidList[] = {&gEfiDriverDiagnosticsProtocolGuid, &gEfiDriverDiagnostics2ProtocolGuid, NULL};
+//
+// We need 1 more item on the list...
+//
+typedef enum {
+ TestModeStandard = EfiDriverDiagnosticTypeStandard,
+ TestModeExtended = EfiDriverDiagnosticTypeExtended,
+ TestModeManufacturing = EfiDriverDiagnosticTypeManufacturing,
+ TestModeList,
+ TestModeMax
+} DRV_DIAG_TEST_MODE;
+
+/**
+ Do the diagnostics call for some set of handles.
+
+ @param[in] Mode The type of diagnostic test to run.
+ @param[in] Lang The language code to use.
+ @param[in] AllChilds Should the test be on all children.
+ @param[in] DriverHandle The driver handle to test with.
+ @param[in] ControllerHandle The specific controller handle to test.
+ @param[in] ChildHandle The specific child handle to test.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_INVALID_PARAMETER A parameter had an invalid value.
+ @retval EFI_NOT_FOUND No diagnostic handle could be found.
+**/
+EFI_STATUS
+EFIAPI
+DoDiagnostics (
+ IN CONST DRV_DIAG_TEST_MODE Mode,
+ IN CONST CHAR8 *Lang,
+ IN CONST BOOLEAN AllChilds,
+ IN CONST EFI_HANDLE DriverHandle,
+ IN CONST EFI_HANDLE ControllerHandle,
+ IN CONST EFI_HANDLE ChildHandle
+ )
+{
+ EFI_DRIVER_DIAGNOSTICS_PROTOCOL *DriverDiagnostics;
+ EFI_DRIVER_DIAGNOSTICS2_PROTOCOL *DriverDiagnostics2;
+ EFI_HANDLE *DriverHandleList;
+ EFI_HANDLE *ControllerHandleList;
+ EFI_HANDLE *ChildHandleList;
+ EFI_HANDLE *Walker;
+ UINTN DriverHandleListCount;
+ UINTN ControllerHandleListCount;
+ UINTN ChildHandleListCount;
+ UINTN DriverHandleListLoop;
+ UINTN ControllerHandleListLoop;
+ UINTN ChildHandleListLoop;
+ EFI_STATUS Status;
+ EFI_STATUS Status2;
+ EFI_GUID *ErrorType;
+ UINTN OutBufferSize;
+ CHAR16 *OutBuffer;
+ UINTN HandleIndex1;
+ UINTN HandleIndex2;
+ CHAR8 *Language;
+ BOOLEAN Found;
+
+ if ((ChildHandle != NULL && AllChilds) || (Mode >= TestModeMax)){
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ DriverDiagnostics = NULL;
+ DriverDiagnostics2 = NULL;
+ Status = EFI_SUCCESS;
+ Status2 = EFI_SUCCESS;
+ DriverHandleList = NULL;
+ ControllerHandleList = NULL;
+ ChildHandleList = NULL;
+ Language = NULL;
+ OutBuffer = NULL;
+ ErrorType = NULL;
+ DriverHandleListCount = 0;
+ ControllerHandleListCount = 0;
+ ChildHandleListCount = 0;
+
+ if (DriverHandle != NULL) {
+ DriverHandleList = AllocateZeroPool(2*sizeof(EFI_HANDLE));
+ if (DriverHandleList == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ DriverHandleList[0] = DriverHandle;
+ DriverHandleListCount = 1;
+ } else {
+ DriverHandleList = GetHandleListByProtocolList(DiagGuidList);
+ if (DriverHandleList == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROTOCOL_NF), gShellDriver1HiiHandle, L"drvdiag", L"gEfiDriverDiagnosticsProtocolGuid", &gEfiDriverDiagnosticsProtocolGuid);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROTOCOL_NF), gShellDriver1HiiHandle, L"drvdiag", L"gEfiDriverDiagnostics2ProtocolGuid", &gEfiDriverDiagnostics2ProtocolGuid);
+ return (EFI_NOT_FOUND);
+ }
+ for (Walker = DriverHandleList ; Walker != NULL && *Walker != NULL ; DriverHandleListCount++, Walker++);
+ }
+
+ if (ControllerHandle != NULL) {
+ ControllerHandleList = AllocateZeroPool(2*sizeof(EFI_HANDLE));
+ if (ControllerHandleList == NULL) {
+ SHELL_FREE_NON_NULL (DriverHandleList);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ControllerHandleList[0] = ControllerHandle;
+ ControllerHandleListCount = 1;
+ } else {
+ ControllerHandleList = NULL;
+ }
+
+ if (ChildHandle != NULL) {
+ ChildHandleList = AllocateZeroPool(2*sizeof(EFI_HANDLE));
+ if (ChildHandleList == NULL) {
+ SHELL_FREE_NON_NULL (ControllerHandleList);
+ SHELL_FREE_NON_NULL (DriverHandleList);
+ return EFI_OUT_OF_RESOURCES;
+ }
+ ChildHandleList[0] = ChildHandle;
+ ChildHandleListCount = 1;
+ } else if (AllChilds) {
+ ChildHandleList = NULL;
+ //
+ // This gets handled in the loop below.
+ //
+ } else {
+ ChildHandleList = NULL;
+ }
+
+ if (Mode == TestModeList) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DRVDIAG_HEADER), gShellDriver1HiiHandle);
+ }
+ for (DriverHandleListLoop = 0
+ ; DriverHandleListLoop < DriverHandleListCount
+ ; DriverHandleListLoop++
+ ){
+ if (Mode == TestModeList) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DRVDIAG_DRIVER_HEADER), gShellDriver1HiiHandle, ConvertHandleToHandleIndex(DriverHandleList[DriverHandleListLoop]));
+ }
+ if (ControllerHandle == NULL) {
+ PARSE_HANDLE_DATABASE_DEVICES(DriverHandleList[DriverHandleListLoop], &ControllerHandleListCount, &ControllerHandleList);
+ }
+ if (ControllerHandleListCount == 0) {
+ if (Mode == TestModeList) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DRVDIAG_DRIVER_NO_HANDLES), gShellDriver1HiiHandle);
+ }
+ } else {
+ if (Mode == TestModeList) {
+ ShellPrintEx(-1, -1, L"\r\n");
+ }
+ for (ControllerHandleListLoop = 0
+ ; ControllerHandleListLoop < ControllerHandleListCount
+ ; ControllerHandleListLoop++
+ ){
+ if (AllChilds) {
+ ASSERT(ChildHandleList == NULL);
+ PARSE_HANDLE_DATABASE_MANAGED_CHILDREN(
+ DriverHandleList[DriverHandleListLoop],
+ ControllerHandleList[ControllerHandleListLoop],
+ &ChildHandleListCount,
+ &ChildHandleList);
+ }
+ for (ChildHandleListLoop = 0
+ ; (ChildHandleListLoop < ChildHandleListCount || ChildHandleList == NULL)
+ ; ChildHandleListLoop++
+ ){
+ Found = FALSE;
+ if (Mode != TestModeList) {
+ if (Lang == NULL || Lang[2] == '-') {
+ //
+ // Get the protocol pointer and call the function
+ //
+ Status = gBS->OpenProtocol(
+ DriverHandleList[DriverHandleListLoop],
+ &gEfiDriverDiagnostics2ProtocolGuid,
+ (VOID**)&DriverDiagnostics2,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (!EFI_ERROR(Status) && (DriverDiagnostics2 != NULL)) {
+ Language = GetBestLanguageForDriver(DriverDiagnostics2->SupportedLanguages, Lang, FALSE);
+ Found = TRUE;
+ Status = DriverDiagnostics2->RunDiagnostics(
+ DriverDiagnostics2,
+ ControllerHandleList[ControllerHandleListLoop],
+ ChildHandleList == NULL?NULL:ChildHandleList[ChildHandleListLoop],
+ (EFI_DRIVER_DIAGNOSTIC_TYPE)Mode,
+ Language,
+ &ErrorType,
+ &OutBufferSize,
+ &OutBuffer);
+ FreePool(Language);
+ }
+ }
+ if (!Found && (Lang == NULL||(Lang!=NULL&&(Lang[2]!='-')))){
+ Status = gBS->OpenProtocol(
+ DriverHandleList[DriverHandleListLoop],
+ &gEfiDriverDiagnosticsProtocolGuid,
+ (VOID**)&DriverDiagnostics,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (!EFI_ERROR(Status)) {
+ Language = GetBestLanguageForDriver(DriverDiagnostics->SupportedLanguages, Lang, FALSE);
+ Status = DriverDiagnostics->RunDiagnostics(
+ DriverDiagnostics,
+ ControllerHandleList[ControllerHandleListLoop],
+ ChildHandleList == NULL?NULL:ChildHandleList[ChildHandleListLoop],
+ (EFI_DRIVER_DIAGNOSTIC_TYPE)Mode,
+ Language,
+ &ErrorType,
+ &OutBufferSize,
+ &OutBuffer);
+ FreePool(Language);
+ }
+ }
+ if (EFI_ERROR(Status)) {
+ Status2 = Status;
+ }
+ HandleIndex1 = ConvertHandleToHandleIndex(DriverHandleList[DriverHandleListLoop]);
+ HandleIndex2 = ConvertHandleToHandleIndex(ControllerHandleList[ControllerHandleListLoop]);
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_3P_RESULT),
+ gShellDriver1HiiHandle,
+ L"DrvDiag",
+ HandleIndex1,
+ HandleIndex2,
+ ChildHandleList == NULL?0:ConvertHandleToHandleIndex(ChildHandleList[ChildHandleListLoop]),
+ Status);
+ if (OutBuffer!=NULL) {
+ FreePool(OutBuffer);
+ OutBuffer = NULL;
+ }
+ if (ErrorType!=NULL) {
+ FreePool(ErrorType);
+ ErrorType = NULL;
+ }
+ } else {
+ HandleIndex1 = ConvertHandleToHandleIndex(DriverHandleList[DriverHandleListLoop]);
+ HandleIndex2 = ConvertHandleToHandleIndex(ControllerHandleList[ControllerHandleListLoop]);
+ //
+ // Print out the information that this set can be tested
+ //
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_DRV_DIAG_ITEM_LINE),
+ gShellDriver1HiiHandle,
+ HandleIndex1,
+ HandleIndex2,
+ ChildHandleList == NULL?0:ConvertHandleToHandleIndex(ChildHandleList[ChildHandleListLoop])
+ );
+ }
+
+ //
+ // If we are doing a single pass with NULL child jump out after a single loop
+ //
+ if (ChildHandleList == NULL) {
+ break;
+ }
+ }
+ if (AllChilds) {
+ SHELL_FREE_NON_NULL(ChildHandleList);
+ ChildHandleList = NULL;
+ ChildHandleListCount = 0;
+ }
+ }
+ if (ControllerHandle == NULL) {
+ SHELL_FREE_NON_NULL(ControllerHandleList);
+ ControllerHandleList = NULL;
+ ControllerHandleListCount = 0;
+ }
+ }
+ }
+
+ if (DriverHandleList != NULL) {
+ FreePool(DriverHandleList);
+ }
+ if (ControllerHandleList != NULL) {
+ FreePool(ControllerHandleList);
+ }
+ if (ChildHandleList != NULL) {
+ FreePool(ChildHandleList);
+ }
+ return (Status2);
+}
+
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-c", TypeFlag},
+ {L"-s", TypeFlag},
+ {L"-e", TypeFlag},
+ {L"-m", TypeFlag},
+ {L"-l", TypeValue},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'drvdiag' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDrvDiag (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ DRV_DIAG_TEST_MODE Mode;
+ CHAR8 *Language;
+ CONST CHAR16 *DriverHandleStr;
+ CONST CHAR16 *ControllerHandleStr;
+ CONST CHAR16 *ChildHandleStr;
+ CONST CHAR16 *Lang;
+ EFI_HANDLE Handle1;
+ EFI_HANDLE Handle2;
+ EFI_HANDLE Handle3;
+ UINT64 Intermediate;
+
+ ShellStatus = SHELL_SUCCESS;
+ Mode = TestModeMax;
+ Language = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"drvdiag", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // if more than 3 'value' parameters (plus the name one) or we have any 2 mode flags
+ //
+ if ((ShellCommandLineGetCount(Package) > 4)
+ ||(ShellCommandLineGetFlag(Package, L"-s") && ShellCommandLineGetFlag(Package, L"-e"))
+ ||(ShellCommandLineGetFlag(Package, L"-s") && ShellCommandLineGetFlag(Package, L"-m"))
+ ||(ShellCommandLineGetFlag(Package, L"-e") && ShellCommandLineGetFlag(Package, L"-m"))
+ ){
+ //
+ // error for too many parameters
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"drvdiag");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if ((ShellCommandLineGetFlag(Package, L"-s"))
+ || (ShellCommandLineGetFlag(Package, L"-e"))
+ || (ShellCommandLineGetFlag(Package, L"-m"))
+ ){
+ //
+ // Run the appropriate test
+ //
+ if (ShellCommandLineGetFlag(Package, L"-s")) {
+ Mode = TestModeStandard;
+ } else if (ShellCommandLineGetFlag(Package, L"-e")) {
+ Mode = TestModeExtended;
+ } else if (ShellCommandLineGetFlag(Package, L"-m")) {
+ Mode = TestModeManufacturing;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // Do a listing of what's available to test
+ //
+ Mode = TestModeList;
+ }
+
+ Lang = ShellCommandLineGetValue(Package, L"-l");
+ if (ShellCommandLineGetFlag(Package, L"-l") && Lang == NULL) {
+ ASSERT(Language == NULL);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellDriver1HiiHandle, L"drvdiag", L"-l");
+ ShellCommandLineFreeVarList (Package);
+ return (SHELL_INVALID_PARAMETER);
+ } else if (Lang != NULL) {
+ Language = AllocateZeroPool(StrSize(Lang));
+ AsciiSPrint(Language, StrSize(Lang), "%S", Lang);
+ }
+
+ DriverHandleStr = ShellCommandLineGetRawValue(Package, 1);
+ ControllerHandleStr = ShellCommandLineGetRawValue(Package, 2);
+ ChildHandleStr = ShellCommandLineGetRawValue(Package, 3);
+
+ if (DriverHandleStr == NULL) {
+ Handle1 = NULL;
+ } else {
+ ShellConvertStringToUint64(DriverHandleStr, &Intermediate, TRUE, FALSE);
+ Handle1 = ConvertHandleIndexToHandle((UINTN)Intermediate);
+ }
+ if (ControllerHandleStr == NULL) {
+ Handle2 = NULL;
+ } else {
+ ShellConvertStringToUint64(ControllerHandleStr, &Intermediate, TRUE, FALSE);
+ Handle2 = ConvertHandleIndexToHandle((UINTN)Intermediate);
+ }
+ if (ChildHandleStr == NULL) {
+ Handle3 = NULL;
+ } else {
+ ShellConvertStringToUint64(ChildHandleStr, &Intermediate, TRUE, FALSE);
+ Handle3 = ConvertHandleIndexToHandle((UINTN)Intermediate);
+ }
+
+ Status = DoDiagnostics (
+ Mode,
+ Language,
+ ShellCommandLineGetFlag(Package, L"-c"),
+ Handle1,
+ Handle2,
+ Handle3
+ );
+
+ SHELL_FREE_NON_NULL(Language);
+ ShellCommandLineFreeVarList (Package);
+
+ }
+ if (ShellStatus == SHELL_SUCCESS) {
+ if (Status == EFI_SECURITY_VIOLATION) {
+ ShellStatus = SHELL_SECURITY_VIOLATION;
+ } else if (Status == EFI_INVALID_PARAMETER) {
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (Status == EFI_NOT_FOUND) {
+ ShellStatus = SHELL_NOT_FOUND;
+ } else if (EFI_ERROR(Status)) {
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ }
+
+ return (ShellStatus);
+}
diff --git a/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/OpenInfo.c b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/OpenInfo.c
new file mode 100644
index 0000000000..e11873aa10
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/OpenInfo.c
@@ -0,0 +1,217 @@
+/** @file
+ Main file for OpenInfo shell Driver1 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDriver1CommandsLib.h"
+
+STATIC CONST CHAR16 StringHandProt[] = L"HandProt ";
+STATIC CONST CHAR16 StringGetProt[] = L"GetProt ";
+STATIC CONST CHAR16 StringTestProt[] = L"TestProt ";
+STATIC CONST CHAR16 StringChild[] = L"Child ";
+STATIC CONST CHAR16 StringDriver[] = L"Driver ";
+STATIC CONST CHAR16 StringExclusive[] = L"Exclusive";
+STATIC CONST CHAR16 StringDriverEx[] = L"DriverEx ";
+STATIC CONST CHAR16 StringUnknown[] = L"Unknown ";
+
+/**
+ Open the database and print out all the info about TheHandle.
+
+ @param[in] TheHandle The handle to print info on.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_INVALID_PARAMETER TheHandle was NULL.
+**/
+EFI_STATUS
+EFIAPI
+TraverseHandleDatabase (
+ IN CONST EFI_HANDLE TheHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_GUID **ProtocolGuidArray;
+ UINTN ArrayCount;
+ UINTN ProtocolIndex;
+ EFI_OPEN_PROTOCOL_INFORMATION_ENTRY *OpenInfo;
+ UINTN OpenInfoCount;
+ UINTN OpenInfoIndex;
+ CONST CHAR16 *OpenTypeString;
+ CHAR16 *TempString;
+ UINTN HandleIndex;
+ CONST CHAR16 *Name;
+ UINTN ControllerIndex;
+
+ if (TheHandle == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ //
+ // Retrieve the list of all the protocols on the handle
+ //
+ Status = gBS->ProtocolsPerHandle (
+ TheHandle,
+ &ProtocolGuidArray,
+ &ArrayCount
+ );
+ ASSERT_EFI_ERROR(Status);
+ if (!EFI_ERROR (Status)) {
+
+ for (ProtocolIndex = 0; ProtocolIndex < ArrayCount; ProtocolIndex++) {
+ //
+ // print out the human readable name for this one.
+ //
+ TempString = GetStringNameFromGuid(ProtocolGuidArray[ProtocolIndex], NULL);
+ if (TempString == NULL) {
+ continue;
+ }
+ ShellPrintEx(-1, -1, L"%H%s%N\r\n", TempString);
+ FreePool(TempString);
+
+ //
+ // Retrieve the list of agents that have opened each protocol
+ //
+ Status = gBS->OpenProtocolInformation (
+ TheHandle,
+ ProtocolGuidArray[ProtocolIndex],
+ &OpenInfo,
+ &OpenInfoCount
+ );
+ ASSERT_EFI_ERROR(Status);
+ if (!EFI_ERROR (Status)) {
+ for (OpenInfoIndex = 0; OpenInfoIndex < OpenInfoCount; OpenInfoIndex++) {
+ switch (OpenInfo[OpenInfoIndex].Attributes) {
+ case EFI_OPEN_PROTOCOL_BY_HANDLE_PROTOCOL: OpenTypeString = StringHandProt; break;
+ case EFI_OPEN_PROTOCOL_GET_PROTOCOL: OpenTypeString = StringGetProt; break;
+ case EFI_OPEN_PROTOCOL_TEST_PROTOCOL: OpenTypeString = StringTestProt; break;
+ case EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER: OpenTypeString = StringChild; break;
+ case EFI_OPEN_PROTOCOL_BY_DRIVER: OpenTypeString = StringDriver; break;
+ case EFI_OPEN_PROTOCOL_EXCLUSIVE: OpenTypeString = StringExclusive; break;
+ case EFI_OPEN_PROTOCOL_BY_DRIVER|EFI_OPEN_PROTOCOL_EXCLUSIVE:
+ OpenTypeString = StringDriverEx; break;
+ default: OpenTypeString = StringUnknown; break;
+ }
+ HandleIndex = ConvertHandleToHandleIndex(OpenInfo[OpenInfoIndex].AgentHandle);
+ Name = GetStringNameFromHandle(OpenInfo[OpenInfoIndex].AgentHandle, NULL);
+ ControllerIndex = ConvertHandleToHandleIndex(OpenInfo[OpenInfoIndex].ControllerHandle);
+ if (ControllerIndex != 0) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_OPENINFO_LINE),
+ gShellDriver1HiiHandle,
+ HandleIndex,
+ ControllerIndex,
+ OpenInfo[OpenInfoIndex].OpenCount,
+ OpenTypeString,
+ Name
+ );
+ } else {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_OPENINFO_MIN_LINE),
+ gShellDriver1HiiHandle,
+ HandleIndex,
+ OpenInfo[OpenInfoIndex].OpenCount,
+ OpenTypeString,
+ Name
+ );
+ }
+ }
+ FreePool (OpenInfo);
+ }
+ }
+ FreePool (ProtocolGuidArray);
+ }
+
+ return Status;
+}
+
+/**
+ Function for 'openinfo' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunOpenInfo (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ EFI_HANDLE TheHandle;
+ CONST CHAR16 *Param1;
+ UINT64 Intermediate;
+
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"openinfo", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetCount(Package) > 2){
+ //
+ // error for too many parameters
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"openinfo");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetCount(Package) == 0) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDriver1HiiHandle, L"openinfo");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Param1 = ShellCommandLineGetRawValue(Package, 1);
+ Status = ShellConvertStringToUint64(Param1, &Intermediate, TRUE, FALSE);
+ if (EFI_ERROR(Status) || Param1 == NULL || ConvertHandleIndexToHandle((UINTN)Intermediate) == NULL){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"openinfo", Param1);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ TheHandle = ConvertHandleIndexToHandle((UINTN)Intermediate);
+ ASSERT(TheHandle != NULL);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_OPENINFO_HEADER_LINE), gShellDriver1HiiHandle, (UINTN)Intermediate, TheHandle);
+
+ Status = TraverseHandleDatabase (TheHandle);
+ if (!EFI_ERROR(Status)) {
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"openinfo", Param1);
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ }
+ }
+ }
+ return (ShellStatus);
+}
diff --git a/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Reconnect.c b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Reconnect.c
new file mode 100644
index 0000000000..d2ae8e8271
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Reconnect.c
@@ -0,0 +1,99 @@
+/** @file
+ Main file for Reconnect shell Driver1 function.
+
+ Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDriver1CommandsLib.h"
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-r", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Connect all the possible console devices.
+
+**/
+VOID
+ConnectAllConsoles (
+ VOID
+ )
+{
+ ShellConnectFromDevPaths(L"ConInDev");
+ ShellConnectFromDevPaths(L"ConOutDev");
+ ShellConnectFromDevPaths(L"ErrOutDev");
+
+ ShellConnectFromDevPaths(L"ErrOut");
+ ShellConnectFromDevPaths(L"ConIn");
+ ShellConnectFromDevPaths(L"ConOut");
+}
+
+
+/**
+ Function for 'reconnect' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunReconnect (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ SHELL_STATUS ShellStatus;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ EFI_STATUS Status;
+
+ gInReconnect = TRUE;
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle, L"reconnect", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ ShellStatus = ShellCommandRunDisconnect(ImageHandle, SystemTable);
+ if (ShellStatus == SHELL_SUCCESS) {
+ if (ShellCommandLineGetFlag(Package, L"-r")) {
+ ConnectAllConsoles();
+ }
+ ShellStatus = ShellCommandRunConnect(ImageHandle, SystemTable);
+ }
+ }
+
+ gInReconnect = FALSE;
+
+ return (ShellStatus);
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.c b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.c
new file mode 100644
index 0000000000..95cd9a0ca8
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.c
@@ -0,0 +1,104 @@
+/** @file
+ Main file for NULL named library for level 1 shell command functions.
+
+ Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDriver1CommandsLib.h"
+
+STATIC CONST CHAR16 mFileName[] = L"Driver1Commands";
+EFI_HANDLE gShellDriver1HiiHandle = NULL;
+BOOLEAN gInReconnect = FALSE;
+
+/**
+ Function to return the name of the file containing help if HII will not be used.
+
+ @return The filename.
+**/
+CONST CHAR16*
+EFIAPI
+ShellCommandGetManFileNameDriver1 (
+ VOID
+ )
+{
+ return (mFileName);
+}
+
+/**
+ Constructor for the Shell Driver1 Commands library.
+
+ @param ImageHandle the image handle of the process
+ @param SystemTable the EFI System Table pointer
+
+ @retval EFI_SUCCESS the shell command handlers were installed sucessfully
+ @retval EFI_UNSUPPORTED the shell level required was not found.
+**/
+EFI_STATUS
+EFIAPI
+UefiShellDriver1CommandsLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ //
+ // check our bit of the profiles mask
+ //
+ if ((PcdGet8(PcdShellProfileMask) & BIT0) == 0) {
+ return (EFI_SUCCESS);
+ }
+
+ //
+ // install the HII stuff.
+ //
+ gShellDriver1HiiHandle = HiiAddPackages (&gShellDriver1HiiGuid, gImageHandle, UefiShellDriver1CommandsLibStrings, NULL);
+ if (gShellDriver1HiiHandle == NULL) {
+ return (EFI_DEVICE_ERROR);
+ }
+
+ //
+ // install our shell command handlers that are always installed
+ //
+ ShellCommandRegisterCommandName(L"connect", ShellCommandRunConnect , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE, gShellDriver1HiiHandle, STRING_TOKEN(STR_GET_HELP_CONNECT) );
+ ShellCommandRegisterCommandName(L"devices", ShellCommandRunDevices , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE, gShellDriver1HiiHandle, STRING_TOKEN(STR_GET_HELP_DEVICES) );
+ ShellCommandRegisterCommandName(L"openinfo", ShellCommandRunOpenInfo , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE, gShellDriver1HiiHandle, STRING_TOKEN(STR_GET_HELP_OPENINFO) );
+ ShellCommandRegisterCommandName(L"disconnect", ShellCommandRunDisconnect , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE, gShellDriver1HiiHandle, STRING_TOKEN(STR_GET_HELP_DISCONNECT));
+ ShellCommandRegisterCommandName(L"reconnect", ShellCommandRunReconnect , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE, gShellDriver1HiiHandle, STRING_TOKEN(STR_GET_HELP_RECONNECT) );
+ ShellCommandRegisterCommandName(L"unload", ShellCommandRunUnload , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE, gShellDriver1HiiHandle, STRING_TOKEN(STR_GET_HELP_UNLOAD) );
+ ShellCommandRegisterCommandName(L"drvdiag", ShellCommandRunDrvDiag , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE, gShellDriver1HiiHandle, STRING_TOKEN(STR_GET_HELP_DRVDIAG) );
+ ShellCommandRegisterCommandName(L"dh", ShellCommandRunDh , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE, gShellDriver1HiiHandle, STRING_TOKEN(STR_GET_HELP_DH) );
+ ShellCommandRegisterCommandName(L"drivers", ShellCommandRunDrivers , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE, gShellDriver1HiiHandle, STRING_TOKEN(STR_GET_HELP_DRIVERS) );
+ ShellCommandRegisterCommandName(L"devtree", ShellCommandRunDevTree , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE, gShellDriver1HiiHandle, STRING_TOKEN(STR_GET_HELP_DEVTREE) );
+ ShellCommandRegisterCommandName(L"drvcfg", ShellCommandRunDrvCfg , ShellCommandGetManFileNameDriver1, 0, L"Driver1", TRUE, gShellDriver1HiiHandle, STRING_TOKEN(STR_GET_HELP_DRVCFG) );
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Destructor for the library. free any resources.
+
+ @param ImageHandle The image handle of the process.
+ @param SystemTable The EFI System Table pointer.
+**/
+EFI_STATUS
+EFIAPI
+UefiShellDriver1CommandsLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ if (gShellDriver1HiiHandle != NULL) {
+ HiiRemovePackages(gShellDriver1HiiHandle);
+ }
+ return (EFI_SUCCESS);
+}
+
+
+
diff --git a/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.h b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.h
new file mode 100644
index 0000000000..c65d0ed695
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.h
@@ -0,0 +1,226 @@
+/** @file
+ Main file for NULL named library for Profile1 shell command functions.
+
+ Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _UEFI_SHELL_DRIVER1_COMMANDS_LIB_H_
+#define _UEFI_SHELL_DRIVER1_COMMANDS_LIB_H_
+
+#include <Uefi.h>
+#include <ShellBase.h>
+
+#include <Guid/GlobalVariable.h>
+#include <Guid/ConsoleInDevice.h>
+#include <Guid/ConsoleOutDevice.h>
+#include <Guid/ShellLibHiiGuid.h>
+
+#include <IndustryStandard/Pci.h>
+
+#include <Protocol/EfiShell.h>
+#include <Protocol/EfiShellParameters.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/UnicodeCollation.h>
+#include <Protocol/DriverDiagnostics2.h>
+#include <Protocol/DriverDiagnostics.h>
+#include <Protocol/PlatformDriverOverride.h>
+#include <Protocol/BusSpecificDriverOverride.h>
+#include <Protocol/PlatformToDriverConfiguration.h>
+#include <Protocol/DriverSupportedEfiVersion.h>
+#include <Protocol/DriverFamilyOverride.h>
+#include <Protocol/DriverHealth.h>
+#include <Protocol/PciIo.h>
+#include <Protocol/PciRootBridgeIo.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/ShellCommandLib.h>
+#include <Library/ShellLib.h>
+#include <Library/SortLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HiiLib.h>
+#include <Library/FileHandleLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PrintLib.h>
+#include <Library/HandleParsingLib.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/HandleParsingLib.h>
+
+
+extern EFI_HANDLE gShellDriver1HiiHandle;
+extern BOOLEAN gInReconnect;
+
+/**
+ Function for 'connect' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunConnect (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'devices' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDevices (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'openinfo' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunOpenInfo (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'devtree' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDevTree (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'dh' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDh (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'disconnect' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDisconnect (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'drivers' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDrivers (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'drvcfg' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDrvCfg (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'drvdiag' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDrvDiag (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'reconnect' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunReconnect (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'unload' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunUnload (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Do a connect from an EFI variable via it's key name.
+
+ @param[in] Key The name of the EFI Variable.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+ShellConnectFromDevPaths (
+ IN CONST CHAR16 *Key
+ );
+
+
+
+#endif
+
diff --git a/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf
new file mode 100644
index 0000000000..0682350891
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf
@@ -0,0 +1,73 @@
+## @file
+# Provides shell driver1 profile functions
+#
+# Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = UefiShellDriver1CommandsLib
+ FILE_GUID = 313D3674-3ED4-48fd-BF97-7DB35D4190D1
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER
+ CONSTRUCTOR = UefiShellDriver1CommandsLibConstructor
+ DESTRUCTOR = UefiShellDriver1CommandsLibDestructor
+
+[Sources]
+ Connect.c
+ Devices.c
+ OpenInfo.c
+ Disconnect.c
+ Reconnect.c
+ Unload.c
+ DrvDiag.c
+ Dh.c
+ Drivers.c
+ DevTree.c
+ DrvCfg.c
+ UefiShellDriver1CommandsLib.c
+ UefiShellDriver1CommandsLib.h
+ UefiShellDriver1CommandsLib.uni
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ ShellCommandLib
+ ShellLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ SortLib
+ PrintLib
+ PeCoffGetEntryPointLib
+
+[Pcd]
+ gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask ## CONSUMES
+
+[Protocols]
+ gEfiDriverHealthProtocolGuid ## UNDEFINED
+ gEfiDriverFamilyOverrideProtocolGuid ## UNDEFINED
+ gEfiHiiConfigAccessProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiHiiDatabaseProtocolGuid ## CONSUMES
+
+[Guids]
+ gEfiGlobalVariableGuid ## SOMETIMES_CONSUMES ## GUID
+ gEfiConsoleInDeviceGuid ## CONSUMES ## GUID
+ gEfiConsoleOutDeviceGuid ## CONSUMES ## GUID
+ gShellDriver1HiiGuid ## PRODUCES ## HII
diff --git a/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.uni b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.uni
new file mode 100644
index 0000000000..a14469afdb
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.uni
@@ -0,0 +1,743 @@
+// /**
+//
+// (C) Copyright 2012-2015 Hewlett-Packard Development Company, L.P.<BR>
+// Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php.
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// Module Name:
+//
+// UefiShellDriver1CommandsLib.uni
+//
+// Abstract:
+//
+// String definitions for UEFI Shell 2.0 driver1 profile commands
+//
+//
+// **/
+
+/=#
+
+#langdef en-US "english"
+
+#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n"
+#string STR_GEN_PROBLEM_VAL #language en-US "%H%s%N: Bad value - '%H%s%N' for flag - '%H%s%N'\r\n"
+#string STR_GEN_PARAM_INV #language en-US "%H%s%N: Invalid argument - '%H%s%N'\r\n"
+#string STR_GEN_TOO_FEW #language en-US "%H%s%N: Too few arguments\r\n"
+#string STR_GEN_TOO_MANY #language en-US "%H%s%N: Too many arguments\r\n"
+#string STR_GEN_INV_HANDLE #language en-US "%H%s%N: Handle - '%H%s%N' not found\r\n"
+#string STR_GEN_PARAM_CONFLICT #language en-US "%H%s%N: Flags conflict with - '%H%s%N' and '%H%s%N'\r\n"
+#string STR_GEN_NO_VALUE #language en-US "%H%s%N: Missing argument for flag - '%H%s%N'\r\n"
+#string STR_GEN_HANDLE_NOT #language en-US "%H%s%N: Handle [%H%02x%N] is not a valid %s\r\n"
+#string STR_GEN_HANDLE_REQ #language en-US "%H%s%N: Handle required with the specified options\r\n"
+#string STR_GEN_PROTOCOL_NF #language en-US "%H%s%N: The protocol '%H%s%N' is required and not found (%g)\r\n"
+#string STR_GEN_FIND_FAIL #language en-US "%H%s%N: File not found - '%H%s%N'\r\n"
+#string STR_GEN_FILE_EXIST #language en-US "%H%s%N: File already exists - '%H%s%N'\r\n"
+#string STR_GEN_FILE_OPEN_FAIL #language en-US "%H%s%N: Cannot open file - '%H%s%N'\r\n"
+#string STR_FILE_WRITE_FAIL #language en-US "%H%s%N: Write file error - '%H%s%N'\r\n"
+#string STR_FILE_READ_FAIL #language en-US "%H%s%N: Read file error - '%H%s%N'\r\n"
+#string STR_GEN_OUT_MEM #language en-US "%H%s%N: Memory allocation was not successful\r\n"
+#string STR_GEN_UEFI_FUNC_ERROR #language en-US "%H%s%N: UEFI function '%H%s%N' returned an incorrect value for: %s (%x)\r\n"
+#string STR_GEN_UEFI_FUNC_WARN #language en-US "%H%s%N: UEFI function '%H%s%N' returned: %r\r\n"
+#string STR_GEN_SFO_HEADER #language en-US "ShellCommand,"%s"\r\n"
+
+#string STR_DRVDIAG_HEADER #language en-US "%EAvailable Diagnostics%N.\r\n"
+#string STR_DRVDIAG_DRIVER_HEADER #language en-US "Driver [%H%02x%N]: "
+#string STR_DRVDIAG_DRIVER_NO_HANDLES #language en-US "No controller handles found.\r\n"
+
+#string STR_HANDLE_RESULT #language en-US "%H%s%N - Handle [%H%02x%N] Result %r.\r\n"
+#string STR_3P_RESULT #language en-US "%H%s%N - (%H%02x%N,%H%02x%N,%H%02x%N) Result %r.\r\n"
+#string STR_CONNECT_NONE #language en-US "%HConnect%N No drivers could be connected.\r\n"
+
+#string STR_DRVCFG_NONE_FOUND #language en-US "%HDrvCfg%N No configurable devices were found.\r\n"
+#string STR_DRVCFG_COMP #language en-US "%HDrvCfg%N - operation complete.\r\n"
+#string STR_DRVCFG_DONE_HII #language en-US "Handle[%H%02x%N] successfully updated from file.\r\n"
+#string STR_DRVCFG_LINE_HII #language en-US "Handle[%H%02x%N] HII Config Access\r\n"
+#string STR_DRVCFG_ALL_LANG #language en-US "Driver[%H%02x%N] Ctrl[--] Lang[%H%a%N] Driver Configuration"
+#string STR_DRVCFG_CTRL_LANG #language en-US "Driver[%H%02x%N] Ctrl[%H%02x%N] Lang[%H%a%N] Driver Configuration"
+#string STR_DRVCFG_CHILD_LANG #language en-US "Driver[%H%02x%N] Ctrl[%H%02x%N] Child[%H%02x%N] Lang[%H%a%N] Driver Configuration"
+#string STR_DRVCFG_RESTART_S #language en-US "Restart %s\r\n"
+#string STR_DRVCFG_STOP #language en-US "Stop Controller\n"
+#string STR_DRVCFG_ENTER_S #language en-US "\nPress [ENTER] to %s"
+#string STR_DRVCFG_NONE #language en-US "None\n"
+#string STR_DRVCFG_CTLR_S #language en-US "Controller %s\n"
+#string STR_DRVCFG_FORCE_D #language en-US "Force Default Configuration to DefaultType %08x\n"
+#string STR_DRVCFG_VALIDATE #language en-US "Validate Configuration Options\n"
+#string STR_DRVCFG_SET #language en-US "Set Configuration Options\n"
+#string STR_DRVCFG_NOT_SUPPORT #language en-US "Handle [%H%02x%N] does not support configuration.\n"
+#string STR_DRVCFG_OPTIONS_SET #language en-US " - Options set. Action Required is "
+#string STR_DRVCFG_NOT_SET #language en-US " - Options not set. Status = %r\n"
+#string STR_DRVCFG_DEF_FORCED #language en-US " - Defaults forced. Action Required is "
+#string STR_DRVCFG_FORCE_FAILED #language en-US " - Force of defaults failed. Status = %r\n"
+#string STR_DRVCFG_OPTIONS_VALID #language en-US " - Options valid\n"
+#string STR_DRVCFG_OPTIONS_INV #language en-US " - Options not valid. Status = %r\n"
+#string STR_DRVCFG_IN_FILE_NF #language en-US "DevicePath '%B%s%N' from file not found in HII DB. Skipped.\r\n"
+
+
+#string STR_DEVICES_HEADER_LINES #language en-US "%N"
+" T D\r\n"
+" Y C I\r\n"
+" P F A\r\n"
+"CTRL E G G #P #D #C Device Name\r\n"
+"==== = = = == == === =========================================================\r\n"
+#string STR_DEVICES_ITEM_LINE #language en-US "%H%4x%N %1c %1c %1c %2d %2d %3d %s\r\n"
+#string STR_DEVICES_ITEM_LINE_SFO #language en-US "DevicesInfo,"%x","%c","%c","%c","%d","%d","%d","%s"\r\n"
+
+#string STR_DRIVERS_HEADER_LINES #language en-US "%N"
+" T D\r\n"
+" Y C I\r\n"
+" P F A\r\n"
+"DRV VERSION E G G #D #C DRIVER NAME IMAGE PATH\r\n"
+"=== ======== = = = === === =================================== ==========\r\n"
+#string STR_DRIVERS_ITEM_LINE #language en-US "%H%3x%N %08x %1c %1c %1c %3d %3d %-35s %s\r\n"
+#string STR_DRIVERS_ITEM_LINE_SFO #language en-US "DriversInfo,"%x","%x","%c","%c","%c","%d","%d","%s","%s"\r\n"
+
+#string STR_DH_NO_GUID_FOUND #language en-US "Protocol ID '%s' could not be identified.\r\n"
+#string STR_DH_SFO_OUTPUT #language en-US "%s, %s, %H%02x%N, %s, &s\r\n"
+#string STR_DH_OUTPUT #language en-US "%H%02x%N: %s\r\n"
+#string STR_DH_OUTPUT_SINGLE #language en-US "%H%02x%N: %x\r\n%s"
+#string STR_DH_OUTPUT_SFO #language en-US "%s, %s, %s, %H%02x%N, %s, %s\r\n"
+#string STR_DH_OUTPUT_DRIVER1 #language en-US " Controller Name : %B%s%N\r\n"
+#string STR_DH_OUTPUT_DRIVER2 #language en-US " Device Path : %B%s%N\r\n"
+ " Controller Type : %B%s%N\r\n"
+ " Configuration : %B%s%N\r\n"
+ " Diagnostics : %B%s%N\r\n"
+#string STR_DH_OUTPUT_DRIVER3 #language en-US " Managed by : %B%s%N\r\n"
+#string STR_DH_OUTPUT_DRIVER4A #language en-US " Drv[%H%02x%N] : Image(%B%s%N)r\n"
+#string STR_DH_OUTPUT_DRIVER4B #language en-US " Drv[%H%02x%N] : %B%s%N\r\n"
+#string STR_DH_OUTPUT_DRIVER5 #language en-US " Parent Controllers : %B%s%N\r\n"
+#string STR_DH_OUTPUT_DRIVER5B #language en-US " Parent[%H%02x%N] : %B%s%N\r\n"
+#string STR_DH_OUTPUT_DRIVER6 #language en-US " Child Controllers : %B%s%N\r\n"
+#string STR_DH_OUTPUT_DRIVER6B #language en-US " Child[%H%02x%N] : %B%s%N\r\n"
+#string STR_DH_OUTPUT_DRIVER7 #language en-US " Driver Name : %B%s%N\r\n"
+#string STR_DH_OUTPUT_DRIVER7B #language en-US " Driver Image Name : %B%s%N\r\n"
+#string STR_DH_OUTPUT_DRIVER8 #language en-US " Driver Version : %B%08x%N\r\n"
+ " Driver Type : %B%s%N\r\n"
+ " Configuration : %B%s%N\r\n"
+ " Diagnostics : %B%s%N\r\n"
+#string STR_DH_OUTPUT_DRIVER9 #language en-US " Managing : %B%s%N\r\n"
+#string STR_DH_OUTPUT_DRIVER9B #language en-US " Ctrl[%H%02x%N] : %B%s%N\r\n"
+
+#string STR_DEV_TREE_OUTPUT #language en-US "Ctrl[%H%02x%N] %s\r\n"
+
+#string STR_UNLOAD_CONF #language en-US "%HUnload%N - Handle [%H%02x%N]. [y/n]?\r\n"
+#string STR_UNLOAD_VERBOSE #language en-US ""
+"Handle [%H%02x%N] (%08x)\r\n"
+" Image (%08x)\r\n"
+" ParentHandle..: %08x\r\n"
+" SystemTable...: %08x\r\n"
+" DeviceHandle..: %08x\r\n"
+" FilePath......: %s\r\n"
+" PDBFileName...: %a\r\n"
+" ImageBase.....: %08x\r\n"
+" ImageSize.....: %Ld\r\n"
+" CodeType......: %s\r\n"
+" DataType......: %s\r\n"
+
+#string STR_OPENINFO_HEADER_LINE #language en-US "Handle %H%02x%N (%H%0p%N)\r\n"
+#string STR_OPENINFO_LINE #language en-US " Drv[%H%02x%N] Ctrl[%H%02x%N] Cnt(%H%02x%N) %H%s Image%N(%s)\r\n"
+#string STR_OPENINFO_MIN_LINE #language en-US " Drv[%H%02x%N] Ctrl[ ] Cnt(%H%02x%N) %H%s Image%N(%s)\r\n"
+
+#string STR_DRV_DIAG_ITEM_LINE #language en-US " Drv[%H%02x%N] Ctrl[%H%02x%N] Child[%H%02x%N]\r\n"
+
+#string STR_GET_HELP_DRVCFG #language en-US ""
+".TH drvcfg 0 "configure a UEFI driver."\r\n"
+".SH NAME\r\n"
+"Invokes the driver configuration.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"DRVCFG [-l XXX] [-c] [-f <Type>|-v|-s] \r\n"
+" [DriverHandle [DeviceHandle [ChildHandle]]] [-i filename] [-o filename]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -c - Configures all child devices.\r\n"
+" -l - Configures using the ISO 3066 language specified by XXX.\r\n"
+" -f - Forces defaults.\r\n"
+" -v - Validates options.\r\n"
+" -s - Sets options.\r\n"
+" -i - Receives configuration updates from an input file.\r\n"
+" -o - Exports the settings of the specified driver instance to a\r\n"
+" file.\r\n"
+" Type - Specifies the type of default configuration options to force on the\r\n"
+" controller.\r\n"
+" 0 - Standard Defaults.\r\n"
+" 1 - Manufacturing Defaults.\r\n"
+" 2 - Safe Defaults.\r\n"
+" 4000-FFFF - Custom Defaults.\r\n"
+" DriverHandle - Specifies the the handle of the driver to configure.\r\n"
+" DeviceHandle - Specifies the handle of a device that the DriverHandle is managing.\r\n"
+" ChildHandle - Specifies the handle of a device that is a child of the DeviceHandle. \r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. Default Type:\r\n"
+" 0 - Safe Defaults. Places a controller in a safe configuration with\r\n"
+" the greatest probability of functioning correctly in a platform.\r\n"
+" 1 - Manufacturing Defaults. Optional type that places the controller in\r\n"
+" a configuration suitable for a manufacturing and test environment.\r\n"
+" 2 - Custom Defaults. Optional type that places the controller in a\r\n"
+" custom configuration.\r\n"
+" 3 - Performance Defaults. Optional type that places the controller in a\r\n"
+" configuration that maximizes the controller's performance in a \r\n"
+" platform. \r\n"
+" Other Value - Depends on the driver's implementation.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display the list of devices that are available for configuration:\r\n"
+" Shell> drvcfg\r\n"
+" \r\n"
+" * To display the list of devices and child devices that are available for\r\n"
+" configuration:\r\n"
+" Shell> drvcfg -c\r\n"
+" \r\n"
+" * To force defaults on all devices:\r\n"
+" Shell> drvcfg -f 0\r\n"
+" \r\n"
+" * To force defaults on all devices that are managed by driver 0x17:\r\n"
+" Shell> drvcfg -f 0 17\r\n"
+" \r\n"
+" * To force defaults on device 0x28 that is managed by driver 0x17:\r\n"
+" Shell> drvcfg -f 0 17 28\r\n"
+" \r\n"
+" * To force defaults on all child devices of device 0x28 that is managed by\r\n"
+" driver 0x17:\r\n"
+" Shell> drvcfg -f 0 17 28 -c\r\n"
+" \r\n"
+" * To force defaults on child device 0x30 of device 0x28 that is managed by\r\n"
+" driver 0x17:\r\n"
+" Shell> drvcfg -f 0 17 28 30\r\n"
+" \r\n"
+" * To validate options on all devices:\r\n"
+" Shell> drvcfg -v\r\n"
+" \r\n"
+" * To validate options on all devices that are managed by driver 0x17:\r\n"
+" Shell> drvcfg -v 17\r\n"
+" \r\n"
+" * To validate options on device 0x28 that is managed by driver 0x17:\r\n"
+" Shell> drvcfg -v 17 28\r\n"
+" \r\n"
+" * To validate options on all child devices of device 0x28 that is managed by\r\n"
+" driver 0x17:\r\n"
+" Shell> drvcfg -v 17 28 -c\r\n"
+" \r\n"
+" * To validate options on child device 0x30 of device 0x28 that is managed by\r\n"
+" driver 0x17:\r\n"
+" Shell> drvcfg -v 17 28 30\r\n"
+" \r\n"
+" * To set options on device 0x28 that is managed by driver 0x17: \r\n"
+" Shell> drvcfg -s 17 28\r\n"
+" \r\n"
+" * To set options on child device 0x30 of device 0x28 that is managed by\r\n"
+" driver 0x17:\r\n"
+" Shell> drvcfg -s 17 28 30\r\n"
+" \r\n"
+" * To set options on device 0x28 that is managed by driver 0x17 in English:\r\n"
+" Shell> drvcfg -s 17 28 -l eng\r\n"
+" \r\n"
+" * To set options on device 0x28 that is managed by driver 0x17 in Spanish:\r\n"
+" Shell> drvcfg -s 17 28 -l spa\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_UNSUPPORTED The action as requested was unsupported.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+
+#string STR_GET_HELP_DRIVERS #language en-US ""
+".TH drivers 0 "display a list of drivers"\r\n"
+".SH NAME\r\n"
+"Displays the UEFI driver list.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"DRIVERS [-l XXX] [-sfo] \r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -l - Displays drivers using the specified language (e.g. ISO 639-2) \r\n"
+" -sfo - Displays information as described in Standard-Format Output.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command displays a list of information for drivers that follow the\r\n"
+" UEFI Driver Model in the UEFI environment. The list includes:\r\n"
+" DRV - The handle number of the UEFI driver.\r\n"
+" VERSION - The version number of the UEFI driver.\r\n"
+" TYPE - The driver type:\r\n"
+" [B] - Bus Driver\r\n"
+" [D] - Device Driver\r\n"
+" CFG - Driver supports the Driver Configuration Protocol.\r\n"
+" DIAG - Driver supports the Driver Diagnostics Protocol.\r\n"
+" #D - The number of devices that this driver is managing.\r\n"
+" #C - The number of child devices that this driver has produced.\r\n"
+" DRIVER NAME - The name of the driver from the Component Name Protocol.\r\n"
+" IMAGE PATH - The file path from which the driver was loaded.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display the list:\r\n"
+" Shell> drivers\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+
+#string STR_GET_HELP_DISCONNECT #language en-US ""
+".TH disconnect 0 "disconnect a driver"\r\n"
+".SH NAME\r\n"
+"Disconnects one or more drivers from the specified devices. \r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"DISCONNECT DeviceHandle [DriverHandle [ChildHandle]] [-r] \r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+"NOTES:\r\n"
+" -r - Disconnects all drivers from all devices.\r\n"
+" DeviceHandle - Specifies a device handle (a hexadecimal number). If not specified, then\r\n"
+" disconnect DriverHandle.\r\n"
+" DriverHandle - Specifies a driver handle (a hexadecimal number).\r\n"
+" ChildHandle - Specifies a child handle of a device (a hexadecimal number). If not\r\n"
+" specified, then all child handles of DeviceHandle are \r\n"
+" disconnected.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. If the 'DriverHandle' parameter is not specified, the default is to\r\n"
+" disconnect 'DeviceHandle'.\r\n"
+" 2. If the 'ChildHandle' parameter is not specified, the default is to\r\n"
+" disconnect all child handles of the 'DeviceHandle'.\r\n"
+" 3. If the '-r' option is specified, all consoles and drivers will be\r\n"
+" disconnected from all devices in the system. In this case, no other\r\n"
+" parameters are allowed.\r\n"
+" 4. This command does not support output redirection.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To disconnect all drivers from all devices:\r\n"
+" Shell> disconnect -r\r\n"
+" \r\n"
+" * To disconnect all drivers from device 0x28:\r\n"
+" fs0:\> disconnect 28\r\n"
+" \r\n"
+" * To disconnect driver 0x17 from device 0x28:\r\n"
+" fs0:\> disconnect 28 17\r\n"
+" \r\n"
+" * To disconnect driver 0x17 from controlling the child 0x32 of device 0x28:\r\n"
+" fs0:\> disconnect 28 17 32\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+
+#string STR_GET_HELP_DH #language en-US ""
+".TH dh 0 "displays list of handles"\r\n"
+".SH NAME\r\n"
+"Displays the device handles in the UEFI environment. \r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"DH [-l <lang>] [handle | -p <prot_id>] [-d] [-v] \r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -p - Dumps all handles of a protocol specified by the GUID.\r\n"
+" -d - Dumps UEFI Driver Model-related information.\r\n"
+" -l - Dumps information using the language codes (e.g. ISO 639-2).\r\n"
+" -sfo - Displays information as described in Standard-Format Output.\r\n"
+" -v - Dumps verbose information about a specific handle.\r\n"
+" handle - Specifies a handle to dump information about (a hexadecimal number).\r\n"
+" If not present, then all information will be dumped.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. When neither 'handle' nor 'prot_id' is specified, a list of all the\r\n"
+" device handles in the UEFI environment is displayed. \r\n"
+" 2. The '-d' option displays UEFI Driver Model related information including\r\n"
+" parent handles, child handles, all drivers installed on the handle, etc.\r\n"
+" 3. The '-v' option displays verbose information for the specified handle\r\n"
+" including all the protocols on the handle and their details.\r\n"
+" 4. If the '-p' option is specified, all handles containing the specified\r\n"
+" protocol will be displayed. Otherwise, the 'handle' parameter has to be\r\n"
+" specified for display. In this case, the '-d' option will be enabled\r\n"
+" automatically if the '-v' option is not specified.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display all handles and display one screen at a time:\r\n"
+" Shell> dh -b\r\n"
+" \r\n"
+" * To display the detailed information on handle 0x30:\r\n"
+" Shell> dh 30\r\n"
+" \r\n"
+" * To display all handles with 'diskio' protocol:\r\n"
+" Shell> dh -p diskio\r\n"
+" \r\n"
+" * To display all handles with 'Image' protocol and break when the screen is\r\n"
+" full:\r\n"
+" Shell> dh -p Image -b\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+
+#string STR_GET_HELP_DEVTREE #language en-US ""
+".TH devtree 0 "display device tree"\r\n"
+".SH NAME\r\n"
+"Displays the UEFI Driver Model compliant device tree.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"DEVTREE [-b] [-d] [-l XXX] [DeviceHandle] \r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -b - Displays one screen at a time.\r\n"
+" -d - Displays the device tree using device paths.\r\n"
+" -l - Displays the device tree using the specified language.\r\n"
+" DeviceHandle - Displays the device tree below a certain handle.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command prints a tree of devices that are being managed by drivers\r\n"
+" that follow the UEFI Driver Model. By default, the devices are printed in\r\n"
+" device names that are retrieved from the Component Name Protocol.\r\n"
+" 2. If the option -d is specified, the device paths will be printed instead.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display the tree of all devices compliant with the UEFI Driver Model:\r\n"
+" Shell> devtree\r\n"
+" \r\n"
+" * To display the tree of all devices below device 28 compliant with the UEFI\r\n"
+" Driver Model:\r\n"
+" Shell> devtree 28\r\n"
+" \r\n"
+" * To display the tree of all devices compliant with the UEFI Driver Model\r\n"
+" one screen at a time:\r\n"
+" Shell> devtree -b\r\n"
+" \r\n"
+
+#string STR_GET_HELP_DEVICES #language en-US ""
+".TH devices 0 "display a list of devices"\r\n"
+".SH NAME\r\n"
+"Displays the list of devices managed by UEFI drivers. \r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"DEVICES [-b] [-l XXX] [-sfo] \r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -b - Display one screen at a time\r\n"
+" -l XXX - Display devices using the specified ISO 639-2 language\r\n"
+" -sfo - Displays information as described in Standard-Format Output.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. The command prints a list of devices that are being managed by drivers\r\n"
+" that follow the UEFI Driver Model.\r\n"
+" 2. Display Format:\r\n"
+" CTRL - The handle number of the UEFI device\r\n"
+" TYPE - The device type:\r\n"
+" [R] - Root Controller\r\n"
+" [B] - Bus Controller\r\n"
+" [D] - Device Controller\r\n"
+" CFG - A managing driver supports the Driver Configuration\r\n"
+" Protocol. Yes if 'Y' or 'X'; No if 'N' or '-'.\r\n"
+" DIAG - A managing driver supports the Driver Diagnostics\r\n"
+" Protocol. Yes if 'Y' or 'X'; No if 'N' or '-'.\r\n"
+" #P - The number of parent controllers for this device\r\n"
+" #D - The number of drivers managing the device\r\n"
+" #C - The number of child controllers produced by this device\r\n"
+" DEVICE NAME - The name of the device from the Component Name Protocol\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display all devices compliant with the UEFI Driver Model:\r\n"
+" Shell> devices\r\n"
+" \r\n"
+
+#string STR_GET_HELP_CONNECT #language en-US ""
+".TH connect 0 "connect a driver"\r\n"
+".SH NAME\r\n"
+"Binds a driver to a specific device and starts the driver. \r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"CONNECT [[DeviceHandle] [DriverHandle] | [-c] | [-r]] \r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -c - Connects console devices\r\n"
+" -r - Connects recursively\r\n"
+" DeviceHandle - Specifies a device handle in hexadecimal format.\r\n"
+" DriverHandle - Specifies a driver handle in hexadecimal format.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. If no 'DeviceHandle' parameter is specified, all device handles in the\r\n"
+" current system will be the default.\r\n"
+" 2. If no 'DriverHandle' parameter is specified, all matched drivers will be\r\n"
+" bound to the specified device.\r\n"
+" 3. If 'DriverHandle' parameter is provided, the specified driver will have\r\n"
+" highest priority on connecting the device(s).\r\n"
+" 4. If the '-c' option is specified, only console devices described in the\r\n"
+" UEFI Shell environment variables and related devices will be connected.\r\n"
+" 5. If the '-r' option is specified, the command will recursively scan all\r\n"
+" handles and check to see if any loaded or embedded driver can match the\r\n"
+" specified device. If so, the driver will be bound to the device.\r\n"
+" Additionally, if more device handles are created during the binding, \r\n"
+" these handles will also be checked to see if a matching driver can bind\r\n"
+" to these devices as well. The process is repeated until no more drivers\r\n"
+" are able to connect to any devices. However, without the option, the\r\n"
+" newly created device handles will not be further bound to any\r\n"
+" drivers.\r\n"
+" 6. If only a single handle is specified and the handle has an\r\n"
+" EFI_DRIVER_BINDING_PROTOCOL on it, then the handle is assumed to be a\r\n"
+" driver handle. Otherwise, it is assumed to be a device handle.\r\n"
+" 7. If no parameters are specified, then the command will attempt to bind\r\n"
+" all proper drivers to all devices without recursion. Each connection\r\n"
+" status will be displayed.\r\n"
+" 8. Output redirection is not supported for 'connect -r' usage.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To connect all drivers to all devices recursively:\r\n"
+" Shell> connect -r\r\n"
+" \r\n"
+" * To display all connections:\r\n"
+" Shell> connect\r\n"
+" \r\n"
+" * To connect drivers with 0x17 as highest priority to all the devices they\r\n"
+" can manage:\r\n"
+" Shell> connect 17\r\n"
+" \r\n"
+" * To connect all possible drivers to device 0x19:\r\n"
+" Shell> connect 19\r\n"
+" \r\n"
+" * To connect drivers with 0x17 as highest priority to device 0x19 they can\r\n"
+" manage:\r\n"
+" Shell> connect 19 17\r\n"
+" \r\n"
+" * To connect console devices described in the UEFI Shell environment\r\n"
+" variables:\r\n"
+" Shell> connect -c\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+
+#string STR_GET_HELP_OPENINFO #language en-US ""
+".TH openinfo 0 "display info about a handle."\r\n"
+".SH NAME\r\n"
+"Displays the protocols and agents associated with a handle. \r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"OPENINFO Handle [-b] \r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -b - Displays one screen at a time.\r\n"
+" Handle - Displays open protocol information for the specified handle.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command is used to display the open protocols on a given handle.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To show open protocols on handle 0x23:\r\n"
+" Shell> openinfo 23\r\n"
+" \r\n"
+
+#string STR_GET_HELP_DRVDIAG #language en-US ""
+".TH drvdiag 0 "diagnose a driver"\r\n"
+".SH NAME\r\n"
+"Invokes the Driver Diagnostics Protocol. \r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"DRVDIAG [-c] [-l XXX] [-s|-e|-m] [DriverHandle [DeviceHandle [ChildHandle]]] \r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -c - Diagnoses all child devices.\r\n"
+" -l - Diagnoses using the ISO 639-2 language specified by XXX.\r\n"
+" -s - Runs diagnostics in standard mode.\r\n"
+" -e - Runs diagnostics in extended mode.\r\n"
+" -m - Runs diagnostics in manufacturing mode.\r\n"
+" DriverHandle - Specifies the handle of the driver to diagnose.\r\n"
+" DeviceHandle - Specifies the handle of a device that DriverHandle is managing.\r\n"
+" ChildHandle - Specifies the handle of a device that is a child of DeviceHandle.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command invokes the Driver Diagnostics Protocol.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display the list of devices that are available for diagnostics:\r\n"
+" Shell> drvdiag\r\n"
+" \r\n"
+" * To display the list of devices and child devices that are available for\r\n"
+" diagnostics:\r\n"
+" Shell> drvdiag -c\r\n"
+" \r\n"
+" * To run diagnostics in standard mode on all devices:\r\n"
+" Shell> drvdiag -s\r\n"
+" \r\n"
+" * To run diagnostics in standard mode on all devices in English:\r\n"
+" Shell> drvdiag -s -l eng\r\n"
+" \r\n"
+" * To run diagnostics in standard mode on all devices in Spanish:\r\n"
+" Shell> drvdiag -s -l spa\r\n"
+" \r\n"
+" * To run diagnostics in standard mode on all devices and child devices:\r\n"
+" Shell> drvdiag -s -c\r\n"
+" \r\n"
+" * To run diagnostics in extended mode on all devices:\r\n"
+" Shell> drvdiag -e\r\n"
+" \r\n"
+" * To run diagnostics in manufacturing mode on all devices:\r\n"
+" Shell> drvdiag -m\r\n"
+" \r\n"
+" * To run diagnostics in standard mode on all devices managed by driver 0x17:\r\n"
+" Shell> drvdiag -s 17\r\n"
+" \r\n"
+" * To run diagnostics in standard mode on device 0x28 managed by driver 0x17:\r\n"
+" Shell> drvdiag -s 17 28\r\n"
+" \r\n"
+" * To run diagnostics in standard mode on all child devices of device 0x28\r\n"
+" managed by driver 0x17:\r\n"
+" Shell> drvdiag -s 17 28 -c\r\n"
+" \r\n"
+" * To run diagnostics in standard mode on child device 0x30 of device 0x28\r\n"
+" managed by driver 0x17:\r\n"
+" Shell> drvdiag -s 17 28 30\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+
+#string STR_GET_HELP_RECONNECT #language en-US ""
+".TH reconnect 0 "reconnect drivers"\r\n"
+".SH NAME\r\n"
+"Reconnects drivers to the specific device. \r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"RECONNECT DeviceHandle [DriverHandle [ChildHandle]]\r\n"
+"RECONNECT -r \r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -r - Reconnects drivers to all devices.\r\n"
+" DeviceHandle - Specifies a device handle (a hexadecimal number).\r\n"
+" DriverHandle - Specifies a driver handle (a hexadecimal number). If not specified, all\r\n"
+" drivers on the specified device will be reconnected. \r\n"
+" ChildHandle - Specifies the child handle of device (a hexadecimal number). If not\r\n"
+" specified, then all child handles of the specified device are\r\n"
+" reconnected.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command reconnects drivers to the specific device. It will first\r\n"
+" disconnect the specified driver from the specified device and then connect\r\n"
+" the driver to the device recursively.\r\n"
+" 2. If the -r option is used, then all drivers will be reconnected to all\r\n"
+" devices. Any drivers that are bound to any devices will be disconnected\r\n"
+" first and then connected recursively.\r\n"
+" 3. See the connect and disconnect commands for more details. \r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To reconnect all drivers to all devices:\r\n"
+" Shell> reconnect -r\r\n"
+" \r\n"
+" * To reconnect all drivers to device 0x28:\r\n"
+" fs0:\> reconnect 28\r\n"
+" \r\n"
+" * To disconnect 0x17 from 0x28 then reconnect drivers with 0x17 as highest\r\n"
+" priority to device 0x28:\r\n"
+" fs0:\> reconnect 28 17\r\n"
+" \r\n"
+" * To disconnect 0x17 from 0x28 destroying child 0x32 then reconnect drivers\r\n"
+" with 0x17 as highest priority to device 0x28\r\n"
+" fs0:\> reconnect 28 17 32\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+
+#string STR_GET_HELP_UNLOAD #language en-US ""
+".TH unload 0 "unload a driver"\r\n"
+".SH NAME\r\n"
+"Unloads a driver image that was already loaded. \r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"UNLOAD [-n] [-v|-verbose] Handle \r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -n - Skips all prompts during unloading, so that it can be used\r\n"
+" in a script file.\r\n"
+" -v, -verbose - Dumps verbose status information before the image is unloaded.\r\n"
+" Handle - Specifies the handle of driver to unload, always taken as hexadecimal number.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. The '-n' option can be used to skip all prompts during unloading.\r\n"
+" 2. If the '-v' option is specified, verbose image information will be\r\n"
+" displayed before the image is unloaded.\r\n"
+" 3. Only drivers that support unloading can be successfully unloaded.\r\n"
+" 4. Use the 'LOAD' command to load a driver.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To find the handle for the UEFI driver image to unload:\r\n"
+" Shell> dh -b\r\n"
+" \r\n"
+" * To unload the UEFI driver image with handle 27:\r\n"
+" Shell> unload 27\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Unload.c b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Unload.c
new file mode 100644
index 0000000000..0d48f9d5d7
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellDriver1CommandsLib/Unload.c
@@ -0,0 +1,149 @@
+/** @file
+ Main file for Unload shell Driver1 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2010 - 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellDriver1CommandsLib.h"
+
+/**
+ Function to dump LoadedImage info from TheHandle.
+
+ @param[in] TheHandle The handle to dump info from.
+
+ @retval EFI_SUCCESS The info was dumped.
+ @retval EFI_INVALID_PARAMETER The handle did not have LoadedImage
+**/
+EFI_STATUS
+EFIAPI
+DumpLoadedImageProtocolInfo (
+ IN EFI_HANDLE TheHandle
+ )
+{
+ CHAR16 *TheString;
+
+ TheString = GetProtocolInformationDump(TheHandle, &gEfiLoadedImageProtocolGuid, TRUE);
+
+ ShellPrintEx(-1, -1, L"%s", TheString);
+
+ SHELL_FREE_NON_NULL(TheString);
+
+ return (EFI_SUCCESS);
+}
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-n", TypeFlag},
+ {L"-v", TypeFlag},
+ {L"-verbose", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'unload' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunUnload (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ EFI_HANDLE TheHandle;
+ CONST CHAR16 *Param1;
+ SHELL_PROMPT_RESPONSE *Resp;
+ UINT64 Value;
+
+ ShellStatus = SHELL_SUCCESS;
+ Package = NULL;
+ Resp = NULL;
+ Value = 0;
+ TheHandle = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellDriver1HiiHandle,L"unload", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetCount(Package) > 2){
+ //
+ // error for too many parameters
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellDriver1HiiHandle, L"unload");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetCount(Package) < 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellDriver1HiiHandle, L"unload");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Param1 = ShellCommandLineGetRawValue(Package, 1);
+ if (Param1 != NULL) {
+ Status = ShellConvertStringToUint64(Param1, &Value, TRUE, FALSE);
+ TheHandle = ConvertHandleIndexToHandle((UINTN)Value);
+ }
+
+ if (EFI_ERROR(Status) || Param1 == NULL || TheHandle == NULL){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_HANDLE), gShellDriver1HiiHandle, L"unload", Param1);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(TheHandle != NULL);
+ if (ShellCommandLineGetFlag(Package, L"-v") || ShellCommandLineGetFlag(Package, L"-verbose")) {
+ DumpLoadedImageProtocolInfo(TheHandle);
+ }
+
+ if (!ShellCommandLineGetFlag(Package, L"-n")) {
+ Status = ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_UNLOAD_CONF), gShellDriver1HiiHandle, (UINTN)TheHandle);
+ Status = ShellPromptForResponse(ShellPromptResponseTypeYesNo, NULL, (VOID**)&Resp);
+ }
+ if (ShellCommandLineGetFlag(Package, L"-n") || (Resp != NULL && *Resp == ShellPromptResponseYes)) {
+ Status = gBS->UnloadImage(TheHandle);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HANDLE_RESULT), gShellDriver1HiiHandle, L"Unload", (UINTN)TheHandle, Status);
+ }
+ SHELL_FREE_NON_NULL(Resp);
+ }
+ }
+ }
+ if (ShellStatus == SHELL_SUCCESS) {
+ if (Status == EFI_SECURITY_VIOLATION) {
+ ShellStatus = SHELL_SECURITY_VIOLATION;
+ } else if (Status == EFI_INVALID_PARAMETER) {
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (EFI_ERROR(Status)) {
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ }
+
+ if (Package != NULL) {
+ ShellCommandLineFreeVarList(Package);
+ }
+
+ return (ShellStatus);
+}
diff --git a/Core/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.c b/Core/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.c
new file mode 100644
index 0000000000..e26a86283e
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.c
@@ -0,0 +1,59 @@
+/** @file
+ Main file for NULL named library for install1 shell command functions.
+
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include <Library/BcfgCommandLib.h>
+
+/**
+ Constructor for the Shell Level 1 Commands library.
+
+ Install the handlers for level 1 UEFI Shell 2.0 commands.
+
+ @param ImageHandle the image handle of the process
+ @param SystemTable the EFI System Table pointer
+
+ @retval EFI_SUCCESS the shell command handlers were installed sucessfully
+ @retval EFI_UNSUPPORTED the shell level required was not found.
+**/
+EFI_STATUS
+EFIAPI
+ShellInstall1CommandsLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ //
+ // check our bit of the profiles mask
+ //
+ if ((PcdGet8(PcdShellProfileMask) & BIT2) == 0) {
+ return (EFI_SUCCESS);
+ }
+
+ return (BcfgLibraryRegisterBcfgCommand(ImageHandle, SystemTable, L"Install1"));
+}
+
+/**
+ Destructor for the library. free any resources.
+
+ @param ImageHandle The image handle of the process.
+ @param SystemTable The EFI System Table pointer.
+**/
+EFI_STATUS
+EFIAPI
+ShellInstall1CommandsLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ return (BcfgLibraryUnregisterBcfgCommand(ImageHandle, SystemTable));
+}
diff --git a/Core/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf b/Core/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf
new file mode 100644
index 0000000000..dc1b6223e7
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf
@@ -0,0 +1,51 @@
+## @file
+# Provides shell install1 functions
+#
+# Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved. <BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = UefiShellInstall1CommandsLib
+ FILE_GUID = D250E364-51C6-49ed-AEBF-6D83F5130F74
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER
+ CONSTRUCTOR = ShellInstall1CommandsLibConstructor
+ DESTRUCTOR = ShellInstall1CommandsLibDestructor
+
+[Sources.common]
+ UefiShellInstall1CommandsLib.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ ShellCommandLib
+ ShellLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ SortLib
+ PrintLib
+ BcfgCommandLib
+
+[Pcd]
+ gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask ## CONSUMES
+
+[Guids]
+ gShellInstall1HiiGuid ## UNDEFINED
diff --git a/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/Exit.c b/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/Exit.c
new file mode 100644
index 0000000000..08e40dfc05
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/Exit.c
@@ -0,0 +1,97 @@
+/** @file
+ Main file for exit shell level 1 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel1CommandsLib.h"
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"/b", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'exit' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunExit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ UINT64 RetVal;
+ CONST CHAR16 *Return;
+
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel1HiiHandle, L"exit", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+
+ //
+ // return the specified error code
+ //
+ Return = ShellCommandLineGetRawValue(Package, 1);
+ if (Return != NULL) {
+ Status = ShellConvertStringToUint64(Return, &RetVal, FALSE, FALSE);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel1HiiHandle, L"exit", Return);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // If we are in a batch file and /b then pass TRUE otherwise false...
+ //
+ ShellCommandRegisterExit((BOOLEAN)(gEfiShellProtocol->BatchIsActive() && ShellCommandLineGetFlag(Package, L"/b")), RetVal);
+
+ ShellStatus = SHELL_SUCCESS;
+ }
+ } else {
+ // If we are in a batch file and /b then pass TRUE otherwise false...
+ //
+ ShellCommandRegisterExit((BOOLEAN)(gEfiShellProtocol->BatchIsActive() && ShellCommandLineGetFlag(Package, L"/b")), 0);
+
+ ShellStatus = SHELL_SUCCESS;
+ }
+
+ ShellCommandLineFreeVarList (Package);
+ }
+ return (ShellStatus);
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/For.c b/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/For.c
new file mode 100644
index 0000000000..6cfe8a78fe
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/For.c
@@ -0,0 +1,754 @@
+/** @file
+ Main file for endfor and for shell level 1 functions.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel1CommandsLib.h"
+#include <Library/PrintLib.h>
+
+/**
+ Determine if a valid string is a valid number for the 'for' command.
+
+ @param[in] Number The pointer to the string representation of the number to test.
+
+ @retval TRUE The number is valid.
+ @retval FALSE The number is not valid.
+**/
+BOOLEAN
+EFIAPI
+ShellIsValidForNumber (
+ IN CONST CHAR16 *Number
+ )
+{
+ if (Number == NULL || *Number == CHAR_NULL) {
+ return (FALSE);
+ }
+
+ if (*Number == L'-') {
+ Number++;
+ }
+
+ if (StrLen(Number) == 0) {
+ return (FALSE);
+ }
+
+ if (StrLen(Number) >= 7) {
+ if ((StrStr(Number, L" ") == NULL) || (((StrStr(Number, L" ") != NULL) && (StrStr(Number, L" ") - Number) >= 7))) {
+ return (FALSE);
+ }
+ }
+
+ if (!ShellIsDecimalDigitCharacter(*Number)) {
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
+
+/**
+ Function for 'endfor' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunEndFor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Found;
+ SCRIPT_FILE *CurrentScriptFile;
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ if (!gEfiShellProtocol->BatchIsActive()) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"endfor");
+ return (SHELL_UNSUPPORTED);
+ }
+
+ if (gEfiShellParametersProtocol->Argc > 1) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle, L"endfor");
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ Found = MoveToTag(GetPreviousNode, L"for", L"endfor", NULL, ShellCommandGetCurrentScriptFile(), FALSE, FALSE, FALSE);
+
+ if (!Found) {
+ CurrentScriptFile = ShellCommandGetCurrentScriptFile();
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_SYNTAX_NO_MATCHING),
+ gShellLevel1HiiHandle,
+ L"For",
+ L"EndFor",
+ CurrentScriptFile!=NULL
+ && CurrentScriptFile->CurrentCommand!=NULL
+ ? CurrentScriptFile->CurrentCommand->Line:0);
+ return (SHELL_NOT_FOUND);
+ }
+ return (SHELL_SUCCESS);
+}
+
+typedef struct {
+ UINT32 Signature;
+ INTN Current;
+ INTN End;
+ INTN Step;
+ CHAR16 *ReplacementName;
+ CHAR16 *CurrentValue;
+ BOOLEAN RemoveSubstAlias;
+ CHAR16 Set[1];
+ } SHELL_FOR_INFO;
+#define SIZE_OF_SHELL_FOR_INFO OFFSET_OF (SHELL_FOR_INFO, Set)
+#define SHELL_FOR_INFO_SIGNATURE SIGNATURE_32 ('S', 'F', 'I', 's')
+
+/**
+ Update the value of a given alias on the list. If the alias is not there then add it.
+
+ @param[in] Alias The alias to test for.
+ @param[in] CommandString The updated command string.
+ @param[in, out] List The list to search.
+
+ @retval EFI_SUCCESS The operation was completed successfully.
+ @retval EFI_OUT_OF_RESOURCES There was not enough free memory.
+**/
+EFI_STATUS
+EFIAPI
+InternalUpdateAliasOnList(
+ IN CONST CHAR16 *Alias,
+ IN CONST CHAR16 *CommandString,
+ IN OUT LIST_ENTRY *List
+ )
+{
+ ALIAS_LIST *Node;
+ BOOLEAN Found;
+
+ //
+ // assert for NULL parameter
+ //
+ ASSERT(Alias != NULL);
+
+ //
+ // check for the Alias
+ //
+ for ( Node = (ALIAS_LIST *)GetFirstNode(List), Found = FALSE
+ ; !IsNull(List, &Node->Link)
+ ; Node = (ALIAS_LIST *)GetNextNode(List, &Node->Link)
+ ){
+ ASSERT(Node->CommandString != NULL);
+ ASSERT(Node->Alias != NULL);
+ if (StrCmp(Node->Alias, Alias)==0) {
+ FreePool(Node->CommandString);
+ Node->CommandString = NULL;
+ Node->CommandString = StrnCatGrow(&Node->CommandString, NULL, CommandString, 0);
+ Found = TRUE;
+ break;
+ }
+ }
+ if (!Found) {
+ Node = AllocateZeroPool(sizeof(ALIAS_LIST));
+ if (Node == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ ASSERT(Node->Alias == NULL);
+ Node->Alias = StrnCatGrow(&Node->Alias, NULL, Alias, 0);
+ ASSERT(Node->CommandString == NULL);
+ Node->CommandString = StrnCatGrow(&Node->CommandString, NULL, CommandString, 0);
+ InsertTailList(List, &Node->Link);
+ }
+ return (EFI_SUCCESS);
+}
+
+/**
+ Find out if an alias is on the given list.
+
+ @param[in] Alias The alias to test for.
+ @param[in] List The list to search.
+
+ @retval TRUE The alias is on the list.
+ @retval FALSE The alias is not on the list.
+**/
+BOOLEAN
+EFIAPI
+InternalIsAliasOnList(
+ IN CONST CHAR16 *Alias,
+ IN CONST LIST_ENTRY *List
+ )
+{
+ ALIAS_LIST *Node;
+
+ //
+ // assert for NULL parameter
+ //
+ ASSERT(Alias != NULL);
+
+ //
+ // check for the Alias
+ //
+ for ( Node = (ALIAS_LIST *)GetFirstNode(List)
+ ; !IsNull(List, &Node->Link)
+ ; Node = (ALIAS_LIST *)GetNextNode(List, &Node->Link)
+ ){
+ ASSERT(Node->CommandString != NULL);
+ ASSERT(Node->Alias != NULL);
+ if (StrCmp(Node->Alias, Alias)==0) {
+ return (TRUE);
+ }
+ }
+ return (FALSE);
+}
+
+/**
+ Remove an alias from the given list.
+
+ @param[in] Alias The alias to remove.
+ @param[in, out] List The list to search.
+**/
+BOOLEAN
+EFIAPI
+InternalRemoveAliasFromList(
+ IN CONST CHAR16 *Alias,
+ IN OUT LIST_ENTRY *List
+ )
+{
+ ALIAS_LIST *Node;
+
+ //
+ // assert for NULL parameter
+ //
+ ASSERT(Alias != NULL);
+
+ //
+ // check for the Alias
+ //
+ for ( Node = (ALIAS_LIST *)GetFirstNode(List)
+ ; !IsNull(List, &Node->Link)
+ ; Node = (ALIAS_LIST *)GetNextNode(List, &Node->Link)
+ ){
+ ASSERT(Node->CommandString != NULL);
+ ASSERT(Node->Alias != NULL);
+ if (StrCmp(Node->Alias, Alias)==0) {
+ RemoveEntryList(&Node->Link);
+ FreePool(Node->Alias);
+ FreePool(Node->CommandString);
+ FreePool(Node);
+ return (TRUE);
+ }
+ }
+ return (FALSE);
+}
+
+/**
+ Function to determine whether a string is decimal or hex representation of a number
+ and return the number converted from the string.
+
+ @param[in] String String representation of a number
+
+ @return the number
+ @retval (UINTN)(-1) An error ocurred.
+**/
+UINTN
+EFIAPI
+ReturnUintn(
+ IN CONST CHAR16 *String
+ )
+{
+ UINT64 RetVal;
+
+ if (!EFI_ERROR(ShellConvertStringToUint64(String, &RetVal, FALSE, TRUE))) {
+ return ((UINTN)RetVal);
+ }
+ return ((UINTN)(-1));
+}
+
+/**
+ Function for 'for' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunFor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ SHELL_STATUS ShellStatus;
+ SCRIPT_FILE *CurrentScriptFile;
+ CHAR16 *ArgSet;
+ CHAR16 *ArgSetWalker;
+ CHAR16 *Parameter;
+ UINTN ArgSize;
+ UINTN LoopVar;
+ SHELL_FOR_INFO *Info;
+ CHAR16 *TempString;
+ CHAR16 *TempSpot;
+ BOOLEAN FirstPass;
+ EFI_SHELL_FILE_INFO *Node;
+ EFI_SHELL_FILE_INFO *FileList;
+ UINTN NewSize;
+
+ ArgSet = NULL;
+ ArgSize = 0;
+ ShellStatus = SHELL_SUCCESS;
+ ArgSetWalker = NULL;
+ TempString = NULL;
+ Parameter = NULL;
+ FirstPass = FALSE;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ if (!gEfiShellProtocol->BatchIsActive()) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"for");
+ return (SHELL_UNSUPPORTED);
+ }
+
+ if (gEfiShellParametersProtocol->Argc < 4) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel1HiiHandle, L"for");
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ CurrentScriptFile = ShellCommandGetCurrentScriptFile();
+ ASSERT(CurrentScriptFile != NULL);
+
+ if ((CurrentScriptFile->CurrentCommand != NULL) && (CurrentScriptFile->CurrentCommand->Data == NULL)) {
+ FirstPass = TRUE;
+
+ //
+ // Make sure that an End exists.
+ //
+ if (!MoveToTag(GetNextNode, L"endfor", L"for", NULL, CurrentScriptFile, TRUE, TRUE, FALSE)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_SYNTAX_NO_MATCHING),
+ gShellLevel1HiiHandle,
+ L"EndFor",
+ L"For",
+ CurrentScriptFile->CurrentCommand->Line);
+ return (SHELL_DEVICE_ERROR);
+ }
+
+ //
+ // Process the line.
+ //
+ if (gEfiShellParametersProtocol->Argv[1][0] != L'%' || gEfiShellParametersProtocol->Argv[1][2] != CHAR_NULL
+ ||!((gEfiShellParametersProtocol->Argv[1][1] >= L'a' && gEfiShellParametersProtocol->Argv[1][1] <= L'z')
+ ||(gEfiShellParametersProtocol->Argv[1][1] >= L'A' && gEfiShellParametersProtocol->Argv[1][1] <= L'Z'))
+ ) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_INV_VAR), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[1]);
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ L"in",
+ gEfiShellParametersProtocol->Argv[2]) == 0) {
+ for (LoopVar = 0x3 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) {
+ ASSERT((ArgSet == NULL && ArgSize == 0) || (ArgSet != NULL));
+ if (StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"*") != NULL
+ ||StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"?") != NULL
+ ||StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"[") != NULL
+ ||StrStr(gEfiShellParametersProtocol->Argv[LoopVar], L"]") != NULL) {
+ FileList = NULL;
+ Status = ShellOpenFileMetaArg ((CHAR16*)gEfiShellParametersProtocol->Argv[LoopVar], EFI_FILE_MODE_READ, &FileList);
+ if (EFI_ERROR(Status) || FileList == NULL || IsListEmpty(&FileList->Link)) {
+ ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" \"", 0);
+ ArgSet = StrnCatGrow(&ArgSet, &ArgSize, gEfiShellParametersProtocol->Argv[LoopVar], 0);
+ ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0);
+ } else {
+ for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link)
+ ; !IsNull(&FileList->Link, &Node->Link)
+ ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link)
+ ){
+ ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" \"", 0);
+ ArgSet = StrnCatGrow(&ArgSet, &ArgSize, Node->FullName, 0);
+ ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0);
+ }
+ ShellCloseFileMetaArg(&FileList);
+ }
+ } else {
+ Parameter = gEfiShellParametersProtocol->Argv[LoopVar];
+ if (Parameter[0] == L'\"' && Parameter[StrLen(Parameter)-1] == L'\"') {
+ ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" ", 0);
+ ArgSet = StrnCatGrow(&ArgSet, &ArgSize, Parameter, 0);
+ } else {
+ ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" \"", 0);
+ ArgSet = StrnCatGrow(&ArgSet, &ArgSize, Parameter, 0);
+ ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0);
+ }
+ }
+ }
+ if (ArgSet == NULL) {
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ } else {
+ //
+ // set up for an 'in' for loop
+ //
+ NewSize = StrSize(ArgSet);
+ NewSize += sizeof(SHELL_FOR_INFO)+StrSize(gEfiShellParametersProtocol->Argv[1]);
+ Info = AllocateZeroPool(NewSize);
+ if (Info == NULL) {
+ FreePool (ArgSet);
+ return SHELL_OUT_OF_RESOURCES;
+ }
+ Info->Signature = SHELL_FOR_INFO_SIGNATURE;
+ CopyMem(Info->Set, ArgSet, StrSize(ArgSet));
+ NewSize = StrSize(gEfiShellParametersProtocol->Argv[1]);
+ CopyMem(Info->Set+(StrSize(ArgSet)/sizeof(Info->Set[0])), gEfiShellParametersProtocol->Argv[1], NewSize);
+ Info->ReplacementName = Info->Set+StrSize(ArgSet)/sizeof(Info->Set[0]);
+ Info->CurrentValue = (CHAR16*)Info->Set;
+ Info->Step = 0;
+ Info->Current = 0;
+ Info->End = 0;
+
+ if (InternalIsAliasOnList(Info->ReplacementName, &CurrentScriptFile->SubstList)) {
+ Info->RemoveSubstAlias = FALSE;
+ } else {
+ Info->RemoveSubstAlias = TRUE;
+ }
+ CurrentScriptFile->CurrentCommand->Data = Info;
+ }
+ } else if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ L"run",
+ gEfiShellParametersProtocol->Argv[2]) == 0) {
+ for (LoopVar = 0x3 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) {
+ ASSERT((ArgSet == NULL && ArgSize == 0) || (ArgSet != NULL));
+ if (StrStr (gEfiShellParametersProtocol->Argv[LoopVar], L")") != NULL &&
+ (LoopVar + 1) < gEfiShellParametersProtocol->Argc
+ ) {
+ return (SHELL_INVALID_PARAMETER);
+ }
+ if (ArgSet == NULL) {
+// ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L"\"", 0);
+ } else {
+ ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" ", 0);
+ }
+ ArgSet = StrnCatGrow(&ArgSet, &ArgSize, gEfiShellParametersProtocol->Argv[LoopVar], 0);
+// ArgSet = StrnCatGrow(&ArgSet, &ArgSize, L" ", 0);
+ }
+ if (ArgSet == NULL) {
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ } else {
+ //
+ // set up for a 'run' for loop
+ //
+ Info = AllocateZeroPool(sizeof(SHELL_FOR_INFO)+StrSize(gEfiShellParametersProtocol->Argv[1]));
+ if (Info == NULL) {
+ FreePool (ArgSet);
+ return SHELL_OUT_OF_RESOURCES;
+ }
+ Info->Signature = SHELL_FOR_INFO_SIGNATURE;
+ CopyMem(Info->Set, gEfiShellParametersProtocol->Argv[1], StrSize(gEfiShellParametersProtocol->Argv[1]));
+ Info->ReplacementName = Info->Set;
+ Info->CurrentValue = NULL;
+ ArgSetWalker = ArgSet;
+ if (ArgSetWalker[0] != L'(') {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT),
+ gShellLevel1HiiHandle,
+ ArgSet,
+ CurrentScriptFile->CurrentCommand->Line);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ TempSpot = StrStr(ArgSetWalker, L")");
+ if (TempSpot != NULL) {
+ TempString = TempSpot+1;
+ if (*(TempString) != CHAR_NULL) {
+ while(TempString != NULL && *TempString == L' ') {
+ TempString++;
+ }
+ if (StrLen(TempString) > 0) {
+ TempSpot = NULL;
+ }
+ }
+ }
+ if (TempSpot == NULL) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT),
+ gShellLevel1HiiHandle,
+ CurrentScriptFile->CurrentCommand->Line);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ *TempSpot = CHAR_NULL;
+ ArgSetWalker++;
+ while (ArgSetWalker != NULL && ArgSetWalker[0] == L' ') {
+ ArgSetWalker++;
+ }
+ if (!ShellIsValidForNumber(ArgSetWalker)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT),
+ gShellLevel1HiiHandle,
+ ArgSet,
+ CurrentScriptFile->CurrentCommand->Line);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ if (ArgSetWalker[0] == L'-') {
+ Info->Current = 0 - (INTN)ReturnUintn(ArgSetWalker+1);
+ } else {
+ Info->Current = (INTN)ReturnUintn(ArgSetWalker);
+ }
+ ArgSetWalker = StrStr(ArgSetWalker, L" ");
+ while (ArgSetWalker != NULL && ArgSetWalker[0] == L' ') {
+ ArgSetWalker++;
+ }
+ if (ArgSetWalker == NULL || *ArgSetWalker == CHAR_NULL || !ShellIsValidForNumber(ArgSetWalker)){
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT),
+ gShellLevel1HiiHandle,
+ ArgSet,
+ CurrentScriptFile->CurrentCommand->Line);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ if (ArgSetWalker[0] == L'-') {
+ Info->End = 0 - (INTN)ReturnUintn(ArgSetWalker+1);
+ } else {
+ Info->End = (INTN)ReturnUintn(ArgSetWalker);
+ }
+ if (Info->Current < Info->End) {
+ Info->Step = 1;
+ } else {
+ Info->Step = -1;
+ }
+
+ ArgSetWalker = StrStr(ArgSetWalker, L" ");
+ while (ArgSetWalker != NULL && ArgSetWalker[0] == L' ') {
+ ArgSetWalker++;
+ }
+ if (ArgSetWalker != NULL && *ArgSetWalker != CHAR_NULL) {
+ if (ArgSetWalker == NULL || *ArgSetWalker == CHAR_NULL || !ShellIsValidForNumber(ArgSetWalker)){
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT),
+ gShellLevel1HiiHandle,
+ ArgSet,
+ CurrentScriptFile->CurrentCommand->Line);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ if (*ArgSetWalker == L')') {
+ ASSERT(Info->Step == 1 || Info->Step == -1);
+ } else {
+ if (ArgSetWalker[0] == L'-') {
+ Info->Step = 0 - (INTN)ReturnUintn(ArgSetWalker+1);
+ } else {
+ Info->Step = (INTN)ReturnUintn(ArgSetWalker);
+ }
+
+ if (StrStr(ArgSetWalker, L" ") != NULL) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT),
+ gShellLevel1HiiHandle,
+ ArgSet,
+ CurrentScriptFile->CurrentCommand->Line);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ }
+ }
+
+ }
+ }
+ }
+ }
+ }
+ if (ShellStatus == SHELL_SUCCESS) {
+ if (InternalIsAliasOnList(Info->ReplacementName, &CurrentScriptFile->SubstList)) {
+ Info->RemoveSubstAlias = FALSE;
+ } else {
+ Info->RemoveSubstAlias = TRUE;
+ }
+ }
+ if (CurrentScriptFile->CurrentCommand != NULL) {
+ CurrentScriptFile->CurrentCommand->Data = Info;
+ }
+ }
+ } else {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_GEN_PROBLEM_SCRIPT),
+ gShellLevel1HiiHandle,
+ ArgSet,
+ CurrentScriptFile!=NULL
+ && CurrentScriptFile->CurrentCommand!=NULL
+ ? CurrentScriptFile->CurrentCommand->Line:0);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ } else {
+ //
+ // These need to be NULL since they are used to determine if this is the first pass later on...
+ //
+ ASSERT(ArgSetWalker == NULL);
+ ASSERT(ArgSet == NULL);
+ }
+
+ if (CurrentScriptFile != NULL && CurrentScriptFile->CurrentCommand != NULL) {
+ Info = (SHELL_FOR_INFO*)CurrentScriptFile->CurrentCommand->Data;
+ if (CurrentScriptFile->CurrentCommand->Reset) {
+ Info->CurrentValue = (CHAR16*)Info->Set;
+ FirstPass = TRUE;
+ CurrentScriptFile->CurrentCommand->Reset = FALSE;
+ }
+ } else {
+ ShellStatus = SHELL_UNSUPPORTED;
+ Info = NULL;
+ }
+ if (ShellStatus == SHELL_SUCCESS) {
+ ASSERT(Info != NULL);
+ if (Info->Step != 0) {
+ //
+ // only advance if not the first pass
+ //
+ if (!FirstPass) {
+ //
+ // sequence version of for loop...
+ //
+ Info->Current += Info->Step;
+ }
+
+ TempString = AllocateZeroPool(50*sizeof(CHAR16));
+ UnicodeSPrint(TempString, 50*sizeof(CHAR16), L"%d", Info->Current);
+ InternalUpdateAliasOnList(Info->ReplacementName, TempString, &CurrentScriptFile->SubstList);
+ FreePool(TempString);
+
+ if ((Info->Step > 0 && Info->Current > Info->End) || (Info->Step < 0 && Info->Current < Info->End)) {
+ CurrentScriptFile->CurrentCommand->Data = NULL;
+ //
+ // find the matching endfor (we're done with the loop)
+ //
+ if (!MoveToTag(GetNextNode, L"endfor", L"for", NULL, CurrentScriptFile, TRUE, FALSE, FALSE)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_SYNTAX_NO_MATCHING),
+ gShellLevel1HiiHandle,
+ L"EndFor",
+ L"For",
+ CurrentScriptFile!=NULL
+ && CurrentScriptFile->CurrentCommand!=NULL
+ ? CurrentScriptFile->CurrentCommand->Line:0);
+ ShellStatus = SHELL_DEVICE_ERROR;
+ }
+ if (Info->RemoveSubstAlias) {
+ //
+ // remove item from list
+ //
+ InternalRemoveAliasFromList(Info->ReplacementName, &CurrentScriptFile->SubstList);
+ }
+ FreePool(Info);
+ }
+ } else {
+ //
+ // Must be in 'in' version of for loop...
+ //
+ ASSERT(Info->Set != NULL);
+ if (Info->CurrentValue != NULL && *Info->CurrentValue != CHAR_NULL) {
+ if (Info->CurrentValue[0] == L' ') {
+ Info->CurrentValue++;
+ }
+ if (Info->CurrentValue[0] == L'\"') {
+ Info->CurrentValue++;
+ }
+ //
+ // do the next one of the set
+ //
+ ASSERT(TempString == NULL);
+ TempString = StrnCatGrow(&TempString, NULL, Info->CurrentValue, 0);
+ if (TempString == NULL) {
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ } else {
+ TempSpot = StrStr(TempString, L"\" \"");
+ if (TempSpot != NULL) {
+ *TempSpot = CHAR_NULL;
+ }
+ while (TempString[StrLen(TempString)-1] == L'\"') {
+ TempString[StrLen(TempString)-1] = CHAR_NULL;
+ }
+ InternalUpdateAliasOnList(Info->ReplacementName, TempString, &CurrentScriptFile->SubstList);
+ Info->CurrentValue += StrLen(TempString);
+
+ if (Info->CurrentValue[0] == L'\"') {
+ Info->CurrentValue++;
+ }
+ FreePool(TempString);
+ }
+ } else {
+ CurrentScriptFile->CurrentCommand->Data = NULL;
+ //
+ // find the matching endfor (we're done with the loop)
+ //
+ if (!MoveToTag(GetNextNode, L"endfor", L"for", NULL, CurrentScriptFile, TRUE, FALSE, FALSE)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_SYNTAX_NO_MATCHING),
+ gShellLevel1HiiHandle,
+ L"EndFor",
+ L"For",
+ CurrentScriptFile!=NULL
+ && CurrentScriptFile->CurrentCommand!=NULL
+ ? CurrentScriptFile->CurrentCommand->Line:0);
+ ShellStatus = SHELL_DEVICE_ERROR;
+ }
+ if (Info->RemoveSubstAlias) {
+ //
+ // remove item from list
+ //
+ InternalRemoveAliasFromList(Info->ReplacementName, &CurrentScriptFile->SubstList);
+ }
+ FreePool(Info);
+ }
+ }
+ }
+ if (ArgSet != NULL) {
+ FreePool(ArgSet);
+ }
+ return (ShellStatus);
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/Goto.c b/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/Goto.c
new file mode 100644
index 0000000000..88e290daa7
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/Goto.c
@@ -0,0 +1,105 @@
+/** @file
+ Main file for goto shell level 1 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel1CommandsLib.h"
+
+/**
+ Function for 'goto' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunGoto (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ CHAR16 *CompareString;
+ UINTN Size;
+ SCRIPT_FILE *CurrentScriptFile;
+
+ ShellStatus = SHELL_SUCCESS;
+ CompareString = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ if (!gEfiShellProtocol->BatchIsActive()) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"Goto");
+ return (SHELL_UNSUPPORTED);
+ }
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel1HiiHandle, L"goto", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetRawValue(Package, 2) != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle, L"goto");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetRawValue(Package, 1) == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel1HiiHandle, L"goto");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Size = 0;
+ ASSERT((CompareString == NULL && Size == 0) || (CompareString != NULL));
+ CompareString = StrnCatGrow(&CompareString, &Size, L":", 0);
+ CompareString = StrnCatGrow(&CompareString, &Size, ShellCommandLineGetRawValue(Package, 1), 0);
+ //
+ // Check forwards and then backwards for a label...
+ //
+ if (!MoveToTag(GetNextNode, L"endfor", L"for", CompareString, ShellCommandGetCurrentScriptFile(), FALSE, FALSE, TRUE)) {
+ CurrentScriptFile = ShellCommandGetCurrentScriptFile();
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_SYNTAX_NO_MATCHING),
+ gShellLevel1HiiHandle,
+ CompareString,
+ L"Goto",
+ CurrentScriptFile!=NULL
+ && CurrentScriptFile->CurrentCommand!=NULL
+ ? CurrentScriptFile->CurrentCommand->Line:0);
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ FreePool(CompareString);
+ }
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ return (ShellStatus);
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/If.c b/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/If.c
new file mode 100644
index 0000000000..37e196c2c1
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/If.c
@@ -0,0 +1,1117 @@
+/** @file
+ Main file for If and else shell level 1 function.
+
+ (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel1CommandsLib.h"
+#include <Library/PrintLib.h>
+
+typedef enum {
+ EndTagOr,
+ EndTagAnd,
+ EndTagThen,
+ EndTagMax
+} END_TAG_TYPE;
+
+typedef enum {
+ OperatorGreaterThan,
+ OperatorLessThan,
+ OperatorEqual,
+ OperatorNotEqual,
+ OperatorGreatorOrEqual,
+ OperatorLessOrEqual,
+ OperatorUnisgnedGreaterThan,
+ OperatorUnsignedLessThan,
+ OperatorUnsignedGreaterOrEqual,
+ OperatorUnsignedLessOrEqual,
+ OperatorMax
+} BIN_OPERATOR_TYPE;
+
+/**
+ Extract the next fragment, if there is one.
+
+ @param[in, out] Statement The current remaining statement.
+ @param[in] Fragment The current fragment.
+ @param[out] Match TRUE when there is another Fragment in Statement,
+ FALSE otherwise.
+
+ @retval EFI_SUCCESS The match operation is performed successfully.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+**/
+EFI_STATUS
+IsNextFragment (
+ IN OUT CONST CHAR16 **Statement,
+ IN CONST CHAR16 *Fragment,
+ OUT BOOLEAN *Match
+ )
+{
+ CHAR16 *Tester;
+
+ Tester = NULL;
+
+ Tester = StrnCatGrow(&Tester, NULL, *Statement, StrLen(Fragment));
+ if (Tester == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ Tester[StrLen(Fragment)] = CHAR_NULL;
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)Fragment,
+ Tester) == 0) {
+ //
+ // increment the string pointer to the end of what we found and then chop off spaces...
+ //
+ *Statement+=StrLen(Fragment);
+ while (*Statement[0] == L' ') {
+ (*Statement)++;
+ }
+ *Match = TRUE;
+ } else {
+ *Match = FALSE;
+ }
+ FreePool(Tester);
+ return EFI_SUCCESS;
+}
+
+/**
+ Determine if String represents a valid profile.
+
+ @param[in] String The pointer to the string to test.
+
+ @retval TRUE String is a valid profile.
+ @retval FALSE String is not a valid profile.
+**/
+BOOLEAN
+EFIAPI
+IsValidProfile (
+ IN CONST CHAR16 *String
+ )
+{
+ CONST CHAR16 *ProfilesString;
+ CONST CHAR16 *TempLocation;
+
+ ProfilesString = ShellGetEnvironmentVariable(L"profiles");
+ ASSERT(ProfilesString != NULL);
+ TempLocation = StrStr(ProfilesString, String);
+ if ((TempLocation != NULL) && (*(TempLocation-1) == L';') && (*(TempLocation+StrLen(String)) == L';')) {
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/**
+ Do a comparison between 2 things.
+
+ @param[in] Compare1 The first item to compare.
+ @param[in] Compare2 The second item to compare.
+ @param[in] BinOp The type of comparison to perform.
+ @param[in] CaseInsensitive TRUE to do non-case comparison, FALSE otherwise.
+ @param[in] ForceStringCompare TRUE to force string comparison, FALSE otherwise.
+
+ @return The result of the comparison.
+**/
+BOOLEAN
+EFIAPI
+TestOperation (
+ IN CONST CHAR16 *Compare1,
+ IN CONST CHAR16 *Compare2,
+ IN CONST BIN_OPERATOR_TYPE BinOp,
+ IN CONST BOOLEAN CaseInsensitive,
+ IN CONST BOOLEAN ForceStringCompare
+ )
+{
+ INTN Cmp1;
+ INTN Cmp2;
+
+ //
+ // "Compare1 BinOp Compare2"
+ //
+ switch (BinOp) {
+ case OperatorUnisgnedGreaterThan:
+ case OperatorGreaterThan:
+ if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {
+ //
+ // string compare
+ //
+ if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) > 0) || (StringCompare(&Compare1, &Compare2) > 0)) {
+ return (TRUE);
+ }
+ } else {
+ //
+ // numeric compare
+ //
+ if (Compare1[0] == L'-') {
+ Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1);
+ } else {
+ Cmp1 = (INTN)ShellStrToUintn(Compare1);
+ }
+ if (Compare2[0] == L'-') {
+ Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1);
+ } else {
+ Cmp2 = (INTN)ShellStrToUintn(Compare2);
+ }
+ if (BinOp == OperatorGreaterThan) {
+ if (Cmp1 > Cmp2) {
+ return (TRUE);
+ }
+ } else {
+ if ((UINTN)Cmp1 > (UINTN)Cmp2) {
+ return (TRUE);
+ }
+ }
+ }
+ return (FALSE);
+ case OperatorUnsignedLessThan:
+ case OperatorLessThan:
+ if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {
+ //
+ // string compare
+ //
+ if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) < 0) || (StringCompare(&Compare1, &Compare2) < 0)) {
+ return (TRUE);
+ }
+ } else {
+ //
+ // numeric compare
+ //
+ if (Compare1[0] == L'-') {
+ Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1);
+ } else {
+ Cmp1 = (INTN)ShellStrToUintn(Compare1);
+ }
+ if (Compare2[0] == L'-') {
+ Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1);
+ } else {
+ Cmp2 = (INTN)ShellStrToUintn(Compare2);
+ }
+ if (BinOp == OperatorLessThan) {
+ if (Cmp1 < Cmp2) {
+ return (TRUE);
+ }
+ } else {
+ if ((UINTN)Cmp1 < (UINTN)Cmp2) {
+ return (TRUE);
+ }
+ }
+
+ }
+ return (FALSE);
+ case OperatorEqual:
+ if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {
+ //
+ // string compare
+ //
+ if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) == 0) || (StringCompare(&Compare1, &Compare2) == 0)) {
+ return (TRUE);
+ }
+ } else {
+ //
+ // numeric compare
+ //
+ if (Compare1[0] == L'-') {
+ Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1);
+ } else {
+ Cmp1 = (INTN)ShellStrToUintn(Compare1);
+ }
+ if (Compare2[0] == L'-') {
+ Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1);
+ } else {
+ Cmp2 = (INTN)ShellStrToUintn(Compare2);
+ }
+ if (Cmp1 == Cmp2) {
+ return (TRUE);
+ }
+ }
+ return (FALSE);
+ case OperatorNotEqual:
+ if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {
+ //
+ // string compare
+ //
+ if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) != 0) || (StringCompare(&Compare1, &Compare2) != 0)) {
+ return (TRUE);
+ }
+ } else {
+ //
+ // numeric compare
+ //
+ if (Compare1[0] == L'-') {
+ Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1);
+ } else {
+ Cmp1 = (INTN)ShellStrToUintn(Compare1);
+ }
+ if (Compare2[0] == L'-') {
+ Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1);
+ } else {
+ Cmp2 = (INTN)ShellStrToUintn(Compare2);
+ }
+ if (Cmp1 != Cmp2) {
+ return (TRUE);
+ }
+ }
+ return (FALSE);
+ case OperatorUnsignedGreaterOrEqual:
+ case OperatorGreatorOrEqual:
+ if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {
+ //
+ // string compare
+ //
+ if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) >= 0) || (StringCompare(&Compare1, &Compare2) >= 0)) {
+ return (TRUE);
+ }
+ } else {
+ //
+ // numeric compare
+ //
+ if (Compare1[0] == L'-') {
+ Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1);
+ } else {
+ Cmp1 = (INTN)ShellStrToUintn(Compare1);
+ }
+ if (Compare2[0] == L'-') {
+ Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1);
+ } else {
+ Cmp2 = (INTN)ShellStrToUintn(Compare2);
+ }
+ if (BinOp == OperatorGreatorOrEqual) {
+ if (Cmp1 >= Cmp2) {
+ return (TRUE);
+ }
+ } else {
+ if ((UINTN)Cmp1 >= (UINTN)Cmp2) {
+ return (TRUE);
+ }
+ }
+ }
+ return (FALSE);
+ case OperatorLessOrEqual:
+ case OperatorUnsignedLessOrEqual:
+ if (ForceStringCompare || !ShellIsHexOrDecimalNumber(Compare1, FALSE, FALSE) || !ShellIsHexOrDecimalNumber(Compare2, FALSE, FALSE)) {
+ //
+ // string compare
+ //
+ if ((CaseInsensitive && StringNoCaseCompare(&Compare1, &Compare2) <= 0) || (StringCompare(&Compare1, &Compare2) <= 0)) {
+ return (TRUE);
+ }
+ } else {
+ //
+ // numeric compare
+ //
+ if (Compare1[0] == L'-') {
+ Cmp1 = 0 - (INTN)ShellStrToUintn(Compare1+1);
+ } else {
+ Cmp1 = (INTN)ShellStrToUintn(Compare1);
+ }
+ if (Compare2[0] == L'-') {
+ Cmp2 = 0 - (INTN)ShellStrToUintn(Compare2+1);
+ } else {
+ Cmp2 = (INTN)ShellStrToUintn(Compare2);
+ }
+ if (BinOp == OperatorLessOrEqual) {
+ if (Cmp1 <= Cmp2) {
+ return (TRUE);
+ }
+ } else {
+ if ((UINTN)Cmp1 <= (UINTN)Cmp2) {
+ return (TRUE);
+ }
+ }
+ }
+ return (FALSE);
+ default:
+ ASSERT(FALSE);
+ return (FALSE);
+ }
+}
+
+/**
+ Process an if statement and determine if its is valid or not.
+
+ @param[in, out] PassingState Opon entry, the current state. Upon exit,
+ the new state.
+ @param[in] StartParameterNumber The number of the first parameter of
+ this statement.
+ @param[in] EndParameterNumber The number of the final parameter of
+ this statement.
+ @param[in] OperatorToUse The type of termination operator.
+ @param[in] CaseInsensitive TRUE for case insensitive, FALSE otherwise.
+ @param[in] ForceStringCompare TRUE for all string based, FALSE otherwise.
+
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+ProcessStatement (
+ IN OUT BOOLEAN *PassingState,
+ IN UINTN StartParameterNumber,
+ IN UINTN EndParameterNumber,
+ IN CONST END_TAG_TYPE OperatorToUse,
+ IN CONST BOOLEAN CaseInsensitive,
+ IN CONST BOOLEAN ForceStringCompare
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN OperationResult;
+ BOOLEAN NotPresent;
+ CHAR16 *StatementWalker;
+ BIN_OPERATOR_TYPE BinOp;
+ CHAR16 *Compare1;
+ CHAR16 *Compare2;
+ CHAR16 HexString[20];
+ CHAR16 *TempSpot;
+ BOOLEAN Match;
+
+ ASSERT((END_TAG_TYPE)OperatorToUse != EndTagThen);
+
+ Status = EFI_SUCCESS;
+ BinOp = OperatorMax;
+ OperationResult = FALSE;
+ Match = FALSE;
+ StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber];
+ if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"not", &Match)) && Match) {
+ NotPresent = TRUE;
+ StatementWalker = gEfiShellParametersProtocol->Argv[++StartParameterNumber];
+ } else {
+ NotPresent = FALSE;
+ }
+
+ //
+ // now check for 'boolfunc' operators
+ //
+ if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"isint", &Match)) && Match) {
+ if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match
+ && StatementWalker[StrLen(StatementWalker)-1] == L')') {
+ StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL;
+ OperationResult = ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE);
+ } else {
+ Status = EFI_INVALID_PARAMETER;
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"isint");
+ }
+ } else if ((!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"exists", &Match)) && Match) ||
+ (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"exist", &Match)) && Match)) {
+ if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match &&
+ StatementWalker[StrLen(StatementWalker)-1] == L')') {
+ StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL;
+ //
+ // is what remains a file in CWD???
+ //
+ OperationResult = (BOOLEAN)(ShellFileExists(StatementWalker)==EFI_SUCCESS);
+ } else if (StatementWalker[0] == CHAR_NULL && StartParameterNumber+1 == EndParameterNumber) {
+ OperationResult = (BOOLEAN)(ShellFileExists(gEfiShellParametersProtocol->Argv[++StartParameterNumber])==EFI_SUCCESS);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"exist(s)");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"available", &Match)) && Match) {
+ if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match &&
+ StatementWalker[StrLen(StatementWalker)-1] == L')') {
+ StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL;
+ //
+ // is what remains a file in the CWD or path???
+ //
+ OperationResult = (BOOLEAN)(ShellIsFileInPath(StatementWalker)==EFI_SUCCESS);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"available");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"profile", &Match)) && Match) {
+ if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match &&
+ StatementWalker[StrLen(StatementWalker)-1] == L')') {
+ //
+ // Chop off that ')'
+ //
+ StatementWalker[StrLen(StatementWalker)-1] = CHAR_NULL;
+ OperationResult = IsValidProfile(StatementWalker);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"profile");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else if (StartParameterNumber+1 >= EndParameterNumber) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[StartParameterNumber]);
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ //
+ // must be 'item binop item' style
+ //
+ Compare1 = NULL;
+ Compare2 = NULL;
+ BinOp = OperatorMax;
+
+ //
+ // get the first item
+ //
+ StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber];
+ if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"efierror", &Match)) && Match) {
+ TempSpot = StrStr(StatementWalker, L")");
+ if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match && TempSpot != NULL) {
+ *TempSpot = CHAR_NULL;
+ if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
+ UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT);
+ ASSERT(Compare1 == NULL);
+ Compare1 = StrnCatGrow(&Compare1, NULL, HexString, 0);
+ StatementWalker += StrLen(StatementWalker) + 1;
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"pierror", &Match)) && Match) {
+ TempSpot = StrStr(StatementWalker, L")");
+ if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match && TempSpot != NULL) {
+ *TempSpot = CHAR_NULL;
+ if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
+ UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>2));
+ ASSERT(Compare1 == NULL);
+ Compare1 = StrnCatGrow(&Compare1, NULL, HexString, 0);
+ StatementWalker += StrLen(StatementWalker) + 1;
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else if (!EFI_ERROR (IsNextFragment ((CONST CHAR16**)(&StatementWalker), L"oemerror", &Match)) && Match) {
+ TempSpot = StrStr(StatementWalker, L")");
+ if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match && TempSpot != NULL) {
+ TempSpot = CHAR_NULL;
+ if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
+ UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>1));
+ ASSERT(Compare1 == NULL);
+ Compare1 = StrnCatGrow(&Compare1, NULL, HexString, 0);
+ StatementWalker += StrLen(StatementWalker) + 1;
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else {
+ ASSERT(Compare1 == NULL);
+ if (EndParameterNumber - StartParameterNumber > 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_STARTING), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[StartParameterNumber+2]);
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ //
+ // must be a raw string
+ //
+ Compare1 = StrnCatGrow(&Compare1, NULL, StatementWalker, 0);
+ }
+ }
+
+ //
+ // get the operator
+ //
+ ASSERT(StartParameterNumber+1<EndParameterNumber);
+ StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber+1];
+ if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"gt", &Match)) && Match) {
+ BinOp = OperatorGreaterThan;
+ } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"lt", &Match)) && Match) {
+ BinOp = OperatorLessThan;
+ } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"eq", &Match)) && Match) {
+ BinOp = OperatorEqual;
+ } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ne", &Match)) && Match) {
+ BinOp = OperatorNotEqual;
+ } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ge", &Match)) && Match) {
+ BinOp = OperatorGreatorOrEqual;
+ } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"le", &Match)) && Match) {
+ BinOp = OperatorLessOrEqual;
+ } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"==", &Match)) && Match) {
+ BinOp = OperatorEqual;
+ } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ugt", &Match)) && Match) {
+ BinOp = OperatorUnisgnedGreaterThan;
+ } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ult", &Match)) && Match) {
+ BinOp = OperatorUnsignedLessThan;
+ } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"uge", &Match)) && Match) {
+ BinOp = OperatorUnsignedGreaterOrEqual;
+ } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"ule", &Match)) && Match) {
+ BinOp = OperatorUnsignedLessOrEqual;
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_INVALID_BINOP), gShellLevel1HiiHandle, StatementWalker);
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // get the second item
+ //
+ ASSERT(StartParameterNumber+2<=EndParameterNumber);
+ StatementWalker = gEfiShellParametersProtocol->Argv[StartParameterNumber+2];
+ if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"efierror", &Match)) && Match) {
+ TempSpot = StrStr(StatementWalker, L")");
+ if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match && TempSpot != NULL) {
+ TempSpot = CHAR_NULL;
+ if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
+ UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT);
+ ASSERT(Compare2 == NULL);
+ Compare2 = StrnCatGrow(&Compare2, NULL, HexString, 0);
+ StatementWalker += StrLen(StatementWalker) + 1;
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"efierror");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ //
+ // can this be collapsed into the above?
+ //
+ } else if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"pierror", &Match)) && Match) {
+ TempSpot = StrStr(StatementWalker, L")");
+ if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match && TempSpot != NULL) {
+ TempSpot = CHAR_NULL;
+ if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
+ UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>2));
+ ASSERT(Compare2 == NULL);
+ Compare2 = StrnCatGrow(&Compare2, NULL, HexString, 0);
+ StatementWalker += StrLen(StatementWalker) + 1;
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"pierror");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else if (!EFI_ERROR (IsNextFragment ((CONST CHAR16**)(&StatementWalker), L"oemerror", &Match)) && Match) {
+ TempSpot = StrStr(StatementWalker, L")");
+ if (!EFI_ERROR (IsNextFragment((CONST CHAR16**)(&StatementWalker), L"(", &Match)) && Match && TempSpot != NULL) {
+ TempSpot = CHAR_NULL;
+ if (ShellIsHexOrDecimalNumber(StatementWalker, FALSE, FALSE)) {
+ UnicodeSPrint(HexString, sizeof(HexString), L"0x%x", ShellStrToUintn(StatementWalker)|MAX_BIT|(MAX_BIT>>1));
+ ASSERT(Compare2 == NULL);
+ Compare2 = StrnCatGrow(&Compare2, NULL, HexString, 0);
+ StatementWalker += StrLen(StatementWalker) + 1;
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_IN), gShellLevel1HiiHandle, L"oemerror");
+ Status = EFI_INVALID_PARAMETER;
+ }
+ } else {
+ //
+ // must be a raw string
+ //
+ ASSERT(Compare2 == NULL);
+ Compare2 = StrnCatGrow(&Compare2, NULL, StatementWalker, 0);
+ }
+
+ if (Compare1 != NULL && Compare2 != NULL && BinOp != OperatorMax) {
+ OperationResult = TestOperation(Compare1, Compare2, BinOp, CaseInsensitive, ForceStringCompare);
+ }
+
+ SHELL_FREE_NON_NULL(Compare1);
+ SHELL_FREE_NON_NULL(Compare2);
+ }
+
+ //
+ // done processing do result...
+ //
+
+ if (!EFI_ERROR(Status)) {
+ if (NotPresent) {
+ OperationResult = (BOOLEAN)(!OperationResult);
+ }
+ switch(OperatorToUse) {
+ case EndTagOr:
+ *PassingState = (BOOLEAN)(*PassingState || OperationResult);
+ break;
+ case EndTagAnd:
+ *PassingState = (BOOLEAN)(*PassingState && OperationResult);
+ break;
+ case EndTagMax:
+ *PassingState = (BOOLEAN)(OperationResult);
+ break;
+ default:
+ ASSERT(FALSE);
+ }
+ }
+ return (Status);
+}
+
+/**
+ Break up the next part of the if statement (until the next 'and', 'or', or 'then').
+
+ @param[in] ParameterNumber The current parameter number.
+ @param[out] EndParameter Upon successful return, will point to the
+ parameter to start the next iteration with.
+ @param[out] EndTag Upon successful return, will point to the
+ type that was found at the end of this statement.
+
+ @retval TRUE A valid statement was found.
+ @retval FALSE A valid statement was not found.
+**/
+BOOLEAN
+EFIAPI
+BuildNextStatement (
+ IN UINTN ParameterNumber,
+ OUT UINTN *EndParameter,
+ OUT END_TAG_TYPE *EndTag
+ )
+{
+ *EndTag = EndTagMax;
+
+ for(
+ ; ParameterNumber < gEfiShellParametersProtocol->Argc
+ ; ParameterNumber++
+ ) {
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ gEfiShellParametersProtocol->Argv[ParameterNumber],
+ L"or") == 0) {
+ *EndParameter = ParameterNumber - 1;
+ *EndTag = EndTagOr;
+ break;
+ } else if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ gEfiShellParametersProtocol->Argv[ParameterNumber],
+ L"and") == 0) {
+ *EndParameter = ParameterNumber - 1;
+ *EndTag = EndTagAnd;
+ break;
+ } else if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ gEfiShellParametersProtocol->Argv[ParameterNumber],
+ L"then") == 0) {
+ *EndParameter = ParameterNumber - 1;
+ *EndTag = EndTagThen;
+ break;
+ }
+ }
+ if (*EndTag == EndTagMax) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+/**
+ Move the script file pointer to a different place in the script file.
+ This one is special since it handles the if/else/endif syntax.
+
+ @param[in] ScriptFile The script file from GetCurrnetScriptFile().
+
+ @retval TRUE The move target was found and the move was successful.
+ @retval FALSE Something went wrong.
+**/
+BOOLEAN
+EFIAPI
+MoveToTagSpecial (
+ IN SCRIPT_FILE *ScriptFile
+ )
+{
+ SCRIPT_COMMAND_LIST *CommandNode;
+ BOOLEAN Found;
+ UINTN TargetCount;
+ CHAR16 *CommandName;
+ CHAR16 *CommandWalker;
+ CHAR16 *TempLocation;
+
+ TargetCount = 1;
+ Found = FALSE;
+
+ if (ScriptFile == NULL) {
+ return FALSE;
+ }
+
+ for (CommandNode = (SCRIPT_COMMAND_LIST *)GetNextNode(&ScriptFile->CommandList, &ScriptFile->CurrentCommand->Link), Found = FALSE
+ ; !IsNull(&ScriptFile->CommandList, &CommandNode->Link) && !Found
+ ; CommandNode = (SCRIPT_COMMAND_LIST *)GetNextNode(&ScriptFile->CommandList, &CommandNode->Link)
+ ){
+
+ //
+ // get just the first part of the command line...
+ //
+ CommandName = NULL;
+ CommandName = StrnCatGrow(&CommandName, NULL, CommandNode->Cl, 0);
+ if (CommandName == NULL) {
+ continue;
+ }
+ CommandWalker = CommandName;
+
+ //
+ // Skip leading spaces and tabs.
+ //
+ while ((CommandWalker[0] == L' ') || (CommandWalker[0] == L'\t')) {
+ CommandWalker++;
+ }
+ TempLocation = StrStr(CommandWalker, L" ");
+
+ if (TempLocation != NULL) {
+ *TempLocation = CHAR_NULL;
+ }
+
+ //
+ // did we find a nested item ?
+ //
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)CommandWalker,
+ L"If") == 0) {
+ TargetCount++;
+ } else if (TargetCount == 1 && gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)CommandWalker,
+ (CHAR16*)L"else") == 0) {
+ //
+ // else can only decrement the last part... not an nested if
+ // hence the TargetCount compare added
+ //
+ TargetCount--;
+ } else if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)CommandWalker,
+ (CHAR16*)L"endif") == 0) {
+ TargetCount--;
+ }
+ if (TargetCount == 0) {
+ ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)GetNextNode(&ScriptFile->CommandList, &CommandNode->Link);
+ Found = TRUE;
+ }
+
+ //
+ // Free the memory for this loop...
+ //
+ SHELL_FREE_NON_NULL(CommandName);
+ }
+ return (Found);
+}
+
+/**
+ Deal with the result of the if operation.
+
+ @param[in] Result The result of the if.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_NOT_FOUND The ending tag could not be found.
+**/
+EFI_STATUS
+EFIAPI
+PerformResultOperation (
+ IN CONST BOOLEAN Result
+ )
+{
+ if (Result || MoveToTagSpecial(ShellCommandGetCurrentScriptFile())) {
+ return (EFI_SUCCESS);
+ }
+ return (EFI_NOT_FOUND);
+}
+
+/**
+ Function for 'if' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunIf (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ SHELL_STATUS ShellStatus;
+ BOOLEAN CaseInsensitive;
+ BOOLEAN ForceString;
+ UINTN CurrentParameter;
+ UINTN EndParameter;
+ BOOLEAN CurrentValue;
+ END_TAG_TYPE Ending;
+ END_TAG_TYPE PreviousEnding;
+ SCRIPT_FILE *CurrentScriptFile;
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ if (!gEfiShellProtocol->BatchIsActive()) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"if");
+ return (SHELL_UNSUPPORTED);
+ }
+
+ if (gEfiShellParametersProtocol->Argc < 3) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel1HiiHandle, L"if");
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ //
+ // Make sure that an End exists.
+ //
+ CurrentScriptFile = ShellCommandGetCurrentScriptFile();
+ if (!MoveToTag(GetNextNode, L"endif", L"if", NULL, CurrentScriptFile, TRUE, TRUE, FALSE)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_SYNTAX_NO_MATCHING),
+ gShellLevel1HiiHandle,
+ L"EndIf",
+ L"If",
+ CurrentScriptFile!=NULL
+ && CurrentScriptFile->CurrentCommand!=NULL
+ ? CurrentScriptFile->CurrentCommand->Line:0);
+ return (SHELL_DEVICE_ERROR);
+ }
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ CurrentParameter = 1;
+ EndParameter = 0;
+
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ gEfiShellParametersProtocol->Argv[1],
+ L"/i") == 0 ||
+ gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ gEfiShellParametersProtocol->Argv[2],
+ L"/i") == 0 ||
+ (gEfiShellParametersProtocol->Argc > 3 && gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ gEfiShellParametersProtocol->Argv[3],
+ L"/i") == 0)) {
+ CaseInsensitive = TRUE;
+ CurrentParameter++;
+ } else {
+ CaseInsensitive = FALSE;
+ }
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ gEfiShellParametersProtocol->Argv[1],
+ L"/s") == 0 ||
+ gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ gEfiShellParametersProtocol->Argv[2],
+ L"/s") == 0 ||
+ (gEfiShellParametersProtocol->Argc > 3 && gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ gEfiShellParametersProtocol->Argv[3],
+ L"/s") == 0)) {
+ ForceString = TRUE;
+ CurrentParameter++;
+ } else {
+ ForceString = FALSE;
+ }
+
+ for ( ShellStatus = SHELL_SUCCESS, CurrentValue = FALSE, Ending = EndTagMax
+ ; CurrentParameter < gEfiShellParametersProtocol->Argc && ShellStatus == SHELL_SUCCESS
+ ; CurrentParameter++) {
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ gEfiShellParametersProtocol->Argv[CurrentParameter],
+ L"then") == 0) {
+ //
+ // we are at the then
+ //
+ if (CurrentParameter+1 != gEfiShellParametersProtocol->Argc) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TEXT_AFTER_THEN), gShellLevel1HiiHandle, L"if");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Status = PerformResultOperation(CurrentValue);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_AFTER_BAD), gShellLevel1HiiHandle, L"if", gEfiShellParametersProtocol->Argv[CurrentParameter]);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ }
+ } else {
+ PreviousEnding = Ending;
+ //
+ // build up the next statement for analysis
+ //
+ if (!BuildNextStatement(CurrentParameter, &EndParameter, &Ending)) {
+ CurrentScriptFile = ShellCommandGetCurrentScriptFile();
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_SYNTAX_NO_MATCHING),
+ gShellLevel1HiiHandle,
+ L"Then",
+ L"If",
+ CurrentScriptFile!=NULL
+ && CurrentScriptFile->CurrentCommand!=NULL
+ ? CurrentScriptFile->CurrentCommand->Line:0);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // Analyze the statement
+ //
+ Status = ProcessStatement(&CurrentValue, CurrentParameter, EndParameter, PreviousEnding, CaseInsensitive, ForceString);
+ if (EFI_ERROR(Status)) {
+// ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_STARTING), gShellLevel1HiiHandle, gEfiShellParametersProtocol->Argv[CurrentParameter]);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // Optomize to get out of the loop early...
+ //
+ if ((Ending == EndTagOr && CurrentValue) || (Ending == EndTagAnd && !CurrentValue)) {
+ Status = PerformResultOperation(CurrentValue);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SYNTAX_AFTER_BAD), gShellLevel1HiiHandle, L"if", gEfiShellParametersProtocol->Argv[CurrentParameter]);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ break;
+ }
+ }
+ }
+ if (ShellStatus == SHELL_SUCCESS){
+ CurrentParameter = EndParameter;
+ //
+ // Skip over the or or and parameter.
+ //
+ if (Ending == EndTagOr || Ending == EndTagAnd) {
+ CurrentParameter++;
+ }
+ }
+ }
+ }
+ return (ShellStatus);
+}
+
+/**
+ Function for 'else' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunElse (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ SCRIPT_FILE *CurrentScriptFile;
+
+ Status = CommandInit ();
+ ASSERT_EFI_ERROR (Status);
+
+ if (gEfiShellParametersProtocol->Argc > 1) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle, L"if");
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ if (!gEfiShellProtocol->BatchIsActive()) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"Else");
+ return (SHELL_UNSUPPORTED);
+ }
+
+ CurrentScriptFile = ShellCommandGetCurrentScriptFile();
+
+ if (!MoveToTag(GetPreviousNode, L"if", L"endif", NULL, CurrentScriptFile, FALSE, TRUE, FALSE)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_SYNTAX_NO_MATCHING),
+ gShellLevel1HiiHandle,
+ L"If",
+ L"Else",
+ CurrentScriptFile!=NULL
+ && CurrentScriptFile->CurrentCommand!=NULL
+ ? CurrentScriptFile->CurrentCommand->Line:0);
+ return (SHELL_DEVICE_ERROR);
+ }
+ if (!MoveToTag(GetPreviousNode, L"if", L"else", NULL, CurrentScriptFile, FALSE, TRUE, FALSE)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_SYNTAX_NO_MATCHING),
+ gShellLevel1HiiHandle,
+ L"If",
+ L"Else",
+ CurrentScriptFile!=NULL
+ && CurrentScriptFile->CurrentCommand!=NULL
+ ? CurrentScriptFile->CurrentCommand->Line:0);
+ return (SHELL_DEVICE_ERROR);
+ }
+
+ if (!MoveToTag(GetNextNode, L"endif", L"if", NULL, CurrentScriptFile, FALSE, FALSE, FALSE)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_SYNTAX_NO_MATCHING),
+ gShellLevel1HiiHandle,
+ L"EndIf",
+ "Else",
+ CurrentScriptFile!=NULL
+ && CurrentScriptFile->CurrentCommand!=NULL
+ ? CurrentScriptFile->CurrentCommand->Line:0);
+ return (SHELL_DEVICE_ERROR);
+ }
+
+ return (SHELL_SUCCESS);
+}
+
+/**
+ Function for 'endif' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunEndIf (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ SCRIPT_FILE *CurrentScriptFile;
+
+ Status = CommandInit ();
+ ASSERT_EFI_ERROR (Status);
+
+ if (gEfiShellParametersProtocol->Argc > 1) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle, L"if");
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ if (!gEfiShellProtocol->BatchIsActive()) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"Endif");
+ return (SHELL_UNSUPPORTED);
+ }
+
+ CurrentScriptFile = ShellCommandGetCurrentScriptFile();
+ if (!MoveToTag(GetPreviousNode, L"if", L"endif", NULL, CurrentScriptFile, FALSE, TRUE, FALSE)) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_SYNTAX_NO_MATCHING),
+ gShellLevel1HiiHandle,
+ L"If",
+ L"EndIf",
+ CurrentScriptFile!=NULL
+ && CurrentScriptFile->CurrentCommand!=NULL
+ ? CurrentScriptFile->CurrentCommand->Line:0);
+ return (SHELL_DEVICE_ERROR);
+ }
+
+ return (SHELL_SUCCESS);
+}
diff --git a/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/Shift.c b/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/Shift.c
new file mode 100644
index 0000000000..08c54f8f7a
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/Shift.c
@@ -0,0 +1,64 @@
+/** @file
+ Main file for Shift shell level 1 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel1CommandsLib.h"
+
+/**
+ Function for 'shift' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunShift (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ SCRIPT_FILE *CurrentScriptFile;
+ UINTN LoopVar;
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ if (!gEfiShellProtocol->BatchIsActive()) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel1HiiHandle, L"shift");
+ return (SHELL_UNSUPPORTED);
+ }
+
+ CurrentScriptFile = ShellCommandGetCurrentScriptFile();
+ ASSERT(CurrentScriptFile != NULL);
+
+ if (CurrentScriptFile->Argc < 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel1HiiHandle, L"shift");
+ return (SHELL_UNSUPPORTED);
+ }
+
+ for (LoopVar = 0 ; LoopVar < CurrentScriptFile->Argc ; LoopVar++) {
+ if (LoopVar == 0) {
+ SHELL_FREE_NON_NULL(CurrentScriptFile->Argv[LoopVar]);
+ }
+ if (LoopVar < CurrentScriptFile->Argc -1) {
+ CurrentScriptFile->Argv[LoopVar] = CurrentScriptFile->Argv[LoopVar+1];
+ } else {
+ CurrentScriptFile->Argv[LoopVar] = NULL;
+ }
+ }
+ CurrentScriptFile->Argc--;
+ return (SHELL_SUCCESS);
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/Stall.c b/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/Stall.c
new file mode 100644
index 0000000000..476b1bc47f
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/Stall.c
@@ -0,0 +1,84 @@
+/** @file
+ Main file for stall shell level 1 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel1CommandsLib.h"
+
+/**
+ Function for 'stall' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunStall (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ UINT64 Intermediate;
+
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel1HiiHandle, L"stall", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ if (ShellCommandLineGetRawValue(Package, 2) != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel1HiiHandle, L"stall");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetRawValue(Package, 1) == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel1HiiHandle, L"stall");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Status = ShellConvertStringToUint64(ShellCommandLineGetRawValue(Package, 1), &Intermediate, FALSE, FALSE);
+ if (EFI_ERROR(Status) || ((UINT64)(UINTN)(Intermediate)) != Intermediate) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel1HiiHandle, L"stall", ShellCommandLineGetRawValue(Package, 1));
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Status = gBS->Stall((UINTN)Intermediate);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_STALL_FAILED), gShellLevel1HiiHandle, L"stall");
+ ShellStatus = SHELL_DEVICE_ERROR;
+ }
+ }
+ }
+ ShellCommandLineFreeVarList (Package);
+ }
+ return (ShellStatus);
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.c b/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.c
new file mode 100644
index 0000000000..80d0dfe652
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.c
@@ -0,0 +1,310 @@
+/** @file
+ Main file for NULL named library for level 1 shell command functions.
+
+ (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel1CommandsLib.h"
+
+STATIC CONST CHAR16 mFileName[] = L"ShellCommands";
+EFI_HANDLE gShellLevel1HiiHandle = NULL;
+
+/**
+ Return the help text filename. Only used if no HII information found.
+
+ @retval the filename.
+**/
+CONST CHAR16*
+EFIAPI
+ShellCommandGetManFileNameLevel1 (
+ VOID
+ )
+{
+ return (mFileName);
+}
+
+/**
+ Constructor for the Shell Level 1 Commands library.
+
+ Install the handlers for level 1 UEFI Shell 2.0 commands.
+
+ @param ImageHandle the image handle of the process
+ @param SystemTable the EFI System Table pointer
+
+ @retval EFI_SUCCESS the shell command handlers were installed sucessfully
+ @retval EFI_UNSUPPORTED the shell level required was not found.
+**/
+EFI_STATUS
+EFIAPI
+ShellLevel1CommandsLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ //
+ // if shell level is less than 2 do nothing
+ //
+ if (PcdGet8(PcdShellSupportLevel) < 1) {
+ return (EFI_SUCCESS);
+ }
+
+ gShellLevel1HiiHandle = HiiAddPackages (&gShellLevel1HiiGuid, gImageHandle, UefiShellLevel1CommandsLibStrings, NULL);
+ if (gShellLevel1HiiHandle == NULL) {
+ return (EFI_DEVICE_ERROR);
+ }
+
+ //
+ // install our shell command handlers that are always installed
+ //
+ ShellCommandRegisterCommandName(L"stall", ShellCommandRunStall , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_STALL) ));
+ ShellCommandRegisterCommandName(L"for", ShellCommandRunFor , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_FOR) ));
+ ShellCommandRegisterCommandName(L"goto", ShellCommandRunGoto , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_GOTO) ));
+ ShellCommandRegisterCommandName(L"if", ShellCommandRunIf , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_IF) ));
+ ShellCommandRegisterCommandName(L"shift", ShellCommandRunShift , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_SHIFT) ));
+ ShellCommandRegisterCommandName(L"exit", ShellCommandRunExit , ShellCommandGetManFileNameLevel1, 1, L"", TRUE , gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_EXIT) ));
+ ShellCommandRegisterCommandName(L"else", ShellCommandRunElse , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_ELSE) ));
+ ShellCommandRegisterCommandName(L"endif", ShellCommandRunEndIf , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_ENDIF) ));
+ ShellCommandRegisterCommandName(L"endfor", ShellCommandRunEndFor , ShellCommandGetManFileNameLevel1, 1, L"", FALSE, gShellLevel1HiiHandle, (EFI_STRING_ID)(PcdGet8(PcdShellSupportLevel) < 3 ? 0 : STRING_TOKEN(STR_GET_HELP_ENDFOR)));
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Destructor for the library. free any resources.
+
+ @param ImageHandle The image handle of the process.
+ @param SystemTable The EFI System Table pointer.
+**/
+EFI_STATUS
+EFIAPI
+ShellLevel1CommandsLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ if (gShellLevel1HiiHandle != NULL) {
+ HiiRemovePackages(gShellLevel1HiiHandle);
+ }
+ return (EFI_SUCCESS);
+}
+
+/**
+ Test a node to see if meets the criterion.
+
+ It functions so that count starts at 1 and it increases or decreases when it
+ hits the specified tags. when it hits zero the location has been found.
+
+ DecrementerTag and IncrementerTag are used to get around for/endfor and
+ similar paired types where the entire middle should be ignored.
+
+ If label is used it will be used instead of the count.
+
+ @param[in] Function The function to use to enumerate through the
+ list. Normally GetNextNode or GetPreviousNode.
+ @param[in] DecrementerTag The tag to decrement the count at.
+ @param[in] IncrementerTag The tag to increment the count at.
+ @param[in] Label A label to look for.
+ @param[in, out] ScriptFile The pointer to the current script file structure.
+ @param[in] MovePast TRUE makes function return 1 past the found
+ location.
+ @param[in] FindOnly TRUE to not change the ScriptFile.
+ @param[in] CommandNode The pointer to the Node to test.
+ @param[in, out] TargetCount The pointer to the current count.
+**/
+BOOLEAN
+EFIAPI
+TestNodeForMove (
+ IN CONST LIST_MANIP_FUNC Function,
+ IN CONST CHAR16 *DecrementerTag,
+ IN CONST CHAR16 *IncrementerTag,
+ IN CONST CHAR16 *Label OPTIONAL,
+ IN OUT SCRIPT_FILE *ScriptFile,
+ IN CONST BOOLEAN MovePast,
+ IN CONST BOOLEAN FindOnly,
+ IN CONST SCRIPT_COMMAND_LIST *CommandNode,
+ IN OUT UINTN *TargetCount
+ )
+{
+ BOOLEAN Found;
+ CHAR16 *CommandName;
+ CHAR16 *CommandNameWalker;
+ CHAR16 *TempLocation;
+
+ Found = FALSE;
+
+ //
+ // get just the first part of the command line...
+ //
+ CommandName = NULL;
+ CommandName = StrnCatGrow(&CommandName, NULL, CommandNode->Cl, 0);
+ if (CommandName == NULL) {
+ return (FALSE);
+ }
+
+ CommandNameWalker = CommandName;
+
+ //
+ // Skip leading spaces and tabs.
+ //
+ while ((CommandNameWalker[0] == L' ') || (CommandNameWalker[0] == L'\t')) {
+ CommandNameWalker++;
+ }
+ TempLocation = StrStr(CommandNameWalker, L" ");
+
+ if (TempLocation != NULL) {
+ *TempLocation = CHAR_NULL;
+ }
+
+ //
+ // did we find a nested item ?
+ //
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)CommandNameWalker,
+ (CHAR16*)IncrementerTag) == 0) {
+ (*TargetCount)++;
+ } else if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)CommandNameWalker,
+ (CHAR16*)DecrementerTag) == 0) {
+ if (*TargetCount > 0) {
+ (*TargetCount)--;
+ }
+ }
+
+ //
+ // did we find the matching one...
+ //
+ if (Label == NULL) {
+ if (*TargetCount == 0) {
+ Found = TRUE;
+ if (!FindOnly) {
+ if (MovePast) {
+ ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)(*Function)(&ScriptFile->CommandList, &CommandNode->Link);
+ } else {
+ ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)CommandNode;
+ }
+ }
+ }
+ } else {
+ if (gUnicodeCollation->StriColl(
+ gUnicodeCollation,
+ (CHAR16*)CommandNameWalker,
+ (CHAR16*)Label) == 0
+ && (*TargetCount) == 0) {
+ Found = TRUE;
+ if (!FindOnly) {
+ //
+ // we found the target label without loops
+ //
+ if (MovePast) {
+ ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)(*Function)(&ScriptFile->CommandList, &CommandNode->Link);
+ } else {
+ ScriptFile->CurrentCommand = (SCRIPT_COMMAND_LIST *)CommandNode;
+ }
+ }
+ }
+ }
+
+ //
+ // Free the memory for this loop...
+ //
+ FreePool(CommandName);
+ return (Found);
+}
+
+/**
+ Move the script pointer from 1 tag (line) to another.
+
+ It functions so that count starts at 1 and it increases or decreases when it
+ hits the specified tags. when it hits zero the location has been found.
+
+ DecrementerTag and IncrementerTag are used to get around for/endfor and
+ similar paired types where the entire middle should be ignored.
+
+ If label is used it will be used instead of the count.
+
+ @param[in] Function The function to use to enumerate through the
+ list. Normally GetNextNode or GetPreviousNode.
+ @param[in] DecrementerTag The tag to decrement the count at.
+ @param[in] IncrementerTag The tag to increment the count at.
+ @param[in] Label A label to look for.
+ @param[in, out] ScriptFile The pointer to the current script file structure.
+ @param[in] MovePast TRUE makes function return 1 past the found
+ location.
+ @param[in] FindOnly TRUE to not change the ScriptFile.
+ @param[in] WrapAroundScript TRUE to wrap end-to-begining or vise versa in
+ searching.
+**/
+BOOLEAN
+EFIAPI
+MoveToTag (
+ IN CONST LIST_MANIP_FUNC Function,
+ IN CONST CHAR16 *DecrementerTag,
+ IN CONST CHAR16 *IncrementerTag,
+ IN CONST CHAR16 *Label OPTIONAL,
+ IN OUT SCRIPT_FILE *ScriptFile,
+ IN CONST BOOLEAN MovePast,
+ IN CONST BOOLEAN FindOnly,
+ IN CONST BOOLEAN WrapAroundScript
+ )
+{
+ SCRIPT_COMMAND_LIST *CommandNode;
+ BOOLEAN Found;
+ UINTN TargetCount;
+
+ if (Label == NULL) {
+ TargetCount = 1;
+ } else {
+ TargetCount = 0;
+ }
+
+ if (ScriptFile == NULL) {
+ return FALSE;
+ }
+
+ for (CommandNode = (SCRIPT_COMMAND_LIST *)(*Function)(&ScriptFile->CommandList, &ScriptFile->CurrentCommand->Link), Found = FALSE
+ ; !IsNull(&ScriptFile->CommandList, &CommandNode->Link)&& !Found
+ ; CommandNode = (SCRIPT_COMMAND_LIST *)(*Function)(&ScriptFile->CommandList, &CommandNode->Link)
+ ){
+ Found = TestNodeForMove(
+ Function,
+ DecrementerTag,
+ IncrementerTag,
+ Label,
+ ScriptFile,
+ MovePast,
+ FindOnly,
+ CommandNode,
+ &TargetCount);
+ }
+
+ if (WrapAroundScript && !Found) {
+ for (CommandNode = (SCRIPT_COMMAND_LIST *)GetFirstNode(&ScriptFile->CommandList), Found = FALSE
+ ; CommandNode != ScriptFile->CurrentCommand && !Found
+ ; CommandNode = (SCRIPT_COMMAND_LIST *)(*Function)(&ScriptFile->CommandList, &CommandNode->Link)
+ ){
+ Found = TestNodeForMove(
+ Function,
+ DecrementerTag,
+ IncrementerTag,
+ Label,
+ ScriptFile,
+ MovePast,
+ FindOnly,
+ CommandNode,
+ &TargetCount);
+ }
+ }
+ return (Found);
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.h b/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.h
new file mode 100644
index 0000000000..c4ef536202
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.h
@@ -0,0 +1,211 @@
+/** @file
+ Main file for NULL named library for level 1 shell command functions.
+
+ Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _UEFI_SHELL_LEVEL1_COMMANDS_LIB_H_
+#define _UEFI_SHELL_LEVEL1_COMMANDS_LIB_H_
+
+#include <Uefi.h>
+#include <ShellBase.h>
+
+#include <Guid/ShellLibHiiGuid.h>
+
+#include <Protocol/EfiShell.h>
+#include <Protocol/EfiShellParameters.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/UnicodeCollation.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/ShellCommandLib.h>
+#include <Library/ShellLib.h>
+#include <Library/SortLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HiiLib.h>
+#include <Library/FileHandleLib.h>
+
+extern EFI_HANDLE gShellLevel1HiiHandle;
+
+/**
+ Function for 'stall' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunStall (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'exit' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunExit (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'endif' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunEndIf (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'for' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunFor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'endfor' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunEndFor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'if' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunIf (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'goto' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunGoto (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'shift' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunShift (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+
+/**
+ Function for 'else' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunElse (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+///
+/// Function prototype for BOTH GetNextNode and GetPreviousNode...
+/// This is used to control the MoveToTag function direction...
+///
+typedef
+LIST_ENTRY *
+(EFIAPI *LIST_MANIP_FUNC)(
+ IN CONST LIST_ENTRY *List,
+ IN CONST LIST_ENTRY *Node
+ );
+
+/**
+ Move the script pointer from 1 tag (line) to another.
+
+ It functions so that count starts at 1 and it increases or decreases when it
+ hits the specified tags. when it hits zero the location has been found.
+
+ DecrementerTag and IncrementerTag are used to get around for/endfor and
+ similar paired types where the entire middle should be ignored.
+
+ If label is used it will be used instead of the count.
+
+ @param[in] Function The function to use to enumerate through the
+ list. Normally GetNextNode or GetPreviousNode.
+ @param[in] DecrementerTag The tag to decrement the count at.
+ @param[in] IncrementerTag The tag to increment the count at.
+ @param[in] Label A label to look for.
+ @param[in, out] ScriptFile The pointer to the current script file structure.
+ @param[in] MovePast TRUE makes function return 1 past the found
+ location.
+ @param[in] FindOnly TRUE to not change the ScriptFile.
+ @param[in] WrapAroundScript TRUE to wrap end-to-begining or vise versa in
+ searching.
+**/
+BOOLEAN
+EFIAPI
+MoveToTag (
+ IN CONST LIST_MANIP_FUNC Function,
+ IN CONST CHAR16 *DecrementerTag,
+ IN CONST CHAR16 *IncrementerTag,
+ IN CONST CHAR16 *Label OPTIONAL,
+ IN OUT SCRIPT_FILE *ScriptFile,
+ IN CONST BOOLEAN MovePast,
+ IN CONST BOOLEAN FindOnly,
+ IN CONST BOOLEAN WrapAroundScript
+ );
+
+#endif
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf b/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf
new file mode 100644
index 0000000000..4d3713b460
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf
@@ -0,0 +1,58 @@
+## @file
+# Provides shell level 1 functions
+#
+# Copyright (c) 2009-2015, Intel Corporation. All rights reserved. <BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = UefiShellLevel1CommandsLib
+ FILE_GUID = 50cb6037-1102-47af-b2dd-9944b6eb1abe
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER
+ CONSTRUCTOR = ShellLevel1CommandsLibConstructor
+ DESTRUCTOR = ShellLevel1CommandsLibDestructor
+
+[Sources.common]
+ UefiShellLevel1CommandsLib.c
+ UefiShellLevel1CommandsLib.h
+ UefiShellLevel1CommandsLib.uni
+ Exit.c
+ Goto.c
+ If.c
+ For.c
+ Shift.c
+ Stall.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ ShellCommandLib
+ ShellLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ SortLib
+ PrintLib
+
+[Pcd.common]
+ gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel ## CONSUMES
+
+[Guids]
+ gShellLevel1HiiGuid ## SOMETIMES_CONSUMES ## HII
diff --git a/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.uni b/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.uni
new file mode 100644
index 0000000000..73e8655ff5
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.uni
@@ -0,0 +1,504 @@
+// /**
+//
+// (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.<BR>
+// Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// Module Name:
+//
+// UefiShellLevel2CommandsLib.uni
+//
+// Abstract:
+//
+// String definitions for UEFI Shell 2.0 level 1 commands
+//
+//
+// **/
+
+/=#
+
+#langdef en-US "english"
+
+#string STR_NO_SCRIPT #language en-US "The command '%H%s%N' is incorrect outside of a script\r\n"
+#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n"
+#string STR_GEN_PROBLEM_VAL #language en-US "%H%s%N: Bad value - '%H%s%N' for flag - '%H%s%N'\r\n"
+#string STR_GEN_PROBLEM_SCRIPT #language en-US "The argument '%B%s%N' is incorrect. Line: %d\r\n"
+#string STR_GEN_INV_VAR #language en-US "The script's Indexvar '%B%s%N' is incorrect\r\n"
+#string STR_GEN_TOO_FEW #language en-US "%H%s%N: Too few arguments\r\n"
+#string STR_GEN_TOO_MANY #language en-US "%H%s%N: Too many arguments\r\n"
+#string STR_GEN_PARAM_INV #language en-US "%H%s%N: Invalid argument - '%H%s%N'\r\n"
+
+#string STR_TEXT_AFTER_THEN #language en-US "%H%s%N: Then cannot be followed by anything\r\n"
+#string STR_SYNTAX_AFTER_BAD #language en-US "%H%s%N: Syntax after '%H%s%N' is incorrect\r\n"
+#string STR_SYNTAX_IN #language en-US "Syntax after analyzing %s\r\n"
+#string STR_SYNTAX_NO_MATCHING #language en-US "No matching '%H%s%N' for '%H%s%N' statement found. Line: %d\r\n"
+#string STR_INVALID_BINOP #language en-US "Binary operator not found first in '%H%s%N'\r\n"
+#string STR_SYNTAX_STARTING #language en-US "Syntax after %s\r\n"
+
+#string STR_STALL_FAILED #language en-US "%H%s%N: BootService Stall() failed\r\n"
+
+#string STR_GET_HELP_EXIT #language en-US ""
+".TH exit 0 "exits the script or shell"\r\n"
+".SH NAME\r\n"
+"Exits the UEFI Shell or the current script.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"EXIT [/b] [exit-code]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" /b - Indicates that only the current UEFI shell script should be\r\n"
+" terminated. Ignored if not used within a script.\r\n"
+" exit-code - If exiting a UEFI shell script, the value that will be placed\r\n"
+" into the environment variable lasterror. If exiting an instance\r\n"
+" of the UEFI shell, the value that will be returned to the\r\n"
+" caller. If not specified, then 0 will be returned.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command exits the UEFI Shell or, if /b is specified, the current\r\n"
+" script.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To exit shell successfully:\r\n"
+" Shell> exit\r\n"
+" \r\n"
+" * To exit the current UEFI shell script:\r\n"
+" Shell> exit /b \r\n"
+" \r\n"
+" * To exit a UEFI shell script with exit-code value returned to the caller:\r\n"
+" Shell> exit 0\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" 0 Exited normally\r\n"
+" exit-code The return value specified as an option.\r\n"
+
+#string STR_GET_HELP_FOR #language en-US ""
+".TH for 0 "starts a for loop"\r\n"
+".SH NAME\r\n"
+"Starts a loop based on 'for' syntax.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"FOR %indexvar IN set\r\n"
+" command [arguments]\r\n"
+" [command [arguments]]\r\n"
+" ...\r\n"
+"ENDFOR\r\n"
+" \r\n"
+"FOR %indexvar RUN (start end [step])\r\n"
+" command [arguments]\r\n"
+" [command [arguments]]\r\n"
+" ...\r\n"
+"ENDFOR\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" %indexvar - Variable name used to index a set\r\n"
+" set - Set to be searched\r\n"
+" command [arguments] - Command to be executed with optional arguments\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. The FOR command executes one or more commands for each item in a set of\r\n"
+" items. The set may be text strings or filenames or a mixture of both,\r\n"
+" separated by spaces (if not in a quotation).\r\n"
+" 2. If the length of an element in the set is between 0 and 256, and if the\r\n"
+" string contains wildcards, the string will be treated as a file name\r\n"
+" containing wildcards, and be expanded before command is executed.\r\n"
+" 3. If after expansion no such files are found, the literal string itself is\r\n"
+" kept. %indexvar is any alphabet character from 'a' to 'z' or 'A' to 'Z',\r\n"
+" and they are case sensitive. It should not be a digit (0-9) because\r\n"
+" %digit will be interpreted as a positional argument on the command line\r\n"
+" that launches the script. The namespace for index variables is separate\r\n"
+" from that for environment variables, so if %indexvar has the same name as\r\n"
+" an existing environment variable, the environment variable will remain\r\n"
+" unchanged by the FOR loop.\r\n"
+" 4. Each command is executed once for each item in the set, with any\r\n"
+" occurrence of %indexvar in the command replacing with the current item.\r\n"
+" In the second format of FOR ... ENDFOR statement, %indexvar will be\r\n"
+" assigned a value from start to end with an interval of step. Start and\r\n"
+" end can be any integer whose length is less than 7 digits excluding sign,\r\n"
+" and it can also applied to step with one exception of zero. Step is\r\n"
+" optional, if step is not specified it will be automatically determined by\r\n"
+" following rule:\r\n"
+" if start <= end then step = 1, otherwise step = -1.\r\n"
+" start, end and step are divided by space.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * Sample FOR loop - listing all .txt files:\r\n"
+" echo -off\r\n"
+" for %a in *.txt\r\n"
+" echo %a exists\r\n"
+" endfor\r\n"
+" \r\n"
+" # \r\n"
+" # If in current directory, there are 2 files named file1.txt and file2.txt\r\n"
+" # then the output of the sample script will be as shown below.\r\n"
+" # \r\n"
+" Sample1> echo -off\r\n"
+" file1.txt exists\r\n"
+" file2.txt exists\r\n"
+" \r\n"
+" * Theoretically it is legal for 2 nested FOR commands to use the same\r\n"
+" alphabet letter as their index variable, for instance, a: \r\n"
+" #\r\n"
+" # Sample FOR loop from 1 to 3 with step 1\r\n"
+" #\r\n"
+" echo -off\r\n"
+" for %a run (1 3)\r\n"
+" echo %a\r\n"
+" endfor\r\n"
+" \r\n"
+" #\r\n"
+" # Sample FOR loop from 3 down to 1 with step -1\r\n"
+" #\r\n"
+" echo -off\r\n"
+" for %a run (3 1 -1)\r\n"
+" echo %a\r\n"
+" endfor\r\n"
+" \r\n"
+" #\r\n"
+" # Sample FOR loop - 2 nested for using same index variable\r\n"
+" #\r\n"
+" echo -off\r\n"
+" for %a in value1 value2\r\n"
+" for %a in value3 value4\r\n"
+" echo %a\r\n"
+" endfor\r\n"
+" endfor\r\n"
+" \r\n"
+" Note: When processing first FOR and before seeing the ENDFOR, the index\r\n"
+" variable %a has the value "value1", so in second FOR, the %a has\r\n"
+" been already defined and it will be replaced with the current value\r\n"
+" of %a. The string after substitution becomes FOR value1 in value3\r\n"
+" value4, which is not a legal FOR command. Thus only when the value\r\n"
+" of %a is also a single alphabet letter, the script will be executed\r\n"
+" without error. If 2 independent FOR commands use the same index\r\n"
+" variable, when the second FOR is encountered, the first FOR has\r\n"
+" already freed the variable so there will be no problem in this case.\r\n"
+
+#string STR_GET_HELP_ENDFOR #language en-US ""
+".TH endfor 0 "ends a for loop"\r\n"
+".SH NAME\r\n"
+"Ends a 'for' loop.\r\n"
+".SH SYNOPSIS\r\n"
+"See 'for' for usage.\r\n"
+".SH EXAMPLES\r\n"
+"See 'for' for examples.\r\n"
+
+#string STR_GET_HELP_GOTO #language en-US ""
+".TH goto 0 "moves to a label"\r\n"
+".SH NAME\r\n"
+"Moves around the point of execution in a script.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"GOTO label\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" label - Specifies a location in batch file\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. The GOTO command directs script file execution to the line in the script\r\n"
+" file after the given label. The command is not supported from the\r\n"
+" interactive shell.\r\n"
+" 2. A label is a line beginning with a colon (:). It can appear either after\r\n"
+" the GOTO command, or before the GOTO command. The search for label is\r\n"
+" done forward in the script file, from the current file position. If the\r\n"
+" end of the file is reached, the search resumes at the top of the file and\r\n"
+" continues until label is found or the starting point is reached. If label\r\n"
+" is not found, the script process terminates and an error message is\r\n"
+" displayed. If a label is encountered but there is no GOTO command\r\n"
+" executed, the label lines are ignored.\r\n"
+" 3. Using GOTO command to jump into another for loop is not allowed,\r\n"
+" but jumping into an if statement is legal.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * This is a script:\r\n"
+" goto Done\r\n"
+" ...\r\n"
+" :Done\r\n"
+" cleanup.nsh\r\n"
+
+#string STR_GET_HELP_ENDIF #language en-US ""
+".TH endif 0 "ends an if block"\r\n"
+".SH NAME\r\n"
+"Ends the block of a script controlled by an 'if' statement.\r\n"
+".SH SYNOPSIS\r\n"
+"See 'if' for usage.\r\n"
+".SH EXAMPLES\r\n"
+"See 'if' for examples.\r\n"
+
+#string STR_GET_HELP_IF #language en-US ""
+".TH if 0 "controls the execution of a block of a script"\r\n"
+".SH NAME\r\n"
+"Executes commands in specified conditions.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"IF [NOT] EXIST filename THEN\r\n"
+" command [arguments]\r\n"
+" [command [arguments]]\r\n"
+" ...\r\n"
+"[ELSE\r\n"
+" command [arguments]\r\n"
+" [command [arguments]]\r\n"
+" ...\r\n"
+" ]\r\n"
+"ENDIF\r\n"
+" \r\n"
+"IF [/i] [NOT] string1 == string2 THEN\r\n"
+" command [arguments]\r\n"
+" [command [arguments]]\r\n"
+" ...\r\n"
+"[ELSE\r\n"
+" command [arguments]\r\n"
+" [command [arguments]]\r\n"
+" ...\r\n"
+" ]\r\n"
+"ENDIF\r\n"
+"if [/i][/s] ConditionalExpression THEN\r\n"
+" command [arguments]\r\n"
+" [command [arguments]]\r\n"
+" ...\r\n"
+"[ELSE\r\n"
+" command [arguments]\r\n"
+" [command [arguments]]\r\n"
+" ...\r\n"
+" ]\r\n"
+"ENDIF\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. The IF command executes one or more commands before the ELSE or ENDIF\r\n"
+" commands, if the specified condition is TRUE; otherwise commands between\r\n"
+" ELSE (if present) and ENDIF are executed.\r\n"
+" 2. In the first usage of IF, the EXIST condition is true when the file\r\n"
+" specified by filename exists. The filename argument may include device\r\n"
+" and path information. Also wildcard expansion is supported by this form.\r\n"
+" If more than one file matches the wildcard pattern, the condition\r\n"
+" evaluates to TRUE.\r\n"
+" 3. In the second usage, the string1 == string2 condition is TRUE if the two\r\n"
+" strings are identical. Here the comparison can be case sensitive or\r\n"
+" insensitive, it depends on the optional switch /i. If /i is specified,\r\n"
+" it will compare strings in the case insensitive manner; otherwise, it\r\n"
+" compares strings in the case sensitive manner.\r\n"
+" 4. In the third usage, general purpose comparison is supported using\r\n"
+" expressions optionally separated by AND or OR. Since < and > are used for\r\n"
+" redirection, the expressions use common two character (FORTRAN)\r\n"
+" abbreviations for the operators (augmented with unsigned equivalents):\r\n"
+" - Expressions : Conditional expressions are evaluated strictly from left\r\n"
+" to right. Complex conditionals requiring precedence may\r\n"
+" be implemented as nested IFs.\r\n"
+" The expressions used in the third usage can have the\r\n"
+" following syntax:\r\n"
+" conditional-expression := expression |\r\n"
+" expression and expression |\r\n"
+" expression or expression\r\n"
+" expression := expr | not expr\r\n"
+" expr := item binop item | boolfunc(string)\r\n"
+" item := mapfunc(string) | string\r\n"
+" mapfunc := efierror | pierror | oemerror\r\n"
+" boolfunc := isint | exists | available | profile\r\n"
+" binop := gt | lt | eq | ne | ge | le | == | ugt | ult |\r\n"
+" uge | ule\r\n"
+" - Comparisons : By default, comparisons are done numerically if the\r\n"
+" strings on both sides of the operator are numbers\r\n"
+" (as defined below) and in case sensitive character sort\r\n"
+" order otherwise. Spaces separate the operators from\r\n"
+" operands.\r\n"
+" 5. The /s option forces string comparisons and the /i option forces\r\n"
+" case-insensitive string comparisons. If either of these is used, the\r\n"
+" signed or unsigned versions of the operators have the same results.\r\n"
+" The /s and /i apply to the entire line and must appear at the start of\r\n"
+" the line (just after the if itself). The two may appear in either order.\r\n"
+" 6. When performing comparisons, the Unicode Byte Ordering Character is\r\n"
+" ignored at the beginning of any argument.\r\n"
+" 7. Comparison Operator Definition:\r\n"
+" gt : Greater than\r\n"
+" ugt : Unsigned Greater than\r\n"
+" lt : Less than\r\n"
+" ult : Unsigned Less than\r\n"
+" ge : Greater than or equal\r\n"
+" uge : Unsigned greater than or equal\r\n"
+" le : Less than or equal\r\n"
+" ule : Unsigned less than or equal\r\n"
+" ne : Not equal\r\n"
+" eq : Equals (semantically equivalent to ==)\r\n"
+" == : Equals (semantically equivalent to eq)\r\n"
+" 8. Error Mapping Functions are used to convert integers into UEFI, PI or OEM\r\n"
+" error codes.\r\n"
+" Functions used to convert integers into UEFI, PI or OEM error codes:\r\n"
+" UefiError : Sets top nibble of parameter to 1000 binary (0x8)\r\n"
+" PiError : Sets top nibble of parameter to 1010 binary (0xA)\r\n"
+" OemError : Sets top nibble of parameter to 1100 binary (0xC)\r\n"
+" Each function maps the small positive parameter into its equivalent error\r\n"
+" classification.\r\n"
+" For example:\r\n"
+" if %lasterror% == EfiError(8) then # Check for write protect.\r\n"
+" ...\r\n"
+" 9. Boolean Functions may only be used to modify operators in comparisons.\r\n"
+" The following built-in Boolean functions are also available:\r\n"
+" IsInt : Evaluates to true if the parameter string that follows\r\n"
+" is a number (as defined below) and false otherwise.\r\n"
+" Exists : Evaluates to true if the file specified by string exists\r\n"
+" is in the current working directory or false if not.\r\n"
+" Available : Evaluates to true if the file specified by string is in the\r\n"
+" current working directory or current path.\r\n"
+" Profile : Determines whether the parameter string matches one of the\r\n"
+" profile names in the profiles environment variable.\r\n"
+" 10. No spaces are allowed between function names and the open parenthesis,\r\n"
+" between the open parenthesis and the string or between the string and\r\n"
+" the closed parenthesis. Constant strings containing spaces must be\r\n"
+" quoted.\r\n"
+" 11. To avoid ambiguity and current or future incompatibility, users are\r\n"
+" strongly encouraged to surround constant strings that contain\r\n"
+" parenthesis with quotes in if statements.\r\n"
+" 12. Allowable number formats are decimal numbers and C-style case\r\n"
+" insensitive hexadecimal numbers. Numbers may be preceded by a\r\n"
+" "-" indicating a negative number.\r\n"
+" Examples:\r\n"
+" 13\r\n"
+" 46\r\n"
+" -0x3FFF\r\n"
+" 0x3fff\r\n"
+" 0x1234\r\n"
+" 13. Unsigned values must be less than 264. Signed integer values are bounded\r\n"
+" by -/+263.\r\n"
+" 14. Numbers are internally represented in two's compliment form. The\r\n"
+" representation of the number in the string has no bearing on the way\r\n"
+" that number is treated in an numeric expression - type is assigned by\r\n"
+" the operator. So, for example, -1 lt 2 is true but -1 ult 2 is false.\r\n"
+" 15. The IF command is only available in scripts.\r\n"
+" 16. The ELSE command is optional in an IF/ELSE statement.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * Sample script for "if" command usages 1 and 2:\r\n"
+" if exist fs0:\myscript.nsh then\r\n"
+" myscript myarg1 myarg2\r\n"
+" endif\r\n"
+" if %myvar% == runboth then\r\n"
+" myscript1\r\n"
+" myscript2\r\n"
+" else\r\n"
+" echo ^%myvar^% != runboth\r\n"
+" endif\r\n"
+" Note: In this example, if the script file myscript.nsh exists in fs0:\,\r\n"
+" this script will be launched with 2 arguments, myarg1 and myarg2.\r\n"
+" After that, environment variable %myvar% is checked to see if its\r\n"
+" value is runboth, if so, script myscript1 and myscript2 will be\r\n"
+" executed one after the other, otherwise a message %myvar% != runboth\r\n"
+" is printed.\r\n"
+" \r\n"
+" * Sample script for "if" command usage 3:\r\n"
+" :Redo\r\n"
+" echo Enter 0-6 or q to quit\r\n"
+" # assumes "input y" stores a character of user input into variable y\r\n"
+" InputCh MyVar\r\n"
+" if x%MyVar% eq x then\r\n"
+" echo Empty line. Try again\r\n"
+" goto Redo\r\n"
+" endif\r\n"
+" if IsInt(%MyVar%) and %MyVar% le 6 then\r\n"
+" myscript1 %MyVar%\r\n"
+" goto Redo\r\n"
+" endif\r\n"
+" if /i %MyVar% ne q then\r\n"
+" echo Invalid input\r\n"
+" goto Redo\r\n"
+" endif\r\n"
+" Note: In this example, the script requests user input and uses the if\r\n"
+" command for input validation. It checks for empty line first and\r\n"
+" then range checks the input.\r\n"
+
+#string STR_GET_HELP_SHIFT #language en-US ""
+".TH shift 0 "move parameters 1 down"\r\n"
+".SH NAME\r\n"
+"Shifts in-script parameter positions.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"SHIFT\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. The SHIFT command shifts the contents of a UEFI Shell script's positional\r\n"
+" parameters so that %1 is discarded, %2 is copied to %1, %3 is copied to\r\n"
+" %2, %4 is copied to %3 and so on. This allows UEFI Shell scripts to\r\n"
+" process script parameters from left to right.\r\n"
+" 2. This command does not change the UEFI shell environment variable\r\n"
+" lasterror.\r\n"
+" 3. The SHIFT command is available only in UEFI Shell scripts.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * Following script is a sample of 'shift' command:\r\n"
+" fs0:\> type shift.nsh\r\n"
+" #\r\n"
+" # shift.nsh\r\n"
+" # \r\n"
+" echo %1 %2 %3\r\n"
+" shift\r\n"
+" echo %1 %2\r\n"
+" \r\n"
+" * To execute the script with echo on:\r\n"
+" fs0:\> shift.nsh welcome UEFI world\r\n"
+" shift.nsh> echo welcome UEFI world\r\n"
+" welcome UEFI world\r\n"
+" shift\r\n"
+" echo UEFI world\r\n"
+" UEFI world\r\n"
+" \r\n"
+" * To execute the script with echo off:\r\n"
+" fs0:\> echo -off\r\n"
+" fs0:\> shift.nsh welcome UEFI world\r\n"
+" welcome UEFI world\r\n"
+" UEFI world\r\n"
+
+#string STR_GET_HELP_ELSE #language en-US ""
+".TH else 0 "part of an 'if' conditional statement"\r\n"
+".SH NAME\r\n"
+"Identifies the code executed when 'if' is FALSE.\r\n"
+".SH SYNOPSIS\r\n"
+"See 'else' for usage.\r\n"
+".SH EXAMPLES\r\n"
+"See 'if' for examples.\r\n"
+
+#string STR_GET_HELP_STALL #language en-US ""
+".TH stall 0 "stall the operation"\r\n"
+".SH NAME\r\n"
+"Stalls the operation for a specified number of microseconds.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"STALL time\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" time - The number of microseconds for the processor to stall.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command would be used to establish a timed STALL of operations\r\n"
+" during a script.\r\n"
+" 2. Microseconds is in decimal units.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To stall the processor for 1000000 microseconds:\r\n"
+" Shell> stall 1000000\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_NOT_FOUND The requested option was not found.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+" SHELL_DEVICE_ERROR There was a hardware error associated with this\r\n"
+" request.\r\n"
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Attrib.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Attrib.c
new file mode 100644
index 0000000000..30d643431f
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Attrib.c
@@ -0,0 +1,277 @@
+/** @file
+ Main file for attrib shell level 2 function.
+
+ (C) Copyright 2014-2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel2CommandsLib.h"
+
+STATIC CONST CHAR16 AllFiles[] = L"*";
+
+STATIC CONST SHELL_PARAM_ITEM AttribParamList[] = {
+ {L"-a", TypeFlag},
+ {L"+a", TypeFlag},
+ {L"-s", TypeFlag},
+ {L"+s", TypeFlag},
+ {L"-h", TypeFlag},
+ {L"+h", TypeFlag},
+ {L"-r", TypeFlag},
+ {L"+r", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'attrib' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunAttrib (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ UINT64 FileAttributesToAdd;
+ UINT64 FileAttributesToRemove;
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ UINTN ParamNumberCount;
+ CONST CHAR16 *FileName;
+ EFI_SHELL_FILE_INFO *ListOfFiles;
+ EFI_SHELL_FILE_INFO *FileNode;
+ EFI_FILE_INFO *FileInfo;
+
+ ListOfFiles = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ ProblemParam = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (AttribParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"attrib", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ } else {
+ FileAttributesToAdd = 0;
+ FileAttributesToRemove = 0;
+
+ //
+ // apply or remove each flag
+ //
+ if (ShellCommandLineGetFlag(Package, L"+a")) {
+ FileAttributesToAdd |= EFI_FILE_ARCHIVE;
+ }
+ if (ShellCommandLineGetFlag(Package, L"-a")) {
+ FileAttributesToRemove |= EFI_FILE_ARCHIVE;
+ }
+ if (ShellCommandLineGetFlag(Package, L"+s")) {
+ FileAttributesToAdd |= EFI_FILE_SYSTEM;
+ }
+ if (ShellCommandLineGetFlag(Package, L"-s")) {
+ FileAttributesToRemove |= EFI_FILE_SYSTEM;
+ }
+ if (ShellCommandLineGetFlag(Package, L"+h")) {
+ FileAttributesToAdd |= EFI_FILE_HIDDEN;
+ }
+ if (ShellCommandLineGetFlag(Package, L"-h")) {
+ FileAttributesToRemove |= EFI_FILE_HIDDEN;
+ }
+ if (ShellCommandLineGetFlag(Package, L"+r")) {
+ FileAttributesToAdd |= EFI_FILE_READ_ONLY;
+ }
+ if (ShellCommandLineGetFlag(Package, L"-r")) {
+ FileAttributesToRemove |= EFI_FILE_READ_ONLY;
+ }
+
+ if (FileAttributesToRemove == 0 && FileAttributesToAdd == 0) {
+ //
+ // Do display as we have no attributes to change
+ //
+ for ( ParamNumberCount = 1
+ ;
+ ; ParamNumberCount++
+ ){
+ FileName = ShellCommandLineGetRawValue(Package, ParamNumberCount);
+ // if we dont have anything left, move on...
+ if (FileName == NULL && ParamNumberCount == 1) {
+ FileName = (CHAR16*)AllFiles;
+ } else if (FileName == NULL) {
+ break;
+ }
+ ASSERT(ListOfFiles == NULL);
+ Status = ShellOpenFileMetaArg((CHAR16*)FileName, EFI_FILE_MODE_READ, &ListOfFiles);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel2HiiHandle, L"attrib", ShellCommandLineGetRawValue(Package, ParamNumberCount));
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ for (FileNode = (EFI_SHELL_FILE_INFO*)GetFirstNode(&ListOfFiles->Link)
+ ; !IsNull(&ListOfFiles->Link, &FileNode->Link)
+ ; FileNode = (EFI_SHELL_FILE_INFO*)GetNextNode(&ListOfFiles->Link, &FileNode->Link)
+ ){
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_ATTRIB_OUTPUT_LINE),
+ gShellLevel2HiiHandle,
+ FileNode->Info->Attribute&EFI_FILE_DIRECTORY? L'D':L' ',
+ FileNode->Info->Attribute&EFI_FILE_ARCHIVE? L'A':L' ',
+ FileNode->Info->Attribute&EFI_FILE_SYSTEM? L'S':L' ',
+ FileNode->Info->Attribute&EFI_FILE_HIDDEN? L'H':L' ',
+ FileNode->Info->Attribute&EFI_FILE_READ_ONLY? L'R':L' ',
+ FileNode->FileName
+ );
+
+ if (ShellGetExecutionBreakFlag()) {
+ ShellStatus = SHELL_ABORTED;
+ break;
+ }
+ }
+ Status = ShellCloseFileMetaArg(&ListOfFiles);
+ ListOfFiles = NULL;
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_CLOSE_FAIL), gShellLevel2HiiHandle, L"attrib", ShellCommandLineGetRawValue(Package, ParamNumberCount));
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ } // for loop for handling wildcard filenames
+ } // for loop for printing out the info
+ } else if ((FileAttributesToRemove & FileAttributesToAdd) != 0) {
+ //
+ // fail as we have conflcting params.
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellLevel2HiiHandle, L"attrib");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // enumerate through all the files/directories and apply the attributes
+ //
+ for ( ParamNumberCount = 1
+ ;
+ ; ParamNumberCount++
+ ){
+ FileName = ShellCommandLineGetRawValue(Package, ParamNumberCount);
+ // if we dont have anything left, move on...
+ if (FileName == NULL) {
+ //
+ // make sure we are not failing on the first one we do... if yes that's an error...
+ //
+ if (ParamNumberCount == 1) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"attrib");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ break;
+ }
+
+ //
+ // OpenFileByName / GetFileInfo / Change attributes / SetFileInfo / CloseFile / free memory
+ // for each file or directory on the line.
+ //
+
+ //
+ // Open the file(s)
+ //
+ ASSERT(ListOfFiles == NULL);
+ Status = ShellOpenFileMetaArg((CHAR16*)FileName, EFI_FILE_MODE_READ, &ListOfFiles);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel2HiiHandle, L"attrib", ShellCommandLineGetRawValue(Package, ParamNumberCount));
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ for (FileNode = (EFI_SHELL_FILE_INFO*)GetFirstNode(&ListOfFiles->Link)
+ ; !IsNull(&ListOfFiles->Link, &FileNode->Link)
+ ; FileNode = (EFI_SHELL_FILE_INFO*)GetNextNode(&ListOfFiles->Link, &FileNode->Link)
+ ){
+ //
+ // skip the directory traversing stuff...
+ //
+ if (StrCmp(FileNode->FileName, L".") == 0 || StrCmp(FileNode->FileName, L"..") == 0) {
+ continue;
+ }
+
+ FileInfo = gEfiShellProtocol->GetFileInfo(FileNode->Handle);
+
+ //
+ // if we are removing Read-Only we need to do that alone
+ //
+ if ((FileAttributesToRemove & EFI_FILE_READ_ONLY) == EFI_FILE_READ_ONLY) {
+ FileInfo->Attribute &= ~EFI_FILE_READ_ONLY;
+ //
+ // SetFileInfo
+ //
+ Status = ShellSetFileInfo(FileNode->Handle, FileInfo);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_AD), gShellLevel2HiiHandle, L"attrib", ShellCommandLineGetRawValue(Package, ParamNumberCount));
+ ShellStatus = SHELL_ACCESS_DENIED;
+ }
+ }
+
+ //
+ // change the attribute
+ //
+ FileInfo->Attribute &= ~FileAttributesToRemove;
+ FileInfo->Attribute |= FileAttributesToAdd;
+
+ //
+ // SetFileInfo
+ //
+ Status = ShellSetFileInfo(FileNode->Handle, FileInfo);
+ if (EFI_ERROR(Status)) {;
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_AD), gShellLevel2HiiHandle, L"attrib", ShellCommandLineGetRawValue(Package, ParamNumberCount));
+ ShellStatus = SHELL_ACCESS_DENIED;
+ }
+
+ SHELL_FREE_NON_NULL(FileInfo);
+ }
+ Status = ShellCloseFileMetaArg(&ListOfFiles);
+ ListOfFiles = NULL;
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_CLOSE_FAIL), gShellLevel2HiiHandle, L"attrib", ShellCommandLineGetRawValue(Package, ParamNumberCount));
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ } // for loop for handling wildcard filenames
+ }
+ }
+ }
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+
+ //
+ // return the status
+ //
+ return (ShellStatus);
+}
diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c
new file mode 100644
index 0000000000..2e51b4cb4d
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Cd.c
@@ -0,0 +1,278 @@
+/** @file
+ Main file for attrib shell level 2 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel2CommandsLib.h"
+
+/**
+ Function for 'cd' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunCd (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CONST CHAR16 *Directory;
+ CHAR16 *Cwd;
+ CHAR16 *Path;
+ CHAR16 *Drive;
+ UINTN CwdSize;
+ UINTN DriveSize;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ SHELL_FILE_HANDLE Handle;
+ CONST CHAR16 *Param1;
+ CHAR16 *Param1Copy;
+ CHAR16* Walker;
+
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ Drive = NULL;
+ DriveSize = 0;
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"cd", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ }
+
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ } else if (ShellCommandLineGetRawValue(Package, 2) != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"cd");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // remember that param 0 is the command name
+ // If there are 0 value parameters, then print the current directory
+ // else If there are 2 value parameters, then print the error message
+ // else If there is 1 value paramerer , then change the directory
+ //
+ Param1 = ShellCommandLineGetRawValue(Package, 1);
+ if (Param1 == NULL) {
+ //
+ // display the current directory
+ //
+ Directory = ShellGetCurrentDir(NULL);
+ if (Directory != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_PRINT), gShellLevel2HiiHandle, Directory);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cd");
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ } else {
+ Param1Copy = CatSPrint(NULL, L"%s", Param1, NULL);
+ for (Walker = Param1Copy; Walker != NULL && *Walker != CHAR_NULL ; Walker++) {
+ if (*Walker == L'\"') {
+ CopyMem(Walker, Walker+1, StrSize(Walker) - sizeof(Walker[0]));
+ }
+ }
+
+ if (Param1Copy != NULL) {
+ Param1Copy = PathCleanUpDirectories(Param1Copy);
+ }
+ if (Param1Copy != NULL) {
+ if (StrCmp(Param1Copy, L".") == 0) {
+ //
+ // nothing to do... change to current directory
+ //
+ } else if (StrCmp(Param1Copy, L"..") == 0) {
+ //
+ // Change up one directory...
+ //
+ Directory = ShellGetCurrentDir(NULL);
+ if (Directory == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cd");
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ CwdSize = StrSize(Directory) + sizeof(CHAR16);
+ Cwd = AllocateZeroPool(CwdSize);
+ if (Cwd == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellLevel2HiiHandle, L"cd");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ } else {
+ StrCpyS (Cwd, StrSize (Directory) / sizeof (CHAR16) + 1, Directory);
+ StrCatS (Cwd, StrSize (Directory) / sizeof (CHAR16) + 1, L"\\");
+ Drive = GetFullyQualifiedPath (Cwd);
+ PathRemoveLastItem (Drive);
+ FreePool (Cwd);
+ }
+ }
+ if (ShellStatus == SHELL_SUCCESS && Drive != NULL) {
+ //
+ // change directory on current drive letter
+ //
+ Status = gEfiShellProtocol->SetCurDir(NULL, Drive);
+ if (Status == EFI_NOT_FOUND) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd");
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ }
+ } else if (StrCmp(Param1Copy, L"\\") == 0) {
+ //
+ // Move to root of current drive
+ //
+ Directory = ShellGetCurrentDir(NULL);
+ if (Directory == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cd");
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ CwdSize = StrSize(Directory) + sizeof(CHAR16);
+ Cwd = AllocateZeroPool(CwdSize);
+ if (Cwd == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellLevel2HiiHandle, L"cd");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ } else {
+ StrCpyS (Cwd, StrSize (Directory) / sizeof (CHAR16) + 1, Directory);
+ StrCatS (Cwd, StrSize (Directory) / sizeof (CHAR16) + 1, L"\\");
+ Drive = GetFullyQualifiedPath (Cwd);
+ while (PathRemoveLastItem (Drive));
+ FreePool (Cwd);
+ }
+ }
+ if (ShellStatus == SHELL_SUCCESS && Drive != NULL) {
+ //
+ // change directory on current drive letter
+ //
+ Status = gEfiShellProtocol->SetCurDir(NULL, Drive);
+ if (Status == EFI_NOT_FOUND) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd");
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ }
+ } else if (StrStr(Param1Copy, L":") == NULL) {
+ //
+ // change directory without a drive identifier
+ //
+ if (ShellGetCurrentDir(NULL) == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cd");
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ ASSERT((Drive == NULL && DriveSize == 0) || (Drive != NULL));
+ Drive = StrnCatGrow(&Drive, &DriveSize, ShellGetCurrentDir(NULL), 0);
+ Drive = StrnCatGrow(&Drive, &DriveSize, L"\\", 0);
+ if (*Param1Copy == L'\\') {
+ while (PathRemoveLastItem(Drive)) ;
+ Drive = StrnCatGrow(&Drive, &DriveSize, Param1Copy+1, 0);
+ } else {
+ Drive = StrnCatGrow(&Drive, &DriveSize, Param1Copy, 0);
+ }
+ //
+ // Verify that this is a valid directory
+ //
+ Status = gEfiShellProtocol->OpenFileByName(Drive, &Handle, EFI_FILE_MODE_READ);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cd", Drive);
+ ShellStatus = SHELL_NOT_FOUND;
+ } else if (EFI_ERROR(FileHandleIsDirectory(Handle))) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, L"cd", Drive);
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ if (ShellStatus == SHELL_SUCCESS && Drive != NULL) {
+ //
+ // change directory on current drive letter
+ //
+ Status = gEfiShellProtocol->SetCurDir(NULL, Drive);
+ if (Status == EFI_NOT_FOUND) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd");
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ }
+ if (Handle != NULL) {
+ gEfiShellProtocol->CloseFile(Handle);
+ DEBUG_CODE(Handle = NULL;);
+ }
+ }
+ } else {
+ //
+ // change directory with a drive letter
+ //
+ Drive = AllocateCopyPool(StrSize(Param1Copy), Param1Copy);
+ if (Drive == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellLevel2HiiHandle, L"cd");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ } else {
+ Path = StrStr(Drive, L":");
+ ASSERT(Path != NULL);
+ if (EFI_ERROR(ShellIsDirectory(Param1Copy))) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, L"cd", Param1Copy);
+ ShellStatus = SHELL_NOT_FOUND;
+ } else if (*(Path+1) == CHAR_NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd");
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ *(Path+1) = CHAR_NULL;
+ if (Path == Drive + StrLen(Drive)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd");
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ Status = gEfiShellProtocol->SetCurDir(Drive, Path+2);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_PRINT), gShellLevel2HiiHandle, ShellGetCurrentDir(Drive));
+ }
+ }
+ if (Status == EFI_NOT_FOUND) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"cd");
+ Status = SHELL_NOT_FOUND;
+ } else if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cd", Param1Copy);
+ Status = SHELL_NOT_FOUND;
+ }
+ }
+ }
+ }
+ FreePool(Param1Copy);
+ }
+ }
+
+ if (Drive != NULL) {
+ FreePool(Drive);
+ }
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+
+ //
+ // return the status
+ //
+ return (ShellStatus);
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c
new file mode 100644
index 0000000000..eb1f3b65a3
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Cp.c
@@ -0,0 +1,783 @@
+/** @file
+ Main file for cp shell level 2 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel2CommandsLib.h"
+#include <Guid/FileSystemInfo.h>
+#include <Guid/FileSystemVolumeLabelInfo.h>
+
+/**
+ Function to take a list of files to copy and a destination location and do
+ the verification and copying of those files to that location. This function
+ will report any errors to the user and halt.
+
+ @param[in] FileList A LIST_ENTRY* based list of files to move.
+ @param[in] DestDir The destination location.
+ @param[in] SilentMode TRUE to eliminate screen output.
+ @param[in] RecursiveMode TRUE to copy directories.
+ @param[in] Resp The response to the overwrite query (if always).
+
+ @retval SHELL_SUCCESS the files were all moved.
+ @retval SHELL_INVALID_PARAMETER a parameter was invalid
+ @retval SHELL_SECURITY_VIOLATION a security violation ocurred
+ @retval SHELL_WRITE_PROTECTED the destination was write protected
+ @retval SHELL_OUT_OF_RESOURCES a memory allocation failed
+**/
+SHELL_STATUS
+EFIAPI
+ValidateAndCopyFiles(
+ IN CONST EFI_SHELL_FILE_INFO *FileList,
+ IN CONST CHAR16 *DestDir,
+ IN BOOLEAN SilentMode,
+ IN BOOLEAN RecursiveMode,
+ IN VOID **Resp
+ );
+
+/**
+ Function to Copy one file to another location
+
+ If the destination exists the user will be prompted and the result put into *resp
+
+ @param[in] Source pointer to source file name
+ @param[in] Dest pointer to destination file name
+ @param[out] Resp pointer to response from question. Pass back on looped calling
+ @param[in] SilentMode whether to run in quiet mode or not
+ @param[in] CmdName Source command name requesting single file copy
+
+ @retval SHELL_SUCCESS The source file was copied to the destination
+**/
+SHELL_STATUS
+EFIAPI
+CopySingleFile(
+ IN CONST CHAR16 *Source,
+ IN CONST CHAR16 *Dest,
+ OUT VOID **Resp,
+ IN BOOLEAN SilentMode,
+ IN CONST CHAR16 *CmdName
+ )
+{
+ VOID *Response;
+ UINTN ReadSize;
+ SHELL_FILE_HANDLE SourceHandle;
+ SHELL_FILE_HANDLE DestHandle;
+ EFI_STATUS Status;
+ VOID *Buffer;
+ CHAR16 *TempName;
+ UINTN Size;
+ EFI_SHELL_FILE_INFO *List;
+ SHELL_STATUS ShellStatus;
+ UINT64 SourceFileSize;
+ UINT64 DestFileSize;
+ EFI_FILE_PROTOCOL *DestVolumeFP;
+ EFI_FILE_SYSTEM_INFO *DestVolumeInfo;
+ UINTN DestVolumeInfoSize;
+
+ ASSERT(Resp != NULL);
+
+ SourceHandle = NULL;
+ DestHandle = NULL;
+ Response = *Resp;
+ List = NULL;
+ DestVolumeInfo = NULL;
+ ShellStatus = SHELL_SUCCESS;
+
+ ReadSize = PcdGet32(PcdShellFileOperationSize);
+ // Why bother copying a file to itself
+ if (StrCmp(Source, Dest) == 0) {
+ return (SHELL_SUCCESS);
+ }
+
+ //
+ // if the destination file existed check response and possibly prompt user
+ //
+ if (ShellFileExists(Dest) == EFI_SUCCESS) {
+ if (Response == NULL && !SilentMode) {
+ Status = ShellPromptForResponseHii(ShellPromptResponseTypeYesNoAllCancel, STRING_TOKEN (STR_GEN_DEST_EXIST_OVR), gShellLevel2HiiHandle, &Response);
+ }
+ //
+ // possibly return based on response
+ //
+ if (!SilentMode) {
+ switch (*(SHELL_PROMPT_RESPONSE*)Response) {
+ case ShellPromptResponseNo:
+ //
+ // return success here so we dont stop the process
+ //
+ return (SHELL_SUCCESS);
+ case ShellPromptResponseCancel:
+ *Resp = Response;
+ //
+ // indicate to stop everything
+ //
+ return (SHELL_ABORTED);
+ case ShellPromptResponseAll:
+ *Resp = Response;
+ case ShellPromptResponseYes:
+ break;
+ default:
+ return SHELL_ABORTED;
+ }
+ }
+ }
+
+ if (ShellIsDirectory(Source) == EFI_SUCCESS) {
+ Status = ShellCreateDirectory(Dest, &DestHandle);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_DIR_FAIL), gShellLevel2HiiHandle, CmdName, Dest);
+ return (SHELL_ACCESS_DENIED);
+ }
+
+ //
+ // Now copy all the files under the directory...
+ //
+ TempName = NULL;
+ Size = 0;
+ StrnCatGrow(&TempName, &Size, Source, 0);
+ StrnCatGrow(&TempName, &Size, L"\\*", 0);
+ if (TempName != NULL) {
+ ShellOpenFileMetaArg((CHAR16*)TempName, EFI_FILE_MODE_READ, &List);
+ *TempName = CHAR_NULL;
+ StrnCatGrow(&TempName, &Size, Dest, 0);
+ StrnCatGrow(&TempName, &Size, L"\\", 0);
+ ShellStatus = ValidateAndCopyFiles(List, TempName, SilentMode, TRUE, Resp);
+ ShellCloseFileMetaArg(&List);
+ SHELL_FREE_NON_NULL(TempName);
+ Size = 0;
+ }
+ } else {
+ Status = ShellDeleteFileByName(Dest);
+
+ //
+ // open file with create enabled
+ //
+ Status = ShellOpenFileByName(Dest, &DestHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_OPEN_FAIL), gShellLevel2HiiHandle, CmdName, Dest);
+ return (SHELL_ACCESS_DENIED);
+ }
+
+ //
+ // open source file
+ //
+ Status = ShellOpenFileByName (Source, &SourceHandle, EFI_FILE_MODE_READ, 0);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_CP_SRC_OPEN_FAIL), gShellLevel2HiiHandle, CmdName, Source);
+ return (SHELL_ACCESS_DENIED);
+ }
+
+ //
+ //get file size of source file and freespace available on destination volume
+ //
+ ShellGetFileSize(SourceHandle, &SourceFileSize);
+ ShellGetFileSize(DestHandle, &DestFileSize);
+
+ //
+ //if the destination file already exists then it will be replaced, meaning the sourcefile effectively needs less storage space
+ //
+ if(DestFileSize < SourceFileSize){
+ SourceFileSize -= DestFileSize;
+ } else {
+ SourceFileSize = 0;
+ }
+
+ //
+ //get the system volume info to check the free space
+ //
+ DestVolumeFP = ConvertShellHandleToEfiFileProtocol(DestHandle);
+ DestVolumeInfo = NULL;
+ DestVolumeInfoSize = 0;
+ Status = DestVolumeFP->GetInfo(
+ DestVolumeFP,
+ &gEfiFileSystemInfoGuid,
+ &DestVolumeInfoSize,
+ DestVolumeInfo
+ );
+
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ DestVolumeInfo = AllocateZeroPool(DestVolumeInfoSize);
+ Status = DestVolumeFP->GetInfo(
+ DestVolumeFP,
+ &gEfiFileSystemInfoGuid,
+ &DestVolumeInfoSize,
+ DestVolumeInfo
+ );
+ }
+
+ //
+ //check if enough space available on destination drive to complete copy
+ //
+ if (DestVolumeInfo!= NULL && (DestVolumeInfo->FreeSpace < SourceFileSize)) {
+ //
+ //not enough space on destination directory to copy file
+ //
+ SHELL_FREE_NON_NULL(DestVolumeInfo);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_FAIL), gShellLevel2HiiHandle, CmdName);
+ return(SHELL_VOLUME_FULL);
+ } else {
+ //
+ // copy data between files
+ //
+ Buffer = AllocateZeroPool(ReadSize);
+ if (Buffer == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellLevel2HiiHandle, CmdName);
+ return SHELL_OUT_OF_RESOURCES;
+ }
+ while (ReadSize == PcdGet32(PcdShellFileOperationSize) && !EFI_ERROR(Status)) {
+ Status = ShellReadFile(SourceHandle, &ReadSize, Buffer);
+ if (!EFI_ERROR(Status)) {
+ Status = ShellWriteFile(DestHandle, &ReadSize, Buffer);
+ if (EFI_ERROR(Status)) {
+ ShellStatus = (SHELL_STATUS) (Status & (~MAX_BIT));
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_WRITE_ERROR), gShellLevel2HiiHandle, CmdName, Dest);
+ break;
+ }
+ } else {
+ ShellStatus = (SHELL_STATUS) (Status & (~MAX_BIT));
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_CPY_READ_ERROR), gShellLevel2HiiHandle, CmdName, Source);
+ break;
+ }
+ }
+ }
+ SHELL_FREE_NON_NULL(DestVolumeInfo);
+ }
+
+ //
+ // close files
+ //
+ if (DestHandle != NULL) {
+ ShellCloseFile(&DestHandle);
+ DestHandle = NULL;
+ }
+ if (SourceHandle != NULL) {
+ ShellCloseFile(&SourceHandle);
+ SourceHandle = NULL;
+ }
+
+ //
+ // return
+ //
+ return ShellStatus;
+}
+
+/**
+ function to take a list of files to copy and a destination location and do
+ the verification and copying of those files to that location. This function
+ will report any errors to the user and halt.
+
+ The key is to have this function called ONLY once. this allows for the parameter
+ verification to happen correctly.
+
+ @param[in] FileList A LIST_ENTRY* based list of files to move.
+ @param[in] DestDir The destination location.
+ @param[in] SilentMode TRUE to eliminate screen output.
+ @param[in] RecursiveMode TRUE to copy directories.
+ @param[in] Resp The response to the overwrite query (if always).
+
+ @retval SHELL_SUCCESS the files were all moved.
+ @retval SHELL_INVALID_PARAMETER a parameter was invalid
+ @retval SHELL_SECURITY_VIOLATION a security violation ocurred
+ @retval SHELL_WRITE_PROTECTED the destination was write protected
+ @retval SHELL_OUT_OF_RESOURCES a memory allocation failed
+**/
+SHELL_STATUS
+EFIAPI
+ValidateAndCopyFiles(
+ IN CONST EFI_SHELL_FILE_INFO *FileList,
+ IN CONST CHAR16 *DestDir,
+ IN BOOLEAN SilentMode,
+ IN BOOLEAN RecursiveMode,
+ IN VOID **Resp
+ )
+{
+ CHAR16 *HiiOutput;
+ CHAR16 *HiiResultOk;
+ CONST EFI_SHELL_FILE_INFO *Node;
+ SHELL_STATUS ShellStatus;
+ EFI_STATUS Status;
+ CHAR16 *DestPath;
+ VOID *Response;
+ UINTN PathSize;
+ CONST CHAR16 *Cwd;
+ UINTN NewSize;
+ CHAR16 *CleanFilePathStr;
+
+ if (Resp == NULL) {
+ Response = NULL;
+ } else {
+ Response = *Resp;
+ }
+
+ DestPath = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ PathSize = 0;
+ Cwd = ShellGetCurrentDir(NULL);
+ CleanFilePathStr = NULL;
+
+ ASSERT(FileList != NULL);
+ ASSERT(DestDir != NULL);
+
+
+ Status = ShellLevel2StripQuotes (DestDir, &CleanFilePathStr);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_OUT_OF_RESOURCES) {
+ return SHELL_OUT_OF_RESOURCES;
+ } else {
+ return SHELL_INVALID_PARAMETER;
+ }
+ }
+
+ ASSERT (CleanFilePathStr != NULL);
+
+ //
+ // If we are trying to copy multiple files... make sure we got a directory for the target...
+ //
+ if (EFI_ERROR(ShellIsDirectory(CleanFilePathStr)) && FileList->Link.ForwardLink != FileList->Link.BackLink) {
+ //
+ // Error for destination not a directory
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, L"cp", CleanFilePathStr);
+ FreePool (CleanFilePathStr);
+ return (SHELL_INVALID_PARAMETER);
+ }
+ for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link)
+ ; !IsNull(&FileList->Link, &Node->Link)
+ ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link)
+ ){
+ //
+ // skip the directory traversing stuff...
+ //
+ if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) {
+ continue;
+ }
+
+ NewSize = StrSize(CleanFilePathStr);
+ NewSize += StrSize(Node->FullName);
+ NewSize += (Cwd == NULL)? 0 : (StrSize(Cwd) + sizeof(CHAR16));
+ if (NewSize > PathSize) {
+ PathSize = NewSize;
+ }
+
+ //
+ // Make sure got -r if required
+ //
+ if (!RecursiveMode && !EFI_ERROR(ShellIsDirectory(Node->FullName))) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DIR_REQ), gShellLevel2HiiHandle, L"cp");
+ FreePool (CleanFilePathStr);
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ //
+ // make sure got dest as dir if needed
+ //
+ if (!EFI_ERROR(ShellIsDirectory(Node->FullName)) && EFI_ERROR(ShellIsDirectory(CleanFilePathStr))) {
+ //
+ // Error for destination not a directory
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_DIR), gShellLevel2HiiHandle, L"cp", CleanFilePathStr);
+ FreePool (CleanFilePathStr);
+ return (SHELL_INVALID_PARAMETER);
+ }
+ }
+
+ HiiOutput = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_CP_OUTPUT), NULL);
+ HiiResultOk = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_GEN_RES_OK), NULL);
+ DestPath = AllocateZeroPool(PathSize);
+
+ if (DestPath == NULL || HiiOutput == NULL || HiiResultOk == NULL) {
+ SHELL_FREE_NON_NULL(DestPath);
+ SHELL_FREE_NON_NULL(HiiOutput);
+ SHELL_FREE_NON_NULL(HiiResultOk);
+ FreePool (CleanFilePathStr);
+ return (SHELL_OUT_OF_RESOURCES);
+ }
+
+ //
+ // Go through the list of files to copy...
+ //
+ for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link)
+ ; !IsNull(&FileList->Link, &Node->Link)
+ ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link)
+ ){
+ if (ShellGetExecutionBreakFlag()) {
+ break;
+ }
+ ASSERT(Node->FileName != NULL);
+ ASSERT(Node->FullName != NULL);
+
+ //
+ // skip the directory traversing stuff...
+ //
+ if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) {
+ continue;
+ }
+
+ if (FileList->Link.ForwardLink == FileList->Link.BackLink // 1 item
+ && EFI_ERROR(ShellIsDirectory(CleanFilePathStr)) // not an existing directory
+ ) {
+ if (StrStr(CleanFilePathStr, L":") == NULL) {
+ //
+ // simple copy of a single file
+ //
+ if (Cwd != NULL) {
+ StrCpyS(DestPath, PathSize / sizeof(CHAR16), Cwd);
+ StrCatS(DestPath, PathSize / sizeof(CHAR16), L"\\");
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cp", CleanFilePathStr);
+ FreePool (CleanFilePathStr);
+ return (SHELL_INVALID_PARAMETER);
+ }
+ if (DestPath[StrLen(DestPath)-1] != L'\\' && CleanFilePathStr[0] != L'\\') {
+ StrCatS(DestPath, PathSize / sizeof(CHAR16), L"\\");
+ } else if (DestPath[StrLen(DestPath)-1] == L'\\' && CleanFilePathStr[0] == L'\\') {
+ ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL;
+ }
+ StrCatS(DestPath, PathSize/sizeof(CHAR16), CleanFilePathStr);
+ } else {
+ StrCpyS(DestPath, PathSize/sizeof(CHAR16), CleanFilePathStr);
+ }
+ } else {
+ //
+ // we have multiple files or a directory in the DestDir
+ //
+
+ //
+ // Check for leading slash
+ //
+ if (CleanFilePathStr[0] == L'\\') {
+ //
+ // Copy to the root of CWD
+ //
+ if (Cwd != NULL) {
+ StrCpyS(DestPath, PathSize/sizeof(CHAR16), Cwd);
+ StrCatS(DestPath, PathSize/sizeof(CHAR16), L"\\");
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cp", CleanFilePathStr);
+ FreePool(CleanFilePathStr);
+ return (SHELL_INVALID_PARAMETER);
+ }
+ while (PathRemoveLastItem(DestPath));
+ StrCatS(DestPath, PathSize/sizeof(CHAR16), CleanFilePathStr+1);
+ StrCatS(DestPath, PathSize/sizeof(CHAR16), Node->FileName);
+ } else if (StrStr(CleanFilePathStr, L":") == NULL) {
+ if (Cwd != NULL) {
+ StrCpyS(DestPath, PathSize/sizeof(CHAR16), Cwd);
+ StrCatS(DestPath, PathSize/sizeof(CHAR16), L"\\");
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_DIR_NF), gShellLevel2HiiHandle, L"cp", CleanFilePathStr);
+ FreePool(CleanFilePathStr);
+ return (SHELL_INVALID_PARAMETER);
+ }
+ if (DestPath[StrLen(DestPath)-1] != L'\\' && CleanFilePathStr[0] != L'\\') {
+ StrCatS(DestPath, PathSize/sizeof(CHAR16), L"\\");
+ } else if (DestPath[StrLen(DestPath)-1] == L'\\' && CleanFilePathStr[0] == L'\\') {
+ ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL;
+ }
+ StrCatS(DestPath, PathSize/sizeof(CHAR16), CleanFilePathStr);
+ if (CleanFilePathStr[StrLen(CleanFilePathStr)-1] != L'\\' && Node->FileName[0] != L'\\') {
+ StrCatS(DestPath, PathSize/sizeof(CHAR16), L"\\");
+ } else if (CleanFilePathStr[StrLen(CleanFilePathStr)-1] == L'\\' && Node->FileName[0] == L'\\') {
+ ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL;
+ }
+ StrCatS(DestPath, PathSize/sizeof(CHAR16), Node->FileName);
+
+ } else {
+ StrCpyS(DestPath, PathSize/sizeof(CHAR16), CleanFilePathStr);
+ if (CleanFilePathStr[StrLen(CleanFilePathStr)-1] != L'\\' && Node->FileName[0] != L'\\') {
+ StrCatS(DestPath, PathSize/sizeof(CHAR16), L"\\");
+ } else if (CleanFilePathStr[StrLen(CleanFilePathStr)-1] == L'\\' && Node->FileName[0] == L'\\') {
+ ((CHAR16*)CleanFilePathStr)[StrLen(CleanFilePathStr)-1] = CHAR_NULL;
+ }
+ StrCatS(DestPath, PathSize/sizeof(CHAR16), Node->FileName);
+ }
+ }
+
+ //
+ // Make sure the path exists
+ //
+ if (EFI_ERROR(VerifyIntermediateDirectories(DestPath))) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DIR_WNF), gShellLevel2HiiHandle, L"cp", DestPath);
+ ShellStatus = SHELL_DEVICE_ERROR;
+ break;
+ }
+
+ if ( !EFI_ERROR(ShellIsDirectory(Node->FullName))
+ && !EFI_ERROR(ShellIsDirectory(DestPath))
+ && StrniCmp(Node->FullName, DestPath, StrLen(DestPath)) == NULL
+ ){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_PARENT), gShellLevel2HiiHandle, L"cp");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ break;
+ }
+ if (StringNoCaseCompare(&Node->FullName, &DestPath) == 0) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_SAME), gShellLevel2HiiHandle, L"cp");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ break;
+ }
+
+ if ((StrniCmp(Node->FullName, DestPath, StrLen(Node->FullName)) == 0)
+ && (DestPath[StrLen(Node->FullName)] == CHAR_NULL || DestPath[StrLen(Node->FullName)] == L'\\')
+ ) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_SD_SAME), gShellLevel2HiiHandle, L"cp");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ break;
+ }
+
+ PathCleanUpDirectories(DestPath);
+
+ if (!SilentMode) {
+ ShellPrintEx(-1, -1, HiiOutput, Node->FullName, DestPath);
+ }
+
+ //
+ // copy single file...
+ //
+ ShellStatus = CopySingleFile(Node->FullName, DestPath, &Response, SilentMode, L"cp");
+ if (ShellStatus != SHELL_SUCCESS) {
+ break;
+ }
+ }
+ if (ShellStatus == SHELL_SUCCESS && Resp == NULL) {
+ ShellPrintEx(-1, -1, L"%s", HiiResultOk);
+ }
+
+ SHELL_FREE_NON_NULL(DestPath);
+ SHELL_FREE_NON_NULL(HiiOutput);
+ SHELL_FREE_NON_NULL(HiiResultOk);
+ SHELL_FREE_NON_NULL(CleanFilePathStr);
+ if (Resp == NULL) {
+ SHELL_FREE_NON_NULL(Response);
+ }
+
+ return (ShellStatus);
+
+}
+
+/**
+ Validate and if successful copy all the files from the list into
+ destination directory.
+
+ @param[in] FileList The list of files to copy.
+ @param[in] DestDir The directory to copy files to.
+ @param[in] SilentMode TRUE to eliminate screen output.
+ @param[in] RecursiveMode TRUE to copy directories.
+
+ @retval SHELL_INVALID_PARAMETER A parameter was invalid.
+ @retval SHELL_SUCCESS The operation was successful.
+**/
+SHELL_STATUS
+EFIAPI
+ProcessValidateAndCopyFiles(
+ IN EFI_SHELL_FILE_INFO *FileList,
+ IN CONST CHAR16 *DestDir,
+ IN BOOLEAN SilentMode,
+ IN BOOLEAN RecursiveMode
+ )
+{
+ SHELL_STATUS ShellStatus;
+ EFI_SHELL_FILE_INFO *List;
+ EFI_FILE_INFO *FileInfo;
+ CHAR16 *FullName;
+
+ List = NULL;
+ FullName = NULL;
+ FileInfo = NULL;
+
+ ShellOpenFileMetaArg((CHAR16*)DestDir, EFI_FILE_MODE_READ, &List);
+ if (List != NULL && List->Link.ForwardLink != List->Link.BackLink) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_MARG_ERROR), gShellLevel2HiiHandle, L"cp", DestDir);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ ShellCloseFileMetaArg(&List);
+ } else if (List != NULL) {
+ ASSERT(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink) != NULL);
+ ASSERT(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->FullName != NULL);
+ FileInfo = gEfiShellProtocol->GetFileInfo(((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->Handle);
+ ASSERT(FileInfo != NULL);
+ StrnCatGrow(&FullName, NULL, ((EFI_SHELL_FILE_INFO *)List->Link.ForwardLink)->FullName, 0);
+ ShellCloseFileMetaArg(&List);
+ if ((FileInfo->Attribute & EFI_FILE_READ_ONLY) == 0) {
+ ShellStatus = ValidateAndCopyFiles(FileList, FullName, SilentMode, RecursiveMode, NULL);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_CP_DEST_ERROR), gShellLevel2HiiHandle, L"cp");
+ ShellStatus = SHELL_ACCESS_DENIED;
+ }
+ } else {
+ ShellCloseFileMetaArg(&List);
+ ShellStatus = ValidateAndCopyFiles(FileList, DestDir, SilentMode, RecursiveMode, NULL);
+ }
+
+ SHELL_FREE_NON_NULL(FileInfo);
+ SHELL_FREE_NON_NULL(FullName);
+ return (ShellStatus);
+}
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-r", TypeFlag},
+ {L"-q", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'cp' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunCp (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ UINTN ParamCount;
+ UINTN LoopCounter;
+ EFI_SHELL_FILE_INFO *FileList;
+ BOOLEAN SilentMode;
+ BOOLEAN RecursiveMode;
+ CONST CHAR16 *Cwd;
+ CHAR16 *FullCwd;
+
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ ParamCount = 0;
+ FileList = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"cp", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ }
+
+ //
+ // Initialize SilentMode and RecursiveMode
+ //
+ if (gEfiShellProtocol->BatchIsActive()) {
+ SilentMode = TRUE;
+ } else {
+ SilentMode = ShellCommandLineGetFlag(Package, L"-q");
+ }
+ RecursiveMode = ShellCommandLineGetFlag(Package, L"-r");
+
+ switch (ParamCount = ShellCommandLineGetCount(Package)) {
+ case 0:
+ case 1:
+ //
+ // we have insufficient parameters
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"cp");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ break;
+ case 2:
+ //
+ // must have valid CWD for single parameter...
+ //
+ Cwd = ShellGetCurrentDir(NULL);
+ if (Cwd == NULL){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"cp");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, 1), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);
+ if (FileList == NULL || IsListEmpty(&FileList->Link) || EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, L"cp", ShellCommandLineGetRawValue(Package, 1));
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ FullCwd = AllocateZeroPool(StrSize(Cwd) + sizeof(CHAR16));
+ if (FullCwd == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellLevel2HiiHandle, L"cp");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ } else {
+ StrCpyS (FullCwd, StrSize (Cwd) / sizeof (CHAR16) + 1, Cwd);
+ ShellStatus = ProcessValidateAndCopyFiles (FileList, FullCwd, SilentMode, RecursiveMode);
+ FreePool (FullCwd);
+ }
+ }
+ }
+
+ break;
+ default:
+ //
+ // Make a big list of all the files...
+ //
+ for (ParamCount--, LoopCounter = 1 ; LoopCounter < ParamCount && ShellStatus == SHELL_SUCCESS ; LoopCounter++) {
+ if (ShellGetExecutionBreakFlag()) {
+ break;
+ }
+ Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, LoopCounter), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);
+ if (EFI_ERROR(Status) || FileList == NULL || IsListEmpty(&FileList->Link)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, L"cp", ShellCommandLineGetRawValue(Package, LoopCounter));
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ }
+ if (ShellStatus != SHELL_SUCCESS) {
+ Status = ShellCloseFileMetaArg(&FileList);
+ } else {
+ //
+ // now copy them all...
+ //
+ if (FileList != NULL && !IsListEmpty(&FileList->Link)) {
+ ShellStatus = ProcessValidateAndCopyFiles(FileList, PathCleanUpDirectories((CHAR16*)ShellCommandLineGetRawValue(Package, ParamCount)), SilentMode, RecursiveMode);
+ Status = ShellCloseFileMetaArg(&FileList);
+ if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_FILE), gShellLevel2HiiHandle, L"cp", ShellCommandLineGetRawValue(Package, ParamCount), ShellStatus|MAX_BIT);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ }
+ }
+ }
+ break;
+ } // switch on parameter count
+
+ if (FileList != NULL) {
+ ShellCloseFileMetaArg(&FileList);
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ if (ShellGetExecutionBreakFlag()) {
+ return (SHELL_ABORTED);
+ }
+
+ return (ShellStatus);
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Load.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Load.c
new file mode 100644
index 0000000000..ff7c8187c2
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Load.c
@@ -0,0 +1,281 @@
+/** @file
+ Main file for attrib shell level 2 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel2CommandsLib.h"
+
+// This function was from from the BdsLib implementation in
+// IntelFrameworkModulePkg\Library\GenericBdsLib\BdsConnect.c
+// function name: BdsLibConnectAllEfi
+/**
+ This function will connect all current system handles recursively. The
+ connection will finish until every handle's child handle created if it have.
+
+ @retval EFI_SUCCESS All handles and it's child handle have been
+ connected
+ @retval EFI_STATUS Return the status of gBS->LocateHandleBuffer().
+
+**/
+EFI_STATUS
+EFIAPI
+ConnectAllEfi (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleCount;
+ EFI_HANDLE *HandleBuffer;
+ UINTN Index;
+
+ Status = gBS->LocateHandleBuffer (
+ AllHandles,
+ NULL,
+ NULL,
+ &HandleCount,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ for (Index = 0; Index < HandleCount; Index++) {
+ Status = gBS->ConnectController (HandleBuffer[Index], NULL, NULL, TRUE);
+ }
+
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+
+ return EFI_SUCCESS;
+}
+
+/**
+ function to load a .EFI driver into memory and possible connect the driver.
+
+ if FileName is NULL then ASSERT.
+
+ @param[in] FileName FileName of the driver to load
+ @param[in] Connect Whether to connect or not
+
+ @retval EFI_SUCCESS the driver was loaded and if Connect was
+ true then connect was attempted. Connection may
+ have failed.
+ @retval EFI_OUT_OF_RESOURCES there was insufficient memory
+**/
+EFI_STATUS
+EFIAPI
+LoadDriver(
+ IN CONST CHAR16 *FileName,
+ IN CONST BOOLEAN Connect
+ )
+{
+ EFI_HANDLE LoadedDriverHandle;
+ EFI_STATUS Status;
+ EFI_DEVICE_PATH_PROTOCOL *FilePath;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedDriverImage;
+
+ LoadedDriverImage = NULL;
+ FilePath = NULL;
+ LoadedDriverHandle = NULL;
+ Status = EFI_SUCCESS;
+
+ ASSERT (FileName != NULL);
+
+ //
+ // Fix local copies of the protocol pointers
+ //
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Convert to DEVICE_PATH
+ //
+ FilePath = gEfiShellProtocol->GetDevicePathFromFilePath(FileName);
+
+ if (FilePath == NULL) {
+ ASSERT(FALSE);
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ //
+ // Use LoadImage to get it into memory
+ //
+ Status = gBS->LoadImage(
+ FALSE,
+ gImageHandle,
+ FilePath,
+ NULL,
+ 0,
+ &LoadedDriverHandle);
+
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_NOT_IMAGE), gShellLevel2HiiHandle, FileName, Status);
+ } else {
+ //
+ // Make sure it is a driver image
+ //
+ Status = gBS->HandleProtocol (LoadedDriverHandle, &gEfiLoadedImageProtocolGuid, (VOID *) &LoadedDriverImage);
+
+ ASSERT (LoadedDriverImage != NULL);
+
+ if ( EFI_ERROR(Status)
+ || ( LoadedDriverImage->ImageCodeType != EfiBootServicesCode
+ && LoadedDriverImage->ImageCodeType != EfiRuntimeServicesCode)
+ ){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_NOT_DRIVER), gShellLevel2HiiHandle, FileName);
+
+ //
+ // Exit and unload the non-driver image
+ //
+ gBS->Exit(LoadedDriverHandle, EFI_INVALID_PARAMETER, 0, NULL);
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+
+ if (!EFI_ERROR(Status)) {
+ //
+ // Start the image
+ //
+ Status = gBS->StartImage(LoadedDriverHandle, NULL, NULL);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_ERROR), gShellLevel2HiiHandle, FileName, Status);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LOAD_LOADED), gShellLevel2HiiHandle, FileName, LoadedDriverImage->ImageBase, Status);
+ }
+ }
+
+ if (!EFI_ERROR(Status) && Connect) {
+ //
+ // Connect it...
+ //
+ Status = ConnectAllEfi();
+ }
+
+ //
+ // clean up memory...
+ //
+ if (FilePath != NULL) {
+ FreePool(FilePath);
+ }
+
+ return (Status);
+}
+
+STATIC CONST SHELL_PARAM_ITEM LoadParamList[] = {
+ {L"-nc", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'load' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunLoad (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ UINTN ParamCount;
+ EFI_SHELL_FILE_INFO *ListHead;
+ EFI_SHELL_FILE_INFO *Node;
+
+ ListHead = NULL;
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (LoadParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"load", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ } else if (ShellCommandLineGetRawValue(Package, 1) == NULL) {
+ //
+ // we didnt get a single file to load parameter
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"load");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ for ( ParamCount = 1
+ ; ShellCommandLineGetRawValue(Package, ParamCount) != NULL
+ ; ParamCount++
+ ){
+ Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, ParamCount), EFI_FILE_MODE_READ, &ListHead);
+ if (!EFI_ERROR(Status)) {
+ for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link)
+ ; !IsNull(&ListHead->Link, &Node->Link)
+ ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&ListHead->Link, &Node->Link)
+ ){
+ //
+ // once we have an error preserve that value, but finish the loop.
+ //
+ if (EFI_ERROR(Status)) {
+ LoadDriver(Node->FullName, (BOOLEAN)(ShellCommandLineGetFlag(Package, L"-nc")==FALSE));
+ } else {
+ Status = LoadDriver(Node->FullName, (BOOLEAN)(ShellCommandLineGetFlag(Package, L"-nc")==FALSE));
+ }
+ } // for loop for multi-open
+ if (EFI_ERROR(Status)) {
+ ShellCloseFileMetaArg(&ListHead);
+ } else {
+ Status = ShellCloseFileMetaArg(&ListHead);;
+ }
+ } else {
+ //
+ // no files found.
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, L"load", (CHAR16*)ShellCommandLineGetRawValue(Package, ParamCount));
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ } // for loop for params
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) {
+ ShellStatus = SHELL_DEVICE_ERROR;
+ }
+
+ return (ShellStatus);
+}
diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c
new file mode 100644
index 0000000000..25bf8ca9e1
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Ls.c
@@ -0,0 +1,758 @@
+/** @file
+ Main file for ls shell level 2 function.
+
+ (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel2CommandsLib.h"
+#include <Guid/FileSystemInfo.h>
+
+/**
+ print out the standard format output volume entry.
+
+ @param[in] TheList a list of files from the volume.
+**/
+EFI_STATUS
+EFIAPI
+PrintSfoVolumeInfoTableEntry(
+ IN CONST EFI_SHELL_FILE_INFO *TheList
+ )
+{
+ EFI_STATUS Status;
+ EFI_SHELL_FILE_INFO *Node;
+ CHAR16 *DirectoryName;
+ EFI_FILE_SYSTEM_INFO *SysInfo;
+ UINTN SysInfoSize;
+ SHELL_FILE_HANDLE ShellFileHandle;
+ EFI_FILE_PROTOCOL *EfiFpHandle;
+
+ //
+ // Get the first valid handle (directories)
+ //
+ for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&TheList->Link)
+ ; !IsNull(&TheList->Link, &Node->Link) && Node->Handle == NULL
+ ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&TheList->Link, &Node->Link)
+ );
+
+ if (Node->Handle == NULL) {
+ DirectoryName = GetFullyQualifiedPath(((EFI_SHELL_FILE_INFO *)GetFirstNode(&TheList->Link))->FullName);
+
+ //
+ // We need to open something up to get system information
+ //
+ Status = gEfiShellProtocol->OpenFileByName(
+ DirectoryName,
+ &ShellFileHandle,
+ EFI_FILE_MODE_READ
+ );
+
+ ASSERT_EFI_ERROR(Status);
+ FreePool(DirectoryName);
+
+ //
+ // Get the Volume Info from ShellFileHandle
+ //
+ SysInfo = NULL;
+ SysInfoSize = 0;
+ EfiFpHandle = ConvertShellHandleToEfiFileProtocol(ShellFileHandle);
+ Status = EfiFpHandle->GetInfo(
+ EfiFpHandle,
+ &gEfiFileSystemInfoGuid,
+ &SysInfoSize,
+ SysInfo
+ );
+
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ SysInfo = AllocateZeroPool(SysInfoSize);
+ Status = EfiFpHandle->GetInfo(
+ EfiFpHandle,
+ &gEfiFileSystemInfoGuid,
+ &SysInfoSize,
+ SysInfo
+ );
+ }
+
+ ASSERT_EFI_ERROR(Status);
+
+ gEfiShellProtocol->CloseFile(ShellFileHandle);
+ } else {
+ //
+ // Get the Volume Info from Node->Handle
+ //
+ SysInfo = NULL;
+ SysInfoSize = 0;
+ EfiFpHandle = ConvertShellHandleToEfiFileProtocol(Node->Handle);
+ Status = EfiFpHandle->GetInfo(
+ EfiFpHandle,
+ &gEfiFileSystemInfoGuid,
+ &SysInfoSize,
+ SysInfo
+ );
+
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ SysInfo = AllocateZeroPool(SysInfoSize);
+ Status = EfiFpHandle->GetInfo(
+ EfiFpHandle,
+ &gEfiFileSystemInfoGuid,
+ &SysInfoSize,
+ SysInfo
+ );
+ }
+
+ ASSERT_EFI_ERROR(Status);
+ }
+
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_GEN_SFO_HEADER),
+ gShellLevel2HiiHandle,
+ L"ls"
+ );
+ //
+ // print VolumeInfo table
+ //
+ ASSERT(SysInfo != NULL);
+ ShellPrintHiiEx (
+ 0,
+ gST->ConOut->Mode->CursorRow,
+ NULL,
+ STRING_TOKEN (STR_LS_SFO_VOLINFO),
+ gShellLevel2HiiHandle,
+ SysInfo->VolumeLabel,
+ SysInfo->VolumeSize,
+ SysInfo->ReadOnly?L"TRUE":L"FALSE",
+ SysInfo->FreeSpace,
+ SysInfo->BlockSize
+ );
+
+ SHELL_FREE_NON_NULL(SysInfo);
+
+ return (Status);
+}
+
+/**
+ print out the info on a single file.
+
+ @param[in] Sfo TRUE if in SFO, false otherwise.
+ @param[in] TheNode the EFI_SHELL_FILE_INFO node to print out information on.
+ @param[in] Files incremented if a file is printed.
+ @param[in] Size incremented by file size.
+ @param[in] Dirs incremented if a directory is printed.
+
+**/
+VOID
+EFIAPI
+PrintFileInformation(
+ IN CONST BOOLEAN Sfo,
+ IN CONST EFI_SHELL_FILE_INFO *TheNode,
+ IN UINT64 *Files,
+ IN UINT64 *Size,
+ IN UINT64 *Dirs
+ )
+{
+ ASSERT(Files != NULL);
+ ASSERT(Size != NULL);
+ ASSERT(Dirs != NULL);
+ ASSERT(TheNode != NULL);
+
+ if (Sfo) {
+ //
+ // Print the FileInfo Table
+ //
+ ShellPrintHiiEx (
+ 0,
+ gST->ConOut->Mode->CursorRow,
+ NULL,
+ STRING_TOKEN (STR_LS_SFO_FILEINFO),
+ gShellLevel2HiiHandle,
+ TheNode->FullName,
+ TheNode->Info->FileSize,
+ TheNode->Info->PhysicalSize,
+ (TheNode->Info->Attribute & EFI_FILE_ARCHIVE) != 0?L"a":L"",
+ (TheNode->Info->Attribute & EFI_FILE_DIRECTORY) != 0?L"d":L"",
+ (TheNode->Info->Attribute & EFI_FILE_HIDDEN) != 0?L"h":L"",
+ (TheNode->Info->Attribute & EFI_FILE_READ_ONLY) != 0?L"r":L"",
+ (TheNode->Info->Attribute & EFI_FILE_SYSTEM) != 0?L"s":L"",
+ TheNode->Info->CreateTime.Hour,
+ TheNode->Info->CreateTime.Minute,
+ TheNode->Info->CreateTime.Second,
+ TheNode->Info->CreateTime.Day,
+ TheNode->Info->CreateTime.Month,
+ TheNode->Info->CreateTime.Year,
+ TheNode->Info->LastAccessTime.Hour,
+ TheNode->Info->LastAccessTime.Minute,
+ TheNode->Info->LastAccessTime.Second,
+ TheNode->Info->LastAccessTime.Day,
+ TheNode->Info->LastAccessTime.Month,
+ TheNode->Info->LastAccessTime.Year,
+ TheNode->Info->ModificationTime.Hour,
+ TheNode->Info->ModificationTime.Minute,
+ TheNode->Info->ModificationTime.Second,
+ TheNode->Info->ModificationTime.Day,
+ TheNode->Info->ModificationTime.Month,
+ TheNode->Info->ModificationTime.Year
+ );
+ } else {
+ //
+ // print this one out...
+ // first print the universal start, next print the type specific name format, last print the CRLF
+ //
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_LS_LINE_START_ALL),
+ gShellLevel2HiiHandle,
+ &TheNode->Info->ModificationTime,
+ (TheNode->Info->Attribute & EFI_FILE_DIRECTORY) != 0?L"<DIR>":L"",
+ (TheNode->Info->Attribute & EFI_FILE_READ_ONLY) != 0?L'r':L' ',
+ TheNode->Info->FileSize
+ );
+ if (TheNode->Info->Attribute & EFI_FILE_DIRECTORY) {
+ (*Dirs)++;
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_LS_LINE_END_DIR),
+ gShellLevel2HiiHandle,
+ TheNode->FileName
+ );
+ } else {
+ (*Files)++;
+ (*Size) += TheNode->Info->FileSize;
+ if ( (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)L".nsh", (CHAR16*)&(TheNode->FileName[StrLen (TheNode->FileName) - 4])) == 0)
+ || (gUnicodeCollation->StriColl(gUnicodeCollation, (CHAR16*)L".efi", (CHAR16*)&(TheNode->FileName[StrLen (TheNode->FileName) - 4])) == 0)
+ ){
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_LS_LINE_END_EXE),
+ gShellLevel2HiiHandle,
+ TheNode->FileName
+ );
+ } else {
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_LS_LINE_END_FILE),
+ gShellLevel2HiiHandle,
+ TheNode->FileName
+ );
+ }
+ }
+ }
+}
+
+/**
+ print out the header when not using standard format output.
+
+ @param[in] Path String with starting path.
+**/
+VOID
+EFIAPI
+PrintNonSfoHeader(
+ IN CONST CHAR16 *Path
+ )
+{
+ CHAR16 *DirectoryName;
+
+ //
+ // get directory name from path...
+ //
+ DirectoryName = GetFullyQualifiedPath(Path);
+
+ if (DirectoryName != NULL) {
+ //
+ // print header
+ //
+ ShellPrintHiiEx (
+ 0,
+ gST->ConOut->Mode->CursorRow,
+ NULL,
+ STRING_TOKEN (STR_LS_HEADER_LINE1),
+ gShellLevel2HiiHandle,
+ DirectoryName
+ );
+
+ SHELL_FREE_NON_NULL(DirectoryName);
+ }
+}
+
+/**
+ print out the footer when not using standard format output.
+
+ @param[in] Files The number of files.
+ @param[in] Size The size of files in bytes.
+ @param[in] Dirs The number of directories.
+**/
+VOID
+EFIAPI
+PrintNonSfoFooter(
+ IN UINT64 Files,
+ IN UINT64 Size,
+ IN UINT64 Dirs
+ )
+{
+ //
+ // print footer
+ //
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_LS_FOOTER_LINE),
+ gShellLevel2HiiHandle,
+ Files,
+ Size,
+ Dirs
+ );
+}
+
+/**
+ print out the list of files and directories from the LS command
+
+ @param[in] Rec TRUE to automatically recurse into each found directory
+ FALSE to only list the specified directory.
+ @param[in] Attribs List of required Attribute for display.
+ If 0 then all non-system and non-hidden files will be printed.
+ @param[in] Sfo TRUE to use Standard Format Output, FALSE otherwise
+ @param[in] RootPath String with starting path to search in.
+ @param[in] SearchString String with search string.
+ @param[in] Found Set to TRUE, if anyone were found.
+ @param[in] Count The count of bits enabled in Attribs.
+ @param[in] TimeZone The current time zone offset.
+
+ @retval SHELL_SUCCESS the printing was sucessful.
+**/
+SHELL_STATUS
+EFIAPI
+PrintLsOutput(
+ IN CONST BOOLEAN Rec,
+ IN CONST UINT64 Attribs,
+ IN CONST BOOLEAN Sfo,
+ IN CONST CHAR16 *RootPath,
+ IN CONST CHAR16 *SearchString,
+ IN BOOLEAN *Found,
+ IN CONST UINTN Count,
+ IN CONST INT16 TimeZone
+ )
+{
+ EFI_STATUS Status;
+ EFI_SHELL_FILE_INFO *ListHead;
+ EFI_SHELL_FILE_INFO *Node;
+ SHELL_STATUS ShellStatus;
+ UINT64 FileCount;
+ UINT64 DirCount;
+ UINT64 FileSize;
+ UINTN LongestPath;
+ CHAR16 *CorrectedPath;
+ BOOLEAN FoundOne;
+ BOOLEAN HeaderPrinted;
+
+ HeaderPrinted = FALSE;
+ FileCount = 0;
+ DirCount = 0;
+ FileSize = 0;
+ ListHead = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ LongestPath = 0;
+ CorrectedPath = NULL;
+
+ if (Found != NULL) {
+ FoundOne = *Found;
+ } else {
+ FoundOne = FALSE;
+ }
+
+ CorrectedPath = StrnCatGrow(&CorrectedPath, &LongestPath, RootPath, 0);
+ if (CorrectedPath == NULL) {
+ return SHELL_OUT_OF_RESOURCES;
+ }
+ if (CorrectedPath[StrLen(CorrectedPath)-1] != L'\\'
+ &&CorrectedPath[StrLen(CorrectedPath)-1] != L'/') {
+ CorrectedPath = StrnCatGrow(&CorrectedPath, &LongestPath, L"\\", 0);
+ }
+ CorrectedPath = StrnCatGrow(&CorrectedPath, &LongestPath, SearchString, 0);
+ if (CorrectedPath == NULL) {
+ return (SHELL_OUT_OF_RESOURCES);
+ }
+
+ PathCleanUpDirectories(CorrectedPath);
+
+ Status = ShellOpenFileMetaArg((CHAR16*)CorrectedPath, EFI_FILE_MODE_READ, &ListHead);
+ if (!EFI_ERROR(Status)) {
+ if (ListHead == NULL || IsListEmpty(&ListHead->Link)) {
+ SHELL_FREE_NON_NULL(CorrectedPath);
+ return (SHELL_SUCCESS);
+ }
+
+ if (Sfo && Found == NULL) {
+ PrintSfoVolumeInfoTableEntry(ListHead);
+ }
+
+ for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link), LongestPath = 0
+ ; !IsNull(&ListHead->Link, &Node->Link)
+ ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&ListHead->Link, &Node->Link)
+ ){
+ if (ShellGetExecutionBreakFlag ()) {
+ ShellStatus = SHELL_ABORTED;
+ break;
+ }
+ ASSERT(Node != NULL);
+ if (LongestPath < StrSize(Node->FullName)) {
+ LongestPath = StrSize(Node->FullName);
+ }
+ ASSERT(Node->Info != NULL);
+ ASSERT((Node->Info->Attribute & EFI_FILE_VALID_ATTR) == Node->Info->Attribute);
+ if (Attribs == 0) {
+ //
+ // NOT system & NOT hidden
+ //
+ if ( (Node->Info->Attribute & EFI_FILE_SYSTEM)
+ || (Node->Info->Attribute & EFI_FILE_HIDDEN)
+ ){
+ continue;
+ }
+ } else if ((Attribs != EFI_FILE_VALID_ATTR) ||
+ (Count == 5)) {
+ //
+ // Only matches the bits which "Attribs" contains, not
+ // all files/directories with any of the bits.
+ // Count == 5 is used to tell the difference between a user
+ // specifying all bits (EX: -arhsda) and just specifying
+ // -a (means display all files with any attribute).
+ //
+ if ( (Node->Info->Attribute & Attribs) != Attribs) {
+ continue;
+ }
+ }
+
+ if (!Sfo && !HeaderPrinted) {
+ PrintNonSfoHeader(CorrectedPath);
+ }
+ PrintFileInformation(Sfo, Node, &FileCount, &FileSize, &DirCount);
+ FoundOne = TRUE;
+ HeaderPrinted = TRUE;
+ }
+
+ if (!Sfo && ShellStatus != SHELL_ABORTED) {
+ PrintNonSfoFooter(FileCount, FileSize, DirCount);
+ }
+ }
+
+ if (Rec && ShellStatus != SHELL_ABORTED) {
+ //
+ // Re-Open all the files under the starting path for directories that didnt necessarily match our file filter
+ //
+ ShellCloseFileMetaArg(&ListHead);
+ CorrectedPath[0] = CHAR_NULL;
+ CorrectedPath = StrnCatGrow(&CorrectedPath, &LongestPath, RootPath, 0);
+ if (CorrectedPath == NULL) {
+ return SHELL_OUT_OF_RESOURCES;
+ }
+ if (CorrectedPath[StrLen(CorrectedPath)-1] != L'\\'
+ &&CorrectedPath[StrLen(CorrectedPath)-1] != L'/') {
+ CorrectedPath = StrnCatGrow(&CorrectedPath, &LongestPath, L"\\", 0);
+ }
+ CorrectedPath = StrnCatGrow(&CorrectedPath, &LongestPath, L"*", 0);
+ Status = ShellOpenFileMetaArg((CHAR16*)CorrectedPath, EFI_FILE_MODE_READ, &ListHead);
+
+ if (!EFI_ERROR(Status)) {
+ for ( Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&ListHead->Link)
+ ; !IsNull(&ListHead->Link, &Node->Link) && ShellStatus == SHELL_SUCCESS
+ ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&ListHead->Link, &Node->Link)
+ ){
+ if (ShellGetExecutionBreakFlag ()) {
+ ShellStatus = SHELL_ABORTED;
+ break;
+ }
+
+ //
+ // recurse on any directory except the traversing ones...
+ //
+ if (((Node->Info->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY)
+ && StrCmp(Node->FileName, L".") != 0
+ && StrCmp(Node->FileName, L"..") != 0
+ ){
+ ShellStatus = PrintLsOutput(
+ Rec,
+ Attribs,
+ Sfo,
+ Node->FullName,
+ SearchString,
+ &FoundOne,
+ Count,
+ TimeZone);
+
+ //
+ // Since it's running recursively, we have to break immediately when returned SHELL_ABORTED
+ //
+ if (ShellStatus == SHELL_ABORTED) {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ SHELL_FREE_NON_NULL(CorrectedPath);
+ ShellCloseFileMetaArg(&ListHead);
+
+ if (Found == NULL && !FoundOne) {
+ return (SHELL_NOT_FOUND);
+ }
+
+ if (Found != NULL) {
+ *Found = FoundOne;
+ }
+
+ return (ShellStatus);
+}
+
+STATIC CONST SHELL_PARAM_ITEM LsParamList[] = {
+ {L"-r", TypeFlag},
+ {L"-a", TypeStart},
+ {L"-sfo", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'ls' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunLs (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ CONST CHAR16 *Attribs;
+ SHELL_STATUS ShellStatus;
+ UINT64 RequiredAttributes;
+ CONST CHAR16 *PathName;
+ CONST CHAR16 *CurDir;
+ UINTN Count;
+ CHAR16 *FullPath;
+ UINTN Size;
+ EFI_TIME TheTime;
+ CHAR16 *SearchString;
+
+ Size = 0;
+ FullPath = NULL;
+ ProblemParam = NULL;
+ Attribs = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ RequiredAttributes = 0;
+ PathName = NULL;
+ SearchString = NULL;
+ CurDir = NULL;
+ Count = 0;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Fix local copies of the protocol pointers
+ //
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (LsParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"ls", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ }
+
+ if (ShellCommandLineGetCount(Package) > 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"ls");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // check for -a
+ //
+ if (ShellCommandLineGetFlag(Package, L"-a")) {
+ for ( Attribs = ShellCommandLineGetValue(Package, L"-a")
+ ; Attribs != NULL && *Attribs != CHAR_NULL && ShellStatus == SHELL_SUCCESS
+ ; Attribs++
+ ){
+ switch (*Attribs) {
+ case L'a':
+ case L'A':
+ RequiredAttributes |= EFI_FILE_ARCHIVE;
+ Count++;
+ continue;
+ case L's':
+ case L'S':
+ RequiredAttributes |= EFI_FILE_SYSTEM;
+ Count++;
+ continue;
+ case L'h':
+ case L'H':
+ RequiredAttributes |= EFI_FILE_HIDDEN;
+ Count++;
+ continue;
+ case L'r':
+ case L'R':
+ RequiredAttributes |= EFI_FILE_READ_ONLY;
+ Count++;
+ continue;
+ case L'd':
+ case L'D':
+ RequiredAttributes |= EFI_FILE_DIRECTORY;
+ Count++;
+ continue;
+ default:
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ATTRIBUTE), gShellLevel2HiiHandle, L"ls", ShellCommandLineGetValue(Package, L"-a"));
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ break;
+ } // switch
+ } // for loop
+ //
+ // if nothing is specified all are specified
+ //
+ if (RequiredAttributes == 0) {
+ RequiredAttributes = EFI_FILE_VALID_ATTR;
+ }
+ } // if -a present
+ if (ShellStatus == SHELL_SUCCESS) {
+ PathName = ShellCommandLineGetRawValue(Package, 1);
+ if (PathName == NULL) {
+ //
+ // Nothing specified... must start from current directory
+ //
+ CurDir = gEfiShellProtocol->GetCurDir(NULL);
+ if (CurDir == NULL) {
+ ShellStatus = SHELL_NOT_FOUND;
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"ls");
+ }
+ //
+ // Copy to the 2 strings for starting path and file search string
+ //
+ ASSERT(SearchString == NULL);
+ ASSERT(FullPath == NULL);
+ StrnCatGrow(&SearchString, NULL, L"*", 0);
+ StrnCatGrow(&FullPath, NULL, CurDir, 0);
+ Size = FullPath != NULL? StrSize(FullPath) : 0;
+ StrnCatGrow(&FullPath, &Size, L"\\", 0);
+ } else {
+ if (StrStr(PathName, L":") == NULL && gEfiShellProtocol->GetCurDir(NULL) == NULL) {
+ //
+ // If we got something and it doesnt have a fully qualified path, then we needed to have a CWD.
+ //
+ ShellStatus = SHELL_NOT_FOUND;
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"ls");
+ } else {
+ //
+ // We got a valid fully qualified path or we have a CWD
+ //
+ ASSERT((FullPath == NULL && Size == 0) || (FullPath != NULL));
+ if (StrStr(PathName, L":") == NULL) {
+ StrnCatGrow(&FullPath, &Size, gEfiShellProtocol->GetCurDir(NULL), 0);
+ if (FullPath == NULL) {
+ ShellCommandLineFreeVarList (Package);
+ return SHELL_OUT_OF_RESOURCES;
+ }
+ Size = FullPath != NULL? StrSize(FullPath) : 0;
+ StrnCatGrow(&FullPath, &Size, L"\\", 0);
+ }
+ StrnCatGrow(&FullPath, &Size, PathName, 0);
+ if (FullPath == NULL) {
+ ShellCommandLineFreeVarList (Package);
+ return SHELL_OUT_OF_RESOURCES;
+ }
+
+ if (ShellIsDirectory(PathName) == EFI_SUCCESS) {
+ //
+ // is listing ends with a directory, then we list all files in that directory
+ //
+ StrnCatGrow(&SearchString, NULL, L"*", 0);
+ } else {
+ //
+ // must split off the search part that applies to files from the end of the directory part
+ //
+ for (StrnCatGrow(&SearchString, NULL, PathName, 0)
+ ; SearchString != NULL && StrStr(SearchString, L"\\") != NULL
+ ; CopyMem(SearchString, StrStr(SearchString, L"\\") + 1, 1 + StrSize(StrStr(SearchString, L"\\") + 1))) ;
+ FullPath[StrLen(FullPath) - StrLen(SearchString)] = CHAR_NULL;
+ }
+ }
+ }
+ Status = gRT->GetTime(&TheTime, NULL);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"ls", L"gRT->GetTime", Status);
+ TheTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE;
+ }
+
+ if (ShellStatus == SHELL_SUCCESS) {
+ ShellStatus = PrintLsOutput(
+ ShellCommandLineGetFlag(Package, L"-r"),
+ RequiredAttributes,
+ ShellCommandLineGetFlag(Package, L"-sfo"),
+ FullPath,
+ SearchString,
+ NULL,
+ Count,
+ TheTime.TimeZone
+ );
+ if (ShellStatus == SHELL_NOT_FOUND) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_LS_FILE_NOT_FOUND), gShellLevel2HiiHandle, L"ls", FullPath);
+ } else if (ShellStatus == SHELL_INVALID_PARAMETER) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"ls", FullPath);
+ } else if (ShellStatus == SHELL_ABORTED) {
+ //
+ // Ignore aborting.
+ //
+ } else if (ShellStatus != SHELL_SUCCESS) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"ls", FullPath);
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // Free memory allocated
+ //
+ SHELL_FREE_NON_NULL(SearchString);
+ SHELL_FREE_NON_NULL(FullPath);
+ ShellCommandLineFreeVarList (Package);
+
+ return (ShellStatus);
+}
diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c
new file mode 100644
index 0000000000..035aff1a0f
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Map.c
@@ -0,0 +1,1256 @@
+/** @file
+ Main file for map shell level 2 command.
+
+ Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel2CommandsLib.h"
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/BlockIo.h>
+#include <Library/DevicePathLib.h>
+#include <Library/HandleParsingLib.h>
+#include <Library/SortLib.h>
+
+/**
+ Determine if a string has only numbers and letters.
+
+ This is useful for such things as Map names which can only be letters and numbers.
+
+ @param[in] String pointer to the string to analyze,
+ @param[in] Len Number of characters to analyze.
+
+ @retval TRUE String has only numbers and letters
+ @retval FALSE String has at least one other character.
+**/
+BOOLEAN
+EFIAPI
+IsNumberLetterOnly(
+ IN CONST CHAR16 *String,
+ IN CONST UINTN Len
+ )
+{
+ UINTN Count;
+ for (Count = 0 ; Count < Len && String != NULL && *String != CHAR_NULL ; String++,Count++) {
+ if (! ((*String >= L'a' && *String <= L'z') ||
+ (*String >= L'A' && *String <= L'Z') ||
+ (*String >= L'0' && *String <= L'9'))
+ ){
+ return (FALSE);
+ }
+ }
+ return (TRUE);
+}
+
+/**
+ Do a search in the Target delimited list.
+
+ @param[in] List The list to seatch in.
+ @param[in] MetaTarget The item to search for. MetaMatching supported.
+ @param[out] FullName Optional pointer to an allocated buffer containing
+ the match.
+ @param[in] Meta TRUE to use MetaMatching.
+ @param[in] SkipTrailingNumbers TRUE to allow for numbers after the MetaTarget.
+ @param[in] Target The single character that delimits list
+ items (";" normally).
+**/
+BOOLEAN
+EFIAPI
+SearchList(
+ IN CONST CHAR16 *List,
+ IN CONST CHAR16 *MetaTarget,
+ OUT CHAR16 **FullName OPTIONAL,
+ IN CONST BOOLEAN Meta,
+ IN CONST BOOLEAN SkipTrailingNumbers,
+ IN CONST CHAR16 *Target
+
+ )
+{
+ CHAR16 *TempList;
+ CONST CHAR16 *ListWalker;
+ BOOLEAN Result;
+ CHAR16 *TempSpot;
+
+ for (ListWalker = List , TempList = NULL
+ ; ListWalker != NULL && *ListWalker != CHAR_NULL
+ ;
+ ) {
+ TempList = StrnCatGrow(&TempList, NULL, ListWalker, 0);
+ ASSERT(TempList != NULL);
+ TempSpot = StrStr(TempList, Target);
+ if (TempSpot != NULL) {
+ *TempSpot = CHAR_NULL;
+ }
+
+ while (SkipTrailingNumbers && (ShellIsDecimalDigitCharacter(TempList[StrLen(TempList)-1]) || TempList[StrLen(TempList)-1] == L':')) {
+ TempList[StrLen(TempList)-1] = CHAR_NULL;
+ }
+
+ ListWalker = StrStr(ListWalker, Target);
+ while(ListWalker != NULL && *ListWalker == *Target) {
+ ListWalker++;
+ }
+ if (Meta) {
+ Result = gUnicodeCollation->MetaiMatch(gUnicodeCollation, (CHAR16*)TempList, (CHAR16*)MetaTarget);
+ } else {
+ Result = (BOOLEAN)(StrCmp(TempList, MetaTarget)==0);
+ }
+ if (Result) {
+ if (FullName != NULL) {
+ *FullName = TempList;
+ } else {
+ FreePool(TempList);
+ }
+ return (TRUE);
+ }
+ FreePool(TempList);
+ TempList = NULL;
+ }
+
+ return (FALSE);
+}
+
+/**
+ Determine what type of device is represented and return it's string. The
+ string is in allocated memory and must be callee freed. The HII is is listed below.
+ The actual string cannot be determined.
+
+ @param[in] DevicePath The device to analyze.
+
+ @retval STR_MAP_MEDIA_UNKNOWN The media type is unknown.
+ @retval STR_MAP_MEDIA_HARDDISK The media is a hard drive.
+ @retval STR_MAP_MEDIA_CDROM The media is a CD ROM.
+ @retval STR_MAP_MEDIA_FLOPPY The media is a floppy drive.
+**/
+CHAR16*
+EFIAPI
+GetDeviceMediaType (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ ACPI_HID_DEVICE_PATH *Acpi;
+
+ //
+ // Parse the device path:
+ // Devicepath sub type mediatype
+ // MEDIA_HANRDDRIVE_DP -> Hard Disk
+ // MEDIA_CDROM_DP -> CD Rom
+ // Acpi.HID = 0X0604 -> Floppy
+ //
+ if (NULL == DevicePath) {
+ return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_UNKNOWN), NULL);
+ }
+
+ for (;!IsDevicePathEndType (DevicePath) ;DevicePath = NextDevicePathNode (DevicePath)) {
+ if (DevicePathType (DevicePath) == MEDIA_DEVICE_PATH) {
+ switch (DevicePathSubType (DevicePath)) {
+ case MEDIA_HARDDRIVE_DP:
+ return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_HARDDISK), NULL);
+ case MEDIA_CDROM_DP:
+ return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_CDROM), NULL);
+ }
+ } else if (DevicePathType (DevicePath) == ACPI_DEVICE_PATH) {
+ Acpi = (ACPI_HID_DEVICE_PATH *) DevicePath;
+ if (EISA_ID_TO_NUM (Acpi->HID) == 0x0604) {
+ return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_FLOPPY), NULL);
+ }
+ }
+ }
+
+ return HiiGetString(gShellLevel2HiiHandle, STRING_TOKEN(STR_MAP_MEDIA_UNKNOWN), NULL);
+}
+
+/**
+ Function to detemine if a handle has removable storage.
+
+ @param[in] DevicePath DevicePath to test.
+
+ @retval TRUE The handle has removable storage.
+ @retval FALSE The handle does not have removable storage.
+**/
+BOOLEAN
+EFIAPI
+IsRemoveableDevice (
+ IN EFI_DEVICE_PATH_PROTOCOL *DevicePath
+ )
+{
+ if (NULL == DevicePath) {
+ return FALSE;
+ }
+
+ while (!IsDevicePathEndType (DevicePath)) {
+ if (DevicePathType (DevicePath) == MESSAGING_DEVICE_PATH) {
+ switch (DevicePathSubType (DevicePath)) {
+ case MSG_USB_DP:
+ case MSG_SCSI_DP:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+ }
+ DevicePath = NextDevicePathNode (DevicePath);
+ }
+ return FALSE;
+}
+
+/**
+ Function to detemine if a something on the map list matches.
+
+ @param[in] MapList The pointer to the list to test.
+ @param[in] Specific The pointer to a specific name to test for.
+ @param[in] TypeString The pointer to the list of types.
+ @param[in] Normal Always show normal mappings.
+ @param[in] Consist Always show consistent mappings.
+
+ @retval TRUE The map should be displayed.
+ @retval FALSE The map should not be displayed.
+**/
+BOOLEAN
+EFIAPI
+MappingListHasType(
+ IN CONST CHAR16 *MapList,
+ IN CONST CHAR16 *Specific,
+ IN CONST CHAR16 *TypeString,
+ IN CONST BOOLEAN Normal,
+ IN CONST BOOLEAN Consist
+ )
+{
+ CHAR16 *NewSpecific;
+ RETURN_STATUS Status;
+
+ //
+ // specific has priority
+ //
+ if (Specific != NULL) {
+ NewSpecific = AllocateCopyPool(StrSize(Specific) + sizeof(CHAR16), Specific);
+ if (NewSpecific == NULL){
+ return FALSE;
+ }
+ if (NewSpecific[StrLen(NewSpecific)-1] != L':') {
+ Status = StrnCatS(NewSpecific, (StrSize(Specific) + sizeof(CHAR16))/sizeof(CHAR16), L":", StrLen(L":"));
+ if (EFI_ERROR (Status)) {
+ FreePool(NewSpecific);
+ return FALSE;
+ }
+ }
+
+ if (SearchList(MapList, NewSpecific, NULL, TRUE, FALSE, L";")) {
+ FreePool(NewSpecific);
+ return (TRUE);
+ }
+ FreePool(NewSpecific);
+ }
+ if ( Consist
+ && Specific == NULL
+ && (SearchList(MapList, L"HD*", NULL, TRUE, TRUE, L";")
+ ||SearchList(MapList, L"CD*", NULL, TRUE, TRUE, L";")
+ ||SearchList(MapList, L"F*", NULL, TRUE, TRUE, L";")
+ ||SearchList(MapList, L"FP*", NULL, TRUE, TRUE, L";"))){
+ return (TRUE);
+ }
+
+ if ( Normal
+ && Specific == NULL
+ && (SearchList(MapList, L"FS", NULL, FALSE, TRUE, L";")
+ ||SearchList(MapList, L"BLK", NULL, FALSE, TRUE, L";"))){
+ return (TRUE);
+ }
+
+ if (TypeString != NULL && SearchList(MapList, TypeString, NULL, TRUE, TRUE, L";")) {
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+
+/**
+ Display a single map line for device Handle if conditions are met.
+
+ @param[in] Verbose TRUE to display (extra) verbose information.
+ @param[in] Consist TRUE to display consistent mappings.
+ @param[in] Normal TRUE to display normal (not consist) mappings.
+ @param[in] TypeString pointer to string of filter types.
+ @param[in] SFO TRUE to display output in Standard Output Format.
+ @param[in] Specific pointer to string for specific map to display.
+ @param[in] Handle The handle to display from.
+
+ @retval EFI_SUCCESS The mapping was displayed.
+**/
+EFI_STATUS
+EFIAPI
+PerformSingleMappingDisplay(
+ IN CONST BOOLEAN Verbose,
+ IN CONST BOOLEAN Consist,
+ IN CONST BOOLEAN Normal,
+ IN CONST CHAR16 *TypeString,
+ IN CONST BOOLEAN SFO,
+ IN CONST CHAR16 *Specific OPTIONAL,
+ IN CONST EFI_HANDLE Handle
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+ EFI_DEVICE_PATH_PROTOCOL *DevPathCopy;
+ CONST CHAR16 *MapList;
+ CHAR16 *CurrentName;
+ CHAR16 *MediaType;
+ CHAR16 *DevPathString;
+ CHAR16 *TempSpot;
+ CHAR16 *Alias;
+ UINTN TempLen;
+ BOOLEAN Removable;
+ CONST CHAR16 *TempSpot2;
+
+ Alias = NULL;
+ TempSpot2 = NULL;
+ CurrentName = NULL;
+ DevPath = DevicePathFromHandle(Handle);
+ DevPathCopy = DevPath;
+ MapList = gEfiShellProtocol->GetMapFromDevicePath(&DevPathCopy);
+ if (MapList == NULL) {
+ return EFI_NOT_FOUND;
+ }
+
+ if (!MappingListHasType(MapList, Specific, TypeString, Normal, Consist)){
+ return EFI_NOT_FOUND;
+ }
+
+ if (Normal || !Consist) {
+ //
+ // need the Normal here since people can use both on command line. otherwise unused.
+ //
+
+ //
+ // Allocate a name
+ //
+ CurrentName = NULL;
+ CurrentName = StrnCatGrow(&CurrentName, 0, MapList, 0);
+ if (CurrentName == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ //
+ // Chop off the other names that become "Alias(s)"
+ // leaving just the normal name
+ //
+ TempSpot = StrStr(CurrentName, L";");
+ if (TempSpot != NULL) {
+ *TempSpot = CHAR_NULL;
+ }
+ } else {
+ CurrentName = NULL;
+
+ //
+ // Skip the first name. This is the standard name.
+ //
+ TempSpot = StrStr(MapList, L";");
+ if (TempSpot != NULL) {
+ TempSpot++;
+ }
+ SearchList(TempSpot, L"HD*", &CurrentName, TRUE, FALSE, L";");
+ if (CurrentName == NULL) {
+ SearchList(TempSpot, L"CD*", &CurrentName, TRUE, FALSE, L";");
+ }
+ if (CurrentName == NULL) {
+ SearchList(TempSpot, L"FP*", &CurrentName, TRUE, FALSE, L";");
+ }
+ if (CurrentName == NULL) {
+ SearchList(TempSpot, L"F*", &CurrentName, TRUE, FALSE, L";");
+ }
+ if (CurrentName == NULL) {
+ //
+ // We didnt find anything, so just the first one in the list...
+ //
+ CurrentName = StrnCatGrow(&CurrentName, 0, MapList, 0);
+ if (CurrentName == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ TempSpot = StrStr(CurrentName, L";");
+ if (TempSpot != NULL) {
+ *TempSpot = CHAR_NULL;
+ }
+ } else {
+ Alias = StrnCatGrow(&Alias, 0, MapList, 0);
+ if (Alias == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+ TempSpot = StrStr(Alias, CurrentName);
+ if (TempSpot != NULL) {
+ TempSpot2 = StrStr(TempSpot, L";");
+ if (TempSpot2 != NULL) {
+ TempSpot2++; // Move past ";" from CurrentName
+ CopyMem(TempSpot, TempSpot2, StrSize(TempSpot2));
+ } else {
+ *TempSpot = CHAR_NULL;
+ }
+ }
+ if (Alias[StrLen(Alias)-1] == L';') {
+ Alias[StrLen(Alias)-1] = CHAR_NULL;
+ }
+ }
+ }
+ DevPathString = ConvertDevicePathToText(DevPath, TRUE, FALSE);
+ TempLen = StrLen(CurrentName);
+ if (!SFO) {
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_MAP_ENTRY),
+ gShellLevel2HiiHandle,
+ CurrentName,
+ Alias!=NULL?Alias:(TempLen < StrLen(MapList)?MapList + TempLen+1:L""),
+ DevPathString
+ );
+ if (Verbose) {
+ //
+ // also print handle, media type, removable (y/n), and current directory
+ //
+ MediaType = GetDeviceMediaType(DevPath);
+ if ((TypeString != NULL &&MediaType != NULL && StrStr(TypeString, MediaType) != NULL) || TypeString == NULL) {
+ Removable = IsRemoveableDevice(DevPath);
+ TempSpot2 = ShellGetCurrentDir(CurrentName);
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_MAP_ENTRY_VERBOSE),
+ gShellLevel2HiiHandle,
+ ConvertHandleToHandleIndex(Handle),
+ MediaType,
+ Removable?L"Yes":L"No",
+ TempSpot2
+ );
+ }
+ SHELL_FREE_NON_NULL(MediaType);
+ }
+ } else {
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_MAP_SFO_MAPPINGS),
+ gShellLevel2HiiHandle,
+ CurrentName,
+ DevPathString,
+ Consist?L"":(TempLen < StrLen(MapList)?MapList + TempLen+1:L"")
+ );
+ }
+ SHELL_FREE_NON_NULL(DevPathString);
+ SHELL_FREE_NON_NULL(CurrentName);
+ SHELL_FREE_NON_NULL(Alias);
+ return EFI_SUCCESS;
+}
+
+/**
+ Delete Specific from the list of maps for device Handle.
+
+ @param[in] Specific The name to delete.
+ @param[in] Handle The device to look on.
+
+ @retval EFI_SUCCESS The delete was successful.
+ @retval EFI_NOT_FOUND Name was not a map on Handle.
+**/
+EFI_STATUS
+EFIAPI
+PerformSingleMappingDelete(
+ IN CONST CHAR16 *Specific,
+ IN CONST EFI_HANDLE Handle
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+ EFI_DEVICE_PATH_PROTOCOL *DevPathCopy;
+ CONST CHAR16 *MapList;
+ CHAR16 *CurrentName;
+
+ DevPath = DevicePathFromHandle(Handle);
+ DevPathCopy = DevPath;
+ MapList = gEfiShellProtocol->GetMapFromDevicePath(&DevPathCopy);
+ CurrentName = NULL;
+
+ if (MapList == NULL) {
+ return (EFI_NOT_FOUND);
+ }
+ //
+ // if there is a specific and its not on the list...
+ //
+ if (!SearchList(MapList, Specific, &CurrentName, TRUE, FALSE, L";")) {
+ return (EFI_NOT_FOUND);
+ }
+ return (gEfiShellProtocol->SetMap(NULL, CurrentName));
+}
+
+CONST CHAR16 Cd[] = L"cd*";
+CONST CHAR16 Hd[] = L"hd*";
+CONST CHAR16 Fp[] = L"fp*";
+CONST CHAR16 AnyF[] = L"F*";
+/**
+ Function to display mapping information to the user.
+
+ If Specific is specified then Consist and Normal will be ignored since information will
+ be printed for the specific item only.
+
+ @param[in] Verbose TRUE to display (extra) verbose information.
+ @param[in] Consist TRUE to display consistent mappings.
+ @param[in] Normal TRUE to display normal (not consist) mappings.
+ @param[in] TypeString Pointer to string of filter types.
+ @param[in] SFO TRUE to display output in Standard Output Format.
+ @param[in] Specific Pointer to string for specific map to display.
+ @param[in] Header TRUE to print the header block.
+
+ @retval SHELL_SUCCESS The display was printed.
+ @retval SHELL_INVALID_PARAMETER One of Consist or Normal must be TRUE if no Specific.
+
+**/
+SHELL_STATUS
+EFIAPI
+PerformMappingDisplay(
+ IN CONST BOOLEAN Verbose,
+ IN CONST BOOLEAN Consist,
+ IN CONST BOOLEAN Normal,
+ IN CONST CHAR16 *TypeString,
+ IN CONST BOOLEAN SFO,
+ IN CONST CHAR16 *Specific OPTIONAL,
+ IN CONST BOOLEAN Header
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN BufferSize;
+ UINTN LoopVar;
+ CHAR16 *Test;
+ BOOLEAN Found;
+
+ if (!Consist && !Normal && Specific == NULL && TypeString == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"map");
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ if (TypeString != NULL) {
+ Test = (CHAR16*)Cd;
+ if (StrnCmp(TypeString, Test, StrLen(Test)-1) != 0) {
+ Test = (CHAR16*)Hd;
+ if (StrnCmp(TypeString, Test, StrLen(Test)-1) != 0) {
+ Test = (CHAR16*)Fp;
+ if (StrnCmp(TypeString, Test, StrLen(Test)-1) != 0) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"map", TypeString);
+ return (SHELL_INVALID_PARAMETER);
+ }
+ } else if (Test == NULL) {
+ Test = (CHAR16*)AnyF;
+ }
+ }
+ } else {
+ Test = NULL;
+ }
+
+ if (Header) {
+ //
+ // Print the header
+ //
+ if (!SFO) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MAP_HEADER), gShellLevel2HiiHandle);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_SFO_HEADER), gShellLevel2HiiHandle, L"map");
+ }
+ }
+
+ BufferSize = 0;
+ HandleBuffer = NULL;
+
+ //
+ // Look up all SimpleFileSystems in the platform
+ //
+ Status = gBS->LocateHandle(
+ ByProtocol,
+ &gEfiSimpleFileSystemProtocolGuid,
+ NULL,
+ &BufferSize,
+ HandleBuffer);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HandleBuffer = AllocateZeroPool(BufferSize);
+ if (HandleBuffer == NULL) {
+ return (SHELL_OUT_OF_RESOURCES);
+ }
+ Status = gBS->LocateHandle(
+ ByProtocol,
+ &gEfiSimpleFileSystemProtocolGuid,
+ NULL,
+ &BufferSize,
+ HandleBuffer);
+ }
+
+ //
+ // Get the map name(s) for each one.
+ //
+ for ( LoopVar = 0, Found = FALSE
+ ; LoopVar < (BufferSize / sizeof(EFI_HANDLE)) && HandleBuffer != NULL
+ ; LoopVar ++
+ ){
+ Status = PerformSingleMappingDisplay(
+ Verbose,
+ Consist,
+ Normal,
+ Test,
+ SFO,
+ Specific,
+ HandleBuffer[LoopVar]);
+ if (!EFI_ERROR(Status)) {
+ Found = TRUE;
+ }
+ }
+
+ //
+ // Look up all BlockIo in the platform
+ //
+ Status = gBS->LocateHandle(
+ ByProtocol,
+ &gEfiBlockIoProtocolGuid,
+ NULL,
+ &BufferSize,
+ HandleBuffer);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ SHELL_FREE_NON_NULL(HandleBuffer);
+ HandleBuffer = AllocateZeroPool(BufferSize);
+ if (HandleBuffer == NULL) {
+ return (SHELL_OUT_OF_RESOURCES);
+ }
+ Status = gBS->LocateHandle(
+ ByProtocol,
+ &gEfiBlockIoProtocolGuid,
+ NULL,
+ &BufferSize,
+ HandleBuffer);
+ }
+ if (!EFI_ERROR(Status) && HandleBuffer != NULL) {
+ //
+ // Get the map name(s) for each one.
+ //
+ for ( LoopVar = 0
+ ; LoopVar < BufferSize / sizeof(EFI_HANDLE)
+ ; LoopVar ++
+ ){
+ //
+ // Skip any that were already done...
+ //
+ if (gBS->OpenProtocol(
+ HandleBuffer[LoopVar],
+ &gEfiSimpleFileSystemProtocolGuid,
+ NULL,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL) == EFI_SUCCESS) {
+ continue;
+ }
+ Status = PerformSingleMappingDisplay(
+ Verbose,
+ Consist,
+ Normal,
+ Test,
+ SFO,
+ Specific,
+ HandleBuffer[LoopVar]);
+ if (!EFI_ERROR(Status)) {
+ Found = TRUE;
+ }
+ }
+ FreePool(HandleBuffer);
+ }
+ if (!Found) {
+ if (Specific != NULL) {
+ ShellPrintHiiEx(gST->ConOut->Mode->CursorColumn, gST->ConOut->Mode->CursorRow-1, NULL, STRING_TOKEN (STR_MAP_NF), gShellLevel2HiiHandle, L"map", Specific);
+ } else {
+ ShellPrintHiiEx(gST->ConOut->Mode->CursorColumn, gST->ConOut->Mode->CursorRow-1, NULL, STRING_TOKEN (STR_CD_NF), gShellLevel2HiiHandle, L"map");
+ }
+ }
+ return (SHELL_SUCCESS);
+}
+
+/**
+ Perform a mapping display and parse for multiple types in the TypeString.
+
+ @param[in] Verbose TRUE to use verbose output.
+ @param[in] Consist TRUE to display consistent names.
+ @param[in] Normal TRUE to display normal names.
+ @param[in] TypeString An optional comma-delimited list of types.
+ @param[in] SFO TRUE to display in SFO format. See Spec.
+ @param[in] Specific An optional specific map name to display alone.
+
+ @retval SHELL_INVALID_PARAMETER A parameter was invalid.
+ @retval SHELL_SUCCESS The display was successful.
+ @sa PerformMappingDisplay
+**/
+SHELL_STATUS
+EFIAPI
+PerformMappingDisplay2(
+ IN CONST BOOLEAN Verbose,
+ IN CONST BOOLEAN Consist,
+ IN CONST BOOLEAN Normal,
+ IN CONST CHAR16 *TypeString,
+ IN CONST BOOLEAN SFO,
+ IN CONST CHAR16 *Specific OPTIONAL
+ )
+{
+ CONST CHAR16 *TypeWalker;
+ SHELL_STATUS ShellStatus;
+ CHAR16 *Comma;
+
+
+ if (TypeString == NULL) {
+ return (PerformMappingDisplay(Verbose, Consist, Normal, NULL, SFO, Specific, TRUE));
+ }
+ ShellStatus = SHELL_SUCCESS;
+ for (TypeWalker = TypeString ; TypeWalker != NULL && *TypeWalker != CHAR_NULL ;) {
+ Comma = StrStr(TypeWalker, L",");
+ if (Comma == NULL) {
+ if (ShellStatus == SHELL_SUCCESS) {
+ ShellStatus = PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString));
+ } else {
+ PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString));
+ }
+ break;
+ } else {
+ *Comma = CHAR_NULL;
+ if (ShellStatus == SHELL_SUCCESS) {
+ ShellStatus = PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString));
+ } else {
+ PerformMappingDisplay(Verbose, Consist, Normal, TypeWalker, SFO, Specific, (BOOLEAN)(TypeWalker == TypeString));
+ }
+ *Comma = L',';
+ TypeWalker = Comma + 1;
+ }
+ }
+
+ return (ShellStatus);
+}
+
+/**
+ Delete a specific map.
+
+ @param[in] Specific The pointer to the name of the map to delete.
+
+ @retval EFI_INVALID_PARAMETER Specific was NULL.
+ @retval EFI_SUCCESS The operation was successful.
+ @retval EFI_NOT_FOUND Specific could not be found.
+**/
+EFI_STATUS
+EFIAPI
+PerformMappingDelete(
+ IN CONST CHAR16 *Specific
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *HandleBuffer;
+ UINTN BufferSize;
+ UINTN LoopVar;
+ BOOLEAN Deleted;
+
+ if (Specific == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ BufferSize = 0;
+ HandleBuffer = NULL;
+ Deleted = FALSE;
+
+ //
+ // Look up all SimpleFileSystems in the platform
+ //
+ Status = gBS->LocateHandle(
+ ByProtocol,
+ &gEfiDevicePathProtocolGuid,
+ NULL,
+ &BufferSize,
+ HandleBuffer);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ HandleBuffer = AllocateZeroPool(BufferSize);
+ if (HandleBuffer == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ Status = gBS->LocateHandle(
+ ByProtocol,
+ &gEfiDevicePathProtocolGuid,
+ NULL,
+ &BufferSize,
+ HandleBuffer);
+ }
+ if (EFI_ERROR(Status)) {
+ SHELL_FREE_NON_NULL(HandleBuffer);
+ return (Status);
+ }
+
+ if (HandleBuffer != NULL) {
+ //
+ // Get the map name(s) for each one.
+ //
+ for ( LoopVar = 0
+ ; LoopVar < BufferSize / sizeof(EFI_HANDLE)
+ ; LoopVar ++
+ ){
+ if (PerformSingleMappingDelete(Specific,HandleBuffer[LoopVar]) == SHELL_SUCCESS) {
+ Deleted = TRUE;
+ }
+ }
+ }
+ //
+ // Look up all BlockIo in the platform
+ //
+ Status = gBS->LocateHandle(
+ ByProtocol,
+ &gEfiBlockIoProtocolGuid,
+ NULL,
+ &BufferSize,
+ HandleBuffer);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ FreePool(HandleBuffer);
+ HandleBuffer = AllocateZeroPool(BufferSize);
+ if (HandleBuffer == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ Status = gBS->LocateHandle(
+ ByProtocol,
+ &gEfiBlockIoProtocolGuid,
+ NULL,
+ &BufferSize,
+ HandleBuffer);
+ }
+ if (EFI_ERROR(Status)) {
+ SHELL_FREE_NON_NULL(HandleBuffer);
+ return (Status);
+ }
+
+ if (HandleBuffer != NULL) {
+ //
+ // Get the map name(s) for each one.
+ //
+ for ( LoopVar = 0
+ ; LoopVar < BufferSize / sizeof(EFI_HANDLE)
+ ; LoopVar ++
+ ){
+ //
+ // Skip any that were already done...
+ //
+ if (gBS->OpenProtocol(
+ HandleBuffer[LoopVar],
+ &gEfiDevicePathProtocolGuid,
+ NULL,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_TEST_PROTOCOL) == EFI_SUCCESS) {
+ continue;
+ }
+ if (PerformSingleMappingDelete(Specific,HandleBuffer[LoopVar]) == SHELL_SUCCESS) {
+ Deleted = TRUE;
+ }
+ }
+ }
+ SHELL_FREE_NON_NULL(HandleBuffer);
+ if (!Deleted) {
+ return (EFI_NOT_FOUND);
+ }
+ return (EFI_SUCCESS);
+}
+
+/**
+ function to add a mapping from mapping.
+
+ This function will get the device path associated with the mapping and call SetMap.
+
+ @param[in] Map The Map to add a mapping for
+ @param[in] SName The name of the new mapping
+
+ @retval SHELL_SUCCESS the mapping was added
+ @retval SHELL_INVALID_PARAMETER the device path for Map could not be retrieved.
+ @return Shell version of a return value from EfiShellProtocol->SetMap
+
+**/
+SHELL_STATUS
+EFIAPI
+AddMappingFromMapping(
+ IN CONST CHAR16 *Map,
+ IN CONST CHAR16 *SName
+ )
+{
+ CONST EFI_DEVICE_PATH_PROTOCOL *DevPath;
+ EFI_STATUS Status;
+ CHAR16 *NewSName;
+ RETURN_STATUS StrRetStatus;
+
+ NewSName = AllocateCopyPool(StrSize(SName) + sizeof(CHAR16), SName);
+ if (NewSName == NULL) {
+ return (SHELL_OUT_OF_RESOURCES);
+ }
+ if (NewSName[StrLen(NewSName)-1] != L':') {
+ StrRetStatus = StrnCatS(NewSName, (StrSize(SName) + sizeof(CHAR16))/sizeof(CHAR16), L":", StrLen(L":"));
+ if (EFI_ERROR(StrRetStatus)) {
+ FreePool(NewSName);
+ return ((SHELL_STATUS) (StrRetStatus & (~MAX_BIT)));
+ }
+ }
+
+ if (!IsNumberLetterOnly(NewSName, StrLen(NewSName)-1)) {
+ FreePool(NewSName);
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ DevPath = gEfiShellProtocol->GetDevicePathFromMap(Map);
+ if (DevPath == NULL) {
+ FreePool(NewSName);
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ Status = gEfiShellProtocol->SetMap(DevPath, NewSName);
+ FreePool(NewSName);
+ if (EFI_ERROR(Status)) {
+ return (SHELL_DEVICE_ERROR);
+ }
+ return (SHELL_SUCCESS);
+}
+
+/**
+ function to add a mapping from an EFI_HANDLE.
+
+ This function will get the device path associated with the Handle and call SetMap.
+
+ @param[in] Handle The handle to add a mapping for
+ @param[in] SName The name of the new mapping
+
+ @retval SHELL_SUCCESS the mapping was added
+ @retval SHELL_INVALID_PARAMETER SName was not valid for a map name.
+ @return Shell version of a return value from either
+ gBS->OpenProtocol or EfiShellProtocol->SetMap
+
+**/
+SHELL_STATUS
+EFIAPI
+AddMappingFromHandle(
+ IN CONST EFI_HANDLE Handle,
+ IN CONST CHAR16 *SName
+ )
+{
+ EFI_DEVICE_PATH_PROTOCOL *DevPath;
+ EFI_STATUS Status;
+ CHAR16 *NewSName;
+ RETURN_STATUS StrRetStatus;
+
+ NewSName = AllocateCopyPool(StrSize(SName) + sizeof(CHAR16), SName);
+ if (NewSName == NULL) {
+ return (SHELL_OUT_OF_RESOURCES);
+ }
+ if (NewSName[StrLen(NewSName)-1] != L':') {
+ StrRetStatus = StrnCatS(NewSName, (StrSize(SName) + sizeof(CHAR16))/sizeof(CHAR16), L":", StrLen(L":"));
+ if (EFI_ERROR(StrRetStatus)) {
+ FreePool(NewSName);
+ return ((SHELL_STATUS) (StrRetStatus & (~MAX_BIT)));
+ }
+ }
+
+ if (!IsNumberLetterOnly(NewSName, StrLen(NewSName)-1)) {
+ FreePool(NewSName);
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ Status = gBS->OpenProtocol(
+ Handle,
+ &gEfiDevicePathProtocolGuid,
+ (VOID**)&DevPath,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR(Status)) {
+ FreePool(NewSName);
+ return (SHELL_DEVICE_ERROR);
+ }
+ Status = gEfiShellProtocol->SetMap(DevPath, NewSName);
+ FreePool(NewSName);
+ if (EFI_ERROR(Status)) {
+ return (SHELL_DEVICE_ERROR);
+ }
+ return (SHELL_SUCCESS);
+}
+
+STATIC CONST SHELL_PARAM_ITEM MapParamList[] = {
+ {L"-d", TypeValue},
+ {L"-r", TypeFlag},
+ {L"-v", TypeFlag},
+ {L"-c", TypeFlag},
+ {L"-f", TypeFlag},
+ {L"-u", TypeFlag},
+ {L"-t", TypeValue},
+ {L"-sfo", TypeValue},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'map' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunMap (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ CONST CHAR16 *SName;
+ CONST CHAR16 *Mapping;
+ EFI_HANDLE MapAsHandle;
+ SHELL_STATUS ShellStatus;
+ BOOLEAN SfoMode;
+ BOOLEAN ConstMode;
+ BOOLEAN NormlMode;
+ CONST CHAR16 *Param1;
+ CONST CHAR16 *TypeString;
+ UINTN TempStringLength;
+
+ ProblemParam = NULL;
+ Mapping = NULL;
+ SName = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ MapAsHandle = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (MapParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"map", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ SfoMode = ShellCommandLineGetFlag(Package, L"-sfo");
+ ConstMode = ShellCommandLineGetFlag(Package, L"-c");
+ NormlMode = ShellCommandLineGetFlag(Package, L"-f");
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ } else if (ShellCommandLineGetRawValue(Package, 3) != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"map");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // Deleting a map name...
+ //
+ if (ShellCommandLineGetFlag(Package, L"-d")) {
+ if ( ShellCommandLineGetFlag(Package, L"-r")
+ || ShellCommandLineGetFlag(Package, L"-v")
+ || ConstMode
+ || NormlMode
+ || ShellCommandLineGetFlag(Package, L"-u")
+ || ShellCommandLineGetFlag(Package, L"-t")
+ ){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellLevel2HiiHandle, L"map");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ SName = ShellCommandLineGetValue(Package, L"-d");
+ if (SName != NULL) {
+ Status = PerformMappingDelete(SName);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_ACCESS_DENIED) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel2HiiHandle, L"map");
+ ShellStatus = SHELL_ACCESS_DENIED;
+ } else if (Status == EFI_NOT_FOUND) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MAP_NF), gShellLevel2HiiHandle, L"map", SName);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"map", Status);
+ ShellStatus = SHELL_UNSUPPORTED;
+ }
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"map");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ }
+ } else if ( ShellCommandLineGetFlag(Package, L"-r")
+// || ShellCommandLineGetFlag(Package, L"-v")
+ || ConstMode
+ || NormlMode
+ || ShellCommandLineGetFlag(Package, L"-u")
+ || ShellCommandLineGetFlag(Package, L"-t")
+ ){
+ if ( ShellCommandLineGetFlag(Package, L"-r")) {
+ //
+ // Do the reset
+ //
+ Status = ShellCommandCreateInitialMappingsAndPaths();
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"map", Status);
+ ShellStatus = SHELL_UNSUPPORTED;
+ }
+ }
+ if ( ShellStatus == SHELL_SUCCESS && ShellCommandLineGetFlag(Package, L"-u")) {
+ //
+ // Do the Update
+ //
+ Status = ShellCommandUpdateMapping ();
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"map", Status);
+ ShellStatus = SHELL_UNSUPPORTED;
+ }
+ }
+ if (ShellStatus == SHELL_SUCCESS) {
+ Param1 = ShellCommandLineGetRawValue(Package, 1);
+ TypeString = ShellCommandLineGetValue(Package, L"-t");
+ if (!ConstMode
+ &&!NormlMode
+ &&TypeString == NULL
+ ) {
+ //
+ // now do the display...
+ //
+ ShellStatus = PerformMappingDisplay(
+ ShellCommandLineGetFlag(Package, L"-v"),
+ TRUE,
+ TRUE,
+ NULL,
+ SfoMode,
+ Param1,
+ TRUE
+ );
+ } else {
+ //
+ // now do the display...
+ //
+ ShellStatus = PerformMappingDisplay2(
+ ShellCommandLineGetFlag(Package, L"-v"),
+ ConstMode,
+ NormlMode,
+ TypeString,
+ SfoMode,
+ Param1
+ );
+ }
+ }
+ } else {
+ //
+ // adding or displaying (there were no flags)
+ //
+ SName = ShellCommandLineGetRawValue(Package, 1);
+ Mapping = ShellCommandLineGetRawValue(Package, 2);
+ if ( SName == NULL
+ && Mapping == NULL
+ ){
+ //
+ // display only since no flags
+ //
+ ShellStatus = PerformMappingDisplay(
+ ShellCommandLineGetFlag(Package, L"-v"),
+ TRUE,
+ TRUE,
+ NULL,
+ SfoMode,
+ NULL,
+ TRUE
+ );
+ } else if ( SName == NULL
+ || Mapping == NULL
+ ){
+ //
+ // Display only the one specified
+ //
+ ShellStatus = PerformMappingDisplay(
+ FALSE,
+ FALSE,
+ FALSE,
+ NULL,
+ SfoMode,
+ SName, // note the variable here...
+ TRUE
+ );
+ } else {
+ if (ShellIsHexOrDecimalNumber(Mapping, TRUE, FALSE)) {
+ MapAsHandle = ConvertHandleIndexToHandle(ShellStrToUintn(Mapping));
+ } else {
+ MapAsHandle = NULL;
+ }
+ if (MapAsHandle == NULL && Mapping[StrLen(Mapping)-1] != L':') {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"map", Mapping);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ TempStringLength = StrLen(SName);
+ if (!IsNumberLetterOnly(SName, TempStringLength-(SName[TempStringLength-1]==L':'?1:0))) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"map", SName);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+
+ if (ShellStatus == SHELL_SUCCESS) {
+ if (MapAsHandle != NULL) {
+ ShellStatus = AddMappingFromHandle(MapAsHandle, SName);
+ } else {
+ ShellStatus = AddMappingFromMapping(Mapping, SName);
+ }
+
+ if (ShellStatus != SHELL_SUCCESS) {
+ switch (ShellStatus) {
+ case SHELL_ACCESS_DENIED:
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel2HiiHandle, L"map");
+ break;
+ case SHELL_INVALID_PARAMETER:
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"map", Mapping);
+ break;
+ case SHELL_DEVICE_ERROR:
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MAP_NOF), gShellLevel2HiiHandle, L"map", Mapping);
+ break;
+ default:
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"map", ShellStatus|MAX_BIT);
+ }
+ } else {
+ //
+ // now do the display...
+ //
+ ShellStatus = PerformMappingDisplay(
+ FALSE,
+ FALSE,
+ FALSE,
+ NULL,
+ SfoMode,
+ SName,
+ TRUE
+ );
+ } // we were sucessful so do an output
+ }
+ } // got a valid map target
+ } // got 2 variables
+ } // we are adding a mapping
+ } // got valid parameters
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+
+ return (ShellStatus);
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/MkDir.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/MkDir.c
new file mode 100644
index 0000000000..4aade13aac
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/MkDir.c
@@ -0,0 +1,129 @@
+/** @file
+ Main file for attrib shell level 2 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel2CommandsLib.h"
+
+/**
+ Function for 'mkdir' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunMkDir (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ CONST CHAR16 *NewDirName;
+ UINTN DirCreateCount;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_FILE_HANDLE FileHandle;
+ SHELL_STATUS ShellStatus;
+
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"mkdir", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ }
+
+ //
+ // create a set of directories
+ //
+ if (ShellCommandLineGetRawValue(Package, 1) == NULL) {
+ //
+ // we didnt get a single parameter
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"mkdir");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ for ( DirCreateCount = 1
+ ;
+ ; DirCreateCount++
+ ){
+ //
+ // loop through each directory specified
+ //
+
+ NewDirName = ShellCommandLineGetRawValue(Package, DirCreateCount);
+ if (NewDirName == NULL) {
+ break;
+ }
+ //
+ // check if that already exists... if yes fail
+ //
+ FileHandle = NULL;
+ Status = ShellOpenFileByName(NewDirName,
+ &FileHandle,
+ EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE,
+ EFI_FILE_DIRECTORY
+ );
+ if (!EFI_ERROR(Status)) {
+ ShellCloseFile(&FileHandle);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MKDIR_ALREADY), gShellLevel2HiiHandle, NewDirName);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ break;
+ } else {
+ ASSERT(FileHandle == NULL);
+ //
+ // create the directory named NewDirName
+ //
+ Status = ShellCreateDirectory(NewDirName, &FileHandle);
+ if (FileHandle != NULL) {
+ gEfiShellProtocol->CloseFile(FileHandle);
+ }
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MKDIR_CREATEFAIL), gShellLevel2HiiHandle, NewDirName);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+
+ return (ShellStatus);
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Mv.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Mv.c
new file mode 100644
index 0000000000..f93772c6f8
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Mv.c
@@ -0,0 +1,801 @@
+/** @file
+ Main file for mv shell level 2 function.
+
+ (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel2CommandsLib.h"
+
+/**
+ function to determine if a move is between file systems.
+
+ @param FullName [in] The name of the file to move.
+ @param Cwd [in] The current working directory
+ @param DestPath [in] The target location to move to
+
+ @retval TRUE The move is across file system.
+ @retval FALSE The move is within a file system.
+**/
+BOOLEAN
+EFIAPI
+IsBetweenFileSystem(
+ IN CONST CHAR16 *FullName,
+ IN CONST CHAR16 *Cwd,
+ IN CONST CHAR16 *DestPath
+ )
+{
+ CHAR16 *Test;
+ CHAR16 *Test1;
+ UINTN Result;
+
+ Test = StrStr(FullName, L":");
+ if (Test == NULL && Cwd != NULL) {
+ Test = StrStr(Cwd, L":");
+ }
+ Test1 = StrStr(DestPath, L":");
+ if (Test1 == NULL && Cwd != NULL) {
+ Test1 = StrStr(Cwd, L":");
+ }
+ if (Test1 != NULL && Test != NULL) {
+ *Test = CHAR_NULL;
+ *Test1 = CHAR_NULL;
+ Result = StringNoCaseCompare(&FullName, &DestPath);
+ *Test = L':';
+ *Test1 = L':';
+ if (Result != 0) {
+ return (TRUE);
+ }
+ }
+ return (FALSE);
+}
+
+/**
+ Function to validate that moving a specific file (FileName) to a specific
+ location (DestPath) is valid.
+
+ This function will verify that the destination is not a subdirectory of
+ FullName, that the Current working Directory is not being moved, and that
+ the directory is not read only.
+
+ if the move is invalid this function will report the error to StdOut.
+
+ @param SourcePath [in] The name of the file to move.
+ @param Cwd [in] The current working directory
+ @param DestPath [in] The target location to move to
+ @param Attribute [in] The Attribute of the file
+ @param DestAttr [in] The Attribute of the destination
+ @param FileStatus [in] The Status of the file when opened
+
+ @retval TRUE The move is valid
+ @retval FALSE The move is not
+**/
+BOOLEAN
+EFIAPI
+IsValidMove(
+ IN CONST CHAR16 *SourcePath,
+ IN CONST CHAR16 *Cwd,
+ IN CONST CHAR16 *DestPath,
+ IN CONST UINT64 Attribute,
+ IN CONST UINT64 DestAttr,
+ IN CONST EFI_STATUS FileStatus
+ )
+{
+ CHAR16 *DestPathCopy;
+ CHAR16 *DestPathWalker;
+
+ if (Cwd != NULL && StrCmp(SourcePath, Cwd) == 0) {
+ //
+ // Invalid move
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MV_INV_CWD), gShellLevel2HiiHandle);
+ return (FALSE);
+ }
+
+ //
+ // invalid to move read only or move to a read only destination
+ //
+ if (((Attribute & EFI_FILE_READ_ONLY) != 0)
+ || (FileStatus == EFI_WRITE_PROTECTED)
+ || ((DestAttr & EFI_FILE_READ_ONLY) != 0)
+ ) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MV_INV_RO), gShellLevel2HiiHandle, SourcePath);
+ return (FALSE);
+ }
+
+ DestPathCopy = AllocateCopyPool(StrSize(DestPath), DestPath);
+ if (DestPathCopy == NULL) {
+ return (FALSE);
+ }
+
+ for (DestPathWalker = DestPathCopy; *DestPathWalker == L'\\'; DestPathWalker++) ;
+
+ while(DestPathWalker != NULL && DestPathWalker[StrLen(DestPathWalker)-1] == L'\\') {
+ DestPathWalker[StrLen(DestPathWalker)-1] = CHAR_NULL;
+ }
+
+ ASSERT(DestPathWalker != NULL);
+ ASSERT(SourcePath != NULL);
+
+ //
+ // If they're the same, or if source is "above" dest on file path tree
+ //
+ if ( StringNoCaseCompare (&DestPathWalker, &SourcePath) == 0 ||
+ ((StrStr(DestPathWalker, SourcePath) == DestPathWalker) &&
+ (DestPathWalker[StrLen(SourcePath)] == '\\')
+ )
+ ) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_MV_INV_SUB), gShellLevel2HiiHandle);
+ FreePool(DestPathCopy);
+ return (FALSE);
+ }
+ FreePool(DestPathCopy);
+
+ return (TRUE);
+}
+
+/**
+ Function to take a destination path that might contain wildcards and verify
+ that there is only a single possible target (IE we cant have wildcards that
+ have 2 possible destination).
+
+ if the result is sucessful the caller must free *DestPathPointer.
+
+ @param[in] DestParameter The original path to the destination.
+ @param[in, out] DestPathPointer A pointer to the callee allocated final path.
+ @param[in] Cwd A pointer to the current working directory.
+ @param[in] SingleSource TRUE to have only one source file.
+ @param[in, out] DestAttr A pointer to the destination information attribute.
+
+ @retval SHELL_INVALID_PARAMETER The DestParameter could not be resolved to a location.
+ @retval SHELL_INVALID_PARAMETER The DestParameter could be resolved to more than 1 location.
+ @retval SHELL_INVALID_PARAMETER Cwd is required and is NULL.
+ @retval SHELL_SUCCESS The operation was sucessful.
+**/
+SHELL_STATUS
+EFIAPI
+GetDestinationLocation(
+ IN CONST CHAR16 *DestParameter,
+ IN OUT CHAR16 **DestPathPointer,
+ IN CONST CHAR16 *Cwd,
+ IN CONST BOOLEAN SingleSource,
+ IN OUT UINT64 *DestAttr
+ )
+{
+ EFI_SHELL_FILE_INFO *DestList;
+ EFI_SHELL_FILE_INFO *Node;
+ CHAR16 *DestPath;
+ UINTN NewSize;
+ UINTN CurrentSize;
+
+ DestList = NULL;
+ DestPath = NULL;
+
+ ASSERT(DestAttr != NULL);
+
+ if (StrStr(DestParameter, L"\\") == DestParameter) {
+ if (Cwd == NULL) {
+ return SHELL_INVALID_PARAMETER;
+ }
+ DestPath = AllocateZeroPool(StrSize(Cwd));
+ if (DestPath == NULL) {
+ return (SHELL_OUT_OF_RESOURCES);
+ }
+ StrCpyS(DestPath, StrSize(Cwd) / sizeof(CHAR16), Cwd);
+ while (PathRemoveLastItem(DestPath)) ;
+
+ //
+ // Append DestParameter beyond '\' which may be present
+ //
+ CurrentSize = StrSize(DestPath);
+ StrnCatGrow(&DestPath, &CurrentSize, &DestParameter[1], 0);
+
+ *DestPathPointer = DestPath;
+ return (SHELL_SUCCESS);
+ }
+ //
+ // get the destination path
+ //
+ ShellOpenFileMetaArg((CHAR16*)DestParameter, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE, &DestList);
+ if (DestList == NULL || IsListEmpty(&DestList->Link)) {
+ //
+ // Not existing... must be renaming
+ //
+ if (StrStr(DestParameter, L":") == NULL) {
+ if (Cwd == NULL) {
+ ShellCloseFileMetaArg(&DestList);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle);
+ return (SHELL_INVALID_PARAMETER);
+ }
+ NewSize = StrSize(Cwd);
+ NewSize += StrSize(DestParameter);
+ DestPath = AllocateZeroPool(NewSize);
+ if (DestPath == NULL) {
+ ShellCloseFileMetaArg(&DestList);
+ return (SHELL_OUT_OF_RESOURCES);
+ }
+ StrCpyS(DestPath, NewSize / sizeof(CHAR16), Cwd);
+ if (DestPath[StrLen(DestPath)-1] != L'\\' && DestParameter[0] != L'\\') {
+ StrCatS(DestPath, NewSize / sizeof(CHAR16), L"\\");
+ } else if (DestPath[StrLen(DestPath)-1] == L'\\' && DestParameter[0] == L'\\') {
+ ((CHAR16*)DestPath)[StrLen(DestPath)-1] = CHAR_NULL;
+ }
+ StrCatS(DestPath, NewSize / sizeof(CHAR16), DestParameter);
+ } else {
+ ASSERT(DestPath == NULL);
+ DestPath = StrnCatGrow(&DestPath, NULL, DestParameter, 0);
+ if (DestPath == NULL) {
+ ShellCloseFileMetaArg(&DestList);
+ return (SHELL_OUT_OF_RESOURCES);
+ }
+ }
+ } else {
+ Node = (EFI_SHELL_FILE_INFO*)GetFirstNode(&DestList->Link);
+ *DestAttr = Node->Info->Attribute;
+ //
+ // Make sure there is only 1 node in the list.
+ //
+ if (!IsNodeAtEnd(&DestList->Link, &Node->Link)) {
+ ShellCloseFileMetaArg(&DestList);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_MARG_ERROR), gShellLevel2HiiHandle, L"mv", DestParameter);
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ //
+ // If we are a directory or a single file, then one node is fine.
+ //
+ if (ShellIsDirectory(Node->FullName)==EFI_SUCCESS || SingleSource) {
+ DestPath = AllocateZeroPool(StrSize(Node->FullName)+sizeof(CHAR16));
+ if (DestPath == NULL) {
+ ShellCloseFileMetaArg(&DestList);
+ return (SHELL_OUT_OF_RESOURCES);
+ }
+ StrCpyS(DestPath, (StrSize(Node->FullName)+sizeof(CHAR16)) / sizeof(CHAR16), Node->FullName);
+ StrCatS(DestPath, (StrSize(Node->FullName)+sizeof(CHAR16)) / sizeof(CHAR16), L"\\");
+ } else {
+ //
+ // cant move multiple files onto a single file.
+ //
+ ShellCloseFileMetaArg(&DestList);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_ERROR), gShellLevel2HiiHandle, L"mv", DestParameter);
+ return (SHELL_INVALID_PARAMETER);
+ }
+ }
+
+ *DestPathPointer = DestPath;
+ ShellCloseFileMetaArg(&DestList);
+
+ return (SHELL_SUCCESS);
+}
+
+/**
+ Function to do a move across file systems.
+
+ @param[in] Node A pointer to the file to be removed.
+ @param[in] DestPath A pointer to the destination file path.
+ @param[out] Resp A pointer to response from question. Pass back on looped calling
+
+ @retval SHELL_SUCCESS The source file was moved to the destination.
+**/
+EFI_STATUS
+EFIAPI
+MoveBetweenFileSystems(
+ IN EFI_SHELL_FILE_INFO *Node,
+ IN CONST CHAR16 *DestPath,
+ OUT VOID **Resp
+ )
+{
+ SHELL_STATUS ShellStatus;
+
+ //
+ // First we copy the file
+ //
+ ShellStatus = CopySingleFile (Node->FullName, DestPath, Resp, TRUE, L"mv");
+
+ //
+ // Check our result
+ //
+ if (ShellStatus == SHELL_SUCCESS) {
+ //
+ // The copy was successful. delete the source file.
+ //
+ CascadeDelete(Node, TRUE);
+ Node->Handle = NULL;
+ } else if (ShellStatus == SHELL_ABORTED) {
+ return EFI_ABORTED;
+ } else if (ShellStatus == SHELL_ACCESS_DENIED) {
+ return EFI_ACCESS_DENIED;
+ } else if (ShellStatus == SHELL_VOLUME_FULL) {
+ return EFI_VOLUME_FULL;
+ } else {
+ return EFI_UNSUPPORTED;
+ }
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to take the destination path and target file name to generate the full destination path.
+
+ @param[in] DestPath A pointer to the destination file path string.
+ @param[out] FullDestPath A pointer to the full destination path string.
+ @param[in] FileName Name string of the targe file.
+
+ @retval SHELL_SUCCESS the files were all moved.
+ @retval SHELL_INVALID_PARAMETER a parameter was invalid
+ @retval SHELL_OUT_OF_RESOURCES a memory allocation failed
+**/
+EFI_STATUS
+EFIAPI
+CreateFullDestPath(
+ IN CONST CHAR16 **DestPath,
+ OUT CHAR16 **FullDestPath,
+ IN CONST CHAR16 *FileName
+ )
+{
+ UINTN Size;
+ if (FullDestPath == NULL || FileName == NULL || DestPath == NULL || *DestPath == NULL){
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ Size = StrSize(*DestPath) + StrSize(FileName);
+
+ *FullDestPath = AllocateZeroPool(Size);
+ if (*FullDestPath == NULL){
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ StrCpyS(*FullDestPath, Size / sizeof(CHAR16), *DestPath);
+ if ((*FullDestPath)[StrLen(*FullDestPath)-1] != L'\\' && FileName[0] != L'\\') {
+ StrCatS(*FullDestPath, Size / sizeof(CHAR16), L"\\");
+ }
+ StrCatS(*FullDestPath, Size / sizeof(CHAR16), FileName);
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to do a move within a file system.
+
+ @param[in] Node A pointer to the file to be removed.
+ @param[in] DestPath A pointer to the destination file path.
+ @param[out] Resp A pointer to response from question. Pass back on looped calling.
+
+ @retval SHELL_SUCCESS The source file was moved to the destination.
+ @retval SHELL_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+MoveWithinFileSystems(
+ IN EFI_SHELL_FILE_INFO *Node,
+ IN CHAR16 *DestPath,
+ OUT VOID **Resp
+ )
+{
+ EFI_FILE_INFO *NewFileInfo;
+ CHAR16 *TempLocation;
+ UINTN NewSize;
+ UINTN Length;
+ EFI_STATUS Status;
+
+ //
+ // Chop off map info from DestPath
+ //
+ if ((TempLocation = StrStr(DestPath, L":")) != NULL) {
+ CopyMem(DestPath, TempLocation+1, StrSize(TempLocation+1));
+ }
+
+ //
+ // construct the new file info block
+ //
+ NewSize = StrSize(DestPath);
+ NewSize += StrSize(Node->FileName) + SIZE_OF_EFI_FILE_INFO + sizeof(CHAR16);
+ NewFileInfo = AllocateZeroPool(NewSize);
+ if (NewFileInfo == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_MEM), gShellLevel2HiiHandle);
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ CopyMem(NewFileInfo, Node->Info, SIZE_OF_EFI_FILE_INFO);
+ if (DestPath[0] != L'\\') {
+ StrCpyS(NewFileInfo->FileName, (NewSize - SIZE_OF_EFI_FILE_INFO) / sizeof(CHAR16), L"\\");
+ StrCatS(NewFileInfo->FileName, (NewSize - SIZE_OF_EFI_FILE_INFO) / sizeof(CHAR16), DestPath);
+ } else {
+ StrCpyS(NewFileInfo->FileName, (NewSize - SIZE_OF_EFI_FILE_INFO) / sizeof(CHAR16), DestPath);
+ }
+ Length = StrLen(NewFileInfo->FileName);
+ if (Length > 0) {
+ Length--;
+ }
+ if (NewFileInfo->FileName[Length] == L'\\') {
+ if (Node->FileName[0] == L'\\') {
+ //
+ // Don't allow for double slashes. Eliminate one of them.
+ //
+ NewFileInfo->FileName[Length] = CHAR_NULL;
+ }
+ StrCatS(NewFileInfo->FileName, (NewSize - SIZE_OF_EFI_FILE_INFO) / sizeof(CHAR16), Node->FileName);
+ }
+ NewFileInfo->Size = SIZE_OF_EFI_FILE_INFO + StrSize(NewFileInfo->FileName);
+
+ //
+ // Perform the move operation
+ //
+ Status = ShellSetFileInfo(Node->Handle, NewFileInfo);
+
+ //
+ // Free the info object we used...
+ //
+ FreePool(NewFileInfo);
+ }
+
+ return (Status);
+}
+/**
+ function to take a list of files to move and a destination location and do
+ the verification and moving of those files to that location. This function
+ will report any errors to the user and continue to move the rest of the files.
+
+ @param[in] FileList A LIST_ENTRY* based list of files to move
+ @param[out] Resp pointer to response from question. Pass back on looped calling
+ @param[in] DestParameter the originally specified destination location
+
+ @retval SHELL_SUCCESS the files were all moved.
+ @retval SHELL_INVALID_PARAMETER a parameter was invalid
+ @retval SHELL_SECURITY_VIOLATION a security violation ocurred
+ @retval SHELL_WRITE_PROTECTED the destination was write protected
+ @retval SHELL_OUT_OF_RESOURCES a memory allocation failed
+**/
+SHELL_STATUS
+EFIAPI
+ValidateAndMoveFiles(
+ IN EFI_SHELL_FILE_INFO *FileList,
+ OUT VOID **Resp,
+ IN CONST CHAR16 *DestParameter
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *HiiOutput;
+ CHAR16 *HiiResultOk;
+ CHAR16 *DestPath;
+ CHAR16 *FullDestPath;
+ CONST CHAR16 *Cwd;
+ CHAR16 *FullCwd;
+ SHELL_STATUS ShellStatus;
+ EFI_SHELL_FILE_INFO *Node;
+ VOID *Response;
+ UINT64 Attr;
+ CHAR16 *CleanFilePathStr;
+
+ ASSERT(FileList != NULL);
+ ASSERT(DestParameter != NULL);
+
+ DestPath = NULL;
+ FullDestPath = NULL;
+ Cwd = ShellGetCurrentDir(NULL);
+ Response = *Resp;
+ Attr = 0;
+ CleanFilePathStr = NULL;
+ FullCwd = NULL;
+
+ if (Cwd != NULL) {
+ FullCwd = AllocateZeroPool(StrSize(Cwd) + sizeof(CHAR16));
+ if (FullCwd == NULL) {
+ return SHELL_OUT_OF_RESOURCES;
+ } else {
+ StrCpyS(FullCwd, StrSize(Cwd)/sizeof(CHAR16)+1, Cwd);
+ StrCatS(FullCwd, StrSize(Cwd)/sizeof(CHAR16)+1, L"\\");
+ }
+ }
+
+ Status = ShellLevel2StripQuotes (DestParameter, &CleanFilePathStr);
+ if (EFI_ERROR (Status)) {
+ SHELL_FREE_NON_NULL(FullCwd);
+ if (Status == EFI_OUT_OF_RESOURCES) {
+ return SHELL_OUT_OF_RESOURCES;
+ } else {
+ return SHELL_INVALID_PARAMETER;
+ }
+ }
+
+ ASSERT (CleanFilePathStr != NULL);
+
+ //
+ // Get and validate the destination location
+ //
+ ShellStatus = GetDestinationLocation(CleanFilePathStr, &DestPath, FullCwd, (BOOLEAN)(FileList->Link.ForwardLink == FileList->Link.BackLink), &Attr);
+ FreePool (CleanFilePathStr);
+
+ if (ShellStatus != SHELL_SUCCESS) {
+ SHELL_FREE_NON_NULL (FullCwd);
+ return (ShellStatus);
+ }
+ DestPath = PathCleanUpDirectories(DestPath);
+ if (DestPath == NULL) {
+ FreePool (FullCwd);
+ return (SHELL_OUT_OF_RESOURCES);
+ }
+
+ HiiOutput = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_MV_OUTPUT), NULL);
+ HiiResultOk = HiiGetString (gShellLevel2HiiHandle, STRING_TOKEN (STR_GEN_RES_OK), NULL);
+ if (HiiOutput == NULL || HiiResultOk == NULL) {
+ SHELL_FREE_NON_NULL(DestPath);
+ SHELL_FREE_NON_NULL(HiiOutput);
+ SHELL_FREE_NON_NULL(HiiResultOk);
+ SHELL_FREE_NON_NULL(FullCwd);
+ return (SHELL_OUT_OF_RESOURCES);
+ }
+
+ //
+ // Go through the list of files and directories to move...
+ //
+ for (Node = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link)
+ ; !IsNull(&FileList->Link, &Node->Link)
+ ; Node = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Node->Link)
+ ){
+ if (ShellGetExecutionBreakFlag()) {
+ break;
+ }
+
+ //
+ // These should never be NULL
+ //
+ ASSERT(Node->FileName != NULL);
+ ASSERT(Node->FullName != NULL);
+ ASSERT(Node->Info != NULL);
+
+ //
+ // skip the directory traversing stuff...
+ //
+ if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) {
+ continue;
+ }
+
+ SHELL_FREE_NON_NULL(FullDestPath);
+ FullDestPath = NULL;
+ if (ShellIsDirectory(DestPath)==EFI_SUCCESS) {
+ CreateFullDestPath((CONST CHAR16 **)&DestPath, &FullDestPath, Node->FileName);
+ }
+
+ //
+ // Validate that the move is valid
+ //
+ if (!IsValidMove(Node->FullName, FullCwd, FullDestPath!=NULL? FullDestPath:DestPath, Node->Info->Attribute, Attr, Node->Status)) {
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ continue;
+ }
+
+ ShellPrintEx(-1, -1, HiiOutput, Node->FullName, FullDestPath!=NULL? FullDestPath:DestPath);
+
+ //
+ // See if destination exists
+ //
+ if (!EFI_ERROR(ShellFileExists(FullDestPath!=NULL? FullDestPath:DestPath))) {
+ if (Response == NULL) {
+ ShellPromptForResponseHii(ShellPromptResponseTypeYesNoAllCancel, STRING_TOKEN (STR_GEN_DEST_EXIST_OVR), gShellLevel2HiiHandle, &Response);
+ }
+ switch (*(SHELL_PROMPT_RESPONSE*)Response) {
+ case ShellPromptResponseNo:
+ FreePool(Response);
+ Response = NULL;
+ continue;
+ case ShellPromptResponseCancel:
+ *Resp = Response;
+ //
+ // indicate to stop everything
+ //
+ SHELL_FREE_NON_NULL(FullCwd);
+ return (SHELL_ABORTED);
+ case ShellPromptResponseAll:
+ *Resp = Response;
+ break;
+ case ShellPromptResponseYes:
+ FreePool(Response);
+ Response = NULL;
+ break;
+ default:
+ FreePool(Response);
+ SHELL_FREE_NON_NULL(FullCwd);
+ return SHELL_ABORTED;
+ }
+ Status = ShellDeleteFileByName(FullDestPath!=NULL? FullDestPath:DestPath);
+ }
+
+ if (IsBetweenFileSystem(Node->FullName, FullCwd, DestPath)) {
+ while (FullDestPath == NULL && DestPath != NULL && DestPath[0] != CHAR_NULL && DestPath[StrLen(DestPath) - 1] == L'\\') {
+ DestPath[StrLen(DestPath) - 1] = CHAR_NULL;
+ }
+ Status = MoveBetweenFileSystems(Node, FullDestPath!=NULL? FullDestPath:DestPath, &Response);
+ } else {
+ Status = MoveWithinFileSystems(Node, DestPath, &Response);
+ //
+ // Display error status
+ //
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel2HiiHandle, L"mv", Status);
+ }
+ }
+
+ //
+ // Check our result
+ //
+ if (EFI_ERROR(Status)) {
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ if (Status == EFI_SECURITY_VIOLATION) {
+ ShellStatus = SHELL_SECURITY_VIOLATION;
+ } else if (Status == EFI_WRITE_PROTECTED) {
+ ShellStatus = SHELL_WRITE_PROTECTED;
+ } else if (Status == EFI_OUT_OF_RESOURCES) {
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ } else if (Status == EFI_DEVICE_ERROR) {
+ ShellStatus = SHELL_DEVICE_ERROR;
+ } else if (Status == EFI_ACCESS_DENIED) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ }
+ } else {
+ ShellPrintEx(-1, -1, L"%s", HiiResultOk);
+ }
+
+ } // main for loop
+
+ SHELL_FREE_NON_NULL(FullDestPath);
+ SHELL_FREE_NON_NULL(DestPath);
+ SHELL_FREE_NON_NULL(HiiOutput);
+ SHELL_FREE_NON_NULL(HiiResultOk);
+ SHELL_FREE_NON_NULL(FullCwd);
+ return (ShellStatus);
+}
+
+/**
+ Function for 'mv' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunMv (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ CHAR16 *Cwd;
+ UINTN CwdSize;
+ SHELL_STATUS ShellStatus;
+ UINTN ParamCount;
+ UINTN LoopCounter;
+ EFI_SHELL_FILE_INFO *FileList;
+ VOID *Response;
+
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ ParamCount = 0;
+ FileList = NULL;
+ Response = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"mv", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ }
+
+ switch (ParamCount = ShellCommandLineGetCount(Package)) {
+ case 0:
+ case 1:
+ //
+ // we have insufficient parameters
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"mv");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ break;
+ case 2:
+ //
+ // must have valid CWD for single parameter...
+ //
+ if (ShellGetCurrentDir(NULL) == NULL){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"mv");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, 1), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);
+ if (FileList == NULL || IsListEmpty(&FileList->Link) || EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, L"mv", ShellCommandLineGetRawValue(Package, 1));
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ //
+ // ValidateAndMoveFiles will report errors to the screen itself
+ //
+ CwdSize = StrSize(ShellGetCurrentDir(NULL)) + sizeof(CHAR16);
+ Cwd = AllocateZeroPool(CwdSize);
+ if (Cwd == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellLevel2HiiHandle, L"mv");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ } else {
+ StrCpyS (Cwd, CwdSize / sizeof (CHAR16), ShellGetCurrentDir (NULL));
+ StrCatS (Cwd, CwdSize / sizeof (CHAR16), L"\\");
+ ShellStatus = ValidateAndMoveFiles (FileList, &Response, Cwd);
+ FreePool (Cwd);
+ }
+ }
+ }
+
+ break;
+ default:
+ ///@todo make sure this works with error half way through and continues...
+ for (ParamCount--, LoopCounter = 1 ; LoopCounter < ParamCount ; LoopCounter++) {
+ if (ShellGetExecutionBreakFlag()) {
+ break;
+ }
+ Status = ShellOpenFileMetaArg((CHAR16*)ShellCommandLineGetRawValue(Package, LoopCounter), EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);
+ if (FileList == NULL || IsListEmpty(&FileList->Link) || EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, L"mv", ShellCommandLineGetRawValue(Package, LoopCounter));
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ //
+ // ValidateAndMoveFiles will report errors to the screen itself
+ // Only change ShellStatus if it's sucessful
+ //
+ if (ShellStatus == SHELL_SUCCESS) {
+ ShellStatus = ValidateAndMoveFiles(FileList, &Response, ShellCommandLineGetRawValue(Package, ParamCount));
+ } else {
+ ValidateAndMoveFiles(FileList, &Response, ShellCommandLineGetRawValue(Package, ParamCount));
+ }
+ }
+ if (FileList != NULL && !IsListEmpty(&FileList->Link)) {
+ Status = ShellCloseFileMetaArg(&FileList);
+ if (EFI_ERROR(Status) && ShellStatus == SHELL_SUCCESS) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_FILE), gShellLevel2HiiHandle, L"mv", ShellCommandLineGetRawValue(Package, 1), ShellStatus|MAX_BIT);
+ }
+ }
+ }
+ break;
+ } // switch on parameter count
+
+ if (FileList != NULL) {
+ ShellCloseFileMetaArg(&FileList);
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ SHELL_FREE_NON_NULL(Response);
+
+ if (ShellGetExecutionBreakFlag()) {
+ return (SHELL_ABORTED);
+ }
+
+ return (ShellStatus);
+}
diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Parse.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Parse.c
new file mode 100644
index 0000000000..12fe87750c
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Parse.c
@@ -0,0 +1,459 @@
+/** @file
+ Main file for Parse shell level 2 function.
+
+ (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel2CommandsLib.h"
+
+/**
+ Check if data is coming from StdIn output.
+
+ @param[in] None
+
+ @retval TRUE StdIn stream data available to parse
+ @retval FALSE StdIn stream data is not available to parse.
+**/
+BOOLEAN
+IsStdInDataAvailable (
+ VOID
+ )
+{
+ SHELL_FILE_HANDLE FileHandle;
+ EFI_STATUS Status;
+ CHAR16 CharBuffer;
+ UINTN CharSize;
+ UINT64 OriginalFilePosition;
+
+ Status = EFI_SUCCESS;
+ FileHandle = NULL;
+ OriginalFilePosition = 0;
+
+ if (ShellOpenFileByName (L">i", &FileHandle, EFI_FILE_MODE_READ, 0) == EFI_SUCCESS) {
+ CharSize = sizeof(CHAR16);
+ gEfiShellProtocol->GetFilePosition (FileHandle, &OriginalFilePosition);
+ Status = gEfiShellProtocol->ReadFile (FileHandle, &CharSize, &CharBuffer);
+ if (EFI_ERROR (Status) || (CharSize != sizeof(CHAR16))) {
+ return FALSE;
+ }
+ gEfiShellProtocol->SetFilePosition(FileHandle, OriginalFilePosition);
+ }
+
+ if (FileHandle == NULL) {
+ return FALSE;
+ } else {
+ return TRUE;
+ }
+}
+
+/**
+ Function to read a single line (up to but not including the \n) using StdIn data from a SHELL_FILE_HANDLE.
+
+ If the position upon start is 0, then the Ascii Boolean will be set. This should be
+ maintained and not changed for all operations with the same file.
+
+ @param[in] Handle SHELL_FILE_HANDLE to read from.
+ @param[in, out] Buffer The pointer to buffer to read into.
+ @param[in, out] Size The pointer to number of bytes in Buffer.
+ @param[in] Truncate If the buffer is large enough, this has no effect.
+ If the buffer is is too small and Truncate is TRUE,
+ the line will be truncated.
+ If the buffer is is too small and Truncate is FALSE,
+ then no read will occur.
+
+ @retval EFI_SUCCESS The operation was successful. The line is stored in
+ Buffer.
+ @retval EFI_INVALID_PARAMETER Handle was NULL.
+ @retval EFI_INVALID_PARAMETER Size was NULL.
+ @retval EFI_BUFFER_TOO_SMALL Size was not large enough to store the line.
+ Size was updated to the minimum space required.
+**/
+EFI_STATUS
+EFIAPI
+ShellFileHandleReadStdInLine(
+ IN SHELL_FILE_HANDLE Handle,
+ IN OUT CHAR16 *Buffer,
+ IN OUT UINTN *Size,
+ IN BOOLEAN Truncate
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 CharBuffer;
+ UINTN CharSize;
+ UINTN CountSoFar;
+ UINT64 OriginalFilePosition;
+
+
+ if (Handle == NULL
+ ||Size == NULL
+ ){
+ return (EFI_INVALID_PARAMETER);
+ }
+ if (Buffer == NULL) {
+ ASSERT(*Size == 0);
+ } else {
+ *Buffer = CHAR_NULL;
+ }
+ gEfiShellProtocol->GetFilePosition (Handle, &OriginalFilePosition);
+
+ for (CountSoFar = 0;;CountSoFar++){
+ CharBuffer = 0;
+ CharSize = sizeof(CHAR16);
+ Status = gEfiShellProtocol->ReadFile (Handle, &CharSize, &CharBuffer);
+ if ( EFI_ERROR(Status)
+ || CharSize == 0
+ || (CharBuffer == L'\n')
+ ){
+ break;
+ }
+ //
+ // if we have space save it...
+ //
+ if ((CountSoFar+1)*sizeof(CHAR16) < *Size){
+ ASSERT(Buffer != NULL);
+ ((CHAR16*)Buffer)[CountSoFar] = CharBuffer;
+ ((CHAR16*)Buffer)[CountSoFar+1] = CHAR_NULL;
+ }
+ }
+
+ //
+ // if we ran out of space tell when...
+ //
+ if ((CountSoFar+1)*sizeof(CHAR16) > *Size){
+ *Size = (CountSoFar+1)*sizeof(CHAR16);
+ if (!Truncate) {
+ gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);
+ } else {
+ DEBUG((DEBUG_WARN, "The line was truncated in ShellFileHandleReadLine"));
+ }
+ return (EFI_BUFFER_TOO_SMALL);
+ }
+ while(Buffer[StrLen(Buffer)-1] == L'\r') {
+ Buffer[StrLen(Buffer)-1] = CHAR_NULL;
+ }
+
+ return (Status);
+}
+
+
+/**
+ Function to read a single line using StdIn from a SHELL_FILE_HANDLE. The \n is not included in the returned
+ buffer. The returned buffer must be callee freed.
+
+ If the position upon start is 0, then the Ascii Boolean will be set. This should be
+ maintained and not changed for all operations with the same file.
+
+ @param[in] Handle SHELL_FILE_HANDLE to read from.
+
+ @return The line of text from the file.
+ @retval NULL There was not enough memory available.
+
+ @sa ShellFileHandleReadLine
+**/
+CHAR16*
+EFIAPI
+ParseReturnStdInLine (
+ IN SHELL_FILE_HANDLE Handle
+ )
+{
+ CHAR16 *RetVal;
+ UINTN Size;
+ EFI_STATUS Status;
+
+ Size = 0;
+ RetVal = NULL;
+
+ Status = ShellFileHandleReadStdInLine (Handle, RetVal, &Size, FALSE);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ RetVal = AllocateZeroPool(Size);
+ if (RetVal == NULL) {
+ return (NULL);
+ }
+ Status = ShellFileHandleReadStdInLine (Handle, RetVal, &Size, FALSE);
+
+ }
+ if (EFI_ERROR(Status) && (RetVal != NULL)) {
+ FreePool(RetVal);
+ RetVal = NULL;
+ }
+ return (RetVal);
+}
+
+/**
+ Handle stings for SFO Output with escape character ^ in a string
+ 1. Quotation marks in the string must be escaped by using a ^ character (i.e. ^").
+ 2. The ^ character may be inserted using ^^.
+
+ @param[in] String The Unicode NULL-terminated string.
+
+ @retval NewString The new string handled for SFO.
+**/
+EFI_STRING
+HandleStringWithEscapeCharForParse (
+ IN CHAR16 *String
+ )
+{
+ EFI_STRING NewStr;
+ EFI_STRING StrWalker;
+ EFI_STRING ReturnStr;
+
+ if (String == NULL) {
+ return NULL;
+ }
+
+ //
+ // start to parse the input string.
+ //
+ NewStr = AllocateZeroPool (StrSize (String));
+ if (NewStr == NULL) {
+ return NULL;
+ }
+ ReturnStr = NewStr;
+ StrWalker = String;
+ while (*StrWalker != CHAR_NULL) {
+ if (*StrWalker == L'^' && (*(StrWalker + 1) == L'^' || *(StrWalker + 1) == L'"')) {
+ *NewStr = *(StrWalker + 1);
+ StrWalker++;
+ } else {
+ *NewStr = *StrWalker;
+ }
+ StrWalker++;
+ NewStr++;
+ }
+
+ return ReturnStr;
+}
+
+
+/**
+ Do the actual parsing of the file. the file should be SFO output from a
+ shell command or a similar format.
+
+ @param[in] FileName The filename to open.
+ @param[in] TableName The name of the table to find.
+ @param[in] ColumnIndex The column number to get.
+ @param[in] TableNameInstance Which instance of the table to get (row).
+ @param[in] ShellCommandInstance Which instance of the command to get.
+ @param[in] StreamingUnicode Indicates Input file is StdIn Unicode streaming data or not
+
+ @retval SHELL_NOT_FOUND The requested instance was not found.
+ @retval SHELL_SUCCESS The operation was successful.
+**/
+SHELL_STATUS
+EFIAPI
+PerformParsing(
+ IN CONST CHAR16 *FileName,
+ IN CONST CHAR16 *TableName,
+ IN CONST UINTN ColumnIndex,
+ IN CONST UINTN TableNameInstance,
+ IN CONST UINTN ShellCommandInstance,
+ IN BOOLEAN StreamingUnicode
+ )
+{
+ SHELL_FILE_HANDLE FileHandle;
+ EFI_STATUS Status;
+ BOOLEAN Ascii;
+ UINTN LoopVariable;
+ UINTN ColumnLoop;
+ CHAR16 *TempLine;
+ CHAR16 *ColumnPointer;
+ SHELL_STATUS ShellStatus;
+ CHAR16 *TempSpot;
+ CHAR16 *SfoString;
+
+ ASSERT(FileName != NULL);
+ ASSERT(TableName != NULL);
+
+ ShellStatus = SHELL_SUCCESS;
+
+ Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_READ, 0);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel2HiiHandle, L"parse", FileName);
+ ShellStatus = SHELL_NOT_FOUND;
+ } else if (!EFI_ERROR (FileHandleIsDirectory (FileHandle))) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_NOT_FILE), gShellLevel2HiiHandle, L"parse", FileName);
+ ShellStatus = SHELL_NOT_FOUND;
+ } else {
+ for (LoopVariable = 0 ; LoopVariable < ShellCommandInstance && !ShellFileHandleEof(FileHandle);) {
+ if (StreamingUnicode) {
+ TempLine = ParseReturnStdInLine (FileHandle);
+ } else {
+ TempLine = ShellFileHandleReturnLine (FileHandle, &Ascii);
+ }
+
+ if ((TempLine == NULL) || (*TempLine == CHAR_NULL && StreamingUnicode)) {
+ break;
+ }
+
+ //
+ // Search for "ShellCommand," in the file to start the SFO table
+ // for a given ShellCommand. The UEFI Shell spec does not specify
+ // a space after the comma.
+ //
+ if (StrStr (TempLine, L"ShellCommand,") == TempLine) {
+ LoopVariable++;
+ }
+ SHELL_FREE_NON_NULL(TempLine);
+ }
+ if (LoopVariable == ShellCommandInstance) {
+ LoopVariable = 0;
+ while(1) {
+ if (StreamingUnicode) {
+ TempLine = ParseReturnStdInLine (FileHandle);
+ } else {
+ TempLine = ShellFileHandleReturnLine (FileHandle, &Ascii);
+ }
+ if (TempLine == NULL
+ || *TempLine == CHAR_NULL
+ || StrStr (TempLine, L"ShellCommand,") == TempLine) {
+ SHELL_FREE_NON_NULL(TempLine);
+ break;
+ }
+ if (StrStr (TempLine, TableName) == TempLine) {
+ LoopVariable++;
+ if (LoopVariable == TableNameInstance
+ || (TableNameInstance == (UINTN)-1)) {
+ for (ColumnLoop = 1, ColumnPointer = TempLine; ColumnLoop < ColumnIndex && ColumnPointer != NULL && *ColumnPointer != CHAR_NULL; ColumnLoop++) {
+ ColumnPointer = StrStr (ColumnPointer, L",\"");
+ if (ColumnPointer != NULL && *ColumnPointer != CHAR_NULL){
+ ColumnPointer++;
+ }
+ }
+ if (ColumnLoop == ColumnIndex) {
+ if (ColumnPointer == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellLevel2HiiHandle, L"parse", L"Column Index");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ TempSpot = StrStr (ColumnPointer, L",\"");
+ if (TempSpot != NULL) {
+ *TempSpot = CHAR_NULL;
+ }
+ while (ColumnPointer != NULL && *ColumnPointer != CHAR_NULL && ColumnPointer[0] == L' '){
+ ColumnPointer++;
+ }
+ if (ColumnPointer != NULL && *ColumnPointer != CHAR_NULL && ColumnPointer[0] == L'\"'){
+ ColumnPointer++;
+ }
+ if (ColumnPointer != NULL && *ColumnPointer != CHAR_NULL && ColumnPointer[StrLen (ColumnPointer) - 1] == L'\"'){
+ ColumnPointer[StrLen (ColumnPointer) - 1] = CHAR_NULL;
+ }
+ SfoString = HandleStringWithEscapeCharForParse (ColumnPointer);
+ if (SfoString != NULL) {
+ ShellPrintEx (-1, -1, L"%s\r\n", SfoString);
+ SHELL_FREE_NON_NULL (SfoString);
+ }
+ }
+ }
+ }
+ }
+ SHELL_FREE_NON_NULL(TempLine);
+ }
+ }
+ }
+ return (ShellStatus);
+}
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-i", TypeValue},
+ {L"-s", TypeValue},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'parse' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunParse (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ CONST CHAR16 *FileName;
+ CONST CHAR16 *TableName;
+ CONST CHAR16 *ColumnString;
+ SHELL_STATUS ShellStatus;
+ UINTN ShellCommandInstance;
+ UINTN TableNameInstance;
+ BOOLEAN StreamingUnicode;
+
+ ShellStatus = SHELL_SUCCESS;
+ ProblemParam = NULL;
+ StreamingUnicode = FALSE;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParseEx (ParamList, &Package, &ProblemParam, TRUE, FALSE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"parse", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ StreamingUnicode = IsStdInDataAvailable ();
+ if ((!StreamingUnicode && (ShellCommandLineGetCount(Package) < 4)) ||
+ (ShellCommandLineGetCount(Package) < 3)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"parse");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if ((StreamingUnicode && (ShellCommandLineGetCount(Package) > 3)) ||
+ (ShellCommandLineGetCount(Package) > 4)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"parse");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ if (StreamingUnicode) {
+ FileName = L">i";
+ TableName = ShellCommandLineGetRawValue(Package, 1);
+ ColumnString = ShellCommandLineGetRawValue(Package, 2);
+ } else {
+ FileName = ShellCommandLineGetRawValue(Package, 1);
+ TableName = ShellCommandLineGetRawValue(Package, 2);
+ ColumnString = ShellCommandLineGetRawValue(Package, 3);
+ }
+ if (ShellCommandLineGetValue(Package, L"-i") == NULL) {
+ TableNameInstance = (UINTN)-1;
+ } else {
+ TableNameInstance = ShellStrToUintn(ShellCommandLineGetValue(Package, L"-i"));
+ }
+ if (ShellCommandLineGetValue(Package, L"-s") == NULL) {
+ ShellCommandInstance = 1;
+ } else {
+ ShellCommandInstance = ShellStrToUintn(ShellCommandLineGetValue(Package, L"-s"));
+ }
+
+ ShellStatus = PerformParsing(FileName, TableName, ShellStrToUintn(ColumnString), TableNameInstance, ShellCommandInstance, StreamingUnicode);
+ }
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+
+ return (ShellStatus);
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Reset.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Reset.c
new file mode 100644
index 0000000000..7d4cfb470e
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Reset.c
@@ -0,0 +1,132 @@
+/** @file
+ Main file for attrib shell level 2 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel2CommandsLib.h"
+
+STATIC CONST SHELL_PARAM_ITEM ResetParamList[] = {
+ {L"-w", TypeValue},
+ {L"-s", TypeValue},
+ {L"-c", TypeValue},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'reset' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunReset (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CONST CHAR16 *String;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+
+ ShellStatus = SHELL_SUCCESS;
+ ProblemParam = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ResetParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"reset", ProblemParam);
+ FreePool(ProblemParam);
+ return (SHELL_INVALID_PARAMETER);
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ } else if (ShellCommandLineGetRawValue(Package, 1) != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"reset");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // check for warm reset flag, then shutdown reset flag, then cold (default) reset flag
+ //
+ if (ShellCommandLineGetFlag(Package, L"-w")) {
+ if (ShellCommandLineGetFlag(Package, L"-s") || ShellCommandLineGetFlag(Package, L"-c")) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"reset");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ String = ShellCommandLineGetValue(Package, L"-w");
+ if (String != NULL) {
+ gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, StrSize(String), (VOID*)String);
+ } else {
+ gRT->ResetSystem(EfiResetWarm, EFI_SUCCESS, 0, NULL);
+ }
+ }
+ } else if (ShellCommandLineGetFlag(Package, L"-s")) {
+ if (ShellCommandLineGetFlag(Package, L"-c")) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"reset");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ String = ShellCommandLineGetValue(Package, L"-s");
+ DEBUG_CODE(ShellPrintEx(-1,-1,L"Reset with %s (%d bytes)", String, String!=NULL?StrSize(String):0););
+ if (String != NULL) {
+ gRT->ResetSystem(EfiResetShutdown, EFI_SUCCESS, StrSize(String), (VOID*)String);
+ } else {
+ gRT->ResetSystem(EfiResetShutdown, EFI_SUCCESS, 0, NULL);
+ }
+ }
+ } else {
+ //
+ // this is default so dont worry about flag...
+ //
+ String = ShellCommandLineGetValue(Package, L"-c");
+ if (String != NULL) {
+ gRT->ResetSystem(EfiResetCold, EFI_SUCCESS, StrSize(String), (VOID*)String);
+ } else {
+ gRT->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
+ }
+ }
+ }
+ }
+
+ //
+ // we should never get here... so the free and return are for formality more than use
+ // as the ResetSystem function should not return...
+ //
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+
+ //
+ // return the status
+ //
+ return (ShellStatus);
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c
new file mode 100644
index 0000000000..0b23fba150
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Rm.c
@@ -0,0 +1,382 @@
+/** @file
+ Main file for attrib shell level 2 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel2CommandsLib.h"
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-q", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Determine if a directory has no files in it.
+
+ @param[in] FileHandle The EFI_HANDLE to the directory.
+
+ @retval TRUE The directory has no files (or directories).
+ @retval FALSE The directory has at least 1 file or directory in it.
+**/
+BOOLEAN
+EFIAPI
+IsDirectoryEmpty (
+ IN EFI_HANDLE FileHandle
+ )
+{
+ EFI_FILE_INFO *FileInfo;
+ BOOLEAN NoFile;
+ BOOLEAN RetVal;
+
+ RetVal = TRUE;
+ NoFile = FALSE;
+ FileInfo = NULL;
+
+ for (FileHandleFindFirstFile(FileHandle, &FileInfo)
+ ; !NoFile
+ ; FileHandleFindNextFile(FileHandle, FileInfo, &NoFile)
+ ){
+ if (StrStr(FileInfo->FileName, L".") != FileInfo->FileName
+ &&StrStr(FileInfo->FileName, L"..") != FileInfo->FileName) {
+ RetVal = FALSE;
+ }
+ }
+ return (RetVal);
+}
+
+/**
+ Delete a node and all nodes under it (including sub directories).
+
+ @param[in] Node The node to start deleting with.
+ @param[in] Quiet TRUE to print no messages.
+
+ @retval SHELL_SUCCESS The operation was successful.
+ @retval SHELL_ACCESS_DENIED A file was read only.
+ @retval SHELL_ABORTED The abort message was received.
+ @retval SHELL_DEVICE_ERROR A device error occured reading this Node.
+**/
+SHELL_STATUS
+EFIAPI
+CascadeDelete(
+ IN EFI_SHELL_FILE_INFO *Node,
+ IN CONST BOOLEAN Quiet
+ )
+{
+ SHELL_STATUS ShellStatus;
+ EFI_SHELL_FILE_INFO *List;
+ EFI_SHELL_FILE_INFO *Node2;
+ EFI_STATUS Status;
+ SHELL_PROMPT_RESPONSE *Resp;
+ CHAR16 *TempName;
+ UINTN NewSize;
+
+ Resp = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ List = NULL;
+ Status = EFI_SUCCESS;
+
+ if ((Node->Info->Attribute & EFI_FILE_READ_ONLY) == EFI_FILE_READ_ONLY) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DETELE_RO), gShellLevel2HiiHandle, L"rm", Node->FullName);
+ return (SHELL_ACCESS_DENIED);
+ }
+
+ if ((Node->Info->Attribute & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) {
+ if (!IsDirectoryEmpty(Node->Handle)) {
+ if (!Quiet) {
+ Status = ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN(STR_RM_LOG_DELETE_CONF), gShellLevel2HiiHandle, Node->FullName);
+ Status = ShellPromptForResponse(ShellPromptResponseTypeYesNo, NULL, (VOID**)&Resp);
+ ASSERT(Resp != NULL);
+ if (EFI_ERROR(Status) || *Resp != ShellPromptResponseYes) {
+ SHELL_FREE_NON_NULL(Resp);
+ return (SHELL_ABORTED);
+ }
+ SHELL_FREE_NON_NULL(Resp);
+ }
+ //
+ // empty out the directory
+ //
+ Status = gEfiShellProtocol->FindFilesInDir(Node->Handle, &List);
+ if (EFI_ERROR(Status)) {
+ if (List!=NULL) {
+ gEfiShellProtocol->FreeFileList(&List);
+ }
+ return (SHELL_DEVICE_ERROR);
+ }
+ for (Node2 = (EFI_SHELL_FILE_INFO *)GetFirstNode(&List->Link)
+ ; !IsNull(&List->Link, &Node2->Link)
+ ; Node2 = (EFI_SHELL_FILE_INFO *)GetNextNode(&List->Link, &Node2->Link)
+ ){
+ //
+ // skip the directory traversing stuff...
+ //
+ if (StrCmp(Node2->FileName, L".") == 0 || StrCmp(Node2->FileName, L"..") == 0) {
+ continue;
+ }
+ Node2->Status = gEfiShellProtocol->OpenFileByName (Node2->FullName, &Node2->Handle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE);
+ if (EFI_ERROR(Node2->Status) && StrStr(Node2->FileName, L":") == NULL) {
+ //
+ // Update the node filename to have full path with file system identifier
+ //
+ NewSize = StrSize(Node->FullName) + StrSize(Node2->FullName);
+ TempName = AllocateZeroPool(NewSize);
+ if (TempName == NULL) {
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ } else {
+ StrCpyS(TempName, NewSize/sizeof(CHAR16), Node->FullName);
+ TempName[StrStr(TempName, L":")+1-TempName] = CHAR_NULL;
+ StrCatS(TempName, NewSize/sizeof(CHAR16), Node2->FullName);
+ FreePool((VOID*)Node2->FullName);
+ Node2->FullName = TempName;
+
+ //
+ // Now try again to open the file
+ //
+ Node2->Status = gEfiShellProtocol->OpenFileByName (Node2->FullName, &Node2->Handle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE);
+ }
+ }
+ if (!EFI_ERROR(Node2->Status)) {
+ ShellStatus = CascadeDelete(Node2, Quiet);
+ } else if (ShellStatus == SHELL_SUCCESS) {
+ ShellStatus = (SHELL_STATUS)(Node2->Status&(~0x80000000));
+ }
+ if (ShellStatus != SHELL_SUCCESS) {
+ if (List!=NULL) {
+ gEfiShellProtocol->FreeFileList(&List);
+ }
+ return (ShellStatus);
+ }
+ }
+ if (List!=NULL) {
+ gEfiShellProtocol->FreeFileList(&List);
+ }
+ }
+ }
+
+ if (!(StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0)) {
+ //
+ // now delete the current node...
+ //
+ if (!Quiet) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE), gShellLevel2HiiHandle, Node->FullName);
+ }
+ Status = gEfiShellProtocol->DeleteFile(Node->Handle);
+ Node->Handle = NULL;
+ }
+
+ //
+ // We cant allow for the warning here! (Dont use EFI_ERROR Macro).
+ //
+ if (Status != EFI_SUCCESS){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE_ERR), gShellLevel2HiiHandle, Status);
+ return (SHELL_ACCESS_DENIED);
+ } else {
+ if (!Quiet) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE_COMP), gShellLevel2HiiHandle);
+ }
+ return (SHELL_SUCCESS);
+ }
+}
+
+/**
+ Determines if a Node is a valid delete target. Will prevent deleting the root directory.
+
+ @param[in] List RESERVED. Not used.
+ @param[in] Node The node to analyze.
+ @param[in] Package RESERVED. Not used.
+**/
+BOOLEAN
+EFIAPI
+IsValidDeleteTarget(
+ IN CONST EFI_SHELL_FILE_INFO *List,
+ IN CONST EFI_SHELL_FILE_INFO *Node,
+ IN CONST LIST_ENTRY *Package
+ )
+{
+ CONST CHAR16 *TempLocation;
+ BOOLEAN RetVal;
+ CHAR16 *SearchString;
+ CHAR16 *Pattern;
+ UINTN Size;
+
+ if (Node == NULL || Node->FullName == NULL) {
+ return (FALSE);
+ }
+
+ TempLocation = StrStr(Node->FullName, L":");
+ if (StrLen(TempLocation) <= 2) {
+ //
+ // Deleting the root directory is invalid.
+ //
+ return (FALSE);
+ }
+
+ TempLocation = ShellGetCurrentDir(NULL);
+ if (TempLocation == NULL) {
+ //
+ // No working directory is specified so whatever is left is ok.
+ //
+ return (TRUE);
+ }
+
+ Pattern = NULL;
+ SearchString = NULL;
+ Size = 0;
+ Pattern = StrnCatGrow(&Pattern, &Size, TempLocation , 0);
+ Pattern = StrnCatGrow(&Pattern, &Size, L"\\" , 0);
+ Size = 0;
+ SearchString = StrnCatGrow(&SearchString, &Size, Node->FullName, 0);
+ if (!EFI_ERROR(ShellIsDirectory(SearchString))) {
+ SearchString = StrnCatGrow(&SearchString, &Size, L"\\", 0);
+ SearchString = StrnCatGrow(&SearchString, &Size, L"*", 0);
+ }
+
+ if (Pattern == NULL || SearchString == NULL) {
+ RetVal = FALSE;
+ } else {
+ RetVal = TRUE;
+ if (gUnicodeCollation->MetaiMatch(gUnicodeCollation, Pattern, SearchString)) {
+ RetVal = FALSE;
+ }
+ }
+
+ SHELL_FREE_NON_NULL(Pattern );
+ SHELL_FREE_NON_NULL(SearchString);
+
+ return (RetVal);
+}
+
+/**
+ Function for 'rm' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunRm (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ CONST CHAR16 *Param;
+ SHELL_STATUS ShellStatus;
+ UINTN ParamCount;
+ EFI_SHELL_FILE_INFO *FileList;
+ EFI_SHELL_FILE_INFO *Node;
+
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ ParamCount = 0;
+ FileList = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"rm", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ }
+ if (ShellCommandLineGetRawValue(Package, 1) == NULL) {
+ //
+ // we insufficient parameters
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel2HiiHandle, L"rm");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // get a list with each file specified by parameters
+ // if parameter is a directory then add all the files below it to the list
+ //
+ for ( ParamCount = 1, Param = ShellCommandLineGetRawValue(Package, ParamCount)
+ ; Param != NULL
+ ; ParamCount++, Param = ShellCommandLineGetRawValue(Package, ParamCount)
+ ){
+ Status = ShellOpenFileMetaArg((CHAR16*)Param, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ, &FileList);
+ if (EFI_ERROR(Status) || FileList == NULL || IsListEmpty(&FileList->Link)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel2HiiHandle, L"rm", (CHAR16*)Param);
+ ShellStatus = SHELL_NOT_FOUND;
+ break;
+ }
+ }
+
+ if (ShellStatus == SHELL_SUCCESS){
+ //
+ // loop through the list and make sure we are not aborting...
+ //
+ for ( Node = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link)
+ ; !IsNull(&FileList->Link, &Node->Link) && !ShellGetExecutionBreakFlag()
+ ; Node = (EFI_SHELL_FILE_INFO*)GetNextNode(&FileList->Link, &Node->Link)
+ ){
+ //
+ // skip the directory traversing stuff...
+ //
+ if (StrCmp(Node->FileName, L".") == 0 || StrCmp(Node->FileName, L"..") == 0) {
+ continue;
+ }
+
+ //
+ // do the deleting of nodes
+ //
+ if (EFI_ERROR(Node->Status)){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE_ERR2), gShellLevel2HiiHandle, Node->Status);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ break;
+ }
+ if (!IsValidDeleteTarget(FileList, Node, Package)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_RM_LOG_DELETE_ERR3), gShellLevel2HiiHandle, Node->FullName);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ break;
+ }
+
+ ShellStatus = CascadeDelete(Node, ShellCommandLineGetFlag(Package, L"-q"));
+ }
+ }
+ //
+ // Free the fileList
+ //
+ if (FileList != NULL) {
+ Status = ShellCloseFileMetaArg(&FileList);
+ }
+ FileList = NULL;
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ return (ShellStatus);
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Set.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Set.c
new file mode 100644
index 0000000000..d5e6a08978
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Set.c
@@ -0,0 +1,175 @@
+/** @file
+ Main file for attrib shell level 2 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel2CommandsLib.h"
+
+/**
+ Print out each environment variable registered with the Shell 2.0 GUID.
+
+ If you spawn a pre 2.0 shell from the Shell 2.0 the environment variable may not carry through.
+
+ @retval STATUS_SUCCESS the printout was sucessful
+ @return any return code from GetNextVariableName except EFI_NOT_FOUND
+**/
+SHELL_STATUS
+EFIAPI
+PrintAllShellEnvVars(
+ VOID
+ )
+{
+ CONST CHAR16 *Value;
+ CONST CHAR16 *ConstEnvNameList;
+
+ ConstEnvNameList = gEfiShellProtocol->GetEnv(NULL);
+ if (ConstEnvNameList == NULL) {
+ return (SHELL_SUCCESS);
+ }
+ while (*ConstEnvNameList != CHAR_NULL){
+ Value = gEfiShellProtocol->GetEnv(ConstEnvNameList);
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SET_DISP), gShellLevel2HiiHandle, ConstEnvNameList, Value);
+ ConstEnvNameList += StrLen(ConstEnvNameList)+1;
+ }
+
+ return (SHELL_SUCCESS);
+}
+
+STATIC CONST SHELL_PARAM_ITEM SetParamList[] = {
+ {L"-d", TypeValue},
+ {L"-v", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'set' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunSet (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CONST CHAR16 *KeyName;
+ CONST CHAR16 *Value;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Make sure globals are good...
+ //
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (SetParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"set", ProblemParam);
+ FreePool(ProblemParam);
+ return (SHELL_INVALID_PARAMETER);
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ } else if (ShellCommandLineGetRawValue(Package, 3) != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"set");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetRawValue(Package, 1) != NULL && ShellCommandLineGetFlag(Package, L"-d")) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"set");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetFlag(Package, L"-d")) {
+ //
+ // delete a environment variable
+ //
+ KeyName = ShellCommandLineGetValue(Package, L"-d");
+ if (KeyName == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellLevel2HiiHandle, L"set", L"-d");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ Status = ShellSetEnvironmentVariable(KeyName, L"", ShellCommandLineGetFlag(Package, L"-v"));
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SET_ND), gShellLevel2HiiHandle, L"set", KeyName);
+ ShellStatus = SHELL_DEVICE_ERROR;
+ }
+ }
+ } else if (ShellCommandLineGetRawValue(Package, 1) == NULL) {
+ //
+ // print out all current environment variables
+ //
+ return(PrintAllShellEnvVars());
+ } else {
+ //
+ // we are either printing one or assigning one
+ //
+ KeyName = ShellCommandLineGetRawValue(Package, 1);
+ Value = ShellCommandLineGetRawValue(Package, 2);
+ if (KeyName != NULL && Value != NULL) {
+ //
+ // assigning one
+ //
+ Status = ShellSetEnvironmentVariable(KeyName, Value, ShellCommandLineGetFlag(Package, L"-v"));
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SET_ERROR_SET), gShellLevel2HiiHandle, L"set", KeyName);
+ ShellStatus = (SHELL_STATUS) (Status & (~MAX_BIT));
+ }
+
+ } else {
+ if (KeyName != NULL) {
+ //
+ // print out value for this one only.
+ //
+ Value = ShellGetEnvironmentVariable(KeyName);
+ if (Value == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SET_NF), gShellLevel2HiiHandle, L"set", KeyName);
+ ShellStatus = SHELL_SUCCESS;
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SET_DISP), gShellLevel2HiiHandle, KeyName, Value);
+ ShellStatus = SHELL_SUCCESS;
+ }
+ } else {
+ ASSERT(FALSE);
+ }
+ }
+ }
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+
+ return (ShellStatus);
+}
diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/TimeDate.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/TimeDate.c
new file mode 100644
index 0000000000..533519d49d
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/TimeDate.c
@@ -0,0 +1,976 @@
+/** @file
+ Main file for time, timezone, and date shell level 2 and shell level 3 functions.
+
+ (C) Copyright 2012-2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel2CommandsLib.h"
+
+/**
+ Determine if String is a valid representation for a time or date.
+
+ @param[in] String The pointer to the string to test.
+ @param[in] Char The delimeter character.
+ @param[in] Min The minimum value allowed.
+ @param[in] Max The maximum value allowed.
+ @param[in] MinusOk Whether negative numbers are permitted.
+
+ @retval TRUE String is a valid representation.
+ @retval FALSE String is invalid.
+**/
+BOOLEAN
+EFIAPI
+InternalIsTimeLikeString (
+ IN CONST CHAR16 *String,
+ IN CONST CHAR16 Char,
+ IN CONST UINTN Min,
+ IN CONST UINTN Max,
+ IN CONST BOOLEAN MinusOk
+ )
+{
+ UINTN Count;
+ Count = 0;
+
+ if (MinusOk) {
+ //
+ // A single minus is ok.
+ //
+ if (*String == L'-') {
+ String++;
+ }
+ }
+
+ //
+ // the first char must be numeric.
+ //
+ if (!ShellIsDecimalDigitCharacter(*String)) {
+ return (FALSE);
+ }
+ //
+ // loop through the characters and use the lib function
+ //
+ for ( ; String != NULL && *String != CHAR_NULL ; String++){
+ if (*String == Char) {
+ Count++;
+ if (Count > Max) {
+ return (FALSE);
+ }
+ continue;
+ }
+ if (!ShellIsDecimalDigitCharacter(*String)) {
+ return (FALSE);
+ }
+ }
+ if (Count < Min) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+/**
+ Verify that the DateString is valid and if so set that as the current
+ date.
+
+ @param[in] DateString The pointer to a string representation of the date.
+
+ @retval SHELL_INVALID_PARAMETER DateString was NULL.
+ @retval SHELL_INVALID_PARAMETER DateString was mis-formatted.
+ @retval SHELL_SUCCESS The operation was successful.
+**/
+SHELL_STATUS
+EFIAPI
+CheckAndSetDate (
+ IN CONST CHAR16 *DateString
+ )
+{
+ EFI_TIME TheTime;
+ EFI_STATUS Status;
+ CHAR16 *DateStringCopy;
+ CHAR16 *Walker;
+ CHAR16 *Walker1;
+
+ if (!InternalIsTimeLikeString(DateString, L'/', 2, 2, FALSE)) {
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ Status = gRT->GetTime(&TheTime, NULL);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"date", L"gRT->GetTime", Status);
+ return (SHELL_DEVICE_ERROR);
+ }
+
+ DateStringCopy = NULL;
+ DateStringCopy = StrnCatGrow(&DateStringCopy, NULL, DateString, 0);
+ if (DateStringCopy == NULL) {
+ return (SHELL_OUT_OF_RESOURCES);
+ }
+ Walker = DateStringCopy;
+
+ TheTime.Month = 0xFF;
+ TheTime.Day = 0xFF;
+ TheTime.Year = 0xFFFF;
+
+ Walker1 = StrStr(Walker, L"/");
+ if (Walker1 != NULL && *Walker1 == L'/') {
+ *Walker1 = CHAR_NULL;
+ }
+
+ TheTime.Month = (UINT8)ShellStrToUintn (Walker);
+ if (Walker1 != NULL) {
+ Walker = Walker1 + 1;
+ }
+ Walker1 = Walker!=NULL?StrStr(Walker, L"/"):NULL;
+ if (Walker1 != NULL && *Walker1 == L'/') {
+ *Walker1 = CHAR_NULL;
+ }
+ if (Walker != NULL && Walker[0] != CHAR_NULL) {
+ TheTime.Day = (UINT8)ShellStrToUintn (Walker);
+ if (Walker1 != NULL) {
+ Walker = Walker1 + 1;
+ }
+ Walker1 = Walker!=NULL?StrStr(Walker, L"/"):NULL;
+ if (Walker1 != NULL && *Walker1 == L'/') {
+ *Walker1 = CHAR_NULL;
+ }
+ if (Walker != NULL && Walker[0] != CHAR_NULL) {
+ TheTime.Year = (UINT16)ShellStrToUintn (Walker);
+ }
+ }
+
+ if (TheTime.Year < 100) {
+ if (TheTime.Year >= 98) {
+ TheTime.Year = (UINT16)(1900 + TheTime.Year);
+ } else {
+ TheTime.Year = (UINT16)(2000 + TheTime.Year);
+ }
+ }
+
+ Status = gRT->SetTime(&TheTime);
+
+ if (!EFI_ERROR(Status)){
+ return (SHELL_SUCCESS);
+ }
+ return (SHELL_INVALID_PARAMETER);
+}
+
+/**
+ Function for 'date' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDate (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ EFI_TIME TheTime;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ CONST CHAR16 *Param1;
+
+ ShellStatus = SHELL_SUCCESS;
+ ProblemParam = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (SfoParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"date", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ } else if (ShellCommandLineGetRawValue(Package, 2) != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"date");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // If there are 0 value parameters, then print the current date
+ // else If there are any value paramerers, then print error
+ //
+ if (ShellCommandLineGetRawValue(Package, 1) == NULL) {
+ //
+ // get the current date
+ //
+ Status = gRT->GetTime(&TheTime, NULL);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"date", L"gRT->GetTime", Status);
+ return (SHELL_DEVICE_ERROR);
+ }
+
+ //
+ // ShellPrintEx the date in SFO or regular format
+ //
+ if (ShellCommandLineGetFlag(Package, L"-sfo")) {
+ //
+ // Match UEFI Shell spec:
+ // ShellCommand,"date"
+ // Date,"DD","MM","YYYY"
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_SFO_HEADER), gShellLevel2HiiHandle, L"date");
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_DATE_SFO_FORMAT), gShellLevel2HiiHandle, TheTime.Day, TheTime.Month, TheTime.Year);
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_DATE_FORMAT), gShellLevel2HiiHandle, TheTime.Month, TheTime.Day, TheTime.Year);
+ }
+ } else {
+ if (PcdGet8(PcdShellSupportLevel) == 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"date");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // perform level 3 operation here.
+ //
+ Param1 = ShellCommandLineGetRawValue(Package, 1);
+ if (Param1 == NULL) {
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ShellStatus = CheckAndSetDate(Param1);
+ }
+ if (ShellStatus != SHELL_SUCCESS) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"date", Param1);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ }
+ }
+ }
+ }
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+
+ //
+ // return the status
+ //
+ return (ShellStatus);
+}
+
+//
+// Note "-tz" is invalid for this (non-interactive) version of 'time'.
+//
+STATIC CONST SHELL_PARAM_ITEM TimeParamList2[] = {
+ {L"-d", TypeValue},
+ {NULL, TypeMax}
+ };
+
+STATIC CONST SHELL_PARAM_ITEM TimeParamList3[] = {
+ {L"-d", TypeValue},
+ {L"-tz", TypeValue},
+ {NULL, TypeMax}
+ };
+
+/**
+ Verify that the TimeString is valid and if so set that as the current
+ time.
+
+ @param[in] TimeString The pointer to a string representation of the time.
+ @param[in] Tz The value to set for TimeZone.
+ @param[in] Daylight The value to set for Daylight.
+
+ @retval SHELL_INVALID_PARAMETER TimeString was NULL.
+ @retval SHELL_INVALID_PARAMETER TimeString was mis-formatted.
+ @retval SHELL_SUCCESS The operation was successful.
+**/
+SHELL_STATUS
+EFIAPI
+CheckAndSetTime (
+ IN CONST CHAR16 *TimeString,
+ IN CONST INT16 Tz,
+ IN CONST UINT8 Daylight
+ )
+{
+ EFI_TIME TheTime;
+ EFI_STATUS Status;
+ CHAR16 *TimeStringCopy;
+ CHAR16 *Walker1;
+ CHAR16 *Walker2;
+
+ if (TimeString != NULL && !InternalIsTimeLikeString(TimeString, L':', 1, 2, FALSE)) {
+ return (SHELL_INVALID_PARAMETER);
+ }
+ if (Daylight != 0xFF &&((Daylight & (EFI_TIME_IN_DAYLIGHT|EFI_TIME_ADJUST_DAYLIGHT)) != Daylight)) {
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ Status = gRT->GetTime(&TheTime, NULL);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"time", L"gRT->GetTime", Status);
+ return (SHELL_DEVICE_ERROR);
+ }
+
+ if (TimeString != NULL) {
+ TimeStringCopy = NULL;
+ TimeStringCopy = StrnCatGrow(&TimeStringCopy, NULL, TimeString, 0);
+ Walker1 = TimeStringCopy;
+ TheTime.Hour = 0xFF;
+ TheTime.Minute = 0xFF;
+
+ Walker2 = Walker1!=NULL?StrStr(Walker1, L":"):NULL;
+ if (Walker2 != NULL && *Walker2 == L':') {
+ *Walker2 = CHAR_NULL;
+ }
+ TheTime.Hour = (UINT8)ShellStrToUintn (Walker1);
+ if (Walker2 != NULL) {
+ Walker1 = Walker2 + 1;
+ }
+ Walker2 = Walker1!=NULL?StrStr(Walker1, L":"):NULL;
+ if (Walker2 != NULL && *Walker2 == L':') {
+ *Walker2 = CHAR_NULL;
+ TheTime.Second = (UINT8)0;
+ }
+ else if (Walker2 == NULL) {
+ TheTime.Second = (UINT8)0;
+ }
+ if (Walker1 != NULL && Walker1[0] != CHAR_NULL) {
+ TheTime.Minute = (UINT8)ShellStrToUintn (Walker1);
+ if (Walker2 != NULL) {
+ Walker1 = Walker2 + 1;
+ if (Walker1 != NULL && Walker1[0] != CHAR_NULL) {
+ TheTime.Second = (UINT8)ShellStrToUintn (Walker1);
+ }
+ }
+ }
+ SHELL_FREE_NON_NULL(TimeStringCopy);
+ }
+
+
+ if (Tz >= -1440 && Tz <= 1440) {
+ //
+ // EFI_TIME TimeZone is stored to meet the following calculation (see UEFI Spec):
+ // Localtime = UTC - TimeZone
+ // This means the sign must be changed for the user provided Tz.
+ // EX: User wants to set TimeZone to Pacific Standard Time, so runs
+ // time -tz -480 # set to UTC-08:00
+ // To meet the calculation, the sign must be changed.
+ //
+ TheTime.TimeZone = -Tz;
+ } else if (Tz == EFI_UNSPECIFIED_TIMEZONE) {
+ TheTime.TimeZone = Tz;
+ }
+
+ if (Daylight != 0xFF) {
+ TheTime.Daylight = Daylight;
+ }
+
+ Status = gRT->SetTime(&TheTime);
+
+ if (!EFI_ERROR(Status)){
+ return (SHELL_SUCCESS);
+ }
+
+ return (SHELL_INVALID_PARAMETER);
+}
+
+/**
+ Function for 'time' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunTime (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ EFI_TIME TheTime;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ INT16 Tz;
+ UINT8 Daylight;
+ CONST CHAR16 *TempLocation;
+ UINTN TzMinutes;
+
+ //
+ // Initialize variables
+ //
+ ShellStatus = SHELL_SUCCESS;
+ ProblemParam = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ if (PcdGet8(PcdShellSupportLevel) == 2) {
+ Status = ShellCommandLineParseEx (TimeParamList2, &Package, &ProblemParam, TRUE, TRUE);
+ } else {
+ ASSERT(PcdGet8(PcdShellSupportLevel) == 3);
+ Status = ShellCommandLineParseEx (TimeParamList3, &Package, &ProblemParam, TRUE, TRUE);
+ }
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"time", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ Status = gRT->GetTime(&TheTime, NULL);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"time", L"gRT->GetTime", Status);
+ return (SHELL_DEVICE_ERROR);
+ }
+
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ } else if (ShellCommandLineGetRawValue(Package, 2) != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"time");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // If there are no parameters, then print the current time
+ //
+ if (ShellCommandLineGetRawValue(Package, 1) == NULL
+ && !ShellCommandLineGetFlag(Package, L"-d")
+ && !ShellCommandLineGetFlag(Package, L"-tz")) {
+ //
+ // ShellPrintEx the current time
+ //
+ if (TheTime.TimeZone == EFI_UNSPECIFIED_TIMEZONE) {
+ TzMinutes = 0;
+ } else {
+ TzMinutes = (ABS(TheTime.TimeZone)) % 60;
+ }
+
+ if (TheTime.TimeZone != EFI_UNSPECIFIED_TIMEZONE) {
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_TIME_FORMAT),
+ gShellLevel2HiiHandle,
+ TheTime.Hour,
+ TheTime.Minute,
+ TheTime.Second,
+ (TheTime.TimeZone > 0?L"-":L"+"),
+ ((ABS(TheTime.TimeZone)) / 60),
+ TzMinutes
+ );
+ } else {
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_TIME_FORMAT_LOCAL),
+ gShellLevel2HiiHandle,
+ TheTime.Hour,
+ TheTime.Minute,
+ TheTime.Second
+ );
+ }
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF), gShellLevel2HiiHandle);
+ } else if (ShellCommandLineGetFlag(Package, L"-d") && ShellCommandLineGetValue(Package, L"-d") == NULL) {
+ if (TheTime.TimeZone == EFI_UNSPECIFIED_TIMEZONE) {
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_TIME_FORMAT_LOCAL),
+ gShellLevel2HiiHandle,
+ TheTime.Hour,
+ TheTime.Minute,
+ TheTime.Second
+ );
+ } else {
+ TzMinutes = (ABS(TheTime.TimeZone)) % 60;
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_TIME_FORMAT),
+ gShellLevel2HiiHandle,
+ TheTime.Hour,
+ TheTime.Minute,
+ TheTime.Second,
+ (TheTime.TimeZone > 0?L"-":L"+"),
+ ((ABS(TheTime.TimeZone)) / 60),
+ TzMinutes
+ );
+ }
+ switch (TheTime.Daylight) {
+ case 0:
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TIME_DST0), gShellLevel2HiiHandle);
+ break;
+ case EFI_TIME_ADJUST_DAYLIGHT:
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TIME_DST1), gShellLevel2HiiHandle);
+ break;
+ case EFI_TIME_IN_DAYLIGHT:
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TIME_DST2), gShellLevel2HiiHandle);
+ break;
+ case EFI_TIME_IN_DAYLIGHT|EFI_TIME_ADJUST_DAYLIGHT:
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TIME_DST3), gShellLevel2HiiHandle);
+ break;
+ default:
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_ERROR), gShellLevel2HiiHandle, L"time", L"gRT->GetTime", L"TheTime.Daylight", TheTime.Daylight);
+ }
+ } else {
+ if (PcdGet8(PcdShellSupportLevel) == 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"time");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // perform level 3 operation here.
+ //
+ if ((TempLocation = ShellCommandLineGetValue(Package, L"-tz")) != NULL) {
+ if (StrniCmp (TempLocation, L"_local", StrLen (TempLocation)) == NULL) {
+ Tz = EFI_UNSPECIFIED_TIMEZONE;
+ } else if (TempLocation[0] == L'-') {
+
+ Tz = (INT16) ShellStrToUintn (++TempLocation);
+ //
+ // When the argument of "time [-tz tz]" is not numeric, ShellStrToUintn() returns "-1".
+ // Here we can detect the argument error by checking the return of ShellStrToUintn().
+ //
+ if (Tz == -1) {
+ Tz = 1441; //make it to be out of bounds value
+ } else {
+ Tz *= (-1); //sign convert
+ }
+ } else {
+ if (TempLocation[0] == L'+') {
+ Tz = (INT16)ShellStrToUintn (++TempLocation);
+ } else {
+ Tz = (INT16)ShellStrToUintn (TempLocation);
+ }
+ //
+ // Detect the return of ShellStrToUintn() to make sure the argument is valid.
+ //
+ if (Tz == -1) {
+ Tz = 1441; //make it to be out of bounds value
+ }
+ }
+ if (!(Tz >= -1440 && Tz <= 1440) && Tz != EFI_UNSPECIFIED_TIMEZONE) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellLevel2HiiHandle, L"time", TempLocation, L"-tz");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ } else {
+ //
+ // intentionally out of bounds value will prevent changing it...
+ //
+ Tz = 1441;
+ }
+ TempLocation = ShellCommandLineGetValue(Package, L"-d");
+ if (TempLocation != NULL) {
+ Daylight = (UINT8)ShellStrToUintn(TempLocation);
+ //
+ // The argument of "time [-d dl]" is unsigned, if the first character is '-',
+ // the argument is incorrect. That's because ShellStrToUintn() will skip past
+ // any '-' sign and convert what's next, forgetting the sign is here.
+ //
+ if (TempLocation[0] == '-') {
+ Daylight = 0xff; //make it invalid = will not use
+ }
+ if (Daylight != 0 && Daylight != 1 && Daylight != 3) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellLevel2HiiHandle, L"time", TempLocation, L"-d");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ } else {
+ //
+ // invalid = will not use
+ //
+ Daylight = 0xFF;
+ }
+ if (ShellStatus == SHELL_SUCCESS) {
+ ShellStatus = CheckAndSetTime(ShellCommandLineGetRawValue(Package, 1), Tz, Daylight);
+ if (ShellStatus != SHELL_SUCCESS) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"time", ShellCommandLineGetRawValue(Package, 1));
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+
+ //
+ // return the status
+ //
+ return (ShellStatus);
+}
+
+typedef struct {
+ INT16 TimeZone;
+ EFI_STRING_ID StringId;
+} TIME_ZONE_ITEM;
+
+STATIC CONST SHELL_PARAM_ITEM TimeZoneParamList2[] = {
+ {L"-l", TypeFlag},
+ {L"-f", TypeFlag},
+ {NULL, TypeMax}
+ };
+STATIC CONST SHELL_PARAM_ITEM TimeZoneParamList3[] = {
+ {L"-l", TypeFlag},
+ {L"-f", TypeFlag},
+ {L"-s", TypeTimeValue},
+ {NULL, TypeMax}
+ };
+
+ STATIC CONST TIME_ZONE_ITEM TimeZoneList[] = {
+ {720, STRING_TOKEN (STR_TIMEZONE_M12)},
+ {660, STRING_TOKEN (STR_TIMEZONE_M11)},
+ {600, STRING_TOKEN (STR_TIMEZONE_M10)},
+ {540, STRING_TOKEN (STR_TIMEZONE_M9)},
+ {480, STRING_TOKEN (STR_TIMEZONE_M8)},
+ {420, STRING_TOKEN (STR_TIMEZONE_M7)},
+ {360, STRING_TOKEN (STR_TIMEZONE_M6)},
+ {300, STRING_TOKEN (STR_TIMEZONE_M5)},
+ {270, STRING_TOKEN (STR_TIMEZONE_M430)},
+ {240, STRING_TOKEN (STR_TIMEZONE_M4)},
+ {210, STRING_TOKEN (STR_TIMEZONE_M330)},
+ {180, STRING_TOKEN (STR_TIMEZONE_M3)},
+ {120, STRING_TOKEN (STR_TIMEZONE_M2)},
+ {60 , STRING_TOKEN (STR_TIMEZONE_M1)},
+ {0 , STRING_TOKEN (STR_TIMEZONE_0)},
+ {-60 , STRING_TOKEN (STR_TIMEZONE_P1)},
+ {-120 , STRING_TOKEN (STR_TIMEZONE_P2)},
+ {-180 , STRING_TOKEN (STR_TIMEZONE_P3)},
+ {-210 , STRING_TOKEN (STR_TIMEZONE_P330)},
+ {-240 , STRING_TOKEN (STR_TIMEZONE_P4)},
+ {-270 , STRING_TOKEN (STR_TIMEZONE_P430)},
+ {-300 , STRING_TOKEN (STR_TIMEZONE_P5)},
+ {-330 , STRING_TOKEN (STR_TIMEZONE_P530)},
+ {-345 , STRING_TOKEN (STR_TIMEZONE_P545)},
+ {-360 , STRING_TOKEN (STR_TIMEZONE_P6)},
+ {-390 , STRING_TOKEN (STR_TIMEZONE_P630)},
+ {-420 , STRING_TOKEN (STR_TIMEZONE_P7)},
+ {-480 , STRING_TOKEN (STR_TIMEZONE_P8)},
+ {-540 , STRING_TOKEN (STR_TIMEZONE_P9)},
+ {-570 , STRING_TOKEN (STR_TIMEZONE_P930)},
+ {-600 , STRING_TOKEN (STR_TIMEZONE_P10)},
+ {-660 , STRING_TOKEN (STR_TIMEZONE_P11)},
+ {-720 , STRING_TOKEN (STR_TIMEZONE_P12)},
+ {-780 , STRING_TOKEN (STR_TIMEZONE_P13)},
+ {-840 , STRING_TOKEN (STR_TIMEZONE_P14)},
+ {EFI_UNSPECIFIED_TIMEZONE, STRING_TOKEN (STR_TIMEZONE_LOCAL)}
+};
+
+/**
+ Verify that the TimeZoneString is valid and if so set that as the current
+ timezone.
+
+ @param[in] TimeZoneString The pointer to a string representation of the timezone.
+
+ @retval SHELL_INVALID_PARAMETER TimeZoneString was NULL.
+ @retval SHELL_INVALID_PARAMETER TimeZoneString was mis-formatted.
+ @retval SHELL_SUCCESS The operation was successful.
+**/
+SHELL_STATUS
+EFIAPI
+CheckAndSetTimeZone (
+ IN CONST CHAR16 *TimeZoneString
+ )
+{
+ EFI_TIME TheTime;
+ EFI_STATUS Status;
+ CHAR16 *TimeZoneCopy;
+ CHAR16 *Walker;
+ CHAR16 *Walker2;
+ UINTN LoopVar;
+
+ if (TimeZoneString == NULL) {
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ if (StrniCmp (TimeZoneString, L"_local", StrLen (TimeZoneString)) == NULL) {
+ Status = gRT->GetTime (&TheTime, NULL);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"gRT->GetTime", Status);
+ return (SHELL_DEVICE_ERROR);
+ }
+
+ TheTime.TimeZone = EFI_UNSPECIFIED_TIMEZONE;
+ Status = gRT->SetTime (&TheTime);
+ if (!EFI_ERROR(Status)){
+ return (SHELL_SUCCESS);
+ }
+ return (SHELL_INVALID_PARAMETER);
+ }
+ if (TimeZoneString != NULL && !InternalIsTimeLikeString(TimeZoneString, L':', 1, 1, TRUE)) {
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ Status = gRT->GetTime(&TheTime, NULL);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"timezone", L"gRT->GetTime", Status);
+ return (SHELL_DEVICE_ERROR);
+ }
+
+ TimeZoneCopy = NULL;
+ TimeZoneCopy = StrnCatGrow(&TimeZoneCopy, NULL, TimeZoneString, 0);
+ if (TimeZoneCopy == NULL) {
+ return (SHELL_OUT_OF_RESOURCES);
+ }
+ Walker = TimeZoneCopy;
+ Walker2 = StrStr(Walker, L":");
+ if (Walker2 != NULL && *Walker2 == L':') {
+ *Walker2 = CHAR_NULL;
+ }
+ if (*Walker == L'-') {
+ TheTime.TimeZone = (INT16)((ShellStrToUintn (++Walker)) * 60);
+ } else {
+ TheTime.TimeZone = (INT16)((INT16)(ShellStrToUintn (Walker)) * -60);
+ }
+ if (Walker2 != NULL) {
+ Walker = Walker2 + 1;
+ }
+ if (Walker != NULL && Walker[0] != CHAR_NULL) {
+ if (TheTime.TimeZone < 0) {
+ TheTime.TimeZone = (INT16)(TheTime.TimeZone - (UINT8)ShellStrToUintn (Walker));
+ } else {
+ TheTime.TimeZone = (INT16)(TheTime.TimeZone + (UINT8)ShellStrToUintn (Walker));
+ }
+ }
+
+ Status = EFI_INVALID_PARAMETER;
+
+ for ( LoopVar = 0
+ ; LoopVar < sizeof(TimeZoneList) / sizeof(TimeZoneList[0])
+ ; LoopVar++
+ ){
+ if (TheTime.TimeZone == TimeZoneList[LoopVar].TimeZone) {
+ Status = gRT->SetTime(&TheTime);
+ break;
+ }
+ }
+
+ FreePool(TimeZoneCopy);
+
+ if (!EFI_ERROR(Status)){
+ return (SHELL_SUCCESS);
+ }
+ return (SHELL_INVALID_PARAMETER);
+}
+
+
+/**
+ Function for 'timezone' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunTimeZone (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ //
+ // non interactive
+ //
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ UINT8 LoopVar;
+ EFI_TIME TheTime;
+ BOOLEAN Found;
+ UINTN TzMinutes;
+
+ ShellStatus = SHELL_SUCCESS;
+ ProblemParam = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ if (PcdGet8(PcdShellSupportLevel) == 2) {
+ Status = ShellCommandLineParse (TimeZoneParamList2, &Package, &ProblemParam, TRUE);
+ } else {
+ ASSERT(PcdGet8(PcdShellSupportLevel) == 3);
+ Status = ShellCommandLineParseEx (TimeZoneParamList3, &Package, &ProblemParam, TRUE, TRUE);
+ }
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"timezone", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetCount(Package) > 1) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"timezone");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ } else if (ShellCommandLineGetFlag(Package, L"-s")) {
+ if ((ShellCommandLineGetFlag(Package, L"-l")) || (ShellCommandLineGetFlag(Package, L"-f"))) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"timezone", L"-l or -f");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(PcdGet8(PcdShellSupportLevel) == 3);
+ if (ShellCommandLineGetValue(Package, L"-s") == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellLevel2HiiHandle, L"timezone", L"-s");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // Set the time zone
+ //
+ ShellStatus = CheckAndSetTimeZone(ShellCommandLineGetValue(Package, L"-s"));
+ if (ShellStatus != SHELL_SUCCESS) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"timezone", ShellCommandLineGetValue(Package, L"-s"));
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ }
+ }
+ } else if (ShellCommandLineGetFlag(Package, L"-l")) {
+ //
+ // Print a list of all time zones
+ //
+ for ( LoopVar = 0
+ ; LoopVar < sizeof(TimeZoneList) / sizeof(TimeZoneList[0])
+ ; LoopVar++
+ ){
+ ShellPrintHiiEx (-1, -1, NULL, TimeZoneList[LoopVar].StringId, gShellLevel2HiiHandle);
+ }
+ } else {
+ //
+ // Get Current Time Zone Info
+ //
+ Status = gRT->GetTime(&TheTime, NULL);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_UEFI_FUNC_WARN), gShellLevel2HiiHandle, L"timezone", L"gRT->GetTime", Status);
+ return (SHELL_DEVICE_ERROR);
+ }
+
+ if (TheTime.TimeZone != EFI_UNSPECIFIED_TIMEZONE) {
+ Found = FALSE;
+ for ( LoopVar = 0
+ ; LoopVar < sizeof(TimeZoneList) / sizeof(TimeZoneList[0])
+ ; LoopVar++
+ ){
+ if (TheTime.TimeZone == TimeZoneList[LoopVar].TimeZone) {
+ if (ShellCommandLineGetFlag(Package, L"-f")) {
+ //
+ // Print all info about current time zone
+ //
+ ShellPrintHiiEx (-1, -1, NULL, TimeZoneList[LoopVar].StringId, gShellLevel2HiiHandle);
+ } else {
+ //
+ // Print basic info only
+ //
+ TzMinutes = (ABS(TheTime.TimeZone)) % 60;
+
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_TIMEZONE_SIMPLE),
+ gShellLevel2HiiHandle,
+ (TheTime.TimeZone > 0?L"-":L"+"),
+ (ABS(TheTime.TimeZone)) / 60,
+ TzMinutes);
+ }
+ Found = TRUE;
+ break;
+ }
+ }
+ if (!Found) {
+ //
+ // Print basic info only
+ //
+ TzMinutes = (ABS(TheTime.TimeZone)) % 60;
+
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN(STR_TIMEZONE_SIMPLE),
+ gShellLevel2HiiHandle,
+ (TheTime.TimeZone > 0?L"-":L"+"),
+ (ABS(TheTime.TimeZone)) / 60,
+ TzMinutes);
+
+ if (ShellCommandLineGetFlag(Package, L"-f")) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN(STR_TIMEZONE_NI), gShellLevel2HiiHandle);
+ }
+ }
+ } else {
+ //
+ // TimeZone was EFI_UNSPECIFIED_TIMEZONE (local) from GetTime()
+ //
+ if (ShellCommandLineGetFlag (Package, L"-f")) {
+ for ( LoopVar = 0
+ ; LoopVar < sizeof (TimeZoneList) / sizeof (TimeZoneList[0])
+ ; LoopVar++
+ ){
+ if (TheTime.TimeZone == TimeZoneList[LoopVar].TimeZone) {
+ //
+ // Print all info about current time zone
+ //
+ ShellPrintHiiEx (-1, -1, NULL, TimeZoneList[LoopVar].StringId, gShellLevel2HiiHandle);
+ break;
+ }
+ }
+ } else {
+ //
+ // Print basic info only
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_TIMEZONE_SIMPLE_LOCAL), gShellLevel2HiiHandle);
+ }
+ }
+ }
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+
+ return (ShellStatus);
+}
diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c
new file mode 100644
index 0000000000..0dafb19969
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.c
@@ -0,0 +1,351 @@
+/** @file
+ Main file for NULL named library for level 2 shell command functions.
+
+ these functions are:
+ attrib,
+ cd,
+ cp,
+ date*,
+ time*,
+ load,
+ ls,
+ map,
+ mkdir,
+ mv,
+ parse,
+ rm,
+ reset,
+ set,
+ timezone*,
+ vol
+
+ * functions are non-interactive only
+
+ Copyright (c) 2014 Hewlett-Packard Development Company, L.P.
+ Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "UefiShellLevel2CommandsLib.h"
+
+CONST CHAR16 mFileName[] = L"ShellCommands";
+EFI_HANDLE gShellLevel2HiiHandle = NULL;
+
+/**
+ Get the filename to get help text from if not using HII.
+
+ @retval The filename.
+**/
+CONST CHAR16*
+EFIAPI
+ShellCommandGetManFileNameLevel2 (
+ VOID
+ )
+{
+ return (mFileName);
+}
+
+/**
+ Constructor for the Shell Level 2 Commands library.
+
+ Install the handlers for level 2 UEFI Shell 2.0 commands.
+
+ @param ImageHandle the image handle of the process
+ @param SystemTable the EFI System Table pointer
+
+ @retval EFI_SUCCESS the shell command handlers were installed sucessfully
+ @retval EFI_UNSUPPORTED the shell level required was not found.
+**/
+EFI_STATUS
+EFIAPI
+ShellLevel2CommandsLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ //
+ // if shell level is less than 2 do nothing
+ //
+ if (PcdGet8(PcdShellSupportLevel) < 2) {
+ return (EFI_SUCCESS);
+ }
+
+ gShellLevel2HiiHandle = HiiAddPackages (&gShellLevel2HiiGuid, gImageHandle, UefiShellLevel2CommandsLibStrings, NULL);
+ if (gShellLevel2HiiHandle == NULL) {
+ return (EFI_DEVICE_ERROR);
+ }
+
+ //
+ // install our shell command handlers that are always installed
+ //
+ ShellCommandRegisterCommandName(L"attrib", ShellCommandRunAttrib , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_ATTRIB) );
+ ShellCommandRegisterCommandName(L"cd", ShellCommandRunCd , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_CD) );
+ ShellCommandRegisterCommandName(L"cp", ShellCommandRunCp , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_CP) );
+ ShellCommandRegisterCommandName(L"load", ShellCommandRunLoad , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_LOAD) );
+ ShellCommandRegisterCommandName(L"map", ShellCommandRunMap , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_MAP) );
+ ShellCommandRegisterCommandName(L"mkdir", ShellCommandRunMkDir , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_MKDIR) );
+ ShellCommandRegisterCommandName(L"mv", ShellCommandRunMv , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_MV) );
+ ShellCommandRegisterCommandName(L"parse", ShellCommandRunParse , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_PARSE) );
+ ShellCommandRegisterCommandName(L"reset", ShellCommandRunReset , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_RESET) );
+ ShellCommandRegisterCommandName(L"set", ShellCommandRunSet , ShellCommandGetManFileNameLevel2, 2, L"",FALSE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_SET) );
+ ShellCommandRegisterCommandName(L"ls", ShellCommandRunLs , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_LS) );
+ ShellCommandRegisterCommandName(L"rm", ShellCommandRunRm , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_RM) );
+ ShellCommandRegisterCommandName(L"vol", ShellCommandRunVol , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_VOL) );
+
+ //
+ // support for permenant (built in) aliases
+ //
+ ShellCommandRegisterAlias(L"rm", L"del");
+ ShellCommandRegisterAlias(L"ls", L"dir");
+ ShellCommandRegisterAlias(L"cp", L"copy");
+ ShellCommandRegisterAlias(L"mkdir", L"md");
+ ShellCommandRegisterAlias(L"cd ..", L"cd..");
+ ShellCommandRegisterAlias(L"cd \\", L"cd\\");
+ ShellCommandRegisterAlias(L"mv", L"ren");
+ ShellCommandRegisterAlias(L"mv", L"move");
+ ShellCommandRegisterAlias(L"map", L"mount");
+ //
+ // These are installed in level 2 or 3...
+ //
+ if (PcdGet8(PcdShellSupportLevel) == 2 || PcdGet8(PcdShellSupportLevel) == 3) {
+ ShellCommandRegisterCommandName(L"date", ShellCommandRunDate , ShellCommandGetManFileNameLevel2, PcdGet8(PcdShellSupportLevel), L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_DATE) );
+ ShellCommandRegisterCommandName(L"time", ShellCommandRunTime , ShellCommandGetManFileNameLevel2, PcdGet8(PcdShellSupportLevel), L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_TIME) );
+ ShellCommandRegisterCommandName(L"timezone", ShellCommandRunTimeZone, ShellCommandGetManFileNameLevel2, PcdGet8(PcdShellSupportLevel), L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_TIMEZONE));
+ } else {
+ DEBUG_CODE_BEGIN();
+ //
+ // we want to be able to test these so install them under a different name in debug mode...
+ //
+ ShellCommandRegisterCommandName(L"l2date", ShellCommandRunDate , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_DATE) );
+ ShellCommandRegisterCommandName(L"l2time", ShellCommandRunTime , ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_TIME) );
+ ShellCommandRegisterCommandName(L"l2timezone", ShellCommandRunTimeZone, ShellCommandGetManFileNameLevel2, 2, L"", TRUE, gShellLevel2HiiHandle, STRING_TOKEN(STR_GET_HELP_TIMEZONE));
+ DEBUG_CODE_END();
+ }
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Destructor for the library. free any resources.
+
+ @param ImageHandle The image handle of the process.
+ @param SystemTable The EFI System Table pointer.
+
+ @retval EFI_SUCCESS Always returned.
+**/
+EFI_STATUS
+EFIAPI
+ShellLevel2CommandsLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ if (gShellLevel2HiiHandle != NULL) {
+ HiiRemovePackages(gShellLevel2HiiHandle);
+ }
+ return (EFI_SUCCESS);
+}
+
+/**
+ returns a fully qualified directory (contains a map drive at the begining)
+ path from a unknown directory path.
+
+ If Path is already fully qualified this will return a duplicat otherwise this
+ will use get the current directory and use that to build the fully qualified
+ version.
+
+ if the return value is not NULL it must be caller freed.
+
+ @param[in] Path The unknown Path Value
+
+ @retval NULL A memory allocation failed
+ @retval NULL A fully qualified path could not be discovered.
+ @retval other An allocated pointer to a fuly qualified path.
+**/
+CHAR16*
+EFIAPI
+GetFullyQualifiedPath(
+ IN CONST CHAR16* Path
+ )
+{
+ CHAR16 *PathToReturn;
+ UINTN Size;
+ CONST CHAR16 *CurDir;
+
+ PathToReturn = NULL;
+ Size = 0;
+
+ ASSERT((PathToReturn == NULL && Size == 0) || (PathToReturn != NULL));
+ //
+ // convert a local path to an absolute path
+ //
+ if (StrStr(Path, L":") == NULL) {
+ CurDir = gEfiShellProtocol->GetCurDir(NULL);
+ StrnCatGrow(&PathToReturn, &Size, CurDir, 0);
+ StrnCatGrow(&PathToReturn, &Size, L"\\", 0);
+ if (*Path == L'\\') {
+ Path++;
+ }
+ }
+ StrnCatGrow(&PathToReturn, &Size, Path, 0);
+
+ PathCleanUpDirectories(PathToReturn);
+
+ if (PathToReturn == NULL) {
+ return NULL;
+ }
+
+ while (PathToReturn[StrLen(PathToReturn)-1] == L'*') {
+ PathToReturn[StrLen(PathToReturn)-1] = CHAR_NULL;
+ }
+
+ return (PathToReturn);
+}
+
+/**
+ Function to verify all intermediate directories in the path.
+
+ @param[in] Path The pointer to the path to fix.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+VerifyIntermediateDirectories (
+ IN CONST CHAR16 *Path
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *PathCopy;
+ CHAR16 *TempSpot;
+ SHELL_FILE_HANDLE FileHandle;
+
+ ASSERT(Path != NULL);
+
+ Status = EFI_SUCCESS;
+ PathCopy = NULL;
+ PathCopy = StrnCatGrow(&PathCopy, NULL, Path, 0);
+ FileHandle = NULL;
+
+ if (PathCopy == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ for (TempSpot = &PathCopy[StrLen(PathCopy)-1] ; *TempSpot != CHAR_NULL && *TempSpot != L'\\' ; TempSpot = &PathCopy[StrLen(PathCopy)-1]){
+ *TempSpot = CHAR_NULL;
+ }
+ if (*TempSpot == L'\\') {
+ *TempSpot = CHAR_NULL;
+ }
+
+ if (PathCopy != NULL && *PathCopy != CHAR_NULL) {
+ Status = VerifyIntermediateDirectories(PathCopy);
+
+ if (PathCopy[StrLen(PathCopy)-1] != L':') {
+ if (!EFI_ERROR(Status)) {
+ Status = ShellOpenFileByName(PathCopy, &FileHandle, EFI_FILE_MODE_READ, 0);
+ if (FileHandle != NULL) {
+ ShellCloseFile(&FileHandle);
+ }
+ }
+ }
+ }
+
+ SHELL_FREE_NON_NULL(PathCopy);
+
+ return (Status);
+}
+
+/**
+ Be lazy and borrow from baselib.
+
+ @param[in] Char The character to convert to upper case.
+
+ @return Char as an upper case character.
+**/
+CHAR16
+EFIAPI
+InternalCharToUpper (
+ IN CONST CHAR16 Char
+ );
+
+/**
+ String comparison without regard to case for a limited number of characters.
+
+ @param[in] Source The first item to compare.
+ @param[in] Target The second item to compare.
+ @param[in] Count How many characters to compare.
+
+ @retval NULL Source and Target are identical strings without regard to case.
+ @return The location in Source where there is a difference.
+**/
+CONST CHAR16*
+EFIAPI
+StrniCmp(
+ IN CONST CHAR16 *Source,
+ IN CONST CHAR16 *Target,
+ IN CONST UINTN Count
+ )
+{
+ UINTN LoopCount;
+ CHAR16 Char1;
+ CHAR16 Char2;
+
+ ASSERT(Source != NULL);
+ ASSERT(Target != NULL);
+
+ for (LoopCount = 0 ; LoopCount < Count ; LoopCount++) {
+ Char1 = InternalCharToUpper(Source[LoopCount]);
+ Char2 = InternalCharToUpper(Target[LoopCount]);
+ if (Char1 != Char2) {
+ return (&Source[LoopCount]);
+ }
+ }
+ return (NULL);
+}
+
+
+/**
+ Cleans off all the quotes in the string.
+
+ @param[in] OriginalString pointer to the string to be cleaned.
+ @param[out] CleanString The new string with all quotes removed.
+ Memory allocated in the function and free
+ by caller.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+ShellLevel2StripQuotes (
+ IN CONST CHAR16 *OriginalString,
+ OUT CHAR16 **CleanString
+ )
+{
+ CHAR16 *Walker;
+
+ if (OriginalString == NULL || CleanString == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *CleanString = AllocateCopyPool (StrSize (OriginalString), OriginalString);
+ if (*CleanString == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Walker = *CleanString; Walker != NULL && *Walker != CHAR_NULL ; Walker++) {
+ if (*Walker == L'\"') {
+ CopyMem(Walker, Walker+1, StrSize(Walker) - sizeof(Walker[0]));
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h
new file mode 100644
index 0000000000..634515e493
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.h
@@ -0,0 +1,374 @@
+/** @file
+ Main file for NULL named library for level 2 shell command functions.
+
+ these functions are:
+ attrib, cd, cp, date*, time*, rm, reset,
+ load, ls, map, mkdir, mv, parse, set, timezone*
+
+
+ * functions are non-interactive only
+
+
+ Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _UEFI_SHELL_LEVEL2_COMMANDS_LIB_H_
+#define _UEFI_SHELL_LEVEL2_COMMANDS_LIB_H_
+
+#include <Uefi.h>
+#include <ShellBase.h>
+
+#include <Guid/ShellLibHiiGuid.h>
+
+#include <Protocol/EfiShell.h>
+#include <Protocol/EfiShellParameters.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/UnicodeCollation.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/ShellCommandLib.h>
+#include <Library/ShellLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HiiLib.h>
+#include <Library/SortLib.h>
+#include <Library/FileHandleLib.h>
+
+extern CONST CHAR16 mFileName[];
+extern EFI_HANDLE gShellLevel2HiiHandle;
+
+/**
+ Function for 'attrib' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunAttrib (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'date' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunDate (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'time' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunTime (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'load' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunLoad (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'ls' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunLs (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'map' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunMap (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'reset' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunReset (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'timezone' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunTimeZone (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'set' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunSet (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'mkdir' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunMkDir (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'cd' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunCd (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'cp' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunCp (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'parse' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunParse (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'rm' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunRm (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'mv' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunMv (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ returns a fully qualified directory (contains a map drive at the begining)
+ path from a unknown directory path.
+
+ If Path is already fully qualified this will return a duplicat otherwise this
+ will use get the current directory and use that to build the fully qualified
+ version.
+
+ if the return value is not NULL it must be caller freed.
+
+ @param[in] Path The unknown Path Value
+
+ @retval NULL A memory allocation failed
+ @retval NULL a fully qualified path could not be discovered.
+ @retval other pointer to a fuly qualified path.
+**/
+CHAR16*
+EFIAPI
+GetFullyQualifiedPath(
+ IN CONST CHAR16* Path
+ );
+
+/**
+ Function to verify all intermediate directories in the path.
+
+ @param[in] Path The pointer to the path to fix.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+VerifyIntermediateDirectories (
+ IN CONST CHAR16 *Path
+ );
+
+/**
+ CaseInsensitive length limited string comparison.
+
+ @param[in] Source Pointer to first string.
+ @param[in] Target Pointer to second string.
+ @param[in] Count Number of characters to compare.
+
+ @retval 0 The strings are the same.
+ @return non-zero if the strings are different.
+**/
+CONST CHAR16*
+EFIAPI
+StrniCmp(
+ IN CONST CHAR16 *Source,
+ IN CONST CHAR16 *Target,
+ IN CONST UINTN Count
+ );
+
+/**
+ Cleans off all the quotes in the string.
+
+ @param[in] OriginalString pointer to the string to be cleaned.
+ @param[out] CleanString The new string with all quotes removed.
+ Memory allocated in the function and free
+ by caller.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+ShellLevel2StripQuotes (
+ IN CONST CHAR16 *OriginalString,
+ OUT CHAR16 **CleanString
+ );
+
+/**
+ Function for 'Vol' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunVol (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function to Copy one file to another location
+
+ If the destination exists the user will be prompted and the result put into *resp
+
+ @param[in] Source pointer to source file name
+ @param[in] Dest pointer to destination file name
+ @param[out] Resp pointer to response from question. Pass back on looped calling
+ @param[in] SilentMode whether to run in quiet mode or not
+ @param[in] CmdName Source command name requesting single file copy
+
+ @retval SHELL_SUCCESS The source file was copied to the destination
+**/
+SHELL_STATUS
+EFIAPI
+CopySingleFile(
+ IN CONST CHAR16 *Source,
+ IN CONST CHAR16 *Dest,
+ OUT VOID **Resp,
+ IN BOOLEAN SilentMode,
+ IN CONST CHAR16 *CmdName
+ );
+
+/**
+ Delete a node and all nodes under it (including sub directories).
+
+ @param[in] Node The node to start deleting with.
+ @param[in] Quiet TRUE to print no messages.
+
+ @retval SHELL_SUCCESS The operation was successful.
+ @retval SHELL_ACCESS_DENIED A file was read only.
+ @retval SHELL_ABORTED The abort message was received.
+ @retval SHELL_DEVICE_ERROR A device error occured reading this Node.
+**/
+SHELL_STATUS
+EFIAPI
+CascadeDelete(
+ IN EFI_SHELL_FILE_INFO *Node,
+ IN CONST BOOLEAN Quiet
+ );
+
+#endif
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf
new file mode 100644
index 0000000000..16faad2d2d
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf
@@ -0,0 +1,84 @@
+## @file
+# Provides shell level 2 functions
+#
+# Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved. <BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = UefiShellLevel2CommandsLib
+ FILE_GUID = CBF3931C-A2DF-40e5-B77E-CCA9555E9755
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER
+ CONSTRUCTOR = ShellLevel2CommandsLibConstructor
+ DESTRUCTOR = ShellLevel2CommandsLibDestructor
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ UefiShellLevel2CommandsLib.c
+ UefiShellLevel2CommandsLib.h
+ UefiShellLevel2CommandsLib.uni
+ TimeDate.c
+ Load.c
+ Ls.c
+ Map.c
+ Reset.c
+ Set.c
+ MkDir.c
+ Cd.c
+ Cp.c
+ Parse.c
+ Rm.c
+ Mv.c
+ Attrib.c
+ Vol.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ ShellCommandLib
+ ShellLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ PcdLib
+ HiiLib
+ HandleParsingLib
+ DevicePathLib
+
+[Protocols]
+ gEfiUnicodeCollation2ProtocolGuid ## CONSUMES
+ gEfiShellProtocolGuid ## CONSUMES
+ gEfiShellParametersProtocolGuid ## CONSUMES
+ gEfiDevicePathProtocolGuid ## CONSUMES
+ gEfiLoadedImageProtocolGuid ## CONSUMES
+ gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES
+
+[Pcd.common]
+ gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel ## CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdShellFileOperationSize ## CONSUMES
+
+[Guids]
+ gEfiFileSystemInfoGuid ## SOMETIMES_CONSUMES ## GUID
+ gEfiFileInfoGuid ## UNDEFINED
+ gShellLevel2HiiGuid ## SOMETIMES_CONSUMES ## HII
diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.uni b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.uni
new file mode 100644
index 0000000000..60f48f4633
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.uni
@@ -0,0 +1,1088 @@
+// /**
+//
+// (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
+// Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// Module Name:
+//
+// UefiShellLevel2CommandsLib.uni
+//
+// Abstract:
+//
+// String definitions for UEFI Shell 2.0 level 2 commands
+//
+//
+// **/
+
+/=#
+
+#langdef en-US "english"
+
+#string STR_GEN_NO_MEM #language en-US "%H%s%N: Memory is not available.\r\n"
+#string STR_GEN_TOO_MANY #language en-US "%H%s%N: Too many arguments.\r\n"
+#string STR_GEN_TOO_FEW #language en-US "%H%s%N: Too few arguments.\r\n"
+#string STR_GEN_PARAM_INV #language en-US "%H%s%N: Invalid argument - '%H%s%N'\r\n"
+#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n"
+#string STR_GEN_PROBLEM_VAL #language en-US "%H%s%N: Bad value - '%H%s%N' for flag - '%H%s%N'\r\n"
+#string STR_GEN_ATTRIBUTE #language en-US "%H%s%N: Invalid argument - '%H-a%s%N'\r\n"
+#string STR_GEN_NO_VALUE #language en-US "%H%s%N: Missing argument for flag - '%H%s%N'\r\n"
+#string STR_GEN_ERR_AD #language en-US "%H%s%N: Access denied.\r\n"
+#string STR_GEN_ERR_FILE #language en-US "%H%s%N: File '%H%s%N' error - %r\r\n"
+#string STR_GEN_ERR_UK #language en-US "%H%s%N: Status: %r\r\n"
+#string STR_GEN_PARAM_CON #language en-US "%H%s%N: Parameters conflict.\r\n"
+#string STR_GEN_PARAM_CONFLICT #language en-US "%H%s%N: Flags conflict with - '%H%s%N' and '%H%s%N'\r\n"
+#string STR_GEN_FILE_OPEN_FAIL #language en-US "%H%s%N: Cannot open file - '%H%s%N'\r\n"
+#string STR_GEN_FILE_CLOSE_FAIL #language en-US "%H%s%N: Cannot close file - '%H%s%N'\r\n"
+#string STR_GEN_FILE_AD #language en-US "%H%s%N: File access error - '%H%s%N'\r\n"
+#string STR_GEN_FILE_NF #language en-US "%H%s%N: File not found - '%H%s%N'\r\n"
+#string STR_GEN_CRLF #language en-US "\r\n"
+#string STR_GEN_NO_CWD #language en-US "%H%s%N: Current directory not specified.\r\n"
+#string STR_GEN_NO_FILES #language en-US "%H%s%N: No matching files were found.\r\n"
+#string STR_GEN_DIR_NF #language en-US "%H%s%N: Directory not found - '%H%s%N'\r\n"
+#string STR_GEN_RES_OK #language en-US "- [ok]\r\n"
+#string STR_GEN_NOT_DIR #language en-US "%H%s%N: '%H%s%N' is not a directory.\r\n"
+#string STR_GEN_NOT_FILE #language en-US "%H%s%N: '%H%s%N' is not a file.\r\n"
+#string STR_GEN_SFO_HEADER #language en-US "ShellCommand,"%s"\r\n"
+#string STR_GEN_MARG_ERROR #language en-US "%H%s%N: The destination '%H%s%N' is ambiguous.\r\n"
+#string STR_GEN_FILE_ERROR #language en-US "%H%s%N: The destination is an existing file '%H%s%N'.\r\n"
+#string STR_GEN_UEFI_FUNC_ERROR #language en-US "%H%s%N: UEFI function '%H%s%N' returned an incorrect value for: %s (%x).\r\n"
+#string STR_GEN_UEFI_FUNC_WARN #language en-US "%H%s%N: UEFI function '%H%s%N' returned: %r\r\n"
+#string STR_GEN_DEST_EXIST_OVR #language en-US "Destination file already exists. Overwrite? %BY%Nes, %BN%No, %BA%Nll, %BC%Nancel "
+#string STR_GEN_CPY_FAIL #language en-US "%H%s%N: Copy failure: insufficient capacity on destination media.\r\n"
+#string STR_GEN_CPY_READ_ERROR #language en-US "%H%s%N: reading '%B%s%N': IO Error \r\n"
+#string STR_GEN_CPY_WRITE_ERROR #language en-US "%H%s%N: writing '%B%s%N': IO Error \r\n"
+#string STR_GEN_OUT_MEM #language en-US "%H%s%N: Memory allocation was not successful.\r\n"
+
+#string STR_SET_DISP #language en-US "%V%8s %N= %H%s%N\r\n"
+#string STR_SET_NF #language en-US "%H%s%N: Environment Variable '%H%s%N' not defined.\r\n"
+#string STR_SET_ND #language en-US "%H%s%N: Environment Variable '%H%s%N' could not be deleted.\r\n"
+#string STR_SET_ERROR_SET #language en-US "%H%s%N: Unable to set %H%s%N\r\n"
+
+#string STR_CD_PRINT #language en-US "%s\r\n"
+#string STR_CD_NF #language en-US "%H%s%N: No mapping found.\r\n"
+
+#string STR_MAP_NF #language en-US "%H%s%N: Cannot find mapped device - '%H%s%N'\r\n"
+#string STR_MAP_NOF #language en-US "%H%s%N: No mappable target found - '%H%s%N'\r\n"
+#string STR_MAP_SFO_MAPPINGS #language en-US "Mappings,"%s","%s","%s"\r\n"
+#string STR_MAP_HEADER #language en-US "%EMapping table%N\r\n"
+#string STR_MAP_ENTRY #language en-US "%E%10s%N %HAlias(s):%N%s\r\n %s\r\n"
+#string STR_MAP_ENTRY_VERBOSE #language en-US " Handle: [%H%02x%N]\r\n"
+ " Media Type: %s\r\n"
+ " Removable: %s\r\n"
+ " Current Dir: %s\r\n"
+
+#string STR_ATTRIB_OUTPUT_LINE #language en-US "Attrib: %1c%1c%1c%1c%1c %s\r\n"
+
+#string STR_MAP_MEDIA_FLOPPY #language en-US "Floppy"
+#string STR_MAP_MEDIA_UNKNOWN #language en-US "Unknown"
+#string STR_MAP_MEDIA_HARDDISK #language en-US "HardDisk"
+#string STR_MAP_MEDIA_CDROM #language en-US "CD-Rom"
+
+#string STR_MKDIR_ALREADY #language en-US "Directory '%B%s%N' already exists.\r\n"
+#string STR_MKDIR_CREATEFAIL #language en-US "Directory '%B%s%N' unable to create.\r\n"
+
+#string STR_DATE_FORMAT #language en-US "%02d/%02d/%04d\r\n"
+#string STR_DATE_SFO_FORMAT #language en-US "Date,"%02d","%02d","%04d"\r\n"
+
+#string STR_TIME_FORMAT #language en-US "%02d:%02d:%02d (UTC%1s%02d:%02d)"
+#string STR_TIME_FORMAT_LOCAL #language en-US "%02d:%02d:%02d (LOCAL)"
+#string STR_TIME_DST0 #language en-US " DST: Not Affected\r\n"
+#string STR_TIME_DST1 #language en-US " DST: Affected\r\n"
+#string STR_TIME_DST2 #language en-US " DST: Adjusted\r\n"
+#string STR_TIME_DST3 #language en-US " DST: Affected and Adjusted\r\n"
+
+#string STR_TIMEZONE_M12 #language en-US "UTC-12:00, International Date Line West\r\n"
+#string STR_TIMEZONE_M11 #language en-US "UTC-11:00, Midway Island, Samoa\r\n"
+#string STR_TIMEZONE_M10 #language en-US "UTC-10:00, Hawaii\r\n"
+#string STR_TIMEZONE_M9 #language en-US "UTC-09:00, Alaska\r\n"
+#string STR_TIMEZONE_M8 #language en-US "UTC-08:00, Pacific Time(US & Canada), Tijuana, Portland\r\n"
+#string STR_TIMEZONE_M7 #language en-US "UTC-07:00, Arizona, Chihuahua, La Paz, Mazatlan, Mountain Time (US & Canada)\r\n"
+#string STR_TIMEZONE_M6 #language en-US "UTC-06:00, Central America, Central Time(US & Canada)\r\n"
+#string STR_TIMEZONE_M5 #language en-US "UTC-05:00, Bogota, Lima, Quito, Eastern Time(US & Canada)\r\n"
+#string STR_TIMEZONE_M430 #language en-US "UTC-04:30, Caracas\r\n"
+#string STR_TIMEZONE_M4 #language en-US "UTC-04:00, Atlantic Time(Canada), Caracas, Santiago\r\n"
+#string STR_TIMEZONE_M330 #language en-US "UTC-03:30, Newfoundland\r\n"
+#string STR_TIMEZONE_M3 #language en-US "UTC-03:00, Brasilia, Buenos Aires, Georgetown, Greenland\r\n"
+#string STR_TIMEZONE_M2 #language en-US "UTC-02:00, Mid-Atlantic\r\n"
+#string STR_TIMEZONE_M1 #language en-US "UTC-01:00, Azores, Cape Verde Is.\r\n"
+#string STR_TIMEZONE_0 #language en-US "UTC , Greenwich Mean Time, Casablanca, Monrovia, Dublin, London\r\n"
+#string STR_TIMEZONE_P1 #language en-US "UTC+01:00, Amsterdam, Berlin, Bern, Rome, Paris, West Central Africa\r\n"
+#string STR_TIMEZONE_P2 #language en-US "UTC+02:00, Athens, Istanbul, Bucharest, Cairo, Jerusalem\r\n"
+#string STR_TIMEZONE_P3 #language en-US "UTC+03:00, Baghdad, Kuwait, Riyadh, Moscow, Nairobi\r\n"
+#string STR_TIMEZONE_P330 #language en-US "UTC+03:30, Tehran\r\n"
+#string STR_TIMEZONE_P4 #language en-US "UTC+04:00, Abu Dhabi, Muscat, Baku, Tbilisi, Yerevan\r\n"
+#string STR_TIMEZONE_P430 #language en-US "UTC+04:30, Kabul\r\n"
+#string STR_TIMEZONE_P5 #language en-US "UTC+05:00, Ekaterinburg, Islamabad, Karachi, Tashkent\r\n"
+#string STR_TIMEZONE_P530 #language en-US "UTC+05:30, Chennai, Kolkata, Mumbai, New Delhi\r\n"
+#string STR_TIMEZONE_P545 #language en-US "UTC+05:45, Kathmandu\r\n"
+#string STR_TIMEZONE_P6 #language en-US "UTC+06:00, Almaty, Novosibirsk, Astana, Dhaka, Sri Jayawardenepura\r\n"
+#string STR_TIMEZONE_P630 #language en-US "UTC+06:30, Rangoon\r\n"
+#string STR_TIMEZONE_P7 #language en-US "UTC+07:00, Bangkok, Hanio, Jakarta, Krasnoyarsk\r\n"
+#string STR_TIMEZONE_P8 #language en-US "UTC+08:00, Beijing, Chongqing, Hong Kong, Urumqi, Taipei, Perth\r\n"
+#string STR_TIMEZONE_P9 #language en-US "UTC+09:00, Osaka, Sapporo, Tokyo, Seoul, Yakutsk\r\n"
+#string STR_TIMEZONE_P930 #language en-US "UTC+09:30, Adelaide, Darwin\r\n"
+#string STR_TIMEZONE_P10 #language en-US "UTC+10:00, Canberra, Melbourne, Sydney, Guam, Hobart, Vladivostok\r\n"
+#string STR_TIMEZONE_P11 #language en-US "UTC+11:00, Magadan, Solomon Is., New Caledonia\r\n"
+#string STR_TIMEZONE_P12 #language en-US "UTC+12:00, Auckland, Wellington, Fiji, Kamchatka, Marshall Is.\r\n"
+#string STR_TIMEZONE_P13 #language en-US "UTC+13:00, Nuku'alofa\r\n"
+#string STR_TIMEZONE_P14 #language en-US "UTC+14:00, Line Islands\r\n"
+#string STR_TIMEZONE_LOCAL #language en-US "LOCAL , Local Time\r\n"
+#string STR_TIMEZONE_SIMPLE #language en-US "UTC%1s%02d:%02d\r\n"
+#string STR_TIMEZONE_SIMPLE_LOCAL #language en-US "LOCAL\r\n"
+#string STR_TIMEZONE_NI #language en-US "No additional information known."
+
+#string STR_LOAD_NOT_IMAGE #language en-US "Image '%s' is not an image.\r\n"
+#string STR_LOAD_NOT_DRIVER #language en-US "Image '%s' is not a driver.\r\n"
+#string STR_LOAD_LOADED #language en-US "Image '%s' loaded at %x - %r\r\n"
+#string STR_LOAD_ERROR #language en-US "Image '%s' error in StartImage: %r\r\n"
+
+#string STR_LS_LINE_START_ALL #language en-US "%t %5s %1c % ,L11d "
+#string STR_LS_LINE_END_FILE #language en-US "%s\r\n"
+#string STR_LS_LINE_END_EXE #language en-US "%V%s%N\r\n"
+#string STR_LS_LINE_END_DIR #language en-US "%B%s%N\r\n"
+#string STR_LS_FOOTER_LINE #language en-US "% ,L11d File(s) % ,L11d bytes\r\n% ,L11d Dir(s)\r\n"
+#string STR_LS_HEADER_LINE1 #language en-US "Directory of: %H%s%N\r\n"
+#string STR_LS_FILE_NOT_FOUND #language en-US "%H%s%N: File Not Found - '%H%s%N'\r\n"
+#string STR_LS_SFO_VOLINFO #language en-US "VolumeInfo,"%s","%Ld","%5s","%Ld","%Ld"\r\n"
+#string STR_LS_SFO_FILEINFO #language en-US "FileInfo,"%s","%Ld","%Ld","%s%s%s%s%s","%02d:%02d:%02d","%02d.%02d.%04d","%02d:%02d:%02d","%02d.%02d.%04d","%02d:%02d:%02d","%02d.%02d.%04d"\r\n"
+
+#string STR_VOL_VOLINFO #language en-US "Volume %s (%s)\r\n"
+ "%Ld bytes total disk space\r\n"
+ "%Ld bytes available on disk\r\n"
+ "%d bytes in each allocation unit\r\n"
+
+#string STR_RM_LOG_DELETE_CONF #language en-US "Remove Subtree '%B%s%N' [y/n]?"
+#string STR_RM_LOG_DELETE #language en-US "Deleting '%B%s%N'\r\n"
+#string STR_RM_LOG_DELETE_ERR #language en-US "Delete error: %r\r\n"
+#string STR_RM_LOG_DELETE_ERR2 #language en-US "Delete error. Couldn't open file: %r\r\n"
+#string STR_RM_LOG_DELETE_ERR3 #language en-US "Delete error. Invalid target '%B%s%N'\r\n"
+#string STR_RM_LOG_DELETE_COMP #language en-US "Delete successful.\r\n"
+#string STR_RM_LOG_DETELE_RO #language en-US "%H%s%N: '%H%s%N' is read-only\r\n"
+
+#string STR_MV_OUTPUT #language en-US "Moving %s -> %s\r\n"
+#string STR_MV_INV_SUB #language en-US "Cannot move a directory into itself or its subdirectory.\r\n"
+#string STR_MV_INV_RO #language en-US "Cannot move to or from a read-only file or directory '%B%s%N'\r\n"
+#string STR_MV_INV_CWD #language en-US "Cannot move current working directory or its subdirectory.\r\n"
+
+#string STR_CP_OUTPUT #language en-US "Copying %s -> %s\r\n"
+#string STR_CP_ERROR #language en-US "%H%s%N: Could not copy - '%H%s%N'\r\n"
+#string STR_CP_DIR_REQ #language en-US "%H%s%N: Copying a directory requires -r.\r\n"
+#string STR_CP_DIR_WNF #language en-US "%H%s%N: The specified path does not exist - '%H%s%N'\r\n"
+#string STR_CP_SD_SAME #language en-US "%H%s%N: The source and destination are the same.\r\n"
+#string STR_CP_SD_PARENT #language en-US "%H%s%N: The destination is a parent of the source.\r\n"
+#string STR_CP_DEST_ERROR #language en-US "%H%s%N: The destination is read-only.\r\n"
+#string STR_CP_DEST_OPEN_FAIL #language en-US "%H%s%N: The destination file '%B%s%N' failed to open with create.\r\n"
+#string STR_CP_DEST_DIR_FAIL #language en-US "%H%s%N: The destination directory '%B%s%N' could not be created.\r\n"
+#string STR_CP_SRC_OPEN_FAIL #language en-US "%H%s%N: The source file '%B%s%N' failed to open with read.\r\n"
+
+#string STR_GET_HELP_ATTRIB #language en-US ""
+".TH attrib 0 "Displays or modifies the attributes of files or directories."\r\n"
+".SH NAME\r\n"
+"Displays or modifies the attributes of files or directories.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"ATTRIB [+a|-a] [+s|-s] [+h|-h] [+r|-r] [file...] [directory...]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" +a|-a - Sets or clears the 'archive' attribute.\r\n"
+" +s|-s - Sets or clears the 'system' attribute.\r\n"
+" +h|-h - Sets or clears the 'hidden' attribute.\r\n"
+" +r|-r - Sets or clears the 'read-only' attribute.\r\n"
+" file - Specifies the file name (wild cards are permitted).\r\n"
+" directory - Specifies the directory name (wildcards are permitted).\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. Four attribute types are supported in the UEFI file system:\r\n"
+" - Archive [A]\r\n"
+" - System [S]\r\n"
+" - Hidden [H]\r\n"
+" - Read only [R]\r\n"
+" 2. If a file (in general meaning) is a directory, then it is also shown\r\n"
+" to have the attribute [D].\r\n"
+" 3. If any file in the file list that is specified \r\n"
+" does not exist, attrib will continue processing the remaining files\r\n"
+" while reporting the error.\r\n"
+" 4. If no attributes parameters are specified, the current attributes of\r\n"
+" the specified files or directories are displayed.\r\n"
+" 5. If no files or directories are specified, the command applies to\r\n"
+" all files and sub-directories within the current directory.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display the attributes of a directory:\r\n"
+" fs0:\> attrib fs0:\ \r\n"
+" \r\n"
+" * To display the attributes of all files and sub-directories in the current\r\n"
+" directory:\r\n"
+" fs0:\> attrib *\r\n"
+" \r\n"
+" * To add the system attribute to all files with extension '.efi':\r\n"
+" fs0:\> attrib +s *.efi\r\n"
+" \r\n"
+" * To remove the read-only attribute from all files with extension '.inf':\r\n"
+" fs0:\> attrib -r *.inf\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_NOT_FOUND The requested file was not found.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_WRITE_PROTECTED The media that the action was to take place on is\r\n"
+" write-protected.\r\n"
+
+#string STR_GET_HELP_CD #language en-US ""
+".TH cd 0 "Displays or changes the current directory."\r\n"
+".SH NAME\r\n"
+"Displays or changes the current directory.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"CD [path]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" path - Specifies the relative or absolute directory path.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command changes the current working directory that is used by the\r\n"
+" UEFI Shell environment. If a file system mapping is specified, then the\r\n"
+" current working directory is changed for that device. Otherwise, the\r\n"
+" current working directory is changed for the current device.\r\n"
+" 2. If path is not present, then the current working directory (including\r\n"
+" file system mapping) is displayed to standard out.\r\n"
+" 3. The table below describes the conventions that are used to refer to the\r\n"
+" directory, its parent, and the root directory in the UEFI Shell\r\n"
+" environment.\r\n"
+" Convention Description\r\n"
+" '.' Refers to the current directory.\r\n"
+" '..' Refers to the directory's parent.\r\n"
+" '\\\' Refers to the root of the current file system.\r\n"
+" 4. The current working directory is maintained in the environment\r\n"
+" variable %cwd%.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To change the current file system to the mapped fs0 file system:\r\n"
+" Shell> fs0:\r\n"
+" \r\n"
+" * To change the current directory to subdirectory 'efi':\r\n"
+" fs0:\> cd efi\r\n"
+" \r\n"
+" * To change the current directory to the parent directory (fs0:\):\r\n"
+" fs0:\efi\> cd ..\r\n"
+" \r\n"
+" * To change the current directory to 'fs0:\efi\Tools':\r\n"
+" fs0:\> cd efi\Tools\r\n"
+" \r\n"
+" * To change the current directory to the root of the current fs (fs0):\r\n"
+" fs0:\efi\Tools\> cd \ \r\n"
+" \r\n"
+" * To move between volumes and maintain the current path, and then copy\r\n"
+" all of files in fs0:\efi\Tools into the fs1:\Tmp directory:\r\n"
+" fs0:\> cd \efi\Tools\r\n"
+" fs0:\efi\Tools\> fs1:\r\n"
+" fs1:\> cd Tmp\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+
+#string STR_GET_HELP_CP #language en-US ""
+".TH cp 0 "Copies files or directories."\r\n"
+".SH NAME\r\n"
+"Copies one or more files or directories to another location.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"CP [-r] [-q] src [src...] [dst]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -r - Makes a recursive copy.\r\n"
+" -q - Makes a quiet copy (without a prompt).\r\n"
+" src - Specifies a source file/directory name (wildcards are permitted).\r\n"
+" dst - Specifies a destination file/directory name (wildcards are not permitted). \r\n"
+" If more than one directory is specified, the last directory is\r\n"
+" assumed to be the destination.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. '-r' must be specified if src is a directory. If '-r' is specified,\r\n"
+" the source directory is recursively copied to the destination.\r\n"
+" 'src' itself is copied.\r\n"
+" 2. If a destination is not specified, the current working directory is\r\n"
+" assumed to be the destination.\r\n"
+" 3. 'CP -r src1 src2 dst' copies all files and subdirectories in 'src1' and\r\n"
+" 'src2' to the destination 'dst'. 'src1' and 'src2' themselves are also\r\n"
+" copied. The 'dst' parameter is interpreted as a directory.\r\n"
+" 4. Copying a directory or file to itself is not allowed.\r\n"
+" 5. If an error occurs, this command exits immediately and the remaining files or\r\n"
+" directories are not copied.\r\n"
+" 6. When 'cp' is executed with a script file, it always performs quiet\r\n"
+" copying, regardless of whether the '-q' option is specified.\r\n"
+" 7. If you are copying multiple files, the destination must be an existing\r\n"
+" directory.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display the contents of the current directory:\r\n"
+" fs0:\> ls\r\n"
+" \r\n"
+" * To copy a file in the same directory and change the file name:\r\n"
+" fs0:\> cp temp.txt readme.txt\r\n"
+" \r\n"
+" * To copy multiple files to another directory:\r\n"
+" fs0:\> cp temp.txt isaBus.efi \Test\r\n"
+" \r\n"
+" * To copy multiple directories recursively to another directory:\r\n"
+" fs0:\> cp -r test1 test2 boot \Test\r\n"
+" \r\n"
+" * To see the results of the above operations:\r\n"
+" fs0:\> ls \Test\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly \r\n"
+" formatted or its value was out of bounds.\r\n"
+" SHELL_OUT_OF_RESOURCES There was insufficient space to save the \r\n"
+" requested file at the destination.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security \r\n"
+" violation.\r\n"
+" SHELL_WRITE_PROTECTED An attempt was made to create a file on media that\r\n"
+" was write-protected.\r\n"
+
+#string STR_GET_HELP_MAP #language en-US ""
+".TH map 0 "Displays or defines file system mappings"\r\n"
+".SH NAME\r\n"
+"Displays or defines file system mappings.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"MAP [-d <sname>]\r\n"
+"MAP [[-r][-v][-c][-f][-u][-t <type[,type...]>][sname]]\r\n"
+"MAP [sname handle | mapping]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -d - Deletes a file system mapping.\r\n"
+" -r - Resets file system mappings to default values.\r\n"
+" -u - Adds file system mappings for newly-installed devices and\r\n"
+" removes mappings for uninstalled devices. This does not change\r\n"
+" the mappings of existing devices and preserves user-defined mappings.\r\n"
+" -v - Displays verbose information about all file system mappings.\r\n"
+" -c - Displays the consistent mappings.\r\n"
+" -f - Displays the normal mappings (not the consistent mappings).\r\n"
+" -t - Displays the device mappings, filtered according to the device type.\r\n"
+" Supported types are:\r\n"
+" fp - Floppy\r\n"
+" hd - Hard Disk\r\n"
+" cd - CD-ROM\r\n"
+" Types can be combined by putting a comma between two types. Spaces\r\n"
+" are not allowed between types.\r\n"
+" -sfo - Displays information in Standard-Format Output.\r\n"
+" sname - Specifies a mapping name.\r\n"
+" handle - Specifies the number of a handle. Use the same value that is\r\n"
+" displayed by the 'dh' command.\r\n"
+" mapping - Specifies a new mapping name to assign to a device.\r\n"
+" This value must end with a ':'.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command creates a mapping between a user-defined name and a device.\r\n"
+" The most common use of this command is to create a mapped name for\r\n"
+" devices that support a file system protocol. After these mappings are\r\n"
+" created, the names can be used with all the file manipulation commands.\r\n"
+" 2. The UEFI Shell environment creates default mappings for all of the\r\n"
+" devices that support a recognized file system.\r\n"
+" 3. This command can be used to create additional mappings, or \r\n"
+" when used with the -d option, to delete an existing mapping. If it is\r\n"
+" used without any parameters, all of the current mappings are listed.\r\n"
+" If the -v option is used, the mappings are shown with additional\r\n"
+" information about each device.\r\n"
+" 4. The -r option is used to reset all the default mappings in a system,\r\n"
+" which is useful if the system configuration has changed since the\r\n"
+" last boot.\r\n"
+" 5. The -u option adds mappings for newly-installed devices and removes\r\n"
+" mappings for uninstalled devices without changing the mappings of\r\n"
+" existing devices. User-defined mappings are also preserved. A mapping\r\n"
+" history is saved, which preserves the original mapping name for\r\n"
+" a device with a specific device path. The current directory is also\r\n"
+" preserved if the current device is not changed.\r\n"
+" 6. Each device in the system has a consistent mapping. If the hardware\r\n"
+" configuration has not changed, the device's consistent mappings do not\r\n"
+" change. If two or more machines have the same hardware configurations,\r\n"
+" the device's consistent mapping remains the same. Use the -c option to\r\n"
+" list all the consistent mappings in the system.\r\n"
+" 7. The mapping value must consist of digits and characters. Other\r\n"
+" characters are illegal.\r\n"
+" 8. This command support wildcards. You can use the wildcards to delete\r\n"
+" or show the mapping. However, when you assign the mapping, wildcards\r\n"
+" are forbidden.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display verbose mapping table information:\r\n"
+" Shell> map -v\r\n"
+" \r\n"
+" * To assign a different name to fs0:\r\n"
+" Shell> map floppy fs0:\r\n"
+" \r\n"
+" * To operate with the mapped name:\r\n"
+" Shell> floppy:\r\n"
+" \r\n"
+" * To delete a mapped name:\r\n"
+" Shell> map -d floppy:\r\n"
+" \r\n"
+" * To display all the mapped names starting with 'f': \r\n"
+" Shell> map f* \r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+
+#string STR_GET_HELP_MKDIR #language en-US ""
+".TH mkdir 0 "Creates directories."\r\n"
+".SH NAME\r\n"
+"Creates one or more new directories.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"MKDIR dir [dir...]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" dir - Specifies the name of a directory or directories to create. (Wildcards are not\r\n"
+" allowed) \r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. The parent directory must already exist.\r\n"
+" 2. If the directory already exists, mkdir will abort.\r\n"
+" 3. Specifying additional directory parameters dependent on previous\r\n"
+" directory parameters is not allowed:\r\n"
+" For example, mkdir new new\Test is not allowed.\r\n"
+" 4. Redirecting output to a file that exists under the directory specified\r\n"
+" by this command is not allowed.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To create a new directory:\r\n"
+" fs0:\> mkdir rafter\r\n"
+" \r\n"
+" * To create multiple directories:\r\n"
+" fs0:\> mkdir temp1 temp2\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly \r\n"
+" formatted or its value was out of bounds.\r\n"
+" SHELL_OUT_OF_RESOURCES There was insufficient space on the destination \r\n"
+" to create the requested directory.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security \r\n"
+" violation.\r\n"
+" SHELL_WRITE_PROTECTED An attempt was made to create a directory when the\r\n"
+" target media was write-protected.\r\n"
+
+#string STR_GET_HELP_MV #language en-US ""
+".TH mv 0 "Moves files."\r\n"
+".SH NAME\r\n"
+"Moves one or more files to a destination within or between file systems.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"MV src [src...] [dst]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" src - Specifies a source file/directory name (wildcards are permitted).\r\n"
+" dst - Specifies a destination file/directory name (wildcards are permitted).\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command moves one or more files to a destination within or between\r\n"
+" file systems.\r\n"
+" 2. If the destination is an existing directory, the sources are moved\r\n"
+" into that directory. You cannot move the sources to a non-existing\r\n"
+" directory.\r\n"
+" 3. If a destination is not specified, the current directory is assumed to be\r\n"
+" the destination. If there is more than one argument on the command line,\r\n"
+" the last one is assumed to be the destination.\r\n"
+" 4. Attempting to move a read-only file/directory results in an error.\r\n"
+" Moving a directory that contains read-only files is allowed.\r\n"
+" 5. You cannot move a directory into itself or its subdirectories.\r\n"
+" 6. You cannot move a directory if the current working directory is itself or\r\n"
+" its subdirectories.\r\n"
+" 7. If an error occurs, the remaining files or directories are still be\r\n"
+" moved.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To rename a file:\r\n"
+" fs0:\> mv IsaBus.efi Bus.efi\r\n"
+" \r\n"
+" * To move a directory to the current directory:\r\n"
+" fs0:\> mkdir Test1\Temp\r\n"
+" fs0:\> mv Test1\Temp\r\n"
+" \r\n"
+" * To rename a directory:\r\n"
+" fs0:\> mv efi efi1.1\r\n"
+" \r\n"
+" * To move multiple directories at a time:\r\n"
+" fs0:\> mv Test1 Test2 Test\r\n"
+" \r\n"
+" * To attempt moving a read-only directory, which results in a failure:\r\n"
+" fs0:\Test> attrib +r Temp1\r\n"
+" DA R fs0:\Test\Temp1\r\n"
+" fs0:\Test> mv Temp1 Temp2\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+" SHELL_NOT_FOUND The source file was not able to be found.\r\n"
+" SHELL_OUT_OF_RESOURCES There was insufficient free space to move the\r\n"
+" requested file to its destination.\r\n"
+" SHELL_WRITE_PROTECTED An attempt was made to create a file on media that\r\n"
+" was write-protected.\r\n"
+
+#string STR_GET_HELP_PARSE #language en-US ""
+".TH parse 0 "Parses standard format output files."\r\n"
+".SH NAME\r\n"
+"Retrieves a value from a standard format output file.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"PARSE filename tablename column [-i <Instance>] [-s <Instance>]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" filename - Specifies a source file name.\r\n"
+" tablename - Specifies the name of the table to be parsed.\r\n"
+" column - Specifies the one-based column index to use to determine which value\r\n"
+" from a particular record to parse.\r\n"
+" -i <Instance> - Specifies an instance number to use to start parsing the ShellCommand table,\r\n"
+" and then the specified tablename. If not specified, all instances are returned.\r\n"
+" -s <Instance> - Specifies an instance number to use to start parsing the ShellCommand\r\n"
+" table. If not present, then 1 is assumed.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command enables you to parse data from a file that has been output\r\n"
+" using the -sfo parameter.\r\n"
+" 2. Since the standard formatted output has a well known means of parsing,\r\n"
+" this command is intended to provide an easy way of enabling\r\n"
+" scripts to consume retrieved data from such constructed output files, and\r\n"
+" use it in the logic of scripts written for the UEFI shell.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * The following data is contained in a temporary file (temp.txt):\r\n"
+" ShellCommand,"ls"\r\n"
+" VolumeInfo,"MikesVolume","400000000","FALSE","32000000","16000000"\r\n"
+" FileInfo,"FS0:\efi\\boot\winloader.efi","45670","45900","arsh","08:30:12","01.08.2013","00:00:00","01.08.2013","08:30:12","01.08.2013"\r\n"
+" FileInfo,"FS0:\efi\\boot\mikesfile.txt","1250","1280","a","08:30:12","01.08.2013","00:00:00","01.08.2013","08:30:12","01.08.2013"\r\n"
+" FileInfo,"FS0:\efi\\boot\\readme.txt","795","900","a","08:30:12","01.08.2013","00:00:00","01.08.2013","08:30:12","01.08.2013"\r\n"
+" \r\n"
+" * To display VolumeInfo column 2 in temp.txt:\r\n"
+" fs0:\> parse temp.txt VolumeInfo 2\r\n"
+" MikesVolume\r\n"
+" \r\n"
+" * To display FileInfo column 3 in temp.txt, starting with instance 3:\r\n"
+" fs0:\> parse temp.txt FileInfo 3 -i 3\r\n"
+" 795\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+" SHELL_NOT_FOUND The source file was not able to be found.\r\n"
+
+#string STR_GET_HELP_RESET #language en-US ""
+".TH reset 0 "Reset the system."\r\n"
+".SH NAME\r\n"
+"Resets the system.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"RESET [-w [string]]\r\n"
+"RESET [-s [string]]\r\n"
+"RESET [-c [string]]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -s - Performs a shutdown.\r\n"
+" -w - Performs a warm boot.\r\n"
+" -c - Performs a cold boot.\r\n"
+" string - Describes a reason for the reset.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command resets the system.\r\n"
+" 2. The default is to perform a cold reset unless the -w parameter is\r\n"
+" specified.\r\n"
+" 3. If a reset string is specified, it is passed into the Reset() \r\n"
+" function, and the system records the reason for the system reset.\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly \r\n"
+" formatted or its value was out of bounds.\r\n"
+
+#string STR_GET_HELP_RM #language en-US ""
+".TH rm 0 "Deletes one or more files or directories."\r\n"
+".SH NAME\r\n"
+"Deletes one or more files or directories.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"RM [-q] file/directory [file/directory ...]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -q - Specifies quiet mode. Does not prompt for a confirmation.\r\n"
+" file - Specifies a file name (wildcards are permitted).\r\n"
+" directory - Specifies a directory name (wildcards are permitted).\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command deletes one or more files or directories.\r\n"
+" 2. If the target is a directory, it deletes the directory, including all\r\n"
+" its subdirectories.\r\n"
+" 3. Redirecting a file whose parent directory (or the file\r\n"
+" itself) is being deleted is not allowed.\r\n"
+" 4. Removing a read-only file/directory results in a failure.\r\n"
+" 5. Removing a directory containing read-only file(s) results in\r\n"
+" a failure. If an error occurs, the command exits immediately and stops\r\n"
+" removing files/directories.\r\n"
+" 6. You cannot remove a directory when the current directory is itself or its\r\n"
+" subdirectory. If a file contains wildcards, you are not prompted for\r\n"
+" confirmation.\r\n"
+" 7. The root directory cannot be removed.\r\n"
+" 8. The current directory or its ancestor directories cannot be removed.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To remove multiple directories at a time:\r\n"
+" fs0:\> rm Test\Temp1 Temp2\r\n"
+" \r\n"
+" * To remove multiple directories with wildcards:\r\n"
+" fs0:\> rm Test\Temp*\r\n"
+" \r\n"
+" * To attempt removing a directory that contains a read-only file,\r\n"
+" which results in a failure:\r\n"
+" fs0:\> attrib +r Test\Temp1\readme.txt\r\n"
+" A R fs0:\Test\Temp1\readme.txt\r\n"
+" fs0:\> rm Test\Temp1\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_NOT_FOUND The source file was not able to be found.\r\n"
+" SHELL_WRITE_PROTECTED The target was write protected.\r\n"
+
+#string STR_GET_HELP_SET #language en-US ""
+".TH set 0 "Displays or modifies UEFI Shell environment variables."\r\n"
+".SH NAME\r\n"
+"Displays or modifies UEFI Shell environment variables.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"SET [-v] [sname [value]]\r\n"
+"SET [-d <sname>]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -d - Deletes the environment variable.\r\n"
+" -v - Displays or modifies a volatile variable.\r\n"
+" sname - Specifies an environment variable name.\r\n"
+" value - Specifies an environment variable value.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command is used to maintain the UEFI Shell environment variables.\r\n"
+" This command can do the following:\r\n"
+" - Display environment variables.\r\n"
+" - Create new environment variables.\r\n"
+" - Change the value of existing environment variables.\r\n"
+" - Delete environment variables.\r\n"
+" 2. This command sets an environment variable to a specified \r\n"
+" value. You can use it to create a new environment\r\n"
+" variable or to modify an existing environment variable.\r\n"
+" 3. If used without any parameters, all the environment variables\r\n"
+" are displayed.\r\n"
+" 4. If used with the -d option, the environment variable that\r\n"
+" is specified by sname is deleted.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To add an environment variable:\r\n"
+" Shell> set DiagnosticPath fs0:\efi\diag;fs1:\efi\diag\r\n"
+" \r\n"
+" * To display environment variables:\r\n"
+" Shell> set\r\n"
+" \r\n"
+" * To delete an environment variable:\r\n"
+" Shell> set -d diagnosticpath\r\n"
+" \r\n"
+" * To change an environment variable:\r\n"
+" fs0:\> set src efi\r\n"
+" fs0:\> set src efi1.1\r\n"
+" \r\n"
+" * To append an environment variable:\r\n"
+" Shell> set path %path%;fs0:\efi\Tools;fs0:\efi\boot;fs0:\\r\n"
+" \r\n"
+" * To set a volatile variable that will disappear at the next boot:\r\n"
+" Shell> set -v EFI_SOURCE c:\project\EFI1.1\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_OUT_OF_RESOURCES A request to set a variable in a non-volatile \r\n"
+" fashion could not be completed. The resulting \r\n"
+" non-volatile request has been converted into a \r\n"
+" volatile request.\r\n"
+
+#string STR_GET_HELP_DATE #language en-US ""
+".TH date 0 "Displays and sets the current date for the system."\r\n"
+".SH NAME\r\n"
+"Displays and sets the current date for the system.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"DATE [mm/dd/[yy]yy][-sfo]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -sfo - Displays information in Standard-Format Output.\r\n"
+" mm - Specifies the month of the date to be set. (1-12)\r\n"
+" dd - Specifies the day of the date to be set (1-31)\r\n"
+" yy/yyyy - Specifies the year of the date to be set. If only two digits,\r\n"
+" then enter 9x = 199x. Otherwise enter 20xx.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command displays and/or sets the current date for the system.\r\n"
+" If no parameters are used, it shows the current date. If a valid month,\r\n"
+" day, and year are specified, the system's date is updated.\r\n"
+" The following rules apply:\r\n"
+" - Except for numeric characters and /, all other characters in the\r\n"
+" argument are invalid.\r\n"
+" - The Shell reports an error if the number is in the wrong\r\n"
+" month/date/year range.\r\n"
+" - A space before or after the numeric character is not allowed. Inserting\r\n"
+" a space into the number is invalid.\r\n"
+" - Repeated zeros are allowed before the number. For example:\r\n"
+" Shell > date 0000008/000004/000097\r\n"
+" Shell > date\r\n"
+" 08/04/2097\r\n"
+" Shell >\r\n"
+" - The year range must be greater than or equal to 1998.\r\n"
+" - Two numeric characters indicate the year. Numbers below 98 are\r\n"
+" regarded as 20xx, and numbers equal to or above 98 are regarded as\r\n"
+" 19xx. 00 means 2000. For example:\r\n"
+" Shell > date 8/4/97\r\n"
+" Shell > date\r\n"
+" 08/04/2097\r\n"
+" Shell >\r\n"
+" Shell > date 8/4/98\r\n"
+" Shell > date\r\n"
+" 08/04/1998\r\n"
+" Shell >\r\n"
+" 2. The range of valid years is from 1998-2099.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display the current date in the system:\r\n"
+" fs0:\> date\r\n"
+" \r\n"
+" * To set the date with long year format:\r\n"
+" fs0:\> date 01/01/2050\r\n"
+" \r\n"
+" * To set the date with short year format:\r\n"
+" fs0:\> date 06/18/01\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_DEVICE_ERROR There was a hardware error preventing the\r\n"
+" completion of this command.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+
+#string STR_GET_HELP_TIME #language en-US ""
+".TH time 0 "Displays or sets the time for the system."\r\n"
+".SH NAME\r\n"
+"Displays or sets the current time for the system.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"TIME [hh:mm[:ss]] [-tz tz] [-d dl]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -d - Sets or displays a daylight savings time value.\r\n"
+" -tz - Specifies a time zone adjustment, measured in minutes offset from UTC. Valid values\r\n"
+" are between -1440 and 1440 or 2047. If not present or set to 2047,\r\n"
+" time is interpreted as local time.\r\n"
+" hh - Specifies a new hour (0-23) (required).\r\n"
+" mm - Specifies a new minute (0-59) (required).\r\n"
+" ss - Specifies a new second (0-59). If not specified, zero is used.\r\n"
+" dl - Specifies a daylight saving time value to set.\r\n"
+" 0 : Time is not affected.\r\n"
+" 1 : Time is affected, and has not been adjusted for daylight\r\n"
+" savings.\r\n"
+" 3 : Time is affected, and has been adjusted for daylight savings.\r\n"
+" All other values are invalid. If no value follows -d, the\r\n"
+" current daylight savings time is displayed.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command displays or sets the current time for the system.\r\n"
+" If no parameters are used, it shows the current time. If valid hours, \r\n"
+" minutes, and seconds are provided, the system time is\r\n"
+" updated. Note the following rules:\r\n"
+" - Except for numeric characters and the : character, all other\r\n"
+" characters in the argument are invalid.\r\n"
+" - The Shell reports an error if the number is in the wrong \r\n"
+" hour/minute/second range.\r\n"
+" - Spaces before or after the numeric character and spaces inserted into\r\n"
+" the number are not allowed.\r\n"
+" - Repeated zeros are allowed before the number. For example:\r\n"
+" Shell> time 00000017:000004:0000\r\n"
+" Shell> time\r\n"
+" 17:04:00 (UTC+08:00)\r\n"
+" 2. The seconds parameter is optional. If none is specified, it is\r\n"
+" set to zero.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display current system time:\r\n"
+" fs0:\> time\r\n"
+" \r\n"
+" * To set the system time:\r\n"
+" fs0:\> time 9:51:30\r\n"
+" \r\n"
+" * To display the system time, including daylight savings time:\r\n"
+" fs0:\> time -d\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_DEVICE_ERROR There was a hardware error preventing the\r\n"
+" completion of this command\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+
+#string STR_GET_HELP_TIMEZONE #language en-US ""
+".TH timezone 0 "Displays or sets time zone information."\r\n"
+".SH NAME\r\n"
+"Displays or sets time zone information.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"TIMEZONE [-s hh:mm | -l] [-b] [-f]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -s - Sets the time zone associated with hh:mm offset from UTC.\r\n"
+" -l - Displays a list of all time zones.\r\n"
+" -b - Displays one screen at a time.\r\n"
+" -f - Displays full information for the specified time zone.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command displays and sets the current time zone for the system.\r\n"
+" 2. If no parameters are used, it shows the current time zone.\r\n"
+" 3. If a valid hh:mm parameter is provided, the time zone\r\n"
+" information is updated.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display all available time zones:\r\n"
+" Shell> timezone -l\r\n"
+" \r\n"
+" * To set the time zone:\r\n"
+" Shell> timezone -s -7:00\r\n"
+" \r\n"
+" * To display detailed information for the current time zone:\r\n"
+" Shell> timezone -f\r\n"
+
+#string STR_GET_HELP_LS #language en-US ""
+".TH ls 0 "Lists the contents of a directory or file information."\r\n"
+".SH NAME\r\n"
+"Lists the contents of a directory or file information.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"LS [-r] [-a[attrib]][-sfo][file]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -r - Displays recursively (including subdirectories).\r\n"
+" -a - Displays files with a specified attribute. If \r\n"
+" attribute is not specified, all files are listed. If -a is not\r\n"
+" specified, all non-system and non-hidden files are listed.\r\n"
+" -sfo - Displays information in Standard-Format Output.\r\n"
+" attrib - Specifies a file attribute list value:\r\n"
+" a - Archive\r\n"
+" s - System\r\n"
+" h - Hidden\r\n"
+" r - Read-only\r\n"
+" d - Directory\r\n"
+" file - Specifies a name of a file or directory (wildcards are permitted).\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command lists directory contents or file information. If no file\r\n"
+" name or directory name is specified, the current working directory\r\n"
+" is assumed.\r\n"
+" 2. The contents of a directory are listed if all of the following are true:\r\n"
+" - If option -r is not specified.\r\n"
+" - If no wildcard characters are specified in the file parameter.\r\n"
+" - If the file specified represents an existing directory.\r\n"
+" 3. In all other cases, the command functions as follows:\r\n"
+" - All files/directories that match the specified name are displayed.\r\n"
+" - The -r flag determines whether a recursive search is performed.\r\n"
+" - The option flag -a[attrib] only displays those\r\n"
+" files with the attributes that are specified.\r\n"
+" - If more than one attribute is specified, only the files that have all\r\n"
+" those attributes are listed.\r\n"
+" - If -a is followed by nothing, then all files/directories are\r\n"
+" displayed, regardless of their attributes.\r\n"
+" - If -a itself is not specified, then all files except system and\r\n"
+" hidden files are displayed.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To hide files by adding the hidden or system attribute to them:\r\n"
+" fs0:\> attrib +s +h *.efi\r\n"
+" \r\n"
+" * To display all, except the files/directories with 'h' or 's' attribute:\r\n"
+" fs0:\> ls\r\n"
+" \r\n"
+" * To display files with all attributes in the current directory:\r\n"
+" fs0:\> ls -a\r\n"
+" \r\n"
+" * To display files with read-only attributes in the current directory:\r\n"
+" fs0:\> ls -ar\r\n"
+" \r\n"
+" * To display the files with attribute of 's':\r\n"
+" fs0:\> ls -as isabus.efi\r\n"
+" \r\n"
+" * To display all in fs0:\efi directory recursively:\r\n"
+" fs0:\> ls -r -a efi\r\n"
+" \r\n"
+" * To display files with a specified type in the current directory: \r\n"
+" recursively:\r\n"
+" fs0:\> ls -r -a *.efi -b\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_NOT_FOUND The requested file or directory was not found.\r\n"
+
+#string STR_GET_HELP_LOAD #language en-US ""
+".TH load 0 "Loads a UEFI driver into memory."\r\n"
+".SH NAME\r\n"
+"Loads a UEFI driver into memory.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"LOAD [-nc] file [file...]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -nc - Loads the driver, but does not connect the driver.\r\n"
+" File - Specifies a file that contains the image of the UEFI driver (wildcards are\r\n"
+" permitted).\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command loads a driver into memory. It can load multiple files at\r\n"
+" one time. The file name supports wildcards.\r\n"
+" 2. If the -nc flag is not specified, this command attempts to connect the\r\n"
+" driver to a proper device. It might also cause previously loaded drivers\r\n"
+" to be connected to their corresponding devices.\r\n"
+" 3. Use the 'UNLOAD' command to unload a driver.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To load a driver:\r\n"
+" fs0:\> load Isabus.efi\r\n"
+" \r\n"
+" * To load multiple drivers:\r\n"
+" fs0:\> load Isabus.efi IsaSerial.efi\r\n"
+" \r\n"
+" * To load multiple drivers using file name wildcards:\r\n"
+" fs0:\> load Isa*.efi\r\n"
+" \r\n"
+" * To load a driver without connecting it to a device:\r\n"
+" fs0:\> load -nc IsaBus.efi\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_NOT_FOUND The requested file was not found.\r\n"
+
+#string STR_GET_HELP_VOL #language en-US ""
+".TH vol 0 "Displays or modifies information about a disk volume."\r\n"
+".SH NAME\r\n"
+"Displays or modifies information about a disk volume.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"VOL [fs] [-n <VolumeLabel>]\r\n"
+"VOL [fs] [-d]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -n - Displays or modifies a new volume label.\r\n"
+" -d - Displays or modifies an empty volume label.\r\n"
+" fs - Specifies the name of the file system.\r\n"
+" VolumeLabel - Specifies a volume label.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. The following characters cannot be used in a volume label:\r\n"
+" % ^ * + = [ ] | : ; \" < > ? / . \r\n"
+" 2. No spaces are allowed in a volume label.\r\n"
+" 3. This command displays the volume information for the specified file\r\n"
+" system. If fs is not specified, the current file system is used.\r\n"
+" 4. If -n is specified, the volume label for fs is set to\r\n"
+" VolumeLabel.\r\n"
+" 5. The maximum length for volume label is 11 characters.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display the volume of the current file system:\r\n"
+" fs0:\> vol\r\n"
+" \r\n"
+" * To change the label of fs0:\r\n"
+" Shell> vol fs0 -n help_test\r\n"
+" \r\n"
+" * To delete the volume label of fs0:\r\n"
+" fs0:\> vol fs0 -d\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_NOT_FOUND The target file-system was not found.\r\n"
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Vol.c b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Vol.c
new file mode 100644
index 0000000000..a6f0296d76
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel2CommandsLib/Vol.c
@@ -0,0 +1,314 @@
+/** @file
+ Main file for vol shell level 2 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2011 - 2015, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel2CommandsLib.h"
+#include <Guid/FileSystemInfo.h>
+#include <Guid/FileSystemVolumeLabelInfo.h>
+
+/**
+ Print the info or change the volume info.
+
+ @param[in] Path String with starting path.
+ @param[in] Delete TRUE to delete the volume label. FALSE otherwise.
+ @param[in] Name New name to set to the volume label.
+
+ @retval SHELL_SUCCESS The operation was sucessful.
+**/
+SHELL_STATUS
+EFIAPI
+HandleVol(
+ IN CONST CHAR16 *Path,
+ IN CONST BOOLEAN Delete,
+ IN CONST CHAR16 *Name OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ SHELL_STATUS ShellStatus;
+ EFI_FILE_SYSTEM_INFO *SysInfo;
+ UINTN SysInfoSize;
+ SHELL_FILE_HANDLE ShellFileHandle;
+ EFI_FILE_PROTOCOL *EfiFpHandle;
+ UINTN Size1;
+ UINTN Size2;
+
+ ShellStatus = SHELL_SUCCESS;
+
+ if (
+ Name != NULL && (
+ StrStr(Name, L"%") != NULL ||
+ StrStr(Name, L"^") != NULL ||
+ StrStr(Name, L"*") != NULL ||
+ StrStr(Name, L"+") != NULL ||
+ StrStr(Name, L"=") != NULL ||
+ StrStr(Name, L"[") != NULL ||
+ StrStr(Name, L"]") != NULL ||
+ StrStr(Name, L"|") != NULL ||
+ StrStr(Name, L":") != NULL ||
+ StrStr(Name, L";") != NULL ||
+ StrStr(Name, L"\"") != NULL ||
+ StrStr(Name, L"<") != NULL ||
+ StrStr(Name, L">") != NULL ||
+ StrStr(Name, L"?") != NULL ||
+ StrStr(Name, L"/") != NULL ||
+ StrStr(Name, L" ") != NULL )
+ ){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel2HiiHandle, L"vol", Name);
+ return (SHELL_INVALID_PARAMETER);
+ }
+
+ Status = gEfiShellProtocol->OpenFileByName(
+ Path,
+ &ShellFileHandle,
+ Name != NULL?EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE:EFI_FILE_MODE_READ);
+
+ if (EFI_ERROR(Status) || ShellFileHandle == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel2HiiHandle, L"vol", Path);
+ return (SHELL_ACCESS_DENIED);
+ }
+
+ //
+ // Get the Volume Info from ShellFileHandle
+ //
+ SysInfo = NULL;
+ SysInfoSize = 0;
+ EfiFpHandle = ConvertShellHandleToEfiFileProtocol(ShellFileHandle);
+ Status = EfiFpHandle->GetInfo(
+ EfiFpHandle,
+ &gEfiFileSystemInfoGuid,
+ &SysInfoSize,
+ SysInfo);
+
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ SysInfo = AllocateZeroPool(SysInfoSize);
+ Status = EfiFpHandle->GetInfo(
+ EfiFpHandle,
+ &gEfiFileSystemInfoGuid,
+ &SysInfoSize,
+ SysInfo);
+ }
+
+ ASSERT(SysInfo != NULL);
+
+ if (Delete) {
+ *((CHAR16 *) SysInfo->VolumeLabel) = CHAR_NULL;
+ SysInfo->Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize(SysInfo->VolumeLabel);
+ Status = EfiFpHandle->SetInfo(
+ EfiFpHandle,
+ &gEfiFileSystemInfoGuid,
+ (UINTN)SysInfo->Size,
+ SysInfo);
+ } else if (Name != NULL) {
+ Size1 = StrSize(Name);
+ Size2 = StrSize(SysInfo->VolumeLabel);
+ if (Size1 > Size2) {
+ SysInfo = ReallocatePool((UINTN)SysInfo->Size, (UINTN)SysInfo->Size + Size1 - Size2, SysInfo);
+ if (SysInfo == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellLevel2HiiHandle, L"vol");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ }
+ }
+ if (SysInfo != NULL) {
+ StrCpyS ( (CHAR16 *) SysInfo->VolumeLabel,
+ (Size1>Size2? Size1/sizeof(CHAR16) : Size2/sizeof(CHAR16)),
+ Name
+ );
+ SysInfo->Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + Size1;
+ Status = EfiFpHandle->SetInfo(
+ EfiFpHandle,
+ &gEfiFileSystemInfoGuid,
+ (UINTN)SysInfo->Size,
+ SysInfo);
+ }
+ }
+
+ FreePool(SysInfo);
+
+ if (Delete || Name != NULL) {
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_AD), gShellLevel2HiiHandle, L"vol", Path);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ }
+ }
+
+ SysInfoSize = 0;
+ SysInfo = NULL;
+
+ Status = EfiFpHandle->GetInfo(
+ EfiFpHandle,
+ &gEfiFileSystemInfoGuid,
+ &SysInfoSize,
+ SysInfo);
+
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ SysInfo = AllocateZeroPool(SysInfoSize);
+ Status = EfiFpHandle->GetInfo(
+ EfiFpHandle,
+ &gEfiFileSystemInfoGuid,
+ &SysInfoSize,
+ SysInfo);
+ }
+
+ gEfiShellProtocol->CloseFile(ShellFileHandle);
+
+ ASSERT(SysInfo != NULL);
+
+ if (SysInfo != NULL) {
+ //
+ // print VolumeInfo table
+ //
+ ShellPrintHiiEx (
+ 0,
+ gST->ConOut->Mode->CursorRow,
+ NULL,
+ STRING_TOKEN (STR_VOL_VOLINFO),
+ gShellLevel2HiiHandle,
+ SysInfo->VolumeLabel,
+ SysInfo->ReadOnly?L"r":L"rw",
+ SysInfo->VolumeSize,
+ SysInfo->FreeSpace,
+ SysInfo->BlockSize
+ );
+ SHELL_FREE_NON_NULL(SysInfo);
+ }
+
+ return (ShellStatus);
+}
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-d", TypeFlag},
+ {L"-n", TypeValue},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'Vol' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunVol (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ CONST CHAR16 *PathName;
+ CONST CHAR16 *CurDir;
+ BOOLEAN DeleteMode;
+ CHAR16 *FullPath;
+ CHAR16 *TempSpot;
+ UINTN Length;
+ CONST CHAR16 *NewName;
+
+ Length = 0;
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ PathName = NULL;
+ CurDir = NULL;
+ FullPath = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Fix local copies of the protocol pointers
+ //
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel2HiiHandle, L"vol", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ }
+
+ if (ShellCommandLineGetCount(Package) > 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel2HiiHandle, L"vol");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ PathName = ShellCommandLineGetRawValue(Package, 1);
+ if (PathName == NULL) {
+ CurDir = gEfiShellProtocol->GetCurDir(NULL);
+ if (CurDir == NULL) {
+ ShellStatus = SHELL_NOT_FOUND;
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_CWD), gShellLevel2HiiHandle, L"vol");
+ } else {
+ PathName = CurDir;
+ }
+ }
+ if (PathName != NULL) {
+ TempSpot = StrStr(PathName, L":");
+ if (TempSpot != NULL) {
+ *TempSpot = CHAR_NULL;
+ }
+ TempSpot = StrStr(PathName, L"\\");
+ if (TempSpot != NULL) {
+ *TempSpot = CHAR_NULL;
+ }
+ StrnCatGrow(&FullPath, &Length, PathName, 0);
+ StrnCatGrow(&FullPath, &Length, L":\\", 0);
+ DeleteMode = ShellCommandLineGetFlag(Package, L"-d");
+ NewName = ShellCommandLineGetValue(Package, L"-n");
+ if (DeleteMode && ShellCommandLineGetFlag(Package, L"-n")) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CONFLICT), gShellLevel2HiiHandle, L"vol", L"-d", L"-n");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetFlag(Package, L"-n") && NewName == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_NO_VALUE), gShellLevel2HiiHandle, L"vol", L"-n");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (NewName != NULL && StrLen(NewName) > 11) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM_VAL), gShellLevel2HiiHandle, L"vol", NewName, L"-n");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellStatus == SHELL_SUCCESS) {
+ ShellStatus = HandleVol(
+ FullPath,
+ DeleteMode,
+ NewName
+ );
+ }
+ }
+ }
+ }
+
+ SHELL_FREE_NON_NULL(FullPath);
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+
+ return (ShellStatus);
+}
diff --git a/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Alias.c b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Alias.c
new file mode 100644
index 0000000000..bcd14c8541
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Alias.c
@@ -0,0 +1,195 @@
+/** @file
+ Main file for Alias shell level 3 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel3CommandsLib.h"
+
+#include <Library/ShellLib.h>
+
+/**
+ Print out each alias registered with the Shell.
+
+ @retval STATUS_SUCCESS the printout was sucessful
+ @return any return code from GetNextVariableName except EFI_NOT_FOUND
+**/
+SHELL_STATUS
+EFIAPI
+PrintAllShellAlias(
+ VOID
+ )
+{
+ CONST CHAR16 *ConstAllAliasList;
+ CHAR16 *Alias;
+ CONST CHAR16 *Command;
+ CHAR16 *Walker;
+ BOOLEAN Volatile;
+
+ Volatile = FALSE;
+
+ ConstAllAliasList = gEfiShellProtocol->GetAlias(NULL, NULL);
+ if (ConstAllAliasList == NULL) {
+ return (SHELL_SUCCESS);
+ }
+ Alias = AllocateZeroPool(StrSize(ConstAllAliasList));
+ if (Alias == NULL) {
+ return (SHELL_OUT_OF_RESOURCES);
+ }
+ Walker = (CHAR16*)ConstAllAliasList;
+
+ do {
+ CopyMem(Alias, Walker, StrSize(Walker));
+ Walker = StrStr(Alias, L";");
+ if (Walker != NULL) {
+ Walker[0] = CHAR_NULL;
+ Walker = Walker + 1;
+ }
+ Command = gEfiShellProtocol->GetAlias(Alias, &Volatile);
+ if (ShellCommandIsOnAliasList(Alias)) {
+ Volatile = FALSE;
+ }
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_ALIAS_OUTPUT), gShellLevel3HiiHandle, !Volatile?L' ':L'*', Alias, Command);
+ } while (Walker != NULL && Walker[0] != CHAR_NULL);
+
+ FreePool(Alias);
+
+ return (SHELL_SUCCESS);
+}
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-v", TypeFlag},
+ {L"-d", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'alias' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunAlias (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ CONST CHAR16 *Param1;
+ CONST CHAR16 *Param2;
+ CHAR16 *CleanParam2;
+ CONST CHAR16 *ConstAliasVal;
+ BOOLEAN Volatile;
+
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ CleanParam2 = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"alias", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ Param1 = ShellCommandLineGetRawValue(Package, 1);
+ Param2 = ShellCommandLineGetRawValue(Package, 2);
+
+ if (Param2 != NULL) {
+ CleanParam2 = AllocateCopyPool (StrSize(Param2), Param2);
+ if (CleanParam2 == NULL) {
+ return SHELL_OUT_OF_RESOURCES;
+ }
+
+ if (CleanParam2[0] == L'\"' && CleanParam2[StrLen(CleanParam2)-1] == L'\"') {
+ CleanParam2[StrLen(CleanParam2)-1] = L'\0';
+ CopyMem (CleanParam2, CleanParam2 + 1, StrSize(CleanParam2) - sizeof(CleanParam2[0]));
+ }
+ }
+
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ }
+ if (ShellCommandLineGetCount(Package) == 1) {
+ //
+ // print out alias'
+ //
+ Status = PrintAllShellAlias();
+ } else if (ShellCommandLineGetFlag(Package, L"-d")) {
+ //
+ // delete an alias
+ //
+ Status = gEfiShellProtocol->SetAlias(Param1, NULL, TRUE, FALSE);
+ } else if (ShellCommandLineGetCount(Package) == 3) {
+ //
+ // must be adding an alias
+ //
+ Status = gEfiShellProtocol->SetAlias(CleanParam2, Param1, FALSE, ShellCommandLineGetFlag(Package, L"-v"));
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_ACCESS_DENIED) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellLevel3HiiHandle, L"alias");
+ ShellStatus = SHELL_ACCESS_DENIED;
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_UK), gShellLevel3HiiHandle, L"alias", Status);
+ ShellStatus = SHELL_DEVICE_ERROR;
+ }
+ }
+ } else if (ShellCommandLineGetCount(Package) == 2) {
+ //
+ // print out a single alias
+ //
+ ConstAliasVal = gEfiShellProtocol->GetAlias(Param1, &Volatile);
+ if (ConstAliasVal == NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel3HiiHandle, L"alias", Param1);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ if (ShellCommandIsOnAliasList(Param1)) {
+ Volatile = FALSE;
+ }
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_ALIAS_OUTPUT), gShellLevel3HiiHandle, !Volatile?L' ':L'*', Param1, ConstAliasVal);
+ }
+ } else {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle, L"alias");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ SHELL_FREE_NON_NULL (CleanParam2);
+ return (ShellStatus);
+}
diff --git a/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Cls.c b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Cls.c
new file mode 100644
index 0000000000..61b9ef854e
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Cls.c
@@ -0,0 +1,133 @@
+/** @file
+ Main file for attrib shell level 2 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel3CommandsLib.h"
+
+/**
+ Function for 'cls' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunCls (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ UINTN Background;
+ UINTN ForeColor;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ CONST CHAR16 *Param1;
+
+ //
+ // Initialize variables
+ //
+ ShellStatus = SHELL_SUCCESS;
+ ProblemParam = NULL;
+ Background = 0;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"cls", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ } else {
+ //
+ // If there are 0 value parameters, clear sceen
+ //
+ Param1 = ShellCommandLineGetRawValue(Package, 1);
+ if (Param1 == NULL) {
+ //
+ // clear screen
+ //
+ gST->ConOut->ClearScreen (gST->ConOut);
+ } else if (ShellCommandLineGetCount(Package) > 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle, L"cls");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ if (ShellStrToUintn(Param1) > 7 || StrLen(Param1) > 1 || !ShellIsDecimalDigitCharacter(*Param1)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel3HiiHandle, L"cls", Param1);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ switch (ShellStrToUintn(Param1)) {
+ case 0:
+ Background = EFI_BACKGROUND_BLACK;
+ break;
+ case 1:
+ Background = EFI_BACKGROUND_BLUE;
+ break;
+ case 2:
+ Background = EFI_BACKGROUND_GREEN;
+ break;
+ case 3:
+ Background = EFI_BACKGROUND_CYAN;
+ break;
+ case 4:
+ Background = EFI_BACKGROUND_RED;
+ break;
+ case 5:
+ Background = EFI_BACKGROUND_MAGENTA;
+ break;
+ case 6:
+ Background = EFI_BACKGROUND_BROWN;
+ break;
+ case 7:
+ Background = EFI_BACKGROUND_LIGHTGRAY;
+ break;
+ }
+ ForeColor = (~ShellStrToUintn(Param1)) & 0xF;
+ Status = gST->ConOut->SetAttribute (gST->ConOut, (ForeColor | Background) & 0x7F );
+ ASSERT_EFI_ERROR(Status);
+ Status = gST->ConOut->ClearScreen (gST->ConOut);
+ ASSERT_EFI_ERROR(Status);
+ }
+ }
+ }
+ }
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+
+ //
+ // return the status
+ //
+ return (ShellStatus);
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Echo.c b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Echo.c
new file mode 100644
index 0000000000..c98ee8500b
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Echo.c
@@ -0,0 +1,102 @@
+/** @file
+ Main file for Echo shell level 3 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel3CommandsLib.h"
+
+#include <Library/ShellLib.h>
+
+/**
+ Function for 'echo' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunEcho (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ CHAR16 *RawCmdLine;
+ SHELL_STATUS Status;
+ UINTN Size;
+ CHAR16 *Walker;
+ CHAR16 *TempParameter;
+ BOOLEAN OnFlag;
+ BOOLEAN OffFlag;
+ UINTN Count;
+
+ RawCmdLine = ShellGetRawCmdLine ();
+ if (RawCmdLine == NULL) {
+ return SHELL_OUT_OF_RESOURCES;
+ }
+
+ OnFlag = FALSE;
+ OffFlag = FALSE;
+
+ Size = StrSize (RawCmdLine);
+ TempParameter = AllocateZeroPool(Size);
+ if (TempParameter == NULL) {
+ Status = SHELL_OUT_OF_RESOURCES;
+ goto Done;
+ }
+
+ for ( Count = 0
+ , Walker = RawCmdLine
+ ; Walker != NULL && *Walker != CHAR_NULL
+ ; Count++
+ ) {
+ if (EFI_ERROR (ShellGetNextParameter (&Walker, TempParameter, Size, FALSE))) {
+ break;
+ }
+
+ if (Count == 1) {
+ if (gUnicodeCollation->StriColl(gUnicodeCollation, TempParameter, L"-on") == 0 ) {
+ OnFlag = TRUE;
+ }
+ if (gUnicodeCollation->StriColl(gUnicodeCollation, TempParameter, L"-off") == 0 ) {
+ OffFlag = TRUE;
+ }
+ }
+ }
+
+ if (OnFlag || OffFlag) {
+ if (Count != 2) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_ECHO_INVALID_PARAM), gShellLevel3HiiHandle, L"echo", L"-on/-off");
+ Status = SHELL_INVALID_PARAMETER;
+ goto Done;
+ }
+
+ ShellCommandSetEchoState(OnFlag);
+ Status = SHELL_SUCCESS;
+ goto Done;
+ }
+
+ Walker = RawCmdLine + StrLen (L"echo");
+ if (*Walker != CHAR_NULL) {
+ Walker++;
+ ShellPrintEx (-1, -1, L"%s\r\n", Walker);
+ }
+
+ Status = SHELL_SUCCESS;
+
+Done:
+ SHELL_FREE_NON_NULL (TempParameter);
+ SHELL_FREE_NON_NULL (RawCmdLine);
+ return Status;
+
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/GetMtc.c b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/GetMtc.c
new file mode 100644
index 0000000000..21c5bc81eb
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/GetMtc.c
@@ -0,0 +1,97 @@
+/** @file
+ Main file for GetMtc shell level 3 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel3CommandsLib.h"
+
+#include <Library/ShellLib.h>
+
+/**
+ Function for 'getmtc' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunGetMtc (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ UINT64 Mtc;
+
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (EmptyParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"getmtc", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ } else if (ShellCommandLineGetRawValue(Package, 1) != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle, L"getmtc");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // Get the monotonic counter count
+ //
+ Status = gBS->GetNextMonotonicCount(&Mtc);
+ if (Status == EFI_DEVICE_ERROR) {
+ ShellStatus = SHELL_DEVICE_ERROR;
+ } else if (Status == EFI_SECURITY_VIOLATION) {
+ ShellStatus = SHELL_SECURITY_VIOLATION;
+ } else if (EFI_ERROR(Status)) {
+ ShellStatus = SHELL_DEVICE_ERROR;
+ }
+
+ //
+ // print it...
+ //
+ if (ShellStatus == SHELL_SUCCESS) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GET_MTC_OUTPUT), gShellLevel3HiiHandle, Mtc);
+ }
+ }
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ return (ShellStatus);
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Help.c b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Help.c
new file mode 100644
index 0000000000..619cdd38a7
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Help.c
@@ -0,0 +1,478 @@
+/** @file
+ Main file for Help shell level 3 function.
+
+ Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved. <BR>
+ Copyright (c) 2014, ARM Limited. All rights reserved. <BR>
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel3CommandsLib.h"
+
+#include <Library/ShellLib.h>
+#include <Library/HandleParsingLib.h>
+
+#include <Protocol/EfiShellDynamicCommand.h>
+
+/**
+ function to insert string items into a list in the correct alphabetical place
+
+ the resultant list is a double NULL terminated list of NULL terminated strings.
+
+ upon successful return the memory must be caller freed (unless passed back in
+ via a loop where it will get reallocated).
+
+ @param[in,out] DestList double pointer to the list. may be NULL.
+ @param[in,out] DestSize pointer to the size of list. may be 0, if DestList is NULL.
+ @param[in] Item the item to insert.
+
+ @retval EFI_SUCCESS the operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+LexicalInsertIntoList(
+ IN OUT CHAR16 **DestList,
+ IN OUT UINTN *DestSize,
+ IN CONST CHAR16 *Item
+ )
+{
+ CHAR16 *NewList;
+ INTN LexicalMatchValue;
+ CHAR16 *LexicalSpot;
+ UINTN SizeOfAddedNameInBytes;
+
+ //
+ // If there are none, then just return with success
+ //
+ if (Item == NULL || *Item == CHAR_NULL || StrLen(Item)==0) {
+ return (EFI_SUCCESS);
+ }
+
+ NewList = *DestList;
+
+ SizeOfAddedNameInBytes = StrSize(Item);
+ NewList = ReallocatePool(*DestSize, (*DestSize) + SizeOfAddedNameInBytes, NewList);
+ (*DestSize) = (*DestSize) + SizeOfAddedNameInBytes;
+
+ //
+ // Find the correct spot in the list
+ //
+ for (LexicalSpot = NewList
+ ; LexicalSpot != NULL && LexicalSpot < NewList + (*DestSize)
+ ; LexicalSpot += StrLen(LexicalSpot) + 1
+ ) {
+ //
+ // Get Lexical Comparison Value between PrevCommand and Command list entry
+ //
+ LexicalMatchValue = gUnicodeCollation->StriColl (
+ gUnicodeCollation,
+ (CHAR16 *)LexicalSpot,
+ (CHAR16 *)Item
+ );
+ //
+ // The new item goes before this one.
+ //
+ if (LexicalMatchValue > 0 || StrLen(LexicalSpot) == 0) {
+ if (StrLen(LexicalSpot) != 0) {
+ //
+ // Move this and all other items out of the way
+ //
+ CopyMem(
+ LexicalSpot + (SizeOfAddedNameInBytes/sizeof(CHAR16)),
+ LexicalSpot,
+ (*DestSize) - SizeOfAddedNameInBytes - ((LexicalSpot - NewList) * sizeof(CHAR16))
+ );
+ }
+
+ //
+ // Stick this one in place
+ //
+ StrCpyS(LexicalSpot, SizeOfAddedNameInBytes/sizeof(CHAR16), Item);
+ break;
+ }
+ }
+
+ *DestList = NewList;
+ return (EFI_SUCCESS);
+}
+
+/**
+ function to add each command name from the linked list to the string list.
+
+ the resultant list is a double NULL terminated list of NULL terminated strings.
+
+ @param[in,out] DestList double pointer to the list. may be NULL.
+ @param[in,out] DestSize pointer to the size of list. may be 0, if DestList is NULL.
+ @param[in] SourceList the double linked list of commands.
+
+ @retval EFI_SUCCESS the operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+CopyListOfCommandNames(
+ IN OUT CHAR16 **DestList,
+ IN OUT UINTN *DestSize,
+ IN CONST COMMAND_LIST *SourceList
+ )
+{
+ CONST COMMAND_LIST *Node;
+
+ for ( Node = (COMMAND_LIST*)GetFirstNode(&SourceList->Link)
+ ; SourceList != NULL && !IsListEmpty(&SourceList->Link) && !IsNull(&SourceList->Link, &Node->Link)
+ ; Node = (COMMAND_LIST*)GetNextNode(&SourceList->Link, &Node->Link)
+ ) {
+ LexicalInsertIntoList(DestList, DestSize, Node->CommandString);
+ }
+ return (EFI_SUCCESS);
+}
+
+/**
+ function to add each dynamic command name to the string list.
+
+ the resultant list is a double NULL terminated list of NULL terminated strings.
+
+ @param[in,out] DestList double pointer to the list. may be NULL.
+ @param[in,out] DestSize pointer to the size of list. may be 0, if DestList is NULL.
+
+ @retval EFI_SUCCESS the operation was successful.
+ @return an error from HandleProtocol
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+CopyListOfCommandNamesWithDynamic(
+ IN OUT CHAR16** DestList,
+ IN OUT UINTN *DestSize
+ )
+{
+ EFI_HANDLE *CommandHandleList;
+ CONST EFI_HANDLE *NextCommand;
+ EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *DynamicCommand;
+ EFI_STATUS Status;
+
+ CommandHandleList = GetHandleListByProtocol(&gEfiShellDynamicCommandProtocolGuid);
+
+ //
+ // If there are none, then just return with success
+ //
+ if (CommandHandleList == NULL) {
+ return (EFI_SUCCESS);
+ }
+
+ Status = EFI_SUCCESS;
+
+ //
+ // Append those to the list.
+ //
+ for (NextCommand = CommandHandleList ; *NextCommand != NULL && !EFI_ERROR(Status) ; NextCommand++) {
+ Status = gBS->HandleProtocol(
+ *NextCommand,
+ &gEfiShellDynamicCommandProtocolGuid,
+ (VOID **)&DynamicCommand
+ );
+
+ if (EFI_ERROR(Status)) {
+ continue;
+ }
+
+ Status = LexicalInsertIntoList(DestList, DestSize, DynamicCommand->CommandName);
+ }
+
+ SHELL_FREE_NON_NULL(CommandHandleList);
+ return (Status);
+}
+
+
+/**
+ Attempt to print help from a dynamically added command.
+
+ @param[in] CommandToGetHelpOn The unicode name of the command that help is
+ requested on.
+ @param[in] SectionToGetHelpOn Pointer to the section specifier(s).
+ @param[in] PrintCommandText Print the command followed by the help content
+ or just help.
+
+ @retval EFI_SUCCESS The help was displayed
+ @retval EFI_NOT_FOUND The command name could not be found
+ @retval EFI_DEVICE_ERROR The help data format was incorrect.
+**/
+EFI_STATUS
+EFIAPI
+PrintDynamicCommandHelp(
+ IN CONST CHAR16 *CommandToGetHelpOn,
+ IN CONST CHAR16 *SectionToGetHelpOn,
+ IN BOOLEAN PrintCommandText
+ )
+{
+ EFI_STATUS Status;
+ BOOLEAN Found;
+ EFI_HANDLE *CommandHandleList;
+ EFI_HANDLE *NextCommand;
+ EFI_SHELL_DYNAMIC_COMMAND_PROTOCOL *DynamicCommand;
+
+ Status = EFI_NOT_FOUND;
+ Found = FALSE;
+ CommandHandleList = NULL;
+
+ CommandHandleList = GetHandleListByProtocol(&gEfiShellDynamicCommandProtocolGuid);
+
+ if (CommandHandleList == NULL) {
+ //
+ // not found or out of resources
+ //
+ return Status;
+ }
+
+ for (NextCommand = CommandHandleList; *NextCommand != NULL; NextCommand++) {
+ Status = gBS->HandleProtocol(
+ *NextCommand,
+ &gEfiShellDynamicCommandProtocolGuid,
+ (VOID **)&DynamicCommand
+ );
+
+ if (EFI_ERROR(Status)) {
+ continue;
+ }
+
+ //
+ // Check execution break flag when printing multiple command help information.
+ //
+ if (ShellGetExecutionBreakFlag ()) {
+ break;
+ }
+
+ if ((gUnicodeCollation->MetaiMatch (gUnicodeCollation, (CHAR16 *)DynamicCommand->CommandName, (CHAR16*)CommandToGetHelpOn)) ||
+ (gEfiShellProtocol->GetAlias (CommandToGetHelpOn, NULL) != NULL && (gUnicodeCollation->MetaiMatch (gUnicodeCollation, (CHAR16 *)DynamicCommand->CommandName, (CHAR16*)(gEfiShellProtocol->GetAlias(CommandToGetHelpOn, NULL)))))) {
+ // Print as Shell Help if in ManPage format.
+ Status = ShellPrintHelp (DynamicCommand->CommandName, SectionToGetHelpOn,
+ PrintCommandText);
+ if (Status == EFI_DEVICE_ERROR) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_HELP_INV),
+ gShellLevel3HiiHandle, DynamicCommand->CommandName);
+ } else if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_HELP_NF),
+ gShellLevel3HiiHandle, DynamicCommand->CommandName);
+ } else {
+ Found = TRUE;
+ }
+ }
+ }
+
+ SHELL_FREE_NON_NULL(CommandHandleList);
+
+ return (Found ? EFI_SUCCESS : Status);
+
+}
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-usage", TypeFlag},
+ {L"-section", TypeMaxValue},
+ {L"-verbose", TypeFlag},
+ {L"-v", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'help' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunHelp (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ CHAR16 *SortedCommandList;
+ CONST CHAR16 *CurrentCommand;
+ CHAR16 *CommandToGetHelpOn;
+ CHAR16 *SectionToGetHelpOn;
+ CHAR16 *HiiString;
+ BOOLEAN Found;
+ BOOLEAN PrintCommandText;
+ UINTN SortedCommandListSize;
+
+ PrintCommandText = TRUE;
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ CommandToGetHelpOn = NULL;
+ SectionToGetHelpOn = NULL;
+ SortedCommandList = NULL;
+ Found = FALSE;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"help", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // Check for conflicting parameters.
+ //
+ if (ShellCommandLineGetFlag(Package, L"-usage")
+ &&ShellCommandLineGetFlag(Package, L"-section")
+ &&(ShellCommandLineGetFlag(Package, L"-verbose") || ShellCommandLineGetFlag(Package, L"-v"))
+ ){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellLevel3HiiHandle, L"help");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetRawValue(Package, 2) != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle, L"help");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // Get the command name we are getting help on
+ //
+ ASSERT(CommandToGetHelpOn == NULL);
+ StrnCatGrow(&CommandToGetHelpOn, NULL, ShellCommandLineGetRawValue(Package, 1), 0);
+ if (CommandToGetHelpOn == NULL && ShellCommandLineGetFlag(Package, L"-?")) {
+ //
+ // If we dont have a command and we got a simple -?
+ // we are looking for help on help command.
+ //
+ StrnCatGrow(&CommandToGetHelpOn, NULL, L"help", 0);
+ }
+
+ if (CommandToGetHelpOn == NULL) {
+ StrnCatGrow(&CommandToGetHelpOn, NULL, L"*", 0);
+ ASSERT(SectionToGetHelpOn == NULL);
+ StrnCatGrow(&SectionToGetHelpOn, NULL, L"NAME", 0);
+ } else {
+ PrintCommandText = FALSE;
+ ASSERT(SectionToGetHelpOn == NULL);
+ //
+ // Get the section name for the given command name
+ //
+ if (ShellCommandLineGetFlag(Package, L"-section")) {
+ StrnCatGrow(&SectionToGetHelpOn, NULL, ShellCommandLineGetValue(Package, L"-section"), 0);
+ } else if (ShellCommandLineGetFlag(Package, L"-usage")) {
+ StrnCatGrow(&SectionToGetHelpOn, NULL, L"NAME,SYNOPSIS", 0);
+ } else if (ShellCommandLineGetFlag(Package, L"-verbose") || ShellCommandLineGetFlag(Package, L"-v")) {
+ } else {
+ //
+ // The output of help <command> will display NAME, SYNOPSIS, OPTIONS, DESCRIPTION, and EXAMPLES sections.
+ //
+ StrnCatGrow (&SectionToGetHelpOn, NULL, L"NAME,SYNOPSIS,OPTIONS,DESCRIPTION,EXAMPLES", 0);
+ }
+ }
+
+ if (gUnicodeCollation->StriColl(gUnicodeCollation, CommandToGetHelpOn, L"special") == 0) {
+ //
+ // we need info on the special characters
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_SC_HEADER), gShellLevel3HiiHandle);
+ HiiString = HiiGetString(gShellLevel3HiiHandle, STRING_TOKEN(STR_HELP_SC_DATA), NULL);
+ ShellPrintEx(-1, -1, L"%s", HiiString);
+ FreePool(HiiString);
+ Found = TRUE;
+ } else {
+ SortedCommandList = NULL;
+ SortedCommandListSize = 0;
+ CopyListOfCommandNames(&SortedCommandList, &SortedCommandListSize, ShellCommandGetCommandList(TRUE));
+ CopyListOfCommandNamesWithDynamic(&SortedCommandList, &SortedCommandListSize);
+
+ for (CurrentCommand = SortedCommandList
+ ; CurrentCommand != NULL && *CurrentCommand != CHAR_NULL && CurrentCommand < SortedCommandList + SortedCommandListSize/sizeof(CHAR16)
+ ; CurrentCommand += StrLen(CurrentCommand) + 1
+ ) {
+ //
+ // Checking execution break flag when print multiple command help information.
+ //
+ if (ShellGetExecutionBreakFlag ()) {
+ break;
+ }
+
+ if ((gUnicodeCollation->MetaiMatch(gUnicodeCollation, (CHAR16*)CurrentCommand, CommandToGetHelpOn)) ||
+ (gEfiShellProtocol->GetAlias(CommandToGetHelpOn, NULL) != NULL && (gUnicodeCollation->MetaiMatch(gUnicodeCollation, (CHAR16*)CurrentCommand, (CHAR16*)(gEfiShellProtocol->GetAlias(CommandToGetHelpOn, NULL)))))) {
+ //
+ // We have a command to look for help on.
+ //
+ Status = ShellPrintHelp(CurrentCommand, SectionToGetHelpOn, PrintCommandText);
+ if (EFI_ERROR(Status)) {
+ //
+ // now try to match against the dynamic command list and print help
+ //
+ Status = PrintDynamicCommandHelp (CurrentCommand, SectionToGetHelpOn, PrintCommandText);
+ }
+ if (Status == EFI_DEVICE_ERROR) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_INV), gShellLevel3HiiHandle, CurrentCommand);
+ } else if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_NF), gShellLevel3HiiHandle, CurrentCommand);
+ } else {
+ Found = TRUE;
+ }
+ }
+ }
+
+ //
+ // Search the .man file for Shell applications (Shell external commands).
+ //
+ if (!Found) {
+ Status = ShellPrintHelp(CommandToGetHelpOn, SectionToGetHelpOn, FALSE);
+ if (Status == EFI_DEVICE_ERROR) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_INV), gShellLevel3HiiHandle, CommandToGetHelpOn);
+ } else if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_NF), gShellLevel3HiiHandle, CommandToGetHelpOn);
+ } else {
+ Found = TRUE;
+ }
+ }
+ }
+
+ if (!Found) {
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+ }
+ }
+
+ if (CommandToGetHelpOn != NULL && StrCmp(CommandToGetHelpOn, L"*") == 0){
+ //
+ // If '*' then the command entered was 'Help' without qualifiers, This footer
+ // provides additional info on help switches
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_HELP_FOOTER), gShellLevel3HiiHandle);
+ }
+ if (CommandToGetHelpOn != NULL) {
+ FreePool(CommandToGetHelpOn);
+ }
+ if (SectionToGetHelpOn != NULL) {
+ FreePool(SectionToGetHelpOn);
+ }
+ SHELL_FREE_NON_NULL(SortedCommandList);
+
+ return (ShellStatus);
+}
diff --git a/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Pause.c b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Pause.c
new file mode 100644
index 0000000000..ab597060e2
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Pause.c
@@ -0,0 +1,107 @@
+/** @file
+ Main file for Pause shell level 3 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel3CommandsLib.h"
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-q", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'pause' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunPause (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ SHELL_PROMPT_RESPONSE *Resp;
+
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ Resp = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ if (!gEfiShellProtocol->BatchIsActive()) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_NO_SCRIPT), gShellLevel3HiiHandle, L"pause");
+ return (SHELL_UNSUPPORTED);
+ }
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"pause", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ } else if (ShellCommandLineGetRawValue(Package, 1) != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle, L"pause");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ if (!ShellCommandLineGetFlag(Package, L"-q")) {
+ Status = ShellPromptForResponseHii(ShellPromptResponseTypeQuitContinue, STRING_TOKEN (STR_PAUSE_PROMPT), gShellLevel3HiiHandle, (VOID**)&Resp);
+ } else {
+ Status = ShellPromptForResponse(ShellPromptResponseTypeQuitContinue, NULL, (VOID**)&Resp);
+ }
+
+ if (EFI_ERROR(Status) || Resp == NULL || *Resp == ShellPromptResponseQuit) {
+ ShellCommandRegisterExit(TRUE, 0);
+ ShellStatus = SHELL_ABORTED;
+ }
+
+ if (Resp != NULL) {
+ FreePool(Resp);
+ }
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+ }
+
+
+ return (ShellStatus);
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Touch.c b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Touch.c
new file mode 100644
index 0000000000..88c5d750e0
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Touch.c
@@ -0,0 +1,294 @@
+/** @file
+ Main file for Touch shell level 3 function.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel3CommandsLib.h"
+
+#include <Library/ShellLib.h>
+
+/**
+ Do the touch operation on a single handle.
+
+ @param[in] Handle The handle to update the date/time on.
+
+ @retval EFI_ACCESS_DENIED The file referenced by Handle is read only.
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+TouchFileByHandle (
+ IN EFI_HANDLE Handle
+ )
+{
+ EFI_STATUS Status;
+ EFI_FILE_INFO *FileInfo;
+
+ FileInfo = gEfiShellProtocol->GetFileInfo(Handle);
+ if ((FileInfo->Attribute & EFI_FILE_READ_ONLY) != 0){
+ return (EFI_ACCESS_DENIED);
+ }
+ Status = gRT->GetTime(&FileInfo->ModificationTime, NULL);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"gRT->GetTime", Status);
+ return (SHELL_DEVICE_ERROR);
+ }
+
+ CopyMem(&FileInfo->LastAccessTime, &FileInfo->ModificationTime, sizeof(EFI_TIME));
+
+ Status = gEfiShellProtocol->SetFileInfo(Handle, FileInfo);
+
+ FreePool(FileInfo);
+
+ return (Status);
+}
+
+/**
+ Touch a given file and potantially recurse down if it was a directory.
+
+ @param[in] Name The name of this file.
+ @param[in] FS The name of the file system this file is on.
+ @param[in] Handle The handle of this file already opened.
+ @param[in] Rec TRUE to recurse if possible.
+
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+DoTouchByHandle (
+ IN CONST CHAR16 *Name,
+ IN CHAR16 *FS,
+ IN SHELL_FILE_HANDLE Handle,
+ IN BOOLEAN Rec
+ )
+{
+ EFI_STATUS Status;
+ EFI_SHELL_FILE_INFO *FileList;
+ EFI_SHELL_FILE_INFO *Walker;
+ CHAR16 *TempSpot;
+
+ Status = EFI_SUCCESS;
+ FileList = NULL;
+ Walker = NULL;
+
+ if (FS == NULL) {
+ FS = StrnCatGrow(&FS, NULL, Name, 0);
+ if (FS != NULL) {
+ TempSpot = StrStr(FS, L"\\");
+ if (TempSpot != NULL) {
+ *TempSpot = CHAR_NULL;
+ }
+ }
+ }
+ if (FS == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ //
+ // do it
+ //
+ Status = TouchFileByHandle(Handle);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel3HiiHandle, L"touch", Name);
+ return (Status);
+ }
+
+ //
+ // if it's a directory recurse...
+ //
+ if (FileHandleIsDirectory(Handle) == EFI_SUCCESS && Rec) {
+ //
+ // get each file under this directory
+ //
+ if (EFI_ERROR(gEfiShellProtocol->FindFilesInDir(Handle, &FileList))) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // recurse on each
+ //
+ for (Walker = (EFI_SHELL_FILE_INFO *)GetFirstNode(&FileList->Link)
+ ; FileList != NULL && !IsNull(&FileList->Link, &Walker->Link) && !EFI_ERROR(Status)
+ ; Walker = (EFI_SHELL_FILE_INFO *)GetNextNode(&FileList->Link, &Walker->Link)
+ ){
+ if ( (StrCmp(Walker->FileName, L".") != 0)
+ && (StrCmp(Walker->FileName, L"..") != 0)
+ ){
+ //
+ // Open the file since we need that handle.
+ //
+ Status = gEfiShellProtocol->OpenFileByName (Walker->FullName, &Walker->Handle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel3HiiHandle, L"touch", Walker->FullName);
+ Status = EFI_ACCESS_DENIED;
+ } else {
+ Status = DoTouchByHandle(Walker->FullName, FS, Walker->Handle, TRUE);
+ gEfiShellProtocol->CloseFile(Walker->Handle);
+ Walker->Handle = NULL;
+ }
+ }
+ }
+
+ //
+ // free stuff
+ //
+ if (FileList != NULL && EFI_ERROR(gEfiShellProtocol->FreeFileList(&FileList))) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+
+ return (Status);
+}
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-r", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'touch' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunTouch (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ CONST CHAR16 *Param;
+ SHELL_STATUS ShellStatus;
+ UINTN ParamCount;
+ EFI_SHELL_FILE_INFO *FileList;
+ EFI_SHELL_FILE_INFO *Node;
+
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ ParamCount = 0;
+ FileList = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"touch", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ }
+ if (ShellCommandLineGetRawValue(Package, 1) == NULL) {
+ //
+ // we insufficient parameters
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel3HiiHandle, L"touch");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // get a list with each file specified by parameters
+ // if parameter is a directory then add all the files below it to the list
+ //
+ for ( ParamCount = 1, Param = ShellCommandLineGetRawValue(Package, ParamCount)
+ ; Param != NULL
+ ; ParamCount++, Param = ShellCommandLineGetRawValue(Package, ParamCount)
+ ){
+ Status = ShellOpenFileMetaArg((CHAR16*)Param, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, &FileList);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel3HiiHandle, L"touch", (CHAR16*)Param);
+ ShellStatus = SHELL_NOT_FOUND;
+ break;
+ }
+ //
+ // make sure we completed the param parsing sucessfully...
+ // Also make sure that any previous action was sucessful
+ //
+ if (ShellStatus == SHELL_SUCCESS) {
+ //
+ // check that we have at least 1 file
+ //
+ if (FileList == NULL || IsListEmpty(&FileList->Link)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel3HiiHandle, L"touch", Param);
+ continue;
+ } else {
+ //
+ // loop through the list and make sure we are not aborting...
+ //
+ for ( Node = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link)
+ ; !IsNull(&FileList->Link, &Node->Link) && !ShellGetExecutionBreakFlag()
+ ; Node = (EFI_SHELL_FILE_INFO*)GetNextNode(&FileList->Link, &Node->Link)
+ ){
+ //
+ // make sure the file opened ok
+ //
+ if (EFI_ERROR(Node->Status)){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel3HiiHandle, L"touch", Node->FileName);
+ ShellStatus = SHELL_NOT_FOUND;
+ continue;
+ }
+
+ Status = DoTouchByHandle(Node->FullName, NULL, Node->Handle, ShellCommandLineGetFlag(Package, L"-r"));
+ if (EFI_ERROR(Status) && Status != EFI_ACCESS_DENIED) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel3HiiHandle, L"touch", Node->FileName);
+ ShellStatus = SHELL_NOT_FOUND;
+ }
+ }
+ }
+ }
+ //
+ // Free the fileList
+ //
+ if (FileList != NULL && !IsListEmpty(&FileList->Link)) {
+ Status = ShellCloseFileMetaArg(&FileList);
+ ASSERT_EFI_ERROR(Status);
+ }
+ FileList = NULL;
+ }
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ if (ShellGetExecutionBreakFlag()) {
+ return (SHELL_ABORTED);
+ }
+
+ return (ShellStatus);
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Type.c b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Type.c
new file mode 100644
index 0000000000..ccd1199bd1
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Type.c
@@ -0,0 +1,328 @@
+/** @file
+ Main file for Type shell level 3 function.
+
+ (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel3CommandsLib.h"
+
+#include <Library/ShellLib.h>
+
+/**
+ Display a single file to StdOut.
+
+ If both Ascii and UCS2 are FALSE attempt to discover the file type.
+
+ @param[in] Handle The handle to the file to display.
+ @param[in] Ascii TRUE to force ASCII, FALSE othewise.
+ @param[in] UCS2 TRUE to force UCS2, FALSE othewise.
+
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+TypeFileByHandle (
+ IN SHELL_FILE_HANDLE Handle,
+ IN BOOLEAN Ascii,
+ IN BOOLEAN UCS2
+ )
+{
+ UINTN ReadSize;
+ VOID *Buffer;
+ VOID *AllocatedBuffer;
+ EFI_STATUS Status;
+ UINTN LoopVar;
+ UINTN LoopSize;
+ CHAR16 AsciiChar;
+ CHAR16 Ucs2Char;
+
+ ReadSize = PcdGet32(PcdShellFileOperationSize);
+ AllocatedBuffer = AllocateZeroPool(ReadSize);
+ if (AllocatedBuffer == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ Status = ShellSetFilePosition(Handle, 0);
+ ASSERT_EFI_ERROR(Status);
+
+ while (ReadSize == ((UINTN)PcdGet32(PcdShellFileOperationSize))) {
+ Buffer = AllocatedBuffer;
+ ZeroMem(Buffer, ReadSize);
+ Status = ShellReadFile(Handle, &ReadSize, Buffer);
+ if (EFI_ERROR(Status)){
+ break;
+ }
+
+ if (!(Ascii|UCS2)) {
+ if (*(UINT16*)Buffer == gUnicodeFileTag) {
+ UCS2 = TRUE;
+ } else {
+ Ascii = TRUE;
+ }
+ }
+
+ if (Ascii) {
+ LoopSize = ReadSize;
+ for (LoopVar = 0 ; LoopVar < LoopSize ; LoopVar++) {
+ //
+ // The valid range of ASCII characters is 0x20-0x7E.
+ // Display "." when there is an invalid character.
+ //
+ AsciiChar = CHAR_NULL;
+ AsciiChar = ((CHAR8*)Buffer)[LoopVar];
+ if (AsciiChar == '\r' || AsciiChar == '\n') {
+ //
+ // Allow Line Feed (LF) (0xA) & Carriage Return (CR) (0xD)
+ // characters to be displayed as is.
+ //
+ if (AsciiChar == '\n' && ((CHAR8*)Buffer)[LoopVar-1] != '\r') {
+ //
+ // In case Line Feed (0xA) is encountered & Carriage Return (0xD)
+ // was not the previous character, print CR and LF. This is because
+ // Shell 2.0 requires carriage return with line feed for displaying
+ // each new line from left.
+ //
+ ShellPrintEx (-1, -1, L"\r\n");
+ continue;
+ }
+ } else {
+ //
+ // For all other characters which are not printable, display '.'
+ //
+ if (AsciiChar < 0x20 || AsciiChar >= 0x7F) {
+ AsciiChar = '.';
+ }
+ }
+ ShellPrintEx (-1, -1, L"%c", AsciiChar);
+ }
+ } else {
+ if (*(UINT16*)Buffer == gUnicodeFileTag) {
+ //
+ // For unicode files, skip displaying the byte order marker.
+ //
+ Buffer = ((UINT16*)Buffer) + 1;
+ LoopSize = (ReadSize / (sizeof (CHAR16))) - 1;
+ } else {
+ LoopSize = ReadSize / (sizeof (CHAR16));
+ }
+
+ for (LoopVar = 0 ; LoopVar < LoopSize ; LoopVar++) {
+ //
+ // An invalid range of characters is 0x0-0x1F.
+ // Display "." when there is an invalid character.
+ //
+ Ucs2Char = CHAR_NULL;
+ Ucs2Char = ((CHAR16*)Buffer)[LoopVar];
+ if (Ucs2Char == '\r' || Ucs2Char == '\n') {
+ //
+ // Allow Line Feed (LF) (0xA) & Carriage Return (CR) (0xD)
+ // characters to be displayed as is.
+ //
+ if (Ucs2Char == '\n' && ((CHAR16*)Buffer)[LoopVar-1] != '\r') {
+ //
+ // In case Line Feed (0xA) is encountered & Carriage Return (0xD)
+ // was not the previous character, print CR and LF. This is because
+ // Shell 2.0 requires carriage return with line feed for displaying
+ // each new line from left.
+ //
+ ShellPrintEx (-1, -1, L"\r\n");
+ continue;
+ }
+ }
+ else if (Ucs2Char < 0x20) {
+ //
+ // For all other characters which are not printable, display '.'
+ //
+ Ucs2Char = L'.';
+ }
+ ShellPrintEx (-1, -1, L"%c", Ucs2Char);
+ }
+ }
+
+ if (ShellGetExecutionBreakFlag()) {
+ break;
+ }
+ }
+ FreePool (AllocatedBuffer);
+ ShellPrintEx (-1, -1, L"\r\n");
+ return (Status);
+}
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-a", TypeFlag},
+ {L"-u", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'type' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunType (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ CONST CHAR16 *Param;
+ SHELL_STATUS ShellStatus;
+ UINTN ParamCount;
+ EFI_SHELL_FILE_INFO *FileList;
+ EFI_SHELL_FILE_INFO *Node;
+ BOOLEAN AsciiMode;
+ BOOLEAN UnicodeMode;
+
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+ ParamCount = 0;
+ FileList = NULL;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"type", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ }
+ AsciiMode = ShellCommandLineGetFlag(Package, L"-a");
+ UnicodeMode = ShellCommandLineGetFlag(Package, L"-u");
+
+ if (AsciiMode && UnicodeMode) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellLevel3HiiHandle, L"type", L"-a & -u");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else if (ShellCommandLineGetRawValue(Package, 1) == NULL) {
+ //
+ // we insufficient parameters
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellLevel3HiiHandle, L"type");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ //
+ // get a list with each file specified by parameters
+ // if parameter is a directory then add all the files below it to the list
+ //
+ for ( ParamCount = 1, Param = ShellCommandLineGetRawValue(Package, ParamCount)
+ ; Param != NULL
+ ; ParamCount++, Param = ShellCommandLineGetRawValue(Package, ParamCount)
+ ){
+ Status = ShellOpenFileMetaArg((CHAR16*)Param, EFI_FILE_MODE_READ, &FileList);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel3HiiHandle, L"type", (CHAR16*)Param);
+ ShellStatus = SHELL_NOT_FOUND;
+ break;
+ }
+ //
+ // make sure we completed the param parsing sucessfully...
+ // Also make sure that any previous action was sucessful
+ //
+ if (ShellStatus == SHELL_SUCCESS) {
+ //
+ // check that we have at least 1 file
+ //
+ if (FileList == NULL || IsListEmpty(&FileList->Link)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_NF), gShellLevel3HiiHandle, L"type", Param);
+ continue;
+ } else {
+ //
+ // loop through the list and make sure we are not aborting...
+ //
+ for ( Node = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FileList->Link)
+ ; !IsNull(&FileList->Link, &Node->Link) && !ShellGetExecutionBreakFlag()
+ ; Node = (EFI_SHELL_FILE_INFO*)GetNextNode(&FileList->Link, &Node->Link)
+ ){
+
+ if (ShellGetExecutionBreakFlag()) {
+ break;
+ }
+
+ //
+ // make sure the file opened ok
+ //
+ if (EFI_ERROR(Node->Status)){
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL), gShellLevel3HiiHandle, L"type", Node->FileName);
+ ShellStatus = SHELL_NOT_FOUND;
+ continue;
+ }
+
+ //
+ // make sure its not a directory
+ //
+ if (FileHandleIsDirectory(Node->Handle) == EFI_SUCCESS) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_IS_DIR), gShellLevel3HiiHandle, L"type", Node->FileName);
+ ShellStatus = SHELL_NOT_FOUND;
+ continue;
+ }
+
+ //
+ // do it
+ //
+ Status = TypeFileByHandle (Node->Handle, AsciiMode, UnicodeMode);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_TYP_ERROR), gShellLevel3HiiHandle, L"type", Node->FileName);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ }
+ ASSERT(ShellStatus == SHELL_SUCCESS);
+ }
+ }
+ }
+ //
+ // Free the fileList
+ //
+ if (FileList != NULL && !IsListEmpty(&FileList->Link)) {
+ Status = ShellCloseFileMetaArg(&FileList);
+ }
+ ASSERT_EFI_ERROR(Status);
+ FileList = NULL;
+ }
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ if (ShellGetExecutionBreakFlag()) {
+ return (SHELL_ABORTED);
+ }
+
+ return (ShellStatus);
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.c b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.c
new file mode 100644
index 0000000000..448f7234dd
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.c
@@ -0,0 +1,101 @@
+/** @file
+ Main file for NULL named library for level 3 shell command functions.
+
+ (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "UefiShellLevel3CommandsLib.h"
+
+CONST CHAR16 gShellLevel3FileName[] = L"ShellCommands";
+EFI_HANDLE gShellLevel3HiiHandle = NULL;
+
+/**
+ return the filename to get help from is not using HII.
+
+ @retval The filename.
+**/
+CONST CHAR16*
+EFIAPI
+ShellCommandGetManFileNameLevel3 (
+ VOID
+ )
+{
+ return (gShellLevel3FileName);
+}
+
+/**
+ Constructor for the Shell Level 3 Commands library.
+
+ Install the handlers for level 3 UEFI Shell 2.0 commands.
+
+ @param ImageHandle the image handle of the process
+ @param SystemTable the EFI System Table pointer
+
+ @retval EFI_SUCCESS the shell command handlers were installed sucessfully
+ @retval EFI_UNSUPPORTED the shell level required was not found.
+**/
+EFI_STATUS
+EFIAPI
+ShellLevel3CommandsLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ gShellLevel3HiiHandle = NULL;
+ //
+ // if shell level is less than 3 do nothing
+ //
+ if (PcdGet8(PcdShellSupportLevel) < 3) {
+ return (EFI_SUCCESS);
+ }
+
+ gShellLevel3HiiHandle = HiiAddPackages (&gShellLevel3HiiGuid, gImageHandle, UefiShellLevel3CommandsLibStrings, NULL);
+ if (gShellLevel3HiiHandle == NULL) {
+ return (EFI_DEVICE_ERROR);
+ }
+ //
+ // install our shell command handlers that are always installed
+ //
+ // Note: that Time, Timezone, and Date are part of level 2 library
+ //
+ ShellCommandRegisterCommandName(L"type", ShellCommandRunType , ShellCommandGetManFileNameLevel3, 3, L"", TRUE , gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_TYPE));
+ ShellCommandRegisterCommandName(L"touch", ShellCommandRunTouch , ShellCommandGetManFileNameLevel3, 3, L"", TRUE , gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_TOUCH));
+ ShellCommandRegisterCommandName(L"ver", ShellCommandRunVer , ShellCommandGetManFileNameLevel3, 3, L"", TRUE , gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_VER));
+ ShellCommandRegisterCommandName(L"alias", ShellCommandRunAlias , ShellCommandGetManFileNameLevel3, 3, L"", TRUE , gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_ALIAS));
+ ShellCommandRegisterCommandName(L"cls", ShellCommandRunCls , ShellCommandGetManFileNameLevel3, 3, L"", TRUE , gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_CLS));
+ ShellCommandRegisterCommandName(L"echo", ShellCommandRunEcho , ShellCommandGetManFileNameLevel3, 3, L"", FALSE, gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_ECHO));
+ ShellCommandRegisterCommandName(L"pause", ShellCommandRunPause , ShellCommandGetManFileNameLevel3, 3, L"", TRUE , gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_PAUSE));
+ ShellCommandRegisterCommandName(L"getmtc", ShellCommandRunGetMtc , ShellCommandGetManFileNameLevel3, 3, L"", TRUE , gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_GETMTC));
+ ShellCommandRegisterCommandName(L"help", ShellCommandRunHelp , ShellCommandGetManFileNameLevel3, 3, L"", TRUE , gShellLevel3HiiHandle, STRING_TOKEN(STR_GET_HELP_HELP));
+
+ ShellCommandRegisterAlias(L"type", L"cat");
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Destructor for the library. free any resources.
+
+ @param ImageHandle The image handle of the process.
+ @param SystemTable The EFI System Table pointer.
+**/
+EFI_STATUS
+EFIAPI
+ShellLevel3CommandsLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ if (gShellLevel3HiiHandle != NULL) {
+ HiiRemovePackages(gShellLevel3HiiHandle);
+ }
+ return (EFI_SUCCESS);
+}
diff --git a/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.h b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.h
new file mode 100644
index 0000000000..bd5b9bec9c
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.h
@@ -0,0 +1,162 @@
+/** @file
+ header file for NULL named library for level 3 shell command functions.
+
+ Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _UEFI_SHELL_LEVEL3_COMMANDS_LIB_H_
+#define _UEFI_SHELL_LEVEL3_COMMANDS_LIB_H_
+
+#include <Uefi.h>
+#include <ShellBase.h>
+
+#include <Guid/ShellLibHiiGuid.h>
+
+#include <Protocol/EfiShell.h>
+#include <Protocol/EfiShellParameters.h>
+#include <Protocol/DevicePath.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/UnicodeCollation.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/ShellCommandLib.h>
+#include <Library/ShellLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HiiLib.h>
+#include <Library/FileHandleLib.h>
+
+extern EFI_HANDLE gShellLevel3HiiHandle;
+
+/**
+ Function for 'type' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunType (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'touch' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunTouch (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'ver' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunVer (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'alias' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunAlias (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'cls' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunCls (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'echo' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunEcho (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'pause' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunPause (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'getmtc' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunGetMtc (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'help' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunHelp (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+#endif
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf
new file mode 100644
index 0000000000..a13cd9babf
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf
@@ -0,0 +1,74 @@
+## @file
+# Provides shell level 3 functions
+# Note that the interactive versions of the time, date, and timezone functions are handled in the level 2 library.
+#
+# (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR>
+# Copyright (c) 2009-2015, Intel Corporation. All rights reserved. <BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = UefiShellLevel3CommandsLib
+ FILE_GUID = 71374B42-85D7-4753-AD17-AA84C3A0EB93
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER
+ CONSTRUCTOR = ShellLevel3CommandsLibConstructor
+ DESTRUCTOR = ShellLevel3CommandsLibDestructor
+
+[Sources.common]
+# note that time, timezone, and date are part of the level 2 library
+ Type.c
+ Touch.c
+ Ver.c
+ UefiShellLevel3CommandsLib.uni
+ UefiShellLevel3CommandsLib.c
+ UefiShellLevel3CommandsLib.h
+ Cls.c
+ Alias.c
+ Echo.c
+ Pause.c
+ GetMtc.c
+ Help.c
+
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ ShellCommandLib
+ ShellLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ PcdLib
+ HiiLib
+ FileHandleLib
+ HandleParsingLib
+
+[Guids]
+ gEfiFileInfoGuid ## UNDEFINED
+ gShellLevel3HiiGuid ## SOMETIMES_CONSUMES ## HII
+
+[Pcd.common]
+ gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel ## CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdShellFileOperationSize ## SOMETIMES_CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdShellSupplier ## SOMETIMES_CONSUMES
+
+[Protocols]
+ gEfiShellDynamicCommandProtocolGuid ## SOMETIMES_CONSUMES
diff --git a/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.uni b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.uni
new file mode 100644
index 0000000000..eeb870a395
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.uni
@@ -0,0 +1,518 @@
+// /**
+//
+// (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
+// Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved. <BR>
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// Module Name:
+//
+// UefiShellLevel3CommandsLib.uni
+//
+// Abstract:
+//
+// String definitions for UEFI Shell 2.0 level 3 commands
+//
+//
+// **/
+
+/=#
+
+#langdef en-US "english"
+
+#string STR_GEN_TOO_MANY #language en-US "%H%s%N: Too many arguments\r\n"
+#string STR_GEN_TOO_FEW #language en-US "%H%s%N: Too few arguments\r\n"
+#string STR_GEN_PARAM_INV #language en-US "%H%s%N: Invalid argument - '%H%s%N'\r\n"
+#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n"
+#string STR_GEN_NO_VALUE #language en-US "%H%s%N: Missing argument for flag - '%H%s%N'\r\n"
+#string STR_GEN_ERR_AD #language en-US "%H%s%N: Access denied.\r\n"
+#string STR_GEN_ERR_UK #language en-US "%H%s%N: Status: %r\r\n"
+#string STR_GEN_PARAM_CON #language en-US "%H%s%N: Parameters conflict\r\n"
+#string STR_GEN_PARAM_CONFLICT #language en-US "%H%s%N: Flags conflict with - '%H%s%N' and '%H%s%N'\r\n"
+#string STR_GEN_FILE_OPEN_FAIL #language en-US "%H%s%N: Cannot open file - '%H%s%N'\r\n"
+#string STR_GEN_FILE_AD #language en-US "%H%s%N: Access file error - '%H%s%N'\r\n"
+#string STR_GEN_CRLF #language en-US "\r\n"
+#string STR_GEN_NO_CWD #language en-US "%H%s%N: Current directory not specified\r\n"
+#string STR_GEN_NO_FILES #language en-US "%H%s%N: No matching files were found\r\n"
+#string STR_GEN_DIR_NF #language en-US "%H%s%N: Directory not found - '%H%s%N'\r\n"
+#string STR_GEN_FILE_NF #language en-US "%H%s%N: File not found - '%H%s%N'\r\n"
+#string STR_GEN_IS_DIR #language en-US "%H%s%N: '%H%s%N' is a directory\r\n"
+#string STR_NO_SCRIPT #language en-US "The command '%H%s%N' is not allowed outside of a script\r\n"
+
+#string STR_TYP_ERROR #language en-US "%H%s%N: Operation was not successful on '%H%s%N'\r\n"
+
+#string STR_TOUCH_ERROR #language en-US "%H%s%N: Operation was not successful on '%H%s%N'\r\n"
+
+#string STR_VER_OUTPUT_SHELL #language en-US "UEFI %s Shell v%d.%d\r\n"
+#string STR_VER_OUTPUT_SIMPLE #language en-US "%d.%d\r\n"
+#string STR_VER_OUTPUT_UEFI #language en-US "UEFI v%d.%02d (%s, 0x%08x)\r\n"
+#string STR_VER_OUTPUT_SUPPLIER #language en-US "%s\r\n"
+
+#string STR_ECHO_ON #language en-US "Echo is on.\r\n"
+#string STR_ECHO_OFF #language en-US "Echo is off.\r\n"
+#string STR_ECHO_INVALID_PARAM #language en-US "%H%s%N: Invalid - too many parameters after '%s'\r\n"
+
+#string STR_PAUSE_PROMPT #language en-US "Enter 'q' to quit, any other key to continue:\r\n"
+
+#string STR_HELP_NF #language en-US "No help could be found for command '%B%s%N'.\r\n"
+#string STR_HELP_INV #language en-US "The help data for command '%B%s%N' was incorrect format.\r\n"
+#string STR_HELP_SC_HEADER #language en-US "Character Description\r\n"
+ "--------- ---------------------------------------------- \r\n"
+#string STR_HELP_SC_DATA #language en-US "<newline> Ends a command line.\r\n"
+ "<space> Ends an argument, if it is not in a quotation.\r\n"
+ "# Starts a comment.\r\n"
+ "> Used for output redirection.\r\n"
+ "< Used for input redirection.\r\n"
+ "| Used for pipe command support.\r\n"
+ "% Used to delimit a variable or an argument.\r\n"
+ "\" Used to delimit a quotation.\r\n"
+ "^ Prevents the next character from being\r\n"
+ " interpreted as having special meaning.\r\n"
+ " Can be used inside quoted strings.\r\n"
+ "*, ?, [, ] Wildcards to specify multiple similar file names.\r\n"
+#string STR_HELP_COMMAND #language en-US "%H%-14s%N- %s\r\n"
+#string STR_HELP_FOOTER #language en-US "%N\r\nHelp usage:help [%Hcmd%N|%Hpattern%N|%Hspecial%N] [%H-usage%N] [%H-verbose%N] [%H-section name%N][%H-b%N]\r\n"
+
+#string STR_HELP_PAGE_COMMAND #language en-US "%N%s\r\n"
+
+#string STR_ALIAS_OUTPUT #language en-US "%1c %10s:%s\r\n"
+
+#string STR_GET_MTC_OUTPUT #language en-US "%016Lx\r\n"
+
+#string STR_GET_HELP_HELP #language en-US ""
+".TH help 0 "Displays help information from the UEFI Shell."\r\n"
+".SH NAME\r\n"
+"Displays the UEFI Shell command list or verbose command help.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"HELP [cmd | pattern | special] [-usage] [-verbose] [-section sectionname][-b]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -usage - Displays the usage information for the command. The same as\r\n"
+" specifying "-section NAME" and "-section SYNOPSIS" \r\n"
+" -section - Displays the specified section of the help information.\r\n"
+" -b - Displays one page on screen and allows user to continue\r\n"
+" to next page\r\n"
+" cmd - Specifies a command to display help about.\r\n"
+" pattern - Specifies a pattern which describes the commands to be displayed.\r\n"
+" special - Displays a list of the special characters used in the shell\r\n"
+" command line.\r\n"
+" sectionname - Specifies a section name. Supported options are:\r\n"
+" - NAME\r\n"
+" - SYNOPSIS\r\n"
+" - OPTIONS\r\n"
+" - DESCRIPTION\r\n"
+" - EXAMPLES\r\n"
+" - RETURNVALUES\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. The HELP command displays information about one or more shell commands.\r\n"
+" 2. If no other options are specified, each command will be displayed along\r\n"
+" with a brief description of its function.\r\n"
+" 3. If -verbose is specified, then display all help information for the\r\n"
+" specified commands.\r\n"
+" 4. If -section is specified, only the help section specified will be\r\n"
+" displayed.\r\n"
+" 5. If -usage is specified, then the command, a brief description\r\n"
+" and the usage will be displayed.\r\n"
+" 6. The help text is gathered from UCS-2 text files found in the directory\r\n"
+" where the shell or shell command executable was located. The files have\r\n"
+" the name commandname.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display the list of commands in the UEFI Shell and break after one\r\n"
+" screen:\r\n"
+" Shell> help -b\r\n"
+" \r\n"
+" * To display help information of a Shell command - ls:\r\n"
+" Shell> help ls\r\n"
+" Shell> -? ls\r\n"
+" Shell> ls -?\r\n"
+" \r\n"
+" * To display the list of commands that start with character 'p':\r\n"
+" Shell> help p*\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" 0 The help was displayed\r\n"
+" 1 No command help was displayed\r\n"
+
+#string STR_GET_HELP_ALIAS #language en-US ""
+".TH alias 0 "Handles aliases in the Shell."\r\n"
+".SH NAME\r\n"
+"Displays, creates, or deletes UEFI Shell aliases.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"ALIAS [-d|-v] [alias-name] [command-name]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -d - Deletes an alias. Command-name must not be specified.\r\n"
+" -v - Makes the alias volatile.\r\n"
+" alias-name - Specifies an alias name.\r\n"
+" command-name - Specifies an original command's name or path.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command displays, creates, or deletes aliases in the UEFI Shell\r\n"
+" environment.\r\n"
+" 2. An alias provides a new name for an existing UEFI Shell\r\n"
+" command or UEFI application. Once the alias is created, it can be used\r\n"
+" to run the command or launch the UEFI application.\r\n"
+" 3. There are some aliases that are predefined in the UEFI Shell environment.\r\n"
+" These aliases provide the MS-DOS and UNIX equivalent names for the file\r\n"
+" manipulation commands.\r\n"
+" 4. Aliases will be retained even after exiting the shell unless the -v option\r\n"
+" is specified. If -v is specified then the alias will not be valid after\r\n"
+" leaving the shell.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display all aliases in the UEFI Shell environment:\r\n"
+" Shell> alias\r\n"
+" \r\n"
+" * To create an alias in the UEFI Shell environment:\r\n"
+" Shell> alias shutdown "reset -s" \r\n"
+" \r\n"
+" * To delete an alias in the UEFI Shell environment:\r\n"
+" Shell> alias -d shutdown\r\n"
+" \r\n"
+" * To add a volatile alias in the current UEFI environment, which has a star *\r\n"
+" at the line head. This volatile alias will disappear at next boot.\r\n"
+" Shell> alias -v fs0 floppy\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+" SHELL_OUT_OF_RESOURCES A request to set a variable in a non-volatile\r\n"
+" fashion could not be completed. The resulting\r\n"
+" non-volatile request has been converted into\r\n"
+" a volatile request.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+
+#string STR_GET_HELP_CLS #language en-US ""
+".TH cls 0 "clear screen"\r\n"
+".SH NAME\r\n"
+"Clears standard output and optionally changes background color.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"CLS [color]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" color - Sets a new background color:\r\n"
+" 0 - Black\r\n"
+" 1 - Blue\r\n"
+" 2 - Green\r\n"
+" 3 - Cyan\r\n"
+" 4 - Red\r\n"
+" 5 - Magenta\r\n"
+" 6 - Yellow\r\n"
+" 7 - Light gray\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command clears the standard output device with an optional\r\n"
+" background color attribute. If a color is not specified, then the\r\n"
+" background color does not change.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To clear standard output without changing the background color:\r\n"
+" fs0:\> cls\r\n"
+" \r\n"
+" * To clear standard output and change the background color to cyan:\r\n"
+" fs0:\> cls 3\r\n"
+" \r\n"
+" * To clear standard output and change the background to the default color:\r\n"
+" fs0:\> cls 0\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_NOT_FOUND The requested file was not found.\r\n"
+
+#string STR_GET_HELP_ECHO #language en-US ""
+".TH echo 0 "display text or control text output"\r\n"
+".SH NAME\r\n"
+"Controls script file command echoing or displays a message.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"ECHO [-on|-off]\r\n"
+"ECHO [message]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -on - Enables display when reading commands from script files.\r\n"
+" -off - Disables display when reading commands from script files.\r\n"
+" message - Specifies a message to display.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. The first form of this command controls whether script commands are\r\n"
+" displayed as they are read from the script file. If no argument is given,\r\n"
+" the current "on" or "off" status is displayed.\r\n"
+" 2. The second form prints the given message to the display.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display a message string of 'Hello World':\r\n"
+" fs0:\> echo Hello World\r\n"
+" \r\n"
+" * To turn command echoing on:\r\n"
+" fs0:\> echo -on\r\n"
+" \r\n"
+" * To execute HelloWorld.nsh, and display when reading lines from the script\r\n"
+" file:\r\n"
+" fs0:\> HelloWorld.nsh\r\n"
+" +HelloWorld.nsh> echo Hello World\r\n"
+" \r\n"
+" * To turn command echoing off:\r\n"
+" fs0:\> echo -off\r\n"
+" \r\n"
+" * To display the current echo setting:\r\n"
+" fs0:\> echo\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+
+#string STR_GET_HELP_GETMTC #language en-US ""
+".TH getmtc 0 "gets the MTC count"\r\n"
+".SH NAME\r\n"
+"Gets the MTC from BootServices and displays it.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"GETMTC\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command displays the current monotonic counter value. The lower 32\r\n"
+" bits increment every time this command is executed. Every time the system\r\n"
+" is reset, the upper 32 bits will be incremented, and the lower 32 bits\r\n"
+" will be reset to 0.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display the current monotonic counter value:\r\n"
+" fs0:\> getmtc\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_DEVICE_ERROR The underlying device was not working correctly.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+
+#string STR_GET_HELP_PAUSE #language en-US ""
+".TH pause 0 "pauses scripts"\r\n"
+".SH NAME\r\n"
+"Pauses a script and waits for an operator to press a key.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"PAUSE [-q]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -q - Does not display a test output prompt.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. The PAUSE command prints a message to the display, then suspends script\r\n"
+" file execution, and waits for keyboard input. Pressing any key resumes\r\n"
+" execution, except for q or Q. If either q or Q is pressed, script\r\n"
+" processing terminates; otherwise, execution continues with the next line\r\n"
+" after the pause command.\r\n"
+" 2. The PAUSE command is available only in scripts. Switch -q can hide the\r\n"
+" message and it's optional.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * Following script is a sample of 'pause' command:\r\n"
+" fs0:\> type pause.nsh\r\n"
+" #\r\n"
+" # Example script for 'pause' command\r\n"
+" #\r\n"
+" echo pause.nsh begin..\r\n"
+" date\r\n"
+" time\r\n"
+" pause\r\n"
+" echo pause.nsh done.\r\n"
+" \r\n"
+" * To execute the script with echo on:\r\n"
+" fs0:\> pause.nsh\r\n"
+" +pause.nsh> echo pause.nsh begin..\r\n"
+" pause.nsh begin..\r\n"
+" +pause.nsh> date\r\n"
+" 06/19/2001\r\n"
+" +pause.nsh> time\r\n"
+" 00:51:45\r\n"
+" +pause.nsh> pause\r\n"
+" Enter 'q' to quit, or any other key to continue:\r\n"
+" +pause.nsh> echo pause.nsh done.\r\n"
+" pause.nsh done.\r\n"
+" \r\n"
+" * To execute the script with echo off:\r\n"
+" fs0:\> echo -off\r\n"
+" fs0:\> pause.nsh\r\n"
+" pause.nsh begin..\r\n"
+" 06/19/2001\r\n"
+" 00:52:50\r\n"
+" Enter 'q' to quit, or any other key to continue: q\r\n"
+" fs0:\>\r\n"
+
+#string STR_GET_HELP_TOUCH #language en-US ""
+".TH touch 0 "Touch a file to update a directory"\r\n"
+".SH NAME\r\n"
+"Updates the filename timestamp with the current system date and time.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"TOUCH [-r] file [file ...]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -r - Sets the update as recurse into subdirectories.\r\n"
+" file - Specifies the name or pattern of the file or directory. There can be multiple \r\n"
+" files on the command-line.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command updates to the current time and date the time and date on\r\n"
+" the file that is specified by the file parameter.\r\n"
+" 2. If multiple files are specified on the command line, it will continue\r\n"
+" processing. It will touch the files one by one and errors will be\r\n"
+" ignored.\r\n"
+" 3. TOUCH cannot change the time and date of read-only files and directories.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To update the timestamp of a specific file:\r\n"
+" fs0:\> touch for.nsh\r\n"
+" \r\n"
+" * To touch a directory recursively:\r\n"
+" fs0:\> touch -r efi1.1\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_NOT_FOUND The target file or set of files were not found.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_WRITE_PROTECTED The media was write-protected or the file had a\r\n"
+" read-only attribute associated with it.\r\n"
+
+#string STR_GET_HELP_TYPE #language en-US ""
+".TH type 0 "print a file to StdOut"\r\n"
+".SH NAME\r\n"
+"Sends the contents of a file to the standard output device.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"TYPE [-a|-u] file [file...]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -a - Displays the file as if it is encoded as 8-bit ASCII\r\n"
+" -u - Displays the file as if it were encoded as UCS-2 Unicode.\r\n"
+" file - Specifies the name of the file to display.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command sends the contents of a file to the standard output device.\r\n"
+" If no options are used, then the command attempts to automatically detect\r\n"
+" the file type. If it fails, then UCS-2 is presumed.\r\n"
+" 2. If the -a option is specified, the file is sent to the standard output\r\n"
+" device as a stream of ASCII characters.\r\n"
+" 3. If the -u option is specified, the file is sent to the standard output\r\n"
+" device as a stream of Unicode (UCS-2) characters.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display a file in UCS-2 format:\r\n"
+" fs0:\> type -u pause.nsh\r\n"
+" \r\n"
+" * To display a file in ASCII format:\r\n"
+" fs0:\> type -a pause.nsh\r\n"
+" \r\n"
+" * To display multiple files:\r\n"
+" fs0:\> type test.*\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+" SHELL_SECURITY_VIOLATION This function was not performed due to a security\r\n"
+" violation.\r\n"
+" SHELL_NOT_FOUND The target file or set of files were not found.\r\n"
+
+#string STR_GET_HELP_VER #language en-US ""
+".TH ver 0 "prints out version info"\r\n"
+".SH NAME\r\n"
+"Displays UEFI Firmware version information.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"VER [-s|-terse]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -s - Displays only the UEFI Shell version.\r\n"
+" -terse - Displays only the first part of the data.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command displays the version information for this UEFI Firmware, or\r\n"
+" the version information for the UEFI Shell itself. The information is\r\n"
+" retrieved through the UEFI System Table or the Shell image.\r\n"
+" \r\n"
+" 2. Standard format for ver output as shown below with a sample:\r\n"
+" UEFI <support-level> Shell v<uefi-shell-version>\r\n"
+" shell-supplier-specific-data\r\n"
+" UEFI v<uefi-firmware-version> (<firmware vendor name>, 0x<firmware vendor\r\n"
+" version as 32-bit hex value> <optional additional vendor version>)\r\n"
+" #\r\n"
+" # Sample \r\n"
+" #\r\n"
+" UEFI Basic Shell v2.0\r\n"
+" Copyright 2008 by Intel(R) Corporation.\r\n"
+" UEFI v2.31 (Intel(R) Corporation., 0x00010100)\r\n"
+" \r\n"
+" 3. UEFI version tag information:\r\n"
+" <support-level>\r\n"
+" 0 = Minimal\r\n"
+" 1 = Scripting\r\n"
+" 2 = Basic\r\n"
+" 3 = Interactive\r\n"
+" <uefi-shell-version>\r\n"
+" Comes from the Shell specification upon which the Shell\r\n"
+" implementation is based.\r\n"
+" <shell-supplier-specific-data>\r\n"
+" Build, copyright, etc.\r\n"
+" <uefi-firmware-version>\r\n"
+" Comes from the UEFI specification upon which the firmware\r\n"
+" implementation is based\r\n"
+" <firmware vendor name>\r\n"
+" Indicates Vendor Name\r\n"
+" <firmware vendor version>\r\n"
+" Indicates Vendor's firmware version\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To display UEFI Firmware version information:\r\n"
+" fs0:\> ver\r\n"
+" \r\n"
+" * To display UEFI Shell version information only:\r\n"
+" Shell> ver -s\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+
diff --git a/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Ver.c b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Ver.c
new file mode 100644
index 0000000000..deefaf0bb2
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLevel3CommandsLib/Ver.c
@@ -0,0 +1,147 @@
+/** @file
+ Main file for Ver shell level 3 function.
+
+ (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLevel3CommandsLib.h"
+
+#include <Library/ShellLib.h>
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-s", TypeFlag},
+ {L"-terse", TypeFlag},
+ {L"-t", TypeFlag},
+ {L"-_pa", TypeFlag},
+ {NULL, TypeMax}
+ };
+
+/**
+ Function for 'ver' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunVer (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY *Package;
+ CHAR16 *ProblemParam;
+ SHELL_STATUS ShellStatus;
+ UINT8 Level;
+
+ Level = PcdGet8(PcdShellSupportLevel);
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // initialize the shell lib (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize();
+ ASSERT_EFI_ERROR(Status);
+
+ Status = CommandInit();
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // parse the command line
+ //
+ Status = ShellCommandLineParse (ParamList, &Package, &ProblemParam, TRUE);
+ if (EFI_ERROR(Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellLevel3HiiHandle, L"ver", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+ } else {
+ //
+ // check for "-?"
+ //
+ if (ShellCommandLineGetFlag(Package, L"-?")) {
+ ASSERT(FALSE);
+ }
+ if (ShellCommandLineGetRawValue(Package, 1) != NULL) {
+ //
+ // we have too many parameters
+ //
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellLevel3HiiHandle, L"ver");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ if (ShellCommandLineGetFlag(Package, L"-s")) {
+ ShellPrintHiiEx (
+ 0,
+ gST->ConOut->Mode->CursorRow,
+ NULL,
+ STRING_TOKEN (STR_VER_OUTPUT_SIMPLE),
+ gShellLevel3HiiHandle,
+ gEfiShellProtocol->MajorVersion,
+ gEfiShellProtocol->MinorVersion
+ );
+ } else {
+ ShellPrintHiiEx (
+ 0,
+ gST->ConOut->Mode->CursorRow,
+ NULL,
+ STRING_TOKEN (STR_VER_OUTPUT_SHELL),
+ gShellLevel3HiiHandle,
+ SupportLevel[Level],
+ gEfiShellProtocol->MajorVersion,
+ gEfiShellProtocol->MinorVersion
+ );
+ if (!ShellCommandLineGetFlag(Package, L"-terse") && !ShellCommandLineGetFlag(Package, L"-t")){
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_VER_OUTPUT_SUPPLIER),
+ gShellLevel3HiiHandle,
+ (CHAR16 *) PcdGetPtr (PcdShellSupplier)
+ );
+
+
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_VER_OUTPUT_UEFI),
+ gShellLevel3HiiHandle,
+ (gST->Hdr.Revision&0xffff0000)>>16,
+ (gST->Hdr.Revision&0x0000ffff),
+ gST->FirmwareVendor,
+ gST->FirmwareRevision
+ );
+ }
+ }
+ //
+ // implementation specific support for displaying processor architecture
+ //
+ if (ShellCommandLineGetFlag(Package, L"-_pa")) {
+ ShellPrintEx(-1, -1, L"%d\r\n", sizeof(UINTN)==sizeof(UINT64)?64:32);
+ }
+ }
+
+ //
+ // free the command line package
+ //
+ ShellCommandLineFreeVarList (Package);
+ }
+
+ return (ShellStatus);
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellLib/UefiShellLib.c b/Core/ShellPkg/Library/UefiShellLib/UefiShellLib.c
new file mode 100644
index 0000000000..3dcdba6ba0
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLib/UefiShellLib.c
@@ -0,0 +1,4361 @@
+/** @file
+ Provides interface to shell functionality for shell commands and applications.
+
+ Copyright 2016 Dell Inc.
+ Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellLib.h"
+#include <ShellBase.h>
+#include <Library/SortLib.h>
+#include <Library/BaseLib.h>
+
+#define FIND_XXXXX_FILE_BUFFER_SIZE (SIZE_OF_EFI_FILE_INFO + MAX_FILE_NAME_LEN)
+
+//
+// globals...
+//
+SHELL_PARAM_ITEM EmptyParamList[] = {
+ {NULL, TypeMax}
+ };
+SHELL_PARAM_ITEM SfoParamList[] = {
+ {L"-sfo", TypeFlag},
+ {NULL, TypeMax}
+ };
+EFI_SHELL_ENVIRONMENT2 *mEfiShellEnvironment2;
+EFI_SHELL_INTERFACE *mEfiShellInterface;
+EFI_SHELL_PROTOCOL *gEfiShellProtocol;
+EFI_SHELL_PARAMETERS_PROTOCOL *gEfiShellParametersProtocol;
+EFI_HANDLE mEfiShellEnvironment2Handle;
+FILE_HANDLE_FUNCTION_MAP FileFunctionMap;
+
+/**
+ Check if a Unicode character is a hexadecimal character.
+
+ This internal function checks if a Unicode character is a
+ numeric character. The valid hexadecimal characters are
+ L'0' to L'9', L'a' to L'f', or L'A' to L'F'.
+
+ @param Char The character to check against.
+
+ @retval TRUE If the Char is a hexadecmial character.
+ @retval FALSE If the Char is not a hexadecmial character.
+
+**/
+BOOLEAN
+EFIAPI
+ShellIsHexaDecimalDigitCharacter (
+ IN CHAR16 Char
+ )
+{
+ return (BOOLEAN) ((Char >= L'0' && Char <= L'9') || (Char >= L'A' && Char <= L'F') || (Char >= L'a' && Char <= L'f'));
+}
+
+/**
+ Check if a Unicode character is a decimal character.
+
+ This internal function checks if a Unicode character is a
+ decimal character. The valid characters are
+ L'0' to L'9'.
+
+
+ @param Char The character to check against.
+
+ @retval TRUE If the Char is a hexadecmial character.
+ @retval FALSE If the Char is not a hexadecmial character.
+
+**/
+BOOLEAN
+EFIAPI
+ShellIsDecimalDigitCharacter (
+ IN CHAR16 Char
+ )
+{
+ return (BOOLEAN) (Char >= L'0' && Char <= L'9');
+}
+
+/**
+ Helper function to find ShellEnvironment2 for constructor.
+
+ @param[in] ImageHandle A copy of the calling image's handle.
+
+ @retval EFI_OUT_OF_RESOURCES Memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+ShellFindSE2 (
+ IN EFI_HANDLE ImageHandle
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE *Buffer;
+ UINTN BufferSize;
+ UINTN HandleIndex;
+
+ BufferSize = 0;
+ Buffer = NULL;
+ Status = gBS->OpenProtocol(ImageHandle,
+ &gEfiShellEnvironment2Guid,
+ (VOID **)&mEfiShellEnvironment2,
+ ImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ //
+ // look for the mEfiShellEnvironment2 protocol at a higher level
+ //
+ if (EFI_ERROR (Status) || !(CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid))){
+ //
+ // figure out how big of a buffer we need.
+ //
+ Status = gBS->LocateHandle (ByProtocol,
+ &gEfiShellEnvironment2Guid,
+ NULL, // ignored for ByProtocol
+ &BufferSize,
+ Buffer
+ );
+ //
+ // maybe it's not there???
+ //
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ Buffer = (EFI_HANDLE*)AllocateZeroPool(BufferSize);
+ if (Buffer == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ Status = gBS->LocateHandle (ByProtocol,
+ &gEfiShellEnvironment2Guid,
+ NULL, // ignored for ByProtocol
+ &BufferSize,
+ Buffer
+ );
+ }
+ if (!EFI_ERROR (Status) && Buffer != NULL) {
+ //
+ // now parse the list of returned handles
+ //
+ Status = EFI_NOT_FOUND;
+ for (HandleIndex = 0; HandleIndex < (BufferSize/sizeof(Buffer[0])); HandleIndex++) {
+ Status = gBS->OpenProtocol(Buffer[HandleIndex],
+ &gEfiShellEnvironment2Guid,
+ (VOID **)&mEfiShellEnvironment2,
+ ImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (CompareGuid (&mEfiShellEnvironment2->SESGuid, &gEfiShellEnvironment2ExtGuid)) {
+ mEfiShellEnvironment2Handle = Buffer[HandleIndex];
+ Status = EFI_SUCCESS;
+ break;
+ }
+ }
+ }
+ }
+ if (Buffer != NULL) {
+ FreePool (Buffer);
+ }
+ return (Status);
+}
+
+/**
+ Function to do most of the work of the constructor. Allows for calling
+ multiple times without complete re-initialization.
+
+ @param[in] ImageHandle A copy of the ImageHandle.
+ @param[in] SystemTable A pointer to the SystemTable for the application.
+
+ @retval EFI_SUCCESS The operationw as successful.
+**/
+EFI_STATUS
+EFIAPI
+ShellLibConstructorWorker (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // UEFI 2.0 shell interfaces (used preferentially)
+ //
+ Status = gBS->OpenProtocol(
+ ImageHandle,
+ &gEfiShellProtocolGuid,
+ (VOID **)&gEfiShellProtocol,
+ ImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR(Status)) {
+ //
+ // Search for the shell protocol
+ //
+ Status = gBS->LocateProtocol(
+ &gEfiShellProtocolGuid,
+ NULL,
+ (VOID **)&gEfiShellProtocol
+ );
+ if (EFI_ERROR(Status)) {
+ gEfiShellProtocol = NULL;
+ }
+ }
+ Status = gBS->OpenProtocol(
+ ImageHandle,
+ &gEfiShellParametersProtocolGuid,
+ (VOID **)&gEfiShellParametersProtocol,
+ ImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR(Status)) {
+ gEfiShellParametersProtocol = NULL;
+ }
+
+ if (gEfiShellParametersProtocol == NULL || gEfiShellProtocol == NULL) {
+ //
+ // Moved to seperate function due to complexity
+ //
+ Status = ShellFindSE2(ImageHandle);
+
+ if (EFI_ERROR(Status)) {
+ DEBUG((DEBUG_ERROR, "Status: 0x%08x\r\n", Status));
+ mEfiShellEnvironment2 = NULL;
+ }
+ Status = gBS->OpenProtocol(ImageHandle,
+ &gEfiShellInterfaceGuid,
+ (VOID **)&mEfiShellInterface,
+ ImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR(Status)) {
+ mEfiShellInterface = NULL;
+ }
+ }
+
+ //
+ // only success getting 2 of either the old or new, but no 1/2 and 1/2
+ //
+ if ((mEfiShellEnvironment2 != NULL && mEfiShellInterface != NULL) ||
+ (gEfiShellProtocol != NULL && gEfiShellParametersProtocol != NULL) ) {
+ if (gEfiShellProtocol != NULL) {
+ FileFunctionMap.GetFileInfo = gEfiShellProtocol->GetFileInfo;
+ FileFunctionMap.SetFileInfo = gEfiShellProtocol->SetFileInfo;
+ FileFunctionMap.ReadFile = gEfiShellProtocol->ReadFile;
+ FileFunctionMap.WriteFile = gEfiShellProtocol->WriteFile;
+ FileFunctionMap.CloseFile = gEfiShellProtocol->CloseFile;
+ FileFunctionMap.DeleteFile = gEfiShellProtocol->DeleteFile;
+ FileFunctionMap.GetFilePosition = gEfiShellProtocol->GetFilePosition;
+ FileFunctionMap.SetFilePosition = gEfiShellProtocol->SetFilePosition;
+ FileFunctionMap.FlushFile = gEfiShellProtocol->FlushFile;
+ FileFunctionMap.GetFileSize = gEfiShellProtocol->GetFileSize;
+ } else {
+ FileFunctionMap.GetFileInfo = (EFI_SHELL_GET_FILE_INFO)FileHandleGetInfo;
+ FileFunctionMap.SetFileInfo = (EFI_SHELL_SET_FILE_INFO)FileHandleSetInfo;
+ FileFunctionMap.ReadFile = (EFI_SHELL_READ_FILE)FileHandleRead;
+ FileFunctionMap.WriteFile = (EFI_SHELL_WRITE_FILE)FileHandleWrite;
+ FileFunctionMap.CloseFile = (EFI_SHELL_CLOSE_FILE)FileHandleClose;
+ FileFunctionMap.DeleteFile = (EFI_SHELL_DELETE_FILE)FileHandleDelete;
+ FileFunctionMap.GetFilePosition = (EFI_SHELL_GET_FILE_POSITION)FileHandleGetPosition;
+ FileFunctionMap.SetFilePosition = (EFI_SHELL_SET_FILE_POSITION)FileHandleSetPosition;
+ FileFunctionMap.FlushFile = (EFI_SHELL_FLUSH_FILE)FileHandleFlush;
+ FileFunctionMap.GetFileSize = (EFI_SHELL_GET_FILE_SIZE)FileHandleGetSize;
+ }
+ return (EFI_SUCCESS);
+ }
+ return (EFI_NOT_FOUND);
+}
+/**
+ Constructor for the Shell library.
+
+ Initialize the library and determine if the underlying is a UEFI Shell 2.0 or an EFI shell.
+
+ @param ImageHandle the image handle of the process
+ @param SystemTable the EFI System Table pointer
+
+ @retval EFI_SUCCESS the initialization was complete sucessfully
+ @return others an error ocurred during initialization
+**/
+EFI_STATUS
+EFIAPI
+ShellLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ mEfiShellEnvironment2 = NULL;
+ gEfiShellProtocol = NULL;
+ gEfiShellParametersProtocol = NULL;
+ mEfiShellInterface = NULL;
+ mEfiShellEnvironment2Handle = NULL;
+
+ //
+ // verify that auto initialize is not set false
+ //
+ if (PcdGetBool(PcdShellLibAutoInitialize) == 0) {
+ return (EFI_SUCCESS);
+ }
+
+ return (ShellLibConstructorWorker(ImageHandle, SystemTable));
+}
+
+/**
+ Destructor for the library. free any resources.
+
+ @param[in] ImageHandle A copy of the ImageHandle.
+ @param[in] SystemTable A pointer to the SystemTable for the application.
+
+ @retval EFI_SUCCESS The operation was successful.
+ @return An error from the CloseProtocol function.
+**/
+EFI_STATUS
+EFIAPI
+ShellLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ if (mEfiShellEnvironment2 != NULL) {
+ gBS->CloseProtocol(mEfiShellEnvironment2Handle==NULL?ImageHandle:mEfiShellEnvironment2Handle,
+ &gEfiShellEnvironment2Guid,
+ ImageHandle,
+ NULL);
+ mEfiShellEnvironment2 = NULL;
+ }
+ if (mEfiShellInterface != NULL) {
+ gBS->CloseProtocol(ImageHandle,
+ &gEfiShellInterfaceGuid,
+ ImageHandle,
+ NULL);
+ mEfiShellInterface = NULL;
+ }
+ if (gEfiShellProtocol != NULL) {
+ gBS->CloseProtocol(ImageHandle,
+ &gEfiShellProtocolGuid,
+ ImageHandle,
+ NULL);
+ gEfiShellProtocol = NULL;
+ }
+ if (gEfiShellParametersProtocol != NULL) {
+ gBS->CloseProtocol(ImageHandle,
+ &gEfiShellParametersProtocolGuid,
+ ImageHandle,
+ NULL);
+ gEfiShellParametersProtocol = NULL;
+ }
+ mEfiShellEnvironment2Handle = NULL;
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ This function causes the shell library to initialize itself. If the shell library
+ is already initialized it will de-initialize all the current protocol poitners and
+ re-populate them again.
+
+ When the library is used with PcdShellLibAutoInitialize set to true this function
+ will return EFI_SUCCESS and perform no actions.
+
+ This function is intended for internal access for shell commands only.
+
+ @retval EFI_SUCCESS the initialization was complete sucessfully
+
+**/
+EFI_STATUS
+EFIAPI
+ShellInitialize (
+ )
+{
+ EFI_STATUS Status;
+
+ //
+ // if auto initialize is not false then skip
+ //
+ if (PcdGetBool(PcdShellLibAutoInitialize) != 0) {
+ return (EFI_SUCCESS);
+ }
+
+ //
+ // deinit the current stuff
+ //
+ Status = ShellLibDestructor (gImageHandle, gST);
+ ASSERT_EFI_ERROR (Status);
+
+ //
+ // init the new stuff
+ //
+ return (ShellLibConstructorWorker(gImageHandle, gST));
+}
+
+/**
+ This function will retrieve the information about the file for the handle
+ specified and store it in allocated pool memory.
+
+ This function allocates a buffer to store the file's information. It is the
+ caller's responsibility to free the buffer
+
+ @param FileHandle The file handle of the file for which information is
+ being requested.
+
+ @retval NULL information could not be retrieved.
+
+ @return the information about the file
+**/
+EFI_FILE_INFO*
+EFIAPI
+ShellGetFileInfo (
+ IN SHELL_FILE_HANDLE FileHandle
+ )
+{
+ return (FileFunctionMap.GetFileInfo(FileHandle));
+}
+
+/**
+ This function sets the information about the file for the opened handle
+ specified.
+
+ @param[in] FileHandle The file handle of the file for which information
+ is being set.
+
+ @param[in] FileInfo The information to set.
+
+ @retval EFI_SUCCESS The information was set.
+ @retval EFI_INVALID_PARAMETER A parameter was out of range or invalid.
+ @retval EFI_UNSUPPORTED The FileHandle does not support FileInfo.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The file or medium is write protected.
+ @retval EFI_ACCESS_DENIED The file was opened read only.
+ @retval EFI_VOLUME_FULL The volume is full.
+**/
+EFI_STATUS
+EFIAPI
+ShellSetFileInfo (
+ IN SHELL_FILE_HANDLE FileHandle,
+ IN EFI_FILE_INFO *FileInfo
+ )
+{
+ return (FileFunctionMap.SetFileInfo(FileHandle, FileInfo));
+}
+
+ /**
+ This function will open a file or directory referenced by DevicePath.
+
+ This function opens a file with the open mode according to the file path. The
+ Attributes is valid only for EFI_FILE_MODE_CREATE.
+
+ @param FilePath on input the device path to the file. On output
+ the remaining device path.
+ @param DeviceHandle pointer to the system device handle.
+ @param FileHandle pointer to the file handle.
+ @param OpenMode the mode to open the file with.
+ @param Attributes the file's file attributes.
+
+ @retval EFI_SUCCESS The information was set.
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
+ @retval EFI_UNSUPPORTED Could not open the file path.
+ @retval EFI_NOT_FOUND The specified file could not be found on the
+ device or the file system could not be found on
+ the device.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_MEDIA_CHANGED The device has a different medium in it or the
+ medium is no longer supported.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The file or medium is write protected.
+ @retval EFI_ACCESS_DENIED The file was opened read only.
+ @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the
+ file.
+ @retval EFI_VOLUME_FULL The volume is full.
+**/
+EFI_STATUS
+EFIAPI
+ShellOpenFileByDevicePath(
+ IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath,
+ OUT EFI_HANDLE *DeviceHandle,
+ OUT SHELL_FILE_HANDLE *FileHandle,
+ IN UINT64 OpenMode,
+ IN UINT64 Attributes
+ )
+{
+ CHAR16 *FileName;
+ EFI_STATUS Status;
+ EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *EfiSimpleFileSystemProtocol;
+ EFI_FILE_PROTOCOL *Handle1;
+ EFI_FILE_PROTOCOL *Handle2;
+ CHAR16 *FnafPathName;
+ UINTN PathLen;
+
+ if (FilePath == NULL || FileHandle == NULL || DeviceHandle == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ //
+ // which shell interface should we use
+ //
+ if (gEfiShellProtocol != NULL) {
+ //
+ // use UEFI Shell 2.0 method.
+ //
+ FileName = gEfiShellProtocol->GetFilePathFromDevicePath(*FilePath);
+ if (FileName == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+ Status = ShellOpenFileByName(FileName, FileHandle, OpenMode, Attributes);
+ FreePool(FileName);
+ return (Status);
+ }
+
+
+ //
+ // use old shell method.
+ //
+ Status = gBS->LocateDevicePath (&gEfiSimpleFileSystemProtocolGuid,
+ FilePath,
+ DeviceHandle);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = gBS->OpenProtocol(*DeviceHandle,
+ &gEfiSimpleFileSystemProtocolGuid,
+ (VOID**)&EfiSimpleFileSystemProtocol,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = EfiSimpleFileSystemProtocol->OpenVolume(EfiSimpleFileSystemProtocol, &Handle1);
+ if (EFI_ERROR (Status)) {
+ FileHandle = NULL;
+ return Status;
+ }
+
+ //
+ // go down directories one node at a time.
+ //
+ while (!IsDevicePathEnd (*FilePath)) {
+ //
+ // For file system access each node should be a file path component
+ //
+ if (DevicePathType (*FilePath) != MEDIA_DEVICE_PATH ||
+ DevicePathSubType (*FilePath) != MEDIA_FILEPATH_DP
+ ) {
+ FileHandle = NULL;
+ return (EFI_INVALID_PARAMETER);
+ }
+ //
+ // Open this file path node
+ //
+ Handle2 = Handle1;
+ Handle1 = NULL;
+
+ //
+ // File Name Alignment Fix (FNAF)
+ // Handle2->Open may be incapable of handling a unaligned CHAR16 data.
+ // The structure pointed to by FilePath may be not CHAR16 aligned.
+ // This code copies the potentially unaligned PathName data from the
+ // FilePath structure to the aligned FnafPathName for use in the
+ // calls to Handl2->Open.
+ //
+
+ //
+ // Determine length of PathName, in bytes.
+ //
+ PathLen = DevicePathNodeLength (*FilePath) - SIZE_OF_FILEPATH_DEVICE_PATH;
+
+ //
+ // Allocate memory for the aligned copy of the string Extra allocation is to allow for forced alignment
+ // Copy bytes from possibly unaligned location to aligned location
+ //
+ FnafPathName = AllocateCopyPool(PathLen, (UINT8 *)((FILEPATH_DEVICE_PATH*)*FilePath)->PathName);
+ if (FnafPathName == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ //
+ // Try to test opening an existing file
+ //
+ Status = Handle2->Open (
+ Handle2,
+ &Handle1,
+ FnafPathName,
+ OpenMode &~EFI_FILE_MODE_CREATE,
+ 0
+ );
+
+ //
+ // see if the error was that it needs to be created
+ //
+ if ((EFI_ERROR (Status)) && (OpenMode != (OpenMode &~EFI_FILE_MODE_CREATE))) {
+ Status = Handle2->Open (
+ Handle2,
+ &Handle1,
+ FnafPathName,
+ OpenMode,
+ Attributes
+ );
+ }
+
+ //
+ // Free the alignment buffer
+ //
+ FreePool(FnafPathName);
+
+ //
+ // Close the last node
+ //
+ Handle2->Close (Handle2);
+
+ if (EFI_ERROR(Status)) {
+ return (Status);
+ }
+
+ //
+ // Get the next node
+ //
+ *FilePath = NextDevicePathNode (*FilePath);
+ }
+
+ //
+ // This is a weak spot since if the undefined SHELL_FILE_HANDLE format changes this must change also!
+ //
+ *FileHandle = (VOID*)Handle1;
+ return (EFI_SUCCESS);
+}
+
+/**
+ This function will open a file or directory referenced by filename.
+
+ If return is EFI_SUCCESS, the Filehandle is the opened file's handle;
+ otherwise, the Filehandle is NULL. The Attributes is valid only for
+ EFI_FILE_MODE_CREATE.
+
+ if FileName is NULL then ASSERT()
+
+ @param FileName pointer to file name
+ @param FileHandle pointer to the file handle.
+ @param OpenMode the mode to open the file with.
+ @param Attributes the file's file attributes.
+
+ @retval EFI_SUCCESS The information was set.
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
+ @retval EFI_UNSUPPORTED Could not open the file path.
+ @retval EFI_NOT_FOUND The specified file could not be found on the
+ device or the file system could not be found
+ on the device.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_MEDIA_CHANGED The device has a different medium in it or the
+ medium is no longer supported.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The file or medium is write protected.
+ @retval EFI_ACCESS_DENIED The file was opened read only.
+ @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the
+ file.
+ @retval EFI_VOLUME_FULL The volume is full.
+**/
+EFI_STATUS
+EFIAPI
+ShellOpenFileByName(
+ IN CONST CHAR16 *FileName,
+ OUT SHELL_FILE_HANDLE *FileHandle,
+ IN UINT64 OpenMode,
+ IN UINT64 Attributes
+ )
+{
+ EFI_HANDLE DeviceHandle;
+ EFI_DEVICE_PATH_PROTOCOL *FilePath;
+ EFI_STATUS Status;
+ EFI_FILE_INFO *FileInfo;
+ CHAR16 *FileNameCopy;
+ EFI_STATUS Status2;
+
+ //
+ // ASSERT if FileName is NULL
+ //
+ ASSERT(FileName != NULL);
+
+ if (FileName == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ if (gEfiShellProtocol != NULL) {
+ if ((OpenMode & EFI_FILE_MODE_CREATE) == EFI_FILE_MODE_CREATE) {
+
+ //
+ // Create only a directory
+ //
+ if ((Attributes & EFI_FILE_DIRECTORY) == EFI_FILE_DIRECTORY) {
+ return ShellCreateDirectory(FileName, FileHandle);
+ }
+
+ //
+ // Create the directory to create the file in
+ //
+ FileNameCopy = AllocateCopyPool (StrSize (FileName), FileName);
+ if (FileName == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ PathCleanUpDirectories (FileNameCopy);
+ if (PathRemoveLastItem (FileNameCopy)) {
+ if (!EFI_ERROR(ShellCreateDirectory (FileNameCopy, FileHandle))) {
+ ShellCloseFile (FileHandle);
+ }
+ }
+ SHELL_FREE_NON_NULL (FileNameCopy);
+ }
+
+ //
+ // Use UEFI Shell 2.0 method to create the file
+ //
+ Status = gEfiShellProtocol->OpenFileByName(FileName,
+ FileHandle,
+ OpenMode);
+ if (StrCmp(FileName, L"NUL") != 0 && !EFI_ERROR(Status) && ((OpenMode & EFI_FILE_MODE_CREATE) != 0)){
+ FileInfo = FileFunctionMap.GetFileInfo(*FileHandle);
+ ASSERT(FileInfo != NULL);
+ FileInfo->Attribute = Attributes;
+ Status2 = FileFunctionMap.SetFileInfo(*FileHandle, FileInfo);
+ FreePool(FileInfo);
+ if (EFI_ERROR (Status2)) {
+ gEfiShellProtocol->CloseFile(*FileHandle);
+ }
+ Status = Status2;
+ }
+ return (Status);
+ }
+ //
+ // Using EFI Shell version
+ // this means convert name to path and call that function
+ // since this will use EFI method again that will open it.
+ //
+ ASSERT(mEfiShellEnvironment2 != NULL);
+ FilePath = mEfiShellEnvironment2->NameToPath ((CHAR16*)FileName);
+ if (FilePath != NULL) {
+ return (ShellOpenFileByDevicePath(&FilePath,
+ &DeviceHandle,
+ FileHandle,
+ OpenMode,
+ Attributes));
+ }
+ return (EFI_DEVICE_ERROR);
+}
+/**
+ This function create a directory
+
+ If return is EFI_SUCCESS, the Filehandle is the opened directory's handle;
+ otherwise, the Filehandle is NULL. If the directory already existed, this
+ function opens the existing directory.
+
+ @param DirectoryName pointer to directory name
+ @param FileHandle pointer to the file handle.
+
+ @retval EFI_SUCCESS The information was set.
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
+ @retval EFI_UNSUPPORTED Could not open the file path.
+ @retval EFI_NOT_FOUND The specified file could not be found on the
+ device or the file system could not be found
+ on the device.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_MEDIA_CHANGED The device has a different medium in it or the
+ medium is no longer supported.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The file or medium is write protected.
+ @retval EFI_ACCESS_DENIED The file was opened read only.
+ @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the
+ file.
+ @retval EFI_VOLUME_FULL The volume is full.
+ @sa ShellOpenFileByName
+**/
+EFI_STATUS
+EFIAPI
+ShellCreateDirectory(
+ IN CONST CHAR16 *DirectoryName,
+ OUT SHELL_FILE_HANDLE *FileHandle
+ )
+{
+ if (gEfiShellProtocol != NULL) {
+ //
+ // Use UEFI Shell 2.0 method
+ //
+ return (gEfiShellProtocol->CreateFile(DirectoryName,
+ EFI_FILE_DIRECTORY,
+ FileHandle
+ ));
+ } else {
+ return (ShellOpenFileByName(DirectoryName,
+ FileHandle,
+ EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE,
+ EFI_FILE_DIRECTORY
+ ));
+ }
+}
+
+/**
+ This function reads information from an opened file.
+
+ If FileHandle is not a directory, the function reads the requested number of
+ bytes from the file at the file's current position and returns them in Buffer.
+ If the read goes beyond the end of the file, the read length is truncated to the
+ end of the file. The file's current position is increased by the number of bytes
+ returned. If FileHandle is a directory, the function reads the directory entry
+ at the file's current position and returns the entry in Buffer. If the Buffer
+ is not large enough to hold the current directory entry, then
+ EFI_BUFFER_TOO_SMALL is returned and the current file position is not updated.
+ BufferSize is set to be the size of the buffer needed to read the entry. On
+ success, the current position is updated to the next directory entry. If there
+ are no more directory entries, the read returns a zero-length buffer.
+ EFI_FILE_INFO is the structure returned as the directory entry.
+
+ @param FileHandle the opened file handle
+ @param BufferSize on input the size of buffer in bytes. on return
+ the number of bytes written.
+ @param Buffer the buffer to put read data into.
+
+ @retval EFI_SUCCESS Data was read.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_BUFFER_TO_SMALL Buffer is too small. ReadSize contains required
+ size.
+
+**/
+EFI_STATUS
+EFIAPI
+ShellReadFile(
+ IN SHELL_FILE_HANDLE FileHandle,
+ IN OUT UINTN *BufferSize,
+ OUT VOID *Buffer
+ )
+{
+ return (FileFunctionMap.ReadFile(FileHandle, BufferSize, Buffer));
+}
+
+
+/**
+ Write data to a file.
+
+ This function writes the specified number of bytes to the file at the current
+ file position. The current file position is advanced the actual number of bytes
+ written, which is returned in BufferSize. Partial writes only occur when there
+ has been a data error during the write attempt (such as "volume space full").
+ The file is automatically grown to hold the data if required. Direct writes to
+ opened directories are not supported.
+
+ @param FileHandle The opened file for writing
+ @param BufferSize on input the number of bytes in Buffer. On output
+ the number of bytes written.
+ @param Buffer the buffer containing data to write is stored.
+
+ @retval EFI_SUCCESS Data was written.
+ @retval EFI_UNSUPPORTED Writes to an open directory are not supported.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The device is write-protected.
+ @retval EFI_ACCESS_DENIED The file was open for read only.
+ @retval EFI_VOLUME_FULL The volume is full.
+**/
+EFI_STATUS
+EFIAPI
+ShellWriteFile(
+ IN SHELL_FILE_HANDLE FileHandle,
+ IN OUT UINTN *BufferSize,
+ IN VOID *Buffer
+ )
+{
+ return (FileFunctionMap.WriteFile(FileHandle, BufferSize, Buffer));
+}
+
+/**
+ Close an open file handle.
+
+ This function closes a specified file handle. All "dirty" cached file data is
+ flushed to the device, and the file is closed. In all cases the handle is
+ closed.
+
+@param FileHandle the file handle to close.
+
+@retval EFI_SUCCESS the file handle was closed sucessfully.
+**/
+EFI_STATUS
+EFIAPI
+ShellCloseFile (
+ IN SHELL_FILE_HANDLE *FileHandle
+ )
+{
+ return (FileFunctionMap.CloseFile(*FileHandle));
+}
+
+/**
+ Delete a file and close the handle
+
+ This function closes and deletes a file. In all cases the file handle is closed.
+ If the file cannot be deleted, the warning code EFI_WARN_DELETE_FAILURE is
+ returned, but the handle is still closed.
+
+ @param FileHandle the file handle to delete
+
+ @retval EFI_SUCCESS the file was closed sucessfully
+ @retval EFI_WARN_DELETE_FAILURE the handle was closed, but the file was not
+ deleted
+ @retval INVALID_PARAMETER One of the parameters has an invalid value.
+**/
+EFI_STATUS
+EFIAPI
+ShellDeleteFile (
+ IN SHELL_FILE_HANDLE *FileHandle
+ )
+{
+ return (FileFunctionMap.DeleteFile(*FileHandle));
+}
+
+/**
+ Set the current position in a file.
+
+ This function sets the current file position for the handle to the position
+ supplied. With the exception of seeking to position 0xFFFFFFFFFFFFFFFF, only
+ absolute positioning is supported, and seeking past the end of the file is
+ allowed (a subsequent write would grow the file). Seeking to position
+ 0xFFFFFFFFFFFFFFFF causes the current position to be set to the end of the file.
+ If FileHandle is a directory, the only position that may be set is zero. This
+ has the effect of starting the read process of the directory entries over.
+
+ @param FileHandle The file handle on which the position is being set
+ @param Position Byte position from begining of file
+
+ @retval EFI_SUCCESS Operation completed sucessfully.
+ @retval EFI_UNSUPPORTED the seek request for non-zero is not valid on
+ directories.
+ @retval INVALID_PARAMETER One of the parameters has an invalid value.
+**/
+EFI_STATUS
+EFIAPI
+ShellSetFilePosition (
+ IN SHELL_FILE_HANDLE FileHandle,
+ IN UINT64 Position
+ )
+{
+ return (FileFunctionMap.SetFilePosition(FileHandle, Position));
+}
+
+/**
+ Gets a file's current position
+
+ This function retrieves the current file position for the file handle. For
+ directories, the current file position has no meaning outside of the file
+ system driver and as such the operation is not supported. An error is returned
+ if FileHandle is a directory.
+
+ @param FileHandle The open file handle on which to get the position.
+ @param Position Byte position from begining of file.
+
+ @retval EFI_SUCCESS the operation completed sucessfully.
+ @retval INVALID_PARAMETER One of the parameters has an invalid value.
+ @retval EFI_UNSUPPORTED the request is not valid on directories.
+**/
+EFI_STATUS
+EFIAPI
+ShellGetFilePosition (
+ IN SHELL_FILE_HANDLE FileHandle,
+ OUT UINT64 *Position
+ )
+{
+ return (FileFunctionMap.GetFilePosition(FileHandle, Position));
+}
+/**
+ Flushes data on a file
+
+ This function flushes all modified data associated with a file to a device.
+
+ @param FileHandle The file handle on which to flush data
+
+ @retval EFI_SUCCESS The data was flushed.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The file or medium is write protected.
+ @retval EFI_ACCESS_DENIED The file was opened for read only.
+**/
+EFI_STATUS
+EFIAPI
+ShellFlushFile (
+ IN SHELL_FILE_HANDLE FileHandle
+ )
+{
+ return (FileFunctionMap.FlushFile(FileHandle));
+}
+
+/** Retrieve first entry from a directory.
+
+ This function takes an open directory handle and gets information from the
+ first entry in the directory. A buffer is allocated to contain
+ the information and a pointer to the buffer is returned in *Buffer. The
+ caller can use ShellFindNextFile() to get subsequent directory entries.
+
+ The buffer will be freed by ShellFindNextFile() when the last directory
+ entry is read. Otherwise, the caller must free the buffer, using FreePool,
+ when finished with it.
+
+ @param[in] DirHandle The file handle of the directory to search.
+ @param[out] Buffer The pointer to the buffer for the file's information.
+
+ @retval EFI_SUCCESS Found the first file.
+ @retval EFI_NOT_FOUND Cannot find the directory.
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @return Others status of ShellGetFileInfo, ShellSetFilePosition,
+ or ShellReadFile
+**/
+EFI_STATUS
+EFIAPI
+ShellFindFirstFile (
+ IN SHELL_FILE_HANDLE DirHandle,
+ OUT EFI_FILE_INFO **Buffer
+ )
+{
+ //
+ // pass to file handle lib
+ //
+ return (FileHandleFindFirstFile(DirHandle, Buffer));
+}
+/** Retrieve next entries from a directory.
+
+ To use this function, the caller must first call the ShellFindFirstFile()
+ function to get the first directory entry. Subsequent directory entries are
+ retrieved by using the ShellFindNextFile() function. This function can
+ be called several times to get each entry from the directory. If the call of
+ ShellFindNextFile() retrieved the last directory entry, the next call of
+ this function will set *NoFile to TRUE and free the buffer.
+
+ @param[in] DirHandle The file handle of the directory.
+ @param[out] Buffer The pointer to buffer for file's information.
+ @param[out] NoFile The pointer to boolean when last file is found.
+
+ @retval EFI_SUCCESS Found the next file, or reached last file
+ @retval EFI_NO_MEDIA The device has no media.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+**/
+EFI_STATUS
+EFIAPI
+ShellFindNextFile(
+ IN SHELL_FILE_HANDLE DirHandle,
+ OUT EFI_FILE_INFO *Buffer,
+ OUT BOOLEAN *NoFile
+ )
+{
+ //
+ // pass to file handle lib
+ //
+ return (FileHandleFindNextFile(DirHandle, Buffer, NoFile));
+}
+/**
+ Retrieve the size of a file.
+
+ if FileHandle is NULL then ASSERT()
+ if Size is NULL then ASSERT()
+
+ This function extracts the file size info from the FileHandle's EFI_FILE_INFO
+ data.
+
+ @param FileHandle file handle from which size is retrieved
+ @param Size pointer to size
+
+ @retval EFI_SUCCESS operation was completed sucessfully
+ @retval EFI_DEVICE_ERROR cannot access the file
+**/
+EFI_STATUS
+EFIAPI
+ShellGetFileSize (
+ IN SHELL_FILE_HANDLE FileHandle,
+ OUT UINT64 *Size
+ )
+{
+ return (FileFunctionMap.GetFileSize(FileHandle, Size));
+}
+/**
+ Retrieves the status of the break execution flag
+
+ this function is useful to check whether the application is being asked to halt by the shell.
+
+ @retval TRUE the execution break is enabled
+ @retval FALSE the execution break is not enabled
+**/
+BOOLEAN
+EFIAPI
+ShellGetExecutionBreakFlag(
+ VOID
+ )
+{
+ //
+ // Check for UEFI Shell 2.0 protocols
+ //
+ if (gEfiShellProtocol != NULL) {
+
+ //
+ // We are using UEFI Shell 2.0; see if the event has been triggered
+ //
+ if (gBS->CheckEvent(gEfiShellProtocol->ExecutionBreak) != EFI_SUCCESS) {
+ return (FALSE);
+ }
+ return (TRUE);
+ }
+
+ //
+ // using EFI Shell; call the function to check
+ //
+ if (mEfiShellEnvironment2 != NULL) {
+ return (mEfiShellEnvironment2->GetExecutionBreak());
+ }
+
+ return (FALSE);
+}
+/**
+ return the value of an environment variable
+
+ this function gets the value of the environment variable set by the
+ ShellSetEnvironmentVariable function
+
+ @param EnvKey The key name of the environment variable.
+
+ @retval NULL the named environment variable does not exist.
+ @return != NULL pointer to the value of the environment variable
+**/
+CONST CHAR16*
+EFIAPI
+ShellGetEnvironmentVariable (
+ IN CONST CHAR16 *EnvKey
+ )
+{
+ //
+ // Check for UEFI Shell 2.0 protocols
+ //
+ if (gEfiShellProtocol != NULL) {
+ return (gEfiShellProtocol->GetEnv(EnvKey));
+ }
+
+ //
+ // Check for EFI shell
+ //
+ if (mEfiShellEnvironment2 != NULL) {
+ return (mEfiShellEnvironment2->GetEnv((CHAR16*)EnvKey));
+ }
+
+ return NULL;
+}
+/**
+ set the value of an environment variable
+
+This function changes the current value of the specified environment variable. If the
+environment variable exists and the Value is an empty string, then the environment
+variable is deleted. If the environment variable exists and the Value is not an empty
+string, then the value of the environment variable is changed. If the environment
+variable does not exist and the Value is an empty string, there is no action. If the
+environment variable does not exist and the Value is a non-empty string, then the
+environment variable is created and assigned the specified value.
+
+ This is not supported pre-UEFI Shell 2.0.
+
+ @param EnvKey The key name of the environment variable.
+ @param EnvVal The Value of the environment variable
+ @param Volatile Indicates whether the variable is non-volatile (FALSE) or volatile (TRUE).
+
+ @retval EFI_SUCCESS the operation was completed sucessfully
+ @retval EFI_UNSUPPORTED This operation is not allowed in pre UEFI 2.0 Shell environments
+**/
+EFI_STATUS
+EFIAPI
+ShellSetEnvironmentVariable (
+ IN CONST CHAR16 *EnvKey,
+ IN CONST CHAR16 *EnvVal,
+ IN BOOLEAN Volatile
+ )
+{
+ //
+ // Check for UEFI Shell 2.0 protocols
+ //
+ if (gEfiShellProtocol != NULL) {
+ return (gEfiShellProtocol->SetEnv(EnvKey, EnvVal, Volatile));
+ }
+
+ //
+ // This feature does not exist under EFI shell
+ //
+ return (EFI_UNSUPPORTED);
+}
+
+/**
+ Cause the shell to parse and execute a command line.
+
+ This function creates a nested instance of the shell and executes the specified
+ command (CommandLine) with the specified environment (Environment). Upon return,
+ the status code returned by the specified command is placed in StatusCode.
+ If Environment is NULL, then the current environment is used and all changes made
+ by the commands executed will be reflected in the current environment. If the
+ Environment is non-NULL, then the changes made will be discarded.
+ The CommandLine is executed from the current working directory on the current
+ device.
+
+ The EnvironmentVariables pararemeter is ignored in a pre-UEFI Shell 2.0
+ environment. The values pointed to by the parameters will be unchanged by the
+ ShellExecute() function. The Output parameter has no effect in a
+ UEFI Shell 2.0 environment.
+
+ @param[in] ParentHandle The parent image starting the operation.
+ @param[in] CommandLine The pointer to a NULL terminated command line.
+ @param[in] Output True to display debug output. False to hide it.
+ @param[in] EnvironmentVariables Optional pointer to array of environment variables
+ in the form "x=y". If NULL, the current set is used.
+ @param[out] Status The status of the run command line.
+
+ @retval EFI_SUCCESS The operation completed sucessfully. Status
+ contains the status code returned.
+ @retval EFI_INVALID_PARAMETER A parameter contains an invalid value.
+ @retval EFI_OUT_OF_RESOURCES Out of resources.
+ @retval EFI_UNSUPPORTED The operation is not allowed.
+**/
+EFI_STATUS
+EFIAPI
+ShellExecute (
+ IN EFI_HANDLE *ParentHandle,
+ IN CHAR16 *CommandLine OPTIONAL,
+ IN BOOLEAN Output OPTIONAL,
+ IN CHAR16 **EnvironmentVariables OPTIONAL,
+ OUT EFI_STATUS *Status OPTIONAL
+ )
+{
+ EFI_STATUS CmdStatus;
+ //
+ // Check for UEFI Shell 2.0 protocols
+ //
+ if (gEfiShellProtocol != NULL) {
+ //
+ // Call UEFI Shell 2.0 version (not using Output parameter)
+ //
+ return (gEfiShellProtocol->Execute(ParentHandle,
+ CommandLine,
+ EnvironmentVariables,
+ Status));
+ }
+
+ //
+ // Check for EFI shell
+ //
+ if (mEfiShellEnvironment2 != NULL) {
+ //
+ // Call EFI Shell version.
+ // Due to oddity in the EFI shell we want to dereference the ParentHandle here
+ //
+ CmdStatus = (mEfiShellEnvironment2->Execute(*ParentHandle,
+ CommandLine,
+ Output));
+ //
+ // No Status output parameter so just use the returned status
+ //
+ if (Status != NULL) {
+ *Status = CmdStatus;
+ }
+ //
+ // If there was an error, we can't tell if it was from the command or from
+ // the Execute() function, so we'll just assume the shell ran successfully
+ // and the error came from the command.
+ //
+ return EFI_SUCCESS;
+ }
+
+ return (EFI_UNSUPPORTED);
+}
+
+/**
+ Retreives the current directory path
+
+ If the DeviceName is NULL, it returns the current device's current directory
+ name. If the DeviceName is not NULL, it returns the current directory name
+ on specified drive.
+
+ Note that the current directory string should exclude the tailing backslash character.
+
+ @param DeviceName the name of the drive to get directory on
+
+ @retval NULL the directory does not exist
+ @return != NULL the directory
+**/
+CONST CHAR16*
+EFIAPI
+ShellGetCurrentDir (
+ IN CHAR16 * CONST DeviceName OPTIONAL
+ )
+{
+ //
+ // Check for UEFI Shell 2.0 protocols
+ //
+ if (gEfiShellProtocol != NULL) {
+ return (gEfiShellProtocol->GetCurDir(DeviceName));
+ }
+
+ //
+ // Check for EFI shell
+ //
+ if (mEfiShellEnvironment2 != NULL) {
+ return (mEfiShellEnvironment2->CurDir(DeviceName));
+ }
+
+ return (NULL);
+}
+/**
+ sets (enabled or disabled) the page break mode
+
+ when page break mode is enabled the screen will stop scrolling
+ and wait for operator input before scrolling a subsequent screen.
+
+ @param CurrentState TRUE to enable and FALSE to disable
+**/
+VOID
+EFIAPI
+ShellSetPageBreakMode (
+ IN BOOLEAN CurrentState
+ )
+{
+ //
+ // check for enabling
+ //
+ if (CurrentState != 0x00) {
+ //
+ // check for UEFI Shell 2.0
+ //
+ if (gEfiShellProtocol != NULL) {
+ //
+ // Enable with UEFI 2.0 Shell
+ //
+ gEfiShellProtocol->EnablePageBreak();
+ return;
+ } else {
+ //
+ // Check for EFI shell
+ //
+ if (mEfiShellEnvironment2 != NULL) {
+ //
+ // Enable with EFI Shell
+ //
+ mEfiShellEnvironment2->EnablePageBreak (DEFAULT_INIT_ROW, DEFAULT_AUTO_LF);
+ return;
+ }
+ }
+ } else {
+ //
+ // check for UEFI Shell 2.0
+ //
+ if (gEfiShellProtocol != NULL) {
+ //
+ // Disable with UEFI 2.0 Shell
+ //
+ gEfiShellProtocol->DisablePageBreak();
+ return;
+ } else {
+ //
+ // Check for EFI shell
+ //
+ if (mEfiShellEnvironment2 != NULL) {
+ //
+ // Disable with EFI Shell
+ //
+ mEfiShellEnvironment2->DisablePageBreak ();
+ return;
+ }
+ }
+ }
+}
+
+///
+/// version of EFI_SHELL_FILE_INFO struct, except has no CONST pointers.
+/// This allows for the struct to be populated.
+///
+typedef struct {
+ LIST_ENTRY Link;
+ EFI_STATUS Status;
+ CHAR16 *FullName;
+ CHAR16 *FileName;
+ SHELL_FILE_HANDLE Handle;
+ EFI_FILE_INFO *Info;
+} EFI_SHELL_FILE_INFO_NO_CONST;
+
+/**
+ Converts a EFI shell list of structures to the coresponding UEFI Shell 2.0 type of list.
+
+ if OldStyleFileList is NULL then ASSERT()
+
+ this function will convert a SHELL_FILE_ARG based list into a callee allocated
+ EFI_SHELL_FILE_INFO based list. it is up to the caller to free the memory via
+ the ShellCloseFileMetaArg function.
+
+ @param[in] FileList the EFI shell list type
+ @param[in, out] ListHead the list to add to
+
+ @retval the resultant head of the double linked new format list;
+**/
+LIST_ENTRY*
+EFIAPI
+InternalShellConvertFileListType (
+ IN LIST_ENTRY *FileList,
+ IN OUT LIST_ENTRY *ListHead
+ )
+{
+ SHELL_FILE_ARG *OldInfo;
+ LIST_ENTRY *Link;
+ EFI_SHELL_FILE_INFO_NO_CONST *NewInfo;
+
+ //
+ // ASSERTs
+ //
+ ASSERT(FileList != NULL);
+ ASSERT(ListHead != NULL);
+
+ //
+ // enumerate through each member of the old list and copy
+ //
+ for (Link = FileList->ForwardLink; Link != FileList; Link = Link->ForwardLink) {
+ OldInfo = CR (Link, SHELL_FILE_ARG, Link, SHELL_FILE_ARG_SIGNATURE);
+ ASSERT(OldInfo != NULL);
+
+ //
+ // Skip ones that failed to open...
+ //
+ if (OldInfo->Status != EFI_SUCCESS) {
+ continue;
+ }
+
+ //
+ // make sure the old list was valid
+ //
+ ASSERT(OldInfo->Info != NULL);
+ ASSERT(OldInfo->FullName != NULL);
+ ASSERT(OldInfo->FileName != NULL);
+
+ //
+ // allocate a new EFI_SHELL_FILE_INFO object
+ //
+ NewInfo = AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));
+ if (NewInfo == NULL) {
+ ShellCloseFileMetaArg((EFI_SHELL_FILE_INFO**)(&ListHead));
+ ListHead = NULL;
+ break;
+ }
+
+ //
+ // copy the simple items
+ //
+ NewInfo->Handle = OldInfo->Handle;
+ NewInfo->Status = OldInfo->Status;
+
+ // old shell checks for 0 not NULL
+ OldInfo->Handle = 0;
+
+ //
+ // allocate new space to copy strings and structure
+ //
+ NewInfo->FullName = AllocateCopyPool(StrSize(OldInfo->FullName), OldInfo->FullName);
+ NewInfo->FileName = AllocateCopyPool(StrSize(OldInfo->FileName), OldInfo->FileName);
+ NewInfo->Info = AllocateCopyPool((UINTN)OldInfo->Info->Size, OldInfo->Info);
+
+ //
+ // make sure all the memory allocations were sucessful
+ //
+ if (NULL == NewInfo->FullName || NewInfo->FileName == NULL || NewInfo->Info == NULL) {
+ //
+ // Free the partially allocated new node
+ //
+ SHELL_FREE_NON_NULL(NewInfo->FullName);
+ SHELL_FREE_NON_NULL(NewInfo->FileName);
+ SHELL_FREE_NON_NULL(NewInfo->Info);
+ SHELL_FREE_NON_NULL(NewInfo);
+
+ //
+ // Free the previously converted stuff
+ //
+ ShellCloseFileMetaArg((EFI_SHELL_FILE_INFO**)(&ListHead));
+ ListHead = NULL;
+ break;
+ }
+
+ //
+ // add that to the list
+ //
+ InsertTailList(ListHead, &NewInfo->Link);
+ }
+ return (ListHead);
+}
+/**
+ Opens a group of files based on a path.
+
+ This function uses the Arg to open all the matching files. Each matched
+ file has a SHELL_FILE_INFO structure to record the file information. These
+ structures are placed on the list ListHead. Users can get the SHELL_FILE_INFO
+ structures from ListHead to access each file. This function supports wildcards
+ and will process '?' and '*' as such. the list must be freed with a call to
+ ShellCloseFileMetaArg().
+
+ If you are NOT appending to an existing list *ListHead must be NULL. If
+ *ListHead is NULL then it must be callee freed.
+
+ @param Arg pointer to path string
+ @param OpenMode mode to open files with
+ @param ListHead head of linked list of results
+
+ @retval EFI_SUCCESS the operation was sucessful and the list head
+ contains the list of opened files
+ @return != EFI_SUCCESS the operation failed
+
+ @sa InternalShellConvertFileListType
+**/
+EFI_STATUS
+EFIAPI
+ShellOpenFileMetaArg (
+ IN CHAR16 *Arg,
+ IN UINT64 OpenMode,
+ IN OUT EFI_SHELL_FILE_INFO **ListHead
+ )
+{
+ EFI_STATUS Status;
+ LIST_ENTRY mOldStyleFileList;
+ CHAR16 *CleanFilePathStr;
+
+ //
+ // ASSERT that Arg and ListHead are not NULL
+ //
+ ASSERT(Arg != NULL);
+ ASSERT(ListHead != NULL);
+
+ CleanFilePathStr = NULL;
+
+ Status = InternalShellStripQuotes (Arg, &CleanFilePathStr);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Check for UEFI Shell 2.0 protocols
+ //
+ if (gEfiShellProtocol != NULL) {
+ if (*ListHead == NULL) {
+ *ListHead = (EFI_SHELL_FILE_INFO*)AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));
+ if (*ListHead == NULL) {
+ FreePool(CleanFilePathStr);
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ InitializeListHead(&((*ListHead)->Link));
+ }
+ Status = gEfiShellProtocol->OpenFileList(CleanFilePathStr,
+ OpenMode,
+ ListHead);
+ if (EFI_ERROR(Status)) {
+ gEfiShellProtocol->RemoveDupInFileList(ListHead);
+ } else {
+ Status = gEfiShellProtocol->RemoveDupInFileList(ListHead);
+ }
+ if (*ListHead != NULL && IsListEmpty(&(*ListHead)->Link)) {
+ FreePool(*ListHead);
+ FreePool(CleanFilePathStr);
+ *ListHead = NULL;
+ return (EFI_NOT_FOUND);
+ }
+ FreePool(CleanFilePathStr);
+ return (Status);
+ }
+
+ //
+ // Check for EFI shell
+ //
+ if (mEfiShellEnvironment2 != NULL) {
+ //
+ // make sure the list head is initialized
+ //
+ InitializeListHead(&mOldStyleFileList);
+
+ //
+ // Get the EFI Shell list of files
+ //
+ Status = mEfiShellEnvironment2->FileMetaArg(CleanFilePathStr, &mOldStyleFileList);
+ if (EFI_ERROR(Status)) {
+ *ListHead = NULL;
+ FreePool(CleanFilePathStr);
+ return (Status);
+ }
+
+ if (*ListHead == NULL) {
+ *ListHead = (EFI_SHELL_FILE_INFO *)AllocateZeroPool(sizeof(EFI_SHELL_FILE_INFO));
+ if (*ListHead == NULL) {
+ FreePool(CleanFilePathStr);
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ InitializeListHead(&((*ListHead)->Link));
+ }
+
+ //
+ // Convert that to equivalent of UEFI Shell 2.0 structure
+ //
+ InternalShellConvertFileListType(&mOldStyleFileList, &(*ListHead)->Link);
+
+ //
+ // Free the EFI Shell version that was converted.
+ //
+ mEfiShellEnvironment2->FreeFileList(&mOldStyleFileList);
+
+ if ((*ListHead)->Link.ForwardLink == (*ListHead)->Link.BackLink && (*ListHead)->Link.BackLink == &((*ListHead)->Link)) {
+ FreePool(*ListHead);
+ *ListHead = NULL;
+ Status = EFI_NOT_FOUND;
+ }
+ FreePool(CleanFilePathStr);
+ return (Status);
+ }
+
+ FreePool(CleanFilePathStr);
+ return (EFI_UNSUPPORTED);
+}
+/**
+ Free the linked list returned from ShellOpenFileMetaArg.
+
+ if ListHead is NULL then ASSERT().
+
+ @param ListHead the pointer to free.
+
+ @retval EFI_SUCCESS the operation was sucessful.
+**/
+EFI_STATUS
+EFIAPI
+ShellCloseFileMetaArg (
+ IN OUT EFI_SHELL_FILE_INFO **ListHead
+ )
+{
+ LIST_ENTRY *Node;
+
+ //
+ // ASSERT that ListHead is not NULL
+ //
+ ASSERT(ListHead != NULL);
+
+ //
+ // Check for UEFI Shell 2.0 protocols
+ //
+ if (gEfiShellProtocol != NULL) {
+ return (gEfiShellProtocol->FreeFileList(ListHead));
+ } else if (mEfiShellEnvironment2 != NULL) {
+ //
+ // Since this is EFI Shell version we need to free our internally made copy
+ // of the list
+ //
+ for ( Node = GetFirstNode(&(*ListHead)->Link)
+ ; *ListHead != NULL && !IsListEmpty(&(*ListHead)->Link)
+ ; Node = GetFirstNode(&(*ListHead)->Link)) {
+ RemoveEntryList(Node);
+ ((EFI_FILE_PROTOCOL*)((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle)->Close(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Handle);
+ FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->FullName);
+ FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->FileName);
+ FreePool(((EFI_SHELL_FILE_INFO_NO_CONST*)Node)->Info);
+ FreePool((EFI_SHELL_FILE_INFO_NO_CONST*)Node);
+ }
+ SHELL_FREE_NON_NULL(*ListHead);
+ return EFI_SUCCESS;
+ }
+
+ return (EFI_UNSUPPORTED);
+}
+
+/**
+ Find a file by searching the CWD and then the path.
+
+ If FileName is NULL then ASSERT.
+
+ If the return value is not NULL then the memory must be caller freed.
+
+ @param FileName Filename string.
+
+ @retval NULL the file was not found
+ @return !NULL the full path to the file.
+**/
+CHAR16 *
+EFIAPI
+ShellFindFilePath (
+ IN CONST CHAR16 *FileName
+ )
+{
+ CONST CHAR16 *Path;
+ SHELL_FILE_HANDLE Handle;
+ EFI_STATUS Status;
+ CHAR16 *RetVal;
+ CHAR16 *TestPath;
+ CONST CHAR16 *Walker;
+ UINTN Size;
+ CHAR16 *TempChar;
+
+ RetVal = NULL;
+
+ //
+ // First make sure its not an absolute path.
+ //
+ Status = ShellOpenFileByName(FileName, &Handle, EFI_FILE_MODE_READ, 0);
+ if (!EFI_ERROR(Status)){
+ if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) {
+ ASSERT(RetVal == NULL);
+ RetVal = StrnCatGrow(&RetVal, NULL, FileName, 0);
+ ShellCloseFile(&Handle);
+ return (RetVal);
+ } else {
+ ShellCloseFile(&Handle);
+ }
+ }
+
+ Path = ShellGetEnvironmentVariable(L"cwd");
+ if (Path != NULL) {
+ Size = StrSize(Path) + sizeof(CHAR16);
+ Size += StrSize(FileName);
+ TestPath = AllocateZeroPool(Size);
+ if (TestPath == NULL) {
+ return (NULL);
+ }
+ StrCpyS(TestPath, Size/sizeof(CHAR16), Path);
+ StrCatS(TestPath, Size/sizeof(CHAR16), L"\\");
+ StrCatS(TestPath, Size/sizeof(CHAR16), FileName);
+ Status = ShellOpenFileByName(TestPath, &Handle, EFI_FILE_MODE_READ, 0);
+ if (!EFI_ERROR(Status)){
+ if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) {
+ ASSERT(RetVal == NULL);
+ RetVal = StrnCatGrow(&RetVal, NULL, TestPath, 0);
+ ShellCloseFile(&Handle);
+ FreePool(TestPath);
+ return (RetVal);
+ } else {
+ ShellCloseFile(&Handle);
+ }
+ }
+ FreePool(TestPath);
+ }
+ Path = ShellGetEnvironmentVariable(L"path");
+ if (Path != NULL) {
+ Size = StrSize(Path)+sizeof(CHAR16);
+ Size += StrSize(FileName);
+ TestPath = AllocateZeroPool(Size);
+ if (TestPath == NULL) {
+ return (NULL);
+ }
+ Walker = (CHAR16*)Path;
+ do {
+ CopyMem(TestPath, Walker, StrSize(Walker));
+ if (TestPath != NULL) {
+ TempChar = StrStr(TestPath, L";");
+ if (TempChar != NULL) {
+ *TempChar = CHAR_NULL;
+ }
+ if (TestPath[StrLen(TestPath)-1] != L'\\') {
+ StrCatS(TestPath, Size/sizeof(CHAR16), L"\\");
+ }
+ if (FileName[0] == L'\\') {
+ FileName++;
+ }
+ StrCatS(TestPath, Size/sizeof(CHAR16), FileName);
+ if (StrStr(Walker, L";") != NULL) {
+ Walker = StrStr(Walker, L";") + 1;
+ } else {
+ Walker = NULL;
+ }
+ Status = ShellOpenFileByName(TestPath, &Handle, EFI_FILE_MODE_READ, 0);
+ if (!EFI_ERROR(Status)){
+ if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) {
+ ASSERT(RetVal == NULL);
+ RetVal = StrnCatGrow(&RetVal, NULL, TestPath, 0);
+ ShellCloseFile(&Handle);
+ break;
+ } else {
+ ShellCloseFile(&Handle);
+ }
+ }
+ }
+ } while (Walker != NULL && Walker[0] != CHAR_NULL);
+ FreePool(TestPath);
+ }
+ return (RetVal);
+}
+
+/**
+ Find a file by searching the CWD and then the path with a variable set of file
+ extensions. If the file is not found it will append each extension in the list
+ in the order provided and return the first one that is successful.
+
+ If FileName is NULL, then ASSERT.
+ If FileExtension is NULL, then behavior is identical to ShellFindFilePath.
+
+ If the return value is not NULL then the memory must be caller freed.
+
+ @param[in] FileName Filename string.
+ @param[in] FileExtension Semi-colon delimeted list of possible extensions.
+
+ @retval NULL The file was not found.
+ @retval !NULL The path to the file.
+**/
+CHAR16 *
+EFIAPI
+ShellFindFilePathEx (
+ IN CONST CHAR16 *FileName,
+ IN CONST CHAR16 *FileExtension
+ )
+{
+ CHAR16 *TestPath;
+ CHAR16 *RetVal;
+ CONST CHAR16 *ExtensionWalker;
+ UINTN Size;
+ CHAR16 *TempChar;
+ CHAR16 *TempChar2;
+
+ ASSERT(FileName != NULL);
+ if (FileExtension == NULL) {
+ return (ShellFindFilePath(FileName));
+ }
+ RetVal = ShellFindFilePath(FileName);
+ if (RetVal != NULL) {
+ return (RetVal);
+ }
+ Size = StrSize(FileName);
+ Size += StrSize(FileExtension);
+ TestPath = AllocateZeroPool(Size);
+ if (TestPath == NULL) {
+ return (NULL);
+ }
+ for (ExtensionWalker = FileExtension, TempChar2 = (CHAR16*)FileExtension; TempChar2 != NULL ; ExtensionWalker = TempChar2 + 1){
+ StrCpyS(TestPath, Size/sizeof(CHAR16), FileName);
+ if (ExtensionWalker != NULL) {
+ StrCatS(TestPath, Size/sizeof(CHAR16), ExtensionWalker);
+ }
+ TempChar = StrStr(TestPath, L";");
+ if (TempChar != NULL) {
+ *TempChar = CHAR_NULL;
+ }
+ RetVal = ShellFindFilePath(TestPath);
+ if (RetVal != NULL) {
+ break;
+ }
+ ASSERT(ExtensionWalker != NULL);
+ TempChar2 = StrStr(ExtensionWalker, L";");
+ }
+ FreePool(TestPath);
+ return (RetVal);
+}
+
+typedef struct {
+ LIST_ENTRY Link;
+ CHAR16 *Name;
+ SHELL_PARAM_TYPE Type;
+ CHAR16 *Value;
+ UINTN OriginalPosition;
+} SHELL_PARAM_PACKAGE;
+
+/**
+ Checks the list of valid arguments and returns TRUE if the item was found. If the
+ return value is TRUE then the type parameter is set also.
+
+ if CheckList is NULL then ASSERT();
+ if Name is NULL then ASSERT();
+ if Type is NULL then ASSERT();
+
+ @param Name pointer to Name of parameter found
+ @param CheckList List to check against
+ @param Type pointer to type of parameter if it was found
+
+ @retval TRUE the Parameter was found. Type is valid.
+ @retval FALSE the Parameter was not found. Type is not valid.
+**/
+BOOLEAN
+EFIAPI
+InternalIsOnCheckList (
+ IN CONST CHAR16 *Name,
+ IN CONST SHELL_PARAM_ITEM *CheckList,
+ OUT SHELL_PARAM_TYPE *Type
+ )
+{
+ SHELL_PARAM_ITEM *TempListItem;
+ CHAR16 *TempString;
+
+ //
+ // ASSERT that all 3 pointer parameters aren't NULL
+ //
+ ASSERT(CheckList != NULL);
+ ASSERT(Type != NULL);
+ ASSERT(Name != NULL);
+
+ //
+ // question mark and page break mode are always supported
+ //
+ if ((StrCmp(Name, L"-?") == 0) ||
+ (StrCmp(Name, L"-b") == 0)
+ ) {
+ *Type = TypeFlag;
+ return (TRUE);
+ }
+
+ //
+ // Enumerate through the list
+ //
+ for (TempListItem = (SHELL_PARAM_ITEM*)CheckList ; TempListItem->Name != NULL ; TempListItem++) {
+ //
+ // If the Type is TypeStart only check the first characters of the passed in param
+ // If it matches set the type and return TRUE
+ //
+ if (TempListItem->Type == TypeStart) {
+ if (StrnCmp(Name, TempListItem->Name, StrLen(TempListItem->Name)) == 0) {
+ *Type = TempListItem->Type;
+ return (TRUE);
+ }
+ TempString = NULL;
+ TempString = StrnCatGrow(&TempString, NULL, Name, StrLen(TempListItem->Name));
+ if (TempString != NULL) {
+ if (StringNoCaseCompare(&TempString, &TempListItem->Name) == 0) {
+ *Type = TempListItem->Type;
+ FreePool(TempString);
+ return (TRUE);
+ }
+ FreePool(TempString);
+ }
+ } else if (StringNoCaseCompare(&Name, &TempListItem->Name) == 0) {
+ *Type = TempListItem->Type;
+ return (TRUE);
+ }
+ }
+
+ return (FALSE);
+}
+/**
+ Checks the string for indicators of "flag" status. this is a leading '/', '-', or '+'
+
+ @param[in] Name pointer to Name of parameter found
+ @param[in] AlwaysAllowNumbers TRUE to allow numbers, FALSE to not.
+ @param[in] TimeNumbers TRUE to allow numbers with ":", FALSE otherwise.
+
+ @retval TRUE the Parameter is a flag.
+ @retval FALSE the Parameter not a flag.
+**/
+BOOLEAN
+EFIAPI
+InternalIsFlag (
+ IN CONST CHAR16 *Name,
+ IN CONST BOOLEAN AlwaysAllowNumbers,
+ IN CONST BOOLEAN TimeNumbers
+ )
+{
+ //
+ // ASSERT that Name isn't NULL
+ //
+ ASSERT(Name != NULL);
+
+ //
+ // If we accept numbers then dont return TRUE. (they will be values)
+ //
+ if (((Name[0] == L'-' || Name[0] == L'+') && InternalShellIsHexOrDecimalNumber(Name+1, FALSE, FALSE, TimeNumbers)) && AlwaysAllowNumbers) {
+ return (FALSE);
+ }
+
+ //
+ // If the Name has a /, +, or - as the first character return TRUE
+ //
+ if ((Name[0] == L'/') ||
+ (Name[0] == L'-') ||
+ (Name[0] == L'+')
+ ) {
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/**
+ Checks the command line arguments passed against the list of valid ones.
+
+ If no initialization is required, then return RETURN_SUCCESS.
+
+ @param[in] CheckList pointer to list of parameters to check
+ @param[out] CheckPackage pointer to pointer to list checked values
+ @param[out] ProblemParam optional pointer to pointer to unicode string for
+ the paramater that caused failure. If used then the
+ caller is responsible for freeing the memory.
+ @param[in] AutoPageBreak will automatically set PageBreakEnabled for "b" parameter
+ @param[in] Argv pointer to array of parameters
+ @param[in] Argc Count of parameters in Argv
+ @param[in] AlwaysAllowNumbers TRUE to allow numbers always, FALSE otherwise.
+
+ @retval EFI_SUCCESS The operation completed sucessfully.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed
+ @retval EFI_INVALID_PARAMETER A parameter was invalid
+ @retval EFI_VOLUME_CORRUPTED the command line was corrupt. an argument was
+ duplicated. the duplicated command line argument
+ was returned in ProblemParam if provided.
+ @retval EFI_NOT_FOUND a argument required a value that was missing.
+ the invalid command line argument was returned in
+ ProblemParam if provided.
+**/
+EFI_STATUS
+EFIAPI
+InternalCommandLineParse (
+ IN CONST SHELL_PARAM_ITEM *CheckList,
+ OUT LIST_ENTRY **CheckPackage,
+ OUT CHAR16 **ProblemParam OPTIONAL,
+ IN BOOLEAN AutoPageBreak,
+ IN CONST CHAR16 **Argv,
+ IN UINTN Argc,
+ IN BOOLEAN AlwaysAllowNumbers
+ )
+{
+ UINTN LoopCounter;
+ SHELL_PARAM_TYPE CurrentItemType;
+ SHELL_PARAM_PACKAGE *CurrentItemPackage;
+ UINTN GetItemValue;
+ UINTN ValueSize;
+ UINTN Count;
+ CONST CHAR16 *TempPointer;
+ UINTN CurrentValueSize;
+ CHAR16 *NewValue;
+
+ CurrentItemPackage = NULL;
+ GetItemValue = 0;
+ ValueSize = 0;
+ Count = 0;
+
+ //
+ // If there is only 1 item we dont need to do anything
+ //
+ if (Argc < 1) {
+ *CheckPackage = NULL;
+ return (EFI_SUCCESS);
+ }
+
+ //
+ // ASSERTs
+ //
+ ASSERT(CheckList != NULL);
+ ASSERT(Argv != NULL);
+
+ //
+ // initialize the linked list
+ //
+ *CheckPackage = (LIST_ENTRY*)AllocateZeroPool(sizeof(LIST_ENTRY));
+ if (*CheckPackage == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ InitializeListHead(*CheckPackage);
+
+ //
+ // loop through each of the arguments
+ //
+ for (LoopCounter = 0 ; LoopCounter < Argc ; ++LoopCounter) {
+ if (Argv[LoopCounter] == NULL) {
+ //
+ // do nothing for NULL argv
+ //
+ } else if (InternalIsOnCheckList(Argv[LoopCounter], CheckList, &CurrentItemType)) {
+ //
+ // We might have leftover if last parameter didnt have optional value
+ //
+ if (GetItemValue != 0) {
+ GetItemValue = 0;
+ InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);
+ }
+ //
+ // this is a flag
+ //
+ CurrentItemPackage = AllocateZeroPool(sizeof(SHELL_PARAM_PACKAGE));
+ if (CurrentItemPackage == NULL) {
+ ShellCommandLineFreeVarList(*CheckPackage);
+ *CheckPackage = NULL;
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ CurrentItemPackage->Name = AllocateCopyPool(StrSize(Argv[LoopCounter]), Argv[LoopCounter]);
+ if (CurrentItemPackage->Name == NULL) {
+ ShellCommandLineFreeVarList(*CheckPackage);
+ *CheckPackage = NULL;
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ CurrentItemPackage->Type = CurrentItemType;
+ CurrentItemPackage->OriginalPosition = (UINTN)(-1);
+ CurrentItemPackage->Value = NULL;
+
+ //
+ // Does this flag require a value
+ //
+ switch (CurrentItemPackage->Type) {
+ //
+ // possibly trigger the next loop(s) to populate the value of this item
+ //
+ case TypeValue:
+ case TypeTimeValue:
+ GetItemValue = 1;
+ ValueSize = 0;
+ break;
+ case TypeDoubleValue:
+ GetItemValue = 2;
+ ValueSize = 0;
+ break;
+ case TypeMaxValue:
+ GetItemValue = (UINTN)(-1);
+ ValueSize = 0;
+ break;
+ default:
+ //
+ // this item has no value expected; we are done
+ //
+ InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);
+ ASSERT(GetItemValue == 0);
+ break;
+ }
+ } else if (GetItemValue != 0 && CurrentItemPackage != NULL && !InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers, (BOOLEAN)(CurrentItemPackage->Type == TypeTimeValue))) {
+ //
+ // get the item VALUE for a previous flag
+ //
+ CurrentValueSize = ValueSize + StrSize(Argv[LoopCounter]) + sizeof(CHAR16);
+ NewValue = ReallocatePool(ValueSize, CurrentValueSize, CurrentItemPackage->Value);
+ if (NewValue == NULL) {
+ SHELL_FREE_NON_NULL (CurrentItemPackage->Value);
+ SHELL_FREE_NON_NULL (CurrentItemPackage);
+ ShellCommandLineFreeVarList (*CheckPackage);
+ *CheckPackage = NULL;
+ return EFI_OUT_OF_RESOURCES;
+ }
+ CurrentItemPackage->Value = NewValue;
+ if (ValueSize == 0) {
+ StrCpyS( CurrentItemPackage->Value,
+ CurrentValueSize/sizeof(CHAR16),
+ Argv[LoopCounter]
+ );
+ } else {
+ StrCatS( CurrentItemPackage->Value,
+ CurrentValueSize/sizeof(CHAR16),
+ L" "
+ );
+ StrCatS( CurrentItemPackage->Value,
+ CurrentValueSize/sizeof(CHAR16),
+ Argv[LoopCounter]
+ );
+ }
+ ValueSize += StrSize(Argv[LoopCounter]) + sizeof(CHAR16);
+
+ GetItemValue--;
+ if (GetItemValue == 0) {
+ InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);
+ }
+ } else if (!InternalIsFlag(Argv[LoopCounter], AlwaysAllowNumbers, FALSE)){
+ //
+ // add this one as a non-flag
+ //
+
+ TempPointer = Argv[LoopCounter];
+ if ((*TempPointer == L'^' && *(TempPointer+1) == L'-')
+ || (*TempPointer == L'^' && *(TempPointer+1) == L'/')
+ || (*TempPointer == L'^' && *(TempPointer+1) == L'+')
+ ){
+ TempPointer++;
+ }
+ CurrentItemPackage = AllocateZeroPool(sizeof(SHELL_PARAM_PACKAGE));
+ if (CurrentItemPackage == NULL) {
+ ShellCommandLineFreeVarList(*CheckPackage);
+ *CheckPackage = NULL;
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ CurrentItemPackage->Name = NULL;
+ CurrentItemPackage->Type = TypePosition;
+ CurrentItemPackage->Value = AllocateCopyPool(StrSize(TempPointer), TempPointer);
+ if (CurrentItemPackage->Value == NULL) {
+ ShellCommandLineFreeVarList(*CheckPackage);
+ *CheckPackage = NULL;
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ CurrentItemPackage->OriginalPosition = Count++;
+ InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);
+ } else {
+ //
+ // this was a non-recognised flag... error!
+ //
+ if (ProblemParam != NULL) {
+ *ProblemParam = AllocateCopyPool(StrSize(Argv[LoopCounter]), Argv[LoopCounter]);
+ }
+ ShellCommandLineFreeVarList(*CheckPackage);
+ *CheckPackage = NULL;
+ return (EFI_VOLUME_CORRUPTED);
+ }
+ }
+ if (GetItemValue != 0) {
+ GetItemValue = 0;
+ InsertHeadList(*CheckPackage, &CurrentItemPackage->Link);
+ }
+ //
+ // support for AutoPageBreak
+ //
+ if (AutoPageBreak && ShellCommandLineGetFlag(*CheckPackage, L"-b")) {
+ ShellSetPageBreakMode(TRUE);
+ }
+ return (EFI_SUCCESS);
+}
+
+/**
+ Checks the command line arguments passed against the list of valid ones.
+ Optionally removes NULL values first.
+
+ If no initialization is required, then return RETURN_SUCCESS.
+
+ @param[in] CheckList The pointer to list of parameters to check.
+ @param[out] CheckPackage The package of checked values.
+ @param[out] ProblemParam Optional pointer to pointer to unicode string for
+ the paramater that caused failure.
+ @param[in] AutoPageBreak Will automatically set PageBreakEnabled.
+ @param[in] AlwaysAllowNumbers Will never fail for number based flags.
+
+ @retval EFI_SUCCESS The operation completed sucessfully.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.
+ @retval EFI_VOLUME_CORRUPTED The command line was corrupt.
+ @retval EFI_DEVICE_ERROR The commands contained 2 opposing arguments. One
+ of the command line arguments was returned in
+ ProblemParam if provided.
+ @retval EFI_NOT_FOUND A argument required a value that was missing.
+ The invalid command line argument was returned in
+ ProblemParam if provided.
+**/
+EFI_STATUS
+EFIAPI
+ShellCommandLineParseEx (
+ IN CONST SHELL_PARAM_ITEM *CheckList,
+ OUT LIST_ENTRY **CheckPackage,
+ OUT CHAR16 **ProblemParam OPTIONAL,
+ IN BOOLEAN AutoPageBreak,
+ IN BOOLEAN AlwaysAllowNumbers
+ )
+{
+ //
+ // ASSERT that CheckList and CheckPackage aren't NULL
+ //
+ ASSERT(CheckList != NULL);
+ ASSERT(CheckPackage != NULL);
+
+ //
+ // Check for UEFI Shell 2.0 protocols
+ //
+ if (gEfiShellParametersProtocol != NULL) {
+ return (InternalCommandLineParse(CheckList,
+ CheckPackage,
+ ProblemParam,
+ AutoPageBreak,
+ (CONST CHAR16**) gEfiShellParametersProtocol->Argv,
+ gEfiShellParametersProtocol->Argc,
+ AlwaysAllowNumbers));
+ }
+
+ //
+ // ASSERT That EFI Shell is not required
+ //
+ ASSERT (mEfiShellInterface != NULL);
+ return (InternalCommandLineParse(CheckList,
+ CheckPackage,
+ ProblemParam,
+ AutoPageBreak,
+ (CONST CHAR16**) mEfiShellInterface->Argv,
+ mEfiShellInterface->Argc,
+ AlwaysAllowNumbers));
+}
+
+/**
+ Frees shell variable list that was returned from ShellCommandLineParse.
+
+ This function will free all the memory that was used for the CheckPackage
+ list of postprocessed shell arguments.
+
+ this function has no return value.
+
+ if CheckPackage is NULL, then return
+
+ @param CheckPackage the list to de-allocate
+ **/
+VOID
+EFIAPI
+ShellCommandLineFreeVarList (
+ IN LIST_ENTRY *CheckPackage
+ )
+{
+ LIST_ENTRY *Node;
+
+ //
+ // check for CheckPackage == NULL
+ //
+ if (CheckPackage == NULL) {
+ return;
+ }
+
+ //
+ // for each node in the list
+ //
+ for ( Node = GetFirstNode(CheckPackage)
+ ; !IsListEmpty(CheckPackage)
+ ; Node = GetFirstNode(CheckPackage)
+ ){
+ //
+ // Remove it from the list
+ //
+ RemoveEntryList(Node);
+
+ //
+ // if it has a name free the name
+ //
+ if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) {
+ FreePool(((SHELL_PARAM_PACKAGE*)Node)->Name);
+ }
+
+ //
+ // if it has a value free the value
+ //
+ if (((SHELL_PARAM_PACKAGE*)Node)->Value != NULL) {
+ FreePool(((SHELL_PARAM_PACKAGE*)Node)->Value);
+ }
+
+ //
+ // free the node structure
+ //
+ FreePool((SHELL_PARAM_PACKAGE*)Node);
+ }
+ //
+ // free the list head node
+ //
+ FreePool(CheckPackage);
+}
+/**
+ Checks for presence of a flag parameter
+
+ flag arguments are in the form of "-<Key>" or "/<Key>", but do not have a value following the key
+
+ if CheckPackage is NULL then return FALSE.
+ if KeyString is NULL then ASSERT()
+
+ @param CheckPackage The package of parsed command line arguments
+ @param KeyString the Key of the command line argument to check for
+
+ @retval TRUE the flag is on the command line
+ @retval FALSE the flag is not on the command line
+ **/
+BOOLEAN
+EFIAPI
+ShellCommandLineGetFlag (
+ IN CONST LIST_ENTRY * CONST CheckPackage,
+ IN CONST CHAR16 * CONST KeyString
+ )
+{
+ LIST_ENTRY *Node;
+ CHAR16 *TempString;
+
+ //
+ // return FALSE for no package or KeyString is NULL
+ //
+ if (CheckPackage == NULL || KeyString == NULL) {
+ return (FALSE);
+ }
+
+ //
+ // enumerate through the list of parametrs
+ //
+ for ( Node = GetFirstNode(CheckPackage)
+ ; !IsNull (CheckPackage, Node)
+ ; Node = GetNextNode(CheckPackage, Node)
+ ){
+ //
+ // If the Name matches, return TRUE (and there may be NULL name)
+ //
+ if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) {
+ //
+ // If Type is TypeStart then only compare the begining of the strings
+ //
+ if (((SHELL_PARAM_PACKAGE*)Node)->Type == TypeStart) {
+ if (StrnCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name, StrLen(KeyString)) == 0) {
+ return (TRUE);
+ }
+ TempString = NULL;
+ TempString = StrnCatGrow(&TempString, NULL, KeyString, StrLen(((SHELL_PARAM_PACKAGE*)Node)->Name));
+ if (TempString != NULL) {
+ if (StringNoCaseCompare(&KeyString, &((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {
+ FreePool(TempString);
+ return (TRUE);
+ }
+ FreePool(TempString);
+ }
+ } else if (StringNoCaseCompare(&KeyString, &((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {
+ return (TRUE);
+ }
+ }
+ }
+ return (FALSE);
+}
+/**
+ Returns value from command line argument.
+
+ Value parameters are in the form of "-<Key> value" or "/<Key> value".
+
+ If CheckPackage is NULL, then return NULL.
+
+ @param[in] CheckPackage The package of parsed command line arguments.
+ @param[in] KeyString The Key of the command line argument to check for.
+
+ @retval NULL The flag is not on the command line.
+ @retval !=NULL The pointer to unicode string of the value.
+**/
+CONST CHAR16*
+EFIAPI
+ShellCommandLineGetValue (
+ IN CONST LIST_ENTRY *CheckPackage,
+ IN CHAR16 *KeyString
+ )
+{
+ LIST_ENTRY *Node;
+ CHAR16 *TempString;
+
+ //
+ // return NULL for no package or KeyString is NULL
+ //
+ if (CheckPackage == NULL || KeyString == NULL) {
+ return (NULL);
+ }
+
+ //
+ // enumerate through the list of parametrs
+ //
+ for ( Node = GetFirstNode(CheckPackage)
+ ; !IsNull (CheckPackage, Node)
+ ; Node = GetNextNode(CheckPackage, Node)
+ ){
+ //
+ // If the Name matches, return TRUE (and there may be NULL name)
+ //
+ if (((SHELL_PARAM_PACKAGE*)Node)->Name != NULL) {
+ //
+ // If Type is TypeStart then only compare the begining of the strings
+ //
+ if (((SHELL_PARAM_PACKAGE*)Node)->Type == TypeStart) {
+ if (StrnCmp(KeyString, ((SHELL_PARAM_PACKAGE*)Node)->Name, StrLen(KeyString)) == 0) {
+ return (((SHELL_PARAM_PACKAGE*)Node)->Name + StrLen(KeyString));
+ }
+ TempString = NULL;
+ TempString = StrnCatGrow(&TempString, NULL, KeyString, StrLen(((SHELL_PARAM_PACKAGE*)Node)->Name));
+ if (TempString != NULL) {
+ if (StringNoCaseCompare(&KeyString, &((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {
+ FreePool(TempString);
+ return (((SHELL_PARAM_PACKAGE*)Node)->Name + StrLen(KeyString));
+ }
+ FreePool(TempString);
+ }
+ } else if (StringNoCaseCompare(&KeyString, &((SHELL_PARAM_PACKAGE*)Node)->Name) == 0) {
+ return (((SHELL_PARAM_PACKAGE*)Node)->Value);
+ }
+ }
+ }
+ return (NULL);
+}
+
+/**
+ Returns raw value from command line argument.
+
+ Raw value parameters are in the form of "value" in a specific position in the list.
+
+ If CheckPackage is NULL, then return NULL.
+
+ @param[in] CheckPackage The package of parsed command line arguments.
+ @param[in] Position The position of the value.
+
+ @retval NULL The flag is not on the command line.
+ @retval !=NULL The pointer to unicode string of the value.
+ **/
+CONST CHAR16*
+EFIAPI
+ShellCommandLineGetRawValue (
+ IN CONST LIST_ENTRY * CONST CheckPackage,
+ IN UINTN Position
+ )
+{
+ LIST_ENTRY *Node;
+
+ //
+ // check for CheckPackage == NULL
+ //
+ if (CheckPackage == NULL) {
+ return (NULL);
+ }
+
+ //
+ // enumerate through the list of parametrs
+ //
+ for ( Node = GetFirstNode(CheckPackage)
+ ; !IsNull (CheckPackage, Node)
+ ; Node = GetNextNode(CheckPackage, Node)
+ ){
+ //
+ // If the position matches, return the value
+ //
+ if (((SHELL_PARAM_PACKAGE*)Node)->OriginalPosition == Position) {
+ return (((SHELL_PARAM_PACKAGE*)Node)->Value);
+ }
+ }
+ return (NULL);
+}
+
+/**
+ returns the number of command line value parameters that were parsed.
+
+ this will not include flags.
+
+ @param[in] CheckPackage The package of parsed command line arguments.
+
+ @retval (UINTN)-1 No parsing has ocurred
+ @return other The number of value parameters found
+**/
+UINTN
+EFIAPI
+ShellCommandLineGetCount(
+ IN CONST LIST_ENTRY *CheckPackage
+ )
+{
+ LIST_ENTRY *Node1;
+ UINTN Count;
+
+ if (CheckPackage == NULL) {
+ return (0);
+ }
+ for ( Node1 = GetFirstNode(CheckPackage), Count = 0
+ ; !IsNull (CheckPackage, Node1)
+ ; Node1 = GetNextNode(CheckPackage, Node1)
+ ){
+ if (((SHELL_PARAM_PACKAGE*)Node1)->Name == NULL) {
+ Count++;
+ }
+ }
+ return (Count);
+}
+
+/**
+ Determines if a parameter is duplicated.
+
+ If Param is not NULL then it will point to a callee allocated string buffer
+ with the parameter value if a duplicate is found.
+
+ If CheckPackage is NULL, then ASSERT.
+
+ @param[in] CheckPackage The package of parsed command line arguments.
+ @param[out] Param Upon finding one, a pointer to the duplicated parameter.
+
+ @retval EFI_SUCCESS No parameters were duplicated.
+ @retval EFI_DEVICE_ERROR A duplicate was found.
+ **/
+EFI_STATUS
+EFIAPI
+ShellCommandLineCheckDuplicate (
+ IN CONST LIST_ENTRY *CheckPackage,
+ OUT CHAR16 **Param
+ )
+{
+ LIST_ENTRY *Node1;
+ LIST_ENTRY *Node2;
+
+ ASSERT(CheckPackage != NULL);
+
+ for ( Node1 = GetFirstNode(CheckPackage)
+ ; !IsNull (CheckPackage, Node1)
+ ; Node1 = GetNextNode(CheckPackage, Node1)
+ ){
+ for ( Node2 = GetNextNode(CheckPackage, Node1)
+ ; !IsNull (CheckPackage, Node2)
+ ; Node2 = GetNextNode(CheckPackage, Node2)
+ ){
+ if ((((SHELL_PARAM_PACKAGE*)Node1)->Name != NULL) && (((SHELL_PARAM_PACKAGE*)Node2)->Name != NULL) && StrCmp(((SHELL_PARAM_PACKAGE*)Node1)->Name, ((SHELL_PARAM_PACKAGE*)Node2)->Name) == 0) {
+ if (Param != NULL) {
+ *Param = NULL;
+ *Param = StrnCatGrow(Param, NULL, ((SHELL_PARAM_PACKAGE*)Node1)->Name, 0);
+ }
+ return (EFI_DEVICE_ERROR);
+ }
+ }
+ }
+ return (EFI_SUCCESS);
+}
+
+/**
+ This is a find and replace function. Upon successful return the NewString is a copy of
+ SourceString with each instance of FindTarget replaced with ReplaceWith.
+
+ If SourceString and NewString overlap the behavior is undefined.
+
+ If the string would grow bigger than NewSize it will halt and return error.
+
+ @param[in] SourceString The string with source buffer.
+ @param[in, out] NewString The string with resultant buffer.
+ @param[in] NewSize The size in bytes of NewString.
+ @param[in] FindTarget The string to look for.
+ @param[in] ReplaceWith The string to replace FindTarget with.
+ @param[in] SkipPreCarrot If TRUE will skip a FindTarget that has a '^'
+ immediately before it.
+ @param[in] ParameterReplacing If TRUE will add "" around items with spaces.
+
+ @retval EFI_INVALID_PARAMETER SourceString was NULL.
+ @retval EFI_INVALID_PARAMETER NewString was NULL.
+ @retval EFI_INVALID_PARAMETER FindTarget was NULL.
+ @retval EFI_INVALID_PARAMETER ReplaceWith was NULL.
+ @retval EFI_INVALID_PARAMETER FindTarget had length < 1.
+ @retval EFI_INVALID_PARAMETER SourceString had length < 1.
+ @retval EFI_BUFFER_TOO_SMALL NewSize was less than the minimum size to hold
+ the new string (truncation occurred).
+ @retval EFI_SUCCESS The string was successfully copied with replacement.
+**/
+EFI_STATUS
+EFIAPI
+ShellCopySearchAndReplace(
+ IN CHAR16 CONST *SourceString,
+ IN OUT CHAR16 *NewString,
+ IN UINTN NewSize,
+ IN CONST CHAR16 *FindTarget,
+ IN CONST CHAR16 *ReplaceWith,
+ IN CONST BOOLEAN SkipPreCarrot,
+ IN CONST BOOLEAN ParameterReplacing
+ )
+{
+ UINTN Size;
+ CHAR16 *Replace;
+
+ if ( (SourceString == NULL)
+ || (NewString == NULL)
+ || (FindTarget == NULL)
+ || (ReplaceWith == NULL)
+ || (StrLen(FindTarget) < 1)
+ || (StrLen(SourceString) < 1)
+ ){
+ return (EFI_INVALID_PARAMETER);
+ }
+ Replace = NULL;
+ if (StrStr(ReplaceWith, L" ") == NULL || !ParameterReplacing) {
+ Replace = StrnCatGrow(&Replace, NULL, ReplaceWith, 0);
+ } else {
+ Replace = AllocateZeroPool(StrSize(ReplaceWith) + 2*sizeof(CHAR16));
+ if (Replace != NULL) {
+ UnicodeSPrint(Replace, StrSize(ReplaceWith) + 2*sizeof(CHAR16), L"\"%s\"", ReplaceWith);
+ }
+ }
+ if (Replace == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ NewString = ZeroMem(NewString, NewSize);
+ while (*SourceString != CHAR_NULL) {
+ //
+ // if we find the FindTarget and either Skip == FALSE or Skip and we
+ // dont have a carrot do a replace...
+ //
+ if (StrnCmp(SourceString, FindTarget, StrLen(FindTarget)) == 0
+ && ((SkipPreCarrot && *(SourceString-1) != L'^') || !SkipPreCarrot)
+ ){
+ SourceString += StrLen(FindTarget);
+ Size = StrSize(NewString);
+ if ((Size + (StrLen(Replace)*sizeof(CHAR16))) > NewSize) {
+ FreePool(Replace);
+ return (EFI_BUFFER_TOO_SMALL);
+ }
+ StrCatS(NewString, NewSize/sizeof(CHAR16), Replace);
+ } else {
+ Size = StrSize(NewString);
+ if (Size + sizeof(CHAR16) > NewSize) {
+ FreePool(Replace);
+ return (EFI_BUFFER_TOO_SMALL);
+ }
+ StrnCatS(NewString, NewSize/sizeof(CHAR16), SourceString, 1);
+ SourceString++;
+ }
+ }
+ FreePool(Replace);
+ return (EFI_SUCCESS);
+}
+
+/**
+ Internal worker function to output a string.
+
+ This function will output a string to the correct StdOut.
+
+ @param[in] String The string to print out.
+
+ @retval EFI_SUCCESS The operation was sucessful.
+ @retval !EFI_SUCCESS The operation failed.
+**/
+EFI_STATUS
+EFIAPI
+InternalPrintTo (
+ IN CONST CHAR16 *String
+ )
+{
+ UINTN Size;
+ Size = StrSize(String) - sizeof(CHAR16);
+ if (Size == 0) {
+ return (EFI_SUCCESS);
+ }
+ if (gEfiShellParametersProtocol != NULL) {
+ return (gEfiShellProtocol->WriteFile(gEfiShellParametersProtocol->StdOut, &Size, (VOID*)String));
+ }
+ if (mEfiShellInterface != NULL) {
+ if (mEfiShellInterface->RedirArgc == 0) {
+ //
+ // Divide in half for old shell. Must be string length not size.
+ //
+ Size /=2; // Divide in half only when no redirection.
+ }
+ return (mEfiShellInterface->StdOut->Write(mEfiShellInterface->StdOut, &Size, (VOID*)String));
+ }
+ ASSERT(FALSE);
+ return (EFI_UNSUPPORTED);
+}
+
+/**
+ Print at a specific location on the screen.
+
+ This function will move the cursor to a given screen location and print the specified string
+
+ If -1 is specified for either the Row or Col the current screen location for BOTH
+ will be used.
+
+ if either Row or Col is out of range for the current console, then ASSERT
+ if Format is NULL, then ASSERT
+
+ In addition to the standard %-based flags as supported by UefiLib Print() this supports
+ the following additional flags:
+ %N - Set output attribute to normal
+ %H - Set output attribute to highlight
+ %E - Set output attribute to error
+ %B - Set output attribute to blue color
+ %V - Set output attribute to green color
+
+ Note: The background color is controlled by the shell command cls.
+
+ @param[in] Col the column to print at
+ @param[in] Row the row to print at
+ @param[in] Format the format string
+ @param[in] Marker the marker for the variable argument list
+
+ @return EFI_SUCCESS The operation was successful.
+ @return EFI_DEVICE_ERROR The console device reported an error.
+**/
+EFI_STATUS
+EFIAPI
+InternalShellPrintWorker(
+ IN INT32 Col OPTIONAL,
+ IN INT32 Row OPTIONAL,
+ IN CONST CHAR16 *Format,
+ IN VA_LIST Marker
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *ResumeLocation;
+ CHAR16 *FormatWalker;
+ UINTN OriginalAttribute;
+ CHAR16 *mPostReplaceFormat;
+ CHAR16 *mPostReplaceFormat2;
+
+ mPostReplaceFormat = AllocateZeroPool (PcdGet16 (PcdShellPrintBufferSize));
+ mPostReplaceFormat2 = AllocateZeroPool (PcdGet16 (PcdShellPrintBufferSize));
+
+ if (mPostReplaceFormat == NULL || mPostReplaceFormat2 == NULL) {
+ SHELL_FREE_NON_NULL(mPostReplaceFormat);
+ SHELL_FREE_NON_NULL(mPostReplaceFormat2);
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ Status = EFI_SUCCESS;
+ OriginalAttribute = gST->ConOut->Mode->Attribute;
+
+ //
+ // Back and forth each time fixing up 1 of our flags...
+ //
+ Status = ShellCopySearchAndReplace(Format, mPostReplaceFormat, PcdGet16 (PcdShellPrintBufferSize), L"%N", L"%%N", FALSE, FALSE);
+ ASSERT_EFI_ERROR(Status);
+ Status = ShellCopySearchAndReplace(mPostReplaceFormat, mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), L"%E", L"%%E", FALSE, FALSE);
+ ASSERT_EFI_ERROR(Status);
+ Status = ShellCopySearchAndReplace(mPostReplaceFormat2, mPostReplaceFormat, PcdGet16 (PcdShellPrintBufferSize), L"%H", L"%%H", FALSE, FALSE);
+ ASSERT_EFI_ERROR(Status);
+ Status = ShellCopySearchAndReplace(mPostReplaceFormat, mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), L"%B", L"%%B", FALSE, FALSE);
+ ASSERT_EFI_ERROR(Status);
+ Status = ShellCopySearchAndReplace(mPostReplaceFormat2, mPostReplaceFormat, PcdGet16 (PcdShellPrintBufferSize), L"%V", L"%%V", FALSE, FALSE);
+ ASSERT_EFI_ERROR(Status);
+
+ //
+ // Use the last buffer from replacing to print from...
+ //
+ UnicodeVSPrint (mPostReplaceFormat2, PcdGet16 (PcdShellPrintBufferSize), mPostReplaceFormat, Marker);
+
+ if (Col != -1 && Row != -1) {
+ Status = gST->ConOut->SetCursorPosition(gST->ConOut, Col, Row);
+ }
+
+ FormatWalker = mPostReplaceFormat2;
+ while (*FormatWalker != CHAR_NULL) {
+ //
+ // Find the next attribute change request
+ //
+ ResumeLocation = StrStr(FormatWalker, L"%");
+ if (ResumeLocation != NULL) {
+ *ResumeLocation = CHAR_NULL;
+ }
+ //
+ // print the current FormatWalker string
+ //
+ if (StrLen(FormatWalker)>0) {
+ Status = InternalPrintTo(FormatWalker);
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+ }
+
+ //
+ // update the attribute
+ //
+ if (ResumeLocation != NULL) {
+ if (*(ResumeLocation-1) == L'^') {
+ //
+ // Move cursor back 1 position to overwrite the ^
+ //
+ gST->ConOut->SetCursorPosition(gST->ConOut, gST->ConOut->Mode->CursorColumn - 1, gST->ConOut->Mode->CursorRow);
+
+ //
+ // Print a simple '%' symbol
+ //
+ Status = InternalPrintTo(L"%");
+ ResumeLocation = ResumeLocation - 1;
+ } else {
+ switch (*(ResumeLocation+1)) {
+ case (L'N'):
+ gST->ConOut->SetAttribute(gST->ConOut, OriginalAttribute);
+ break;
+ case (L'E'):
+ gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_YELLOW, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)));
+ break;
+ case (L'H'):
+ gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_WHITE, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)));
+ break;
+ case (L'B'):
+ gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_BLUE, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)));
+ break;
+ case (L'V'):
+ gST->ConOut->SetAttribute(gST->ConOut, EFI_TEXT_ATTR(EFI_GREEN, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)));
+ break;
+ default:
+ //
+ // Print a simple '%' symbol
+ //
+ Status = InternalPrintTo(L"%");
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+ ResumeLocation = ResumeLocation - 1;
+ break;
+ }
+ }
+ } else {
+ //
+ // reset to normal now...
+ //
+ break;
+ }
+
+ //
+ // update FormatWalker to Resume + 2 (skip the % and the indicator)
+ //
+ FormatWalker = ResumeLocation + 2;
+ }
+
+ gST->ConOut->SetAttribute(gST->ConOut, OriginalAttribute);
+
+ SHELL_FREE_NON_NULL(mPostReplaceFormat);
+ SHELL_FREE_NON_NULL(mPostReplaceFormat2);
+ return (Status);
+}
+
+/**
+ Print at a specific location on the screen.
+
+ This function will move the cursor to a given screen location and print the specified string.
+
+ If -1 is specified for either the Row or Col the current screen location for BOTH
+ will be used.
+
+ If either Row or Col is out of range for the current console, then ASSERT.
+ If Format is NULL, then ASSERT.
+
+ In addition to the standard %-based flags as supported by UefiLib Print() this supports
+ the following additional flags:
+ %N - Set output attribute to normal
+ %H - Set output attribute to highlight
+ %E - Set output attribute to error
+ %B - Set output attribute to blue color
+ %V - Set output attribute to green color
+
+ Note: The background color is controlled by the shell command cls.
+
+ @param[in] Col the column to print at
+ @param[in] Row the row to print at
+ @param[in] Format the format string
+ @param[in] ... The variable argument list.
+
+ @return EFI_SUCCESS The printing was successful.
+ @return EFI_DEVICE_ERROR The console device reported an error.
+**/
+EFI_STATUS
+EFIAPI
+ShellPrintEx(
+ IN INT32 Col OPTIONAL,
+ IN INT32 Row OPTIONAL,
+ IN CONST CHAR16 *Format,
+ ...
+ )
+{
+ VA_LIST Marker;
+ EFI_STATUS RetVal;
+ if (Format == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+ VA_START (Marker, Format);
+ RetVal = InternalShellPrintWorker(Col, Row, Format, Marker);
+ VA_END(Marker);
+ return(RetVal);
+}
+
+/**
+ Print at a specific location on the screen.
+
+ This function will move the cursor to a given screen location and print the specified string.
+
+ If -1 is specified for either the Row or Col the current screen location for BOTH
+ will be used.
+
+ If either Row or Col is out of range for the current console, then ASSERT.
+ If Format is NULL, then ASSERT.
+
+ In addition to the standard %-based flags as supported by UefiLib Print() this supports
+ the following additional flags:
+ %N - Set output attribute to normal.
+ %H - Set output attribute to highlight.
+ %E - Set output attribute to error.
+ %B - Set output attribute to blue color.
+ %V - Set output attribute to green color.
+
+ Note: The background color is controlled by the shell command cls.
+
+ @param[in] Col The column to print at.
+ @param[in] Row The row to print at.
+ @param[in] Language The language of the string to retrieve. If this parameter
+ is NULL, then the current platform language is used.
+ @param[in] HiiFormatStringId The format string Id for getting from Hii.
+ @param[in] HiiFormatHandle The format string Handle for getting from Hii.
+ @param[in] ... The variable argument list.
+
+ @return EFI_SUCCESS The printing was successful.
+ @return EFI_DEVICE_ERROR The console device reported an error.
+**/
+EFI_STATUS
+EFIAPI
+ShellPrintHiiEx(
+ IN INT32 Col OPTIONAL,
+ IN INT32 Row OPTIONAL,
+ IN CONST CHAR8 *Language OPTIONAL,
+ IN CONST EFI_STRING_ID HiiFormatStringId,
+ IN CONST EFI_HANDLE HiiFormatHandle,
+ ...
+ )
+{
+ VA_LIST Marker;
+ CHAR16 *HiiFormatString;
+ EFI_STATUS RetVal;
+
+ RetVal = EFI_DEVICE_ERROR;
+
+ VA_START (Marker, HiiFormatHandle);
+ HiiFormatString = HiiGetString(HiiFormatHandle, HiiFormatStringId, Language);
+ if (HiiFormatString != NULL) {
+ RetVal = InternalShellPrintWorker (Col, Row, HiiFormatString, Marker);
+ SHELL_FREE_NON_NULL (HiiFormatString);
+ }
+ VA_END(Marker);
+
+ return (RetVal);
+}
+
+/**
+ Function to determine if a given filename represents a file or a directory.
+
+ @param[in] DirName Path to directory to test.
+
+ @retval EFI_SUCCESS The Path represents a directory
+ @retval EFI_NOT_FOUND The Path does not represent a directory
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @return The path failed to open
+**/
+EFI_STATUS
+EFIAPI
+ShellIsDirectory(
+ IN CONST CHAR16 *DirName
+ )
+{
+ EFI_STATUS Status;
+ SHELL_FILE_HANDLE Handle;
+ CHAR16 *TempLocation;
+ CHAR16 *TempLocation2;
+
+ ASSERT(DirName != NULL);
+
+ Handle = NULL;
+ TempLocation = NULL;
+
+ Status = ShellOpenFileByName(DirName, &Handle, EFI_FILE_MODE_READ, 0);
+ if (EFI_ERROR(Status)) {
+ //
+ // try good logic first.
+ //
+ if (gEfiShellProtocol != NULL) {
+ TempLocation = StrnCatGrow(&TempLocation, NULL, DirName, 0);
+ if (TempLocation == NULL) {
+ ShellCloseFile(&Handle);
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ TempLocation2 = StrStr(TempLocation, L":");
+ if (TempLocation2 != NULL && StrLen(StrStr(TempLocation, L":")) == 2) {
+ *(TempLocation2+1) = CHAR_NULL;
+ }
+ if (gEfiShellProtocol->GetDevicePathFromMap(TempLocation) != NULL) {
+ FreePool(TempLocation);
+ return (EFI_SUCCESS);
+ }
+ FreePool(TempLocation);
+ } else {
+ //
+ // probably a map name?!?!!?
+ //
+ TempLocation = StrStr(DirName, L"\\");
+ if (TempLocation != NULL && *(TempLocation+1) == CHAR_NULL) {
+ return (EFI_SUCCESS);
+ }
+ }
+ return (Status);
+ }
+
+ if (FileHandleIsDirectory(Handle) == EFI_SUCCESS) {
+ ShellCloseFile(&Handle);
+ return (EFI_SUCCESS);
+ }
+ ShellCloseFile(&Handle);
+ return (EFI_NOT_FOUND);
+}
+
+/**
+ Function to determine if a given filename represents a file.
+
+ @param[in] Name Path to file to test.
+
+ @retval EFI_SUCCESS The Path represents a file.
+ @retval EFI_NOT_FOUND The Path does not represent a file.
+ @retval other The path failed to open.
+**/
+EFI_STATUS
+EFIAPI
+ShellIsFile(
+ IN CONST CHAR16 *Name
+ )
+{
+ EFI_STATUS Status;
+ SHELL_FILE_HANDLE Handle;
+
+ ASSERT(Name != NULL);
+
+ Handle = NULL;
+
+ Status = ShellOpenFileByName(Name, &Handle, EFI_FILE_MODE_READ, 0);
+ if (EFI_ERROR(Status)) {
+ return (Status);
+ }
+
+ if (FileHandleIsDirectory(Handle) != EFI_SUCCESS) {
+ ShellCloseFile(&Handle);
+ return (EFI_SUCCESS);
+ }
+ ShellCloseFile(&Handle);
+ return (EFI_NOT_FOUND);
+}
+
+/**
+ Function to determine if a given filename represents a file.
+
+ This will search the CWD and then the Path.
+
+ If Name is NULL, then ASSERT.
+
+ @param[in] Name Path to file to test.
+
+ @retval EFI_SUCCESS The Path represents a file.
+ @retval EFI_NOT_FOUND The Path does not represent a file.
+ @retval other The path failed to open.
+**/
+EFI_STATUS
+EFIAPI
+ShellIsFileInPath(
+ IN CONST CHAR16 *Name
+ )
+{
+ CHAR16 *NewName;
+ EFI_STATUS Status;
+
+ if (!EFI_ERROR(ShellIsFile(Name))) {
+ return (EFI_SUCCESS);
+ }
+
+ NewName = ShellFindFilePath(Name);
+ if (NewName == NULL) {
+ return (EFI_NOT_FOUND);
+ }
+ Status = ShellIsFile(NewName);
+ FreePool(NewName);
+ return (Status);
+}
+
+/**
+ Function return the number converted from a hex representation of a number.
+
+ Note: this function cannot be used when (UINTN)(-1), (0xFFFFFFFF) may be a valid
+ result. Use ShellConvertStringToUint64 instead.
+
+ @param[in] String String representation of a number.
+
+ @return The unsigned integer result of the conversion.
+ @retval (UINTN)(-1) An error occured.
+**/
+UINTN
+EFIAPI
+ShellHexStrToUintn(
+ IN CONST CHAR16 *String
+ )
+{
+ UINT64 RetVal;
+
+ if (!EFI_ERROR(ShellConvertStringToUint64(String, &RetVal, TRUE, TRUE))) {
+ return ((UINTN)RetVal);
+ }
+
+ return ((UINTN)(-1));
+}
+
+/**
+ Function to determine whether a string is decimal or hex representation of a number
+ and return the number converted from the string. Spaces are always skipped.
+
+ @param[in] String String representation of a number
+
+ @return the number
+ @retval (UINTN)(-1) An error ocurred.
+**/
+UINTN
+EFIAPI
+ShellStrToUintn(
+ IN CONST CHAR16 *String
+ )
+{
+ UINT64 RetVal;
+ BOOLEAN Hex;
+
+ Hex = FALSE;
+
+ if (!InternalShellIsHexOrDecimalNumber(String, Hex, TRUE, FALSE)) {
+ Hex = TRUE;
+ }
+
+ if (!EFI_ERROR(ShellConvertStringToUint64(String, &RetVal, Hex, TRUE))) {
+ return ((UINTN)RetVal);
+ }
+ return ((UINTN)(-1));
+}
+
+/**
+ Safely append with automatic string resizing given length of Destination and
+ desired length of copy from Source.
+
+ append the first D characters of Source to the end of Destination, where D is
+ the lesser of Count and the StrLen() of Source. If appending those D characters
+ will fit within Destination (whose Size is given as CurrentSize) and
+ still leave room for a NULL terminator, then those characters are appended,
+ starting at the original terminating NULL of Destination, and a new terminating
+ NULL is appended.
+
+ If appending D characters onto Destination will result in a overflow of the size
+ given in CurrentSize the string will be grown such that the copy can be performed
+ and CurrentSize will be updated to the new size.
+
+ If Source is NULL, there is nothing to append, just return the current buffer in
+ Destination.
+
+ if Destination is NULL, then ASSERT()
+ if Destination's current length (including NULL terminator) is already more then
+ CurrentSize, then ASSERT()
+
+ @param[in, out] Destination The String to append onto
+ @param[in, out] CurrentSize on call the number of bytes in Destination. On
+ return possibly the new size (still in bytes). if NULL
+ then allocate whatever is needed.
+ @param[in] Source The String to append from
+ @param[in] Count Maximum number of characters to append. if 0 then
+ all are appended.
+
+ @return Destination return the resultant string.
+**/
+CHAR16*
+EFIAPI
+StrnCatGrow (
+ IN OUT CHAR16 **Destination,
+ IN OUT UINTN *CurrentSize,
+ IN CONST CHAR16 *Source,
+ IN UINTN Count
+ )
+{
+ UINTN DestinationStartSize;
+ UINTN NewSize;
+
+ //
+ // ASSERTs
+ //
+ ASSERT(Destination != NULL);
+
+ //
+ // If there's nothing to do then just return Destination
+ //
+ if (Source == NULL) {
+ return (*Destination);
+ }
+
+ //
+ // allow for un-initialized pointers, based on size being 0
+ //
+ if (CurrentSize != NULL && *CurrentSize == 0) {
+ *Destination = NULL;
+ }
+
+ //
+ // allow for NULL pointers address as Destination
+ //
+ if (*Destination != NULL) {
+ ASSERT(CurrentSize != 0);
+ DestinationStartSize = StrSize(*Destination);
+ ASSERT(DestinationStartSize <= *CurrentSize);
+ } else {
+ DestinationStartSize = 0;
+// ASSERT(*CurrentSize == 0);
+ }
+
+ //
+ // Append all of Source?
+ //
+ if (Count == 0) {
+ Count = StrLen(Source);
+ }
+
+ //
+ // Test and grow if required
+ //
+ if (CurrentSize != NULL) {
+ NewSize = *CurrentSize;
+ if (NewSize < DestinationStartSize + (Count * sizeof(CHAR16))) {
+ while (NewSize < (DestinationStartSize + (Count*sizeof(CHAR16)))) {
+ NewSize += 2 * Count * sizeof(CHAR16);
+ }
+ *Destination = ReallocatePool(*CurrentSize, NewSize, *Destination);
+ *CurrentSize = NewSize;
+ }
+ } else {
+ NewSize = (Count+1)*sizeof(CHAR16);
+ *Destination = AllocateZeroPool(NewSize);
+ }
+
+ //
+ // Now use standard StrnCat on a big enough buffer
+ //
+ if (*Destination == NULL) {
+ return (NULL);
+ }
+
+ StrnCatS(*Destination, NewSize/sizeof(CHAR16), Source, Count);
+ return *Destination;
+}
+
+/**
+ Prompt the user and return the resultant answer to the requestor.
+
+ This function will display the requested question on the shell prompt and then
+ wait for an appropriate answer to be input from the console.
+
+ if the SHELL_PROMPT_REQUEST_TYPE is SHELL_PROMPT_REQUEST_TYPE_YESNO, ShellPromptResponseTypeQuitContinue
+ or SHELL_PROMPT_REQUEST_TYPE_YESNOCANCEL then *Response is of type SHELL_PROMPT_RESPONSE.
+
+ if the SHELL_PROMPT_REQUEST_TYPE is ShellPromptResponseTypeFreeform then *Response is of type
+ CHAR16*.
+
+ In either case *Response must be callee freed if Response was not NULL;
+
+ @param Type What type of question is asked. This is used to filter the input
+ to prevent invalid answers to question.
+ @param Prompt Pointer to string prompt to use to request input.
+ @param Response Pointer to Response which will be populated upon return.
+
+ @retval EFI_SUCCESS The operation was sucessful.
+ @retval EFI_UNSUPPORTED The operation is not supported as requested.
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.
+ @return other The operation failed.
+**/
+EFI_STATUS
+EFIAPI
+ShellPromptForResponse (
+ IN SHELL_PROMPT_REQUEST_TYPE Type,
+ IN CHAR16 *Prompt OPTIONAL,
+ IN OUT VOID **Response OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+ EFI_INPUT_KEY Key;
+ UINTN EventIndex;
+ SHELL_PROMPT_RESPONSE *Resp;
+ UINTN Size;
+ CHAR16 *Buffer;
+
+ Status = EFI_UNSUPPORTED;
+ Resp = NULL;
+ Buffer = NULL;
+ Size = 0;
+ if (Type != ShellPromptResponseTypeFreeform) {
+ Resp = (SHELL_PROMPT_RESPONSE*)AllocateZeroPool(sizeof(SHELL_PROMPT_RESPONSE));
+ if (Resp == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+ }
+
+ switch(Type) {
+ case ShellPromptResponseTypeQuitContinue:
+ if (Prompt != NULL) {
+ ShellPrintEx(-1, -1, L"%s", Prompt);
+ }
+ //
+ // wait for valid response
+ //
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+ ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);
+ if (Key.UnicodeChar == L'Q' || Key.UnicodeChar ==L'q') {
+ *Resp = ShellPromptResponseQuit;
+ } else {
+ *Resp = ShellPromptResponseContinue;
+ }
+ break;
+ case ShellPromptResponseTypeYesNoCancel:
+ if (Prompt != NULL) {
+ ShellPrintEx(-1, -1, L"%s", Prompt);
+ }
+ //
+ // wait for valid response
+ //
+ *Resp = ShellPromptResponseMax;
+ while (*Resp == ShellPromptResponseMax) {
+ if (ShellGetExecutionBreakFlag()) {
+ Status = EFI_ABORTED;
+ break;
+ }
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+ ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);
+ switch (Key.UnicodeChar) {
+ case L'Y':
+ case L'y':
+ *Resp = ShellPromptResponseYes;
+ break;
+ case L'N':
+ case L'n':
+ *Resp = ShellPromptResponseNo;
+ break;
+ case L'C':
+ case L'c':
+ *Resp = ShellPromptResponseCancel;
+ break;
+ }
+ }
+ break; case ShellPromptResponseTypeYesNoAllCancel:
+ if (Prompt != NULL) {
+ ShellPrintEx(-1, -1, L"%s", Prompt);
+ }
+ //
+ // wait for valid response
+ //
+ *Resp = ShellPromptResponseMax;
+ while (*Resp == ShellPromptResponseMax) {
+ if (ShellGetExecutionBreakFlag()) {
+ Status = EFI_ABORTED;
+ break;
+ }
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+ ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);
+ switch (Key.UnicodeChar) {
+ case L'Y':
+ case L'y':
+ *Resp = ShellPromptResponseYes;
+ break;
+ case L'N':
+ case L'n':
+ *Resp = ShellPromptResponseNo;
+ break;
+ case L'A':
+ case L'a':
+ *Resp = ShellPromptResponseAll;
+ break;
+ case L'C':
+ case L'c':
+ *Resp = ShellPromptResponseCancel;
+ break;
+ }
+ }
+ break;
+ case ShellPromptResponseTypeEnterContinue:
+ case ShellPromptResponseTypeAnyKeyContinue:
+ if (Prompt != NULL) {
+ ShellPrintEx(-1, -1, L"%s", Prompt);
+ }
+ //
+ // wait for valid response
+ //
+ *Resp = ShellPromptResponseMax;
+ while (*Resp == ShellPromptResponseMax) {
+ if (ShellGetExecutionBreakFlag()) {
+ Status = EFI_ABORTED;
+ break;
+ }
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);
+ if (Type == ShellPromptResponseTypeEnterContinue) {
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+ ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+ *Resp = ShellPromptResponseContinue;
+ break;
+ }
+ }
+ if (Type == ShellPromptResponseTypeAnyKeyContinue) {
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ ASSERT_EFI_ERROR(Status);
+ *Resp = ShellPromptResponseContinue;
+ break;
+ }
+ }
+ break;
+ case ShellPromptResponseTypeYesNo:
+ if (Prompt != NULL) {
+ ShellPrintEx(-1, -1, L"%s", Prompt);
+ }
+ //
+ // wait for valid response
+ //
+ *Resp = ShellPromptResponseMax;
+ while (*Resp == ShellPromptResponseMax) {
+ if (ShellGetExecutionBreakFlag()) {
+ Status = EFI_ABORTED;
+ break;
+ }
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+ ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);
+ switch (Key.UnicodeChar) {
+ case L'Y':
+ case L'y':
+ *Resp = ShellPromptResponseYes;
+ break;
+ case L'N':
+ case L'n':
+ *Resp = ShellPromptResponseNo;
+ break;
+ }
+ }
+ break;
+ case ShellPromptResponseTypeFreeform:
+ if (Prompt != NULL) {
+ ShellPrintEx(-1, -1, L"%s", Prompt);
+ }
+ while(1) {
+ if (ShellGetExecutionBreakFlag()) {
+ Status = EFI_ABORTED;
+ break;
+ }
+ gBS->WaitForEvent (1, &gST->ConIn->WaitForKey, &EventIndex);
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+ if (EFI_ERROR(Status)) {
+ break;
+ }
+ ShellPrintEx(-1, -1, L"%c", Key.UnicodeChar);
+ if (Key.UnicodeChar == CHAR_CARRIAGE_RETURN) {
+ break;
+ }
+ ASSERT((Buffer == NULL && Size == 0) || (Buffer != NULL));
+ StrnCatGrow(&Buffer, &Size, &Key.UnicodeChar, 1);
+ }
+ break;
+ //
+ // This is the location to add new prompt types.
+ // If your new type loops remember to add ExecutionBreak support.
+ //
+ default:
+ ASSERT(FALSE);
+ }
+
+ if (Response != NULL) {
+ if (Resp != NULL) {
+ *Response = Resp;
+ } else if (Buffer != NULL) {
+ *Response = Buffer;
+ }
+ } else {
+ if (Resp != NULL) {
+ FreePool(Resp);
+ }
+ if (Buffer != NULL) {
+ FreePool(Buffer);
+ }
+ }
+
+ ShellPrintEx(-1, -1, L"\r\n");
+ return (Status);
+}
+
+/**
+ Prompt the user and return the resultant answer to the requestor.
+
+ This function is the same as ShellPromptForResponse, except that the prompt is
+ automatically pulled from HII.
+
+ @param Type What type of question is asked. This is used to filter the input
+ to prevent invalid answers to question.
+ @param[in] HiiFormatStringId The format string Id for getting from Hii.
+ @param[in] HiiFormatHandle The format string Handle for getting from Hii.
+ @param Response Pointer to Response which will be populated upon return.
+
+ @retval EFI_SUCCESS the operation was sucessful.
+ @return other the operation failed.
+
+ @sa ShellPromptForResponse
+**/
+EFI_STATUS
+EFIAPI
+ShellPromptForResponseHii (
+ IN SHELL_PROMPT_REQUEST_TYPE Type,
+ IN CONST EFI_STRING_ID HiiFormatStringId,
+ IN CONST EFI_HANDLE HiiFormatHandle,
+ IN OUT VOID **Response
+ )
+{
+ CHAR16 *Prompt;
+ EFI_STATUS Status;
+
+ Prompt = HiiGetString(HiiFormatHandle, HiiFormatStringId, NULL);
+ Status = ShellPromptForResponse(Type, Prompt, Response);
+ FreePool(Prompt);
+ return (Status);
+}
+
+/**
+ Function to determin if an entire string is a valid number.
+
+ If Hex it must be preceeded with a 0x or has ForceHex, set TRUE.
+
+ @param[in] String The string to evaluate.
+ @param[in] ForceHex TRUE - always assume hex.
+ @param[in] StopAtSpace TRUE to halt upon finding a space, FALSE to keep going.
+ @param[in] TimeNumbers TRUE to allow numbers with ":", FALSE otherwise.
+
+ @retval TRUE It is all numeric (dec/hex) characters.
+ @retval FALSE There is a non-numeric character.
+**/
+BOOLEAN
+EFIAPI
+InternalShellIsHexOrDecimalNumber (
+ IN CONST CHAR16 *String,
+ IN CONST BOOLEAN ForceHex,
+ IN CONST BOOLEAN StopAtSpace,
+ IN CONST BOOLEAN TimeNumbers
+ )
+{
+ BOOLEAN Hex;
+
+ //
+ // chop off a single negative sign
+ //
+ if (String != NULL && *String == L'-') {
+ String++;
+ }
+
+ if (String == NULL) {
+ return (FALSE);
+ }
+
+ //
+ // chop leading zeroes
+ //
+ while(String != NULL && *String == L'0'){
+ String++;
+ }
+ //
+ // allow '0x' or '0X', but not 'x' or 'X'
+ //
+ if (String != NULL && (*String == L'x' || *String == L'X')) {
+ if (*(String-1) != L'0') {
+ //
+ // we got an x without a preceeding 0
+ //
+ return (FALSE);
+ }
+ String++;
+ Hex = TRUE;
+ } else if (ForceHex) {
+ Hex = TRUE;
+ } else {
+ Hex = FALSE;
+ }
+
+ //
+ // loop through the remaining characters and use the lib function
+ //
+ for ( ; String != NULL && *String != CHAR_NULL && !(StopAtSpace && *String == L' ') ; String++){
+ if (TimeNumbers && (String[0] == L':')) {
+ continue;
+ }
+ if (Hex) {
+ if (!ShellIsHexaDecimalDigitCharacter(*String)) {
+ return (FALSE);
+ }
+ } else {
+ if (!ShellIsDecimalDigitCharacter(*String)) {
+ return (FALSE);
+ }
+ }
+ }
+
+ return (TRUE);
+}
+
+/**
+ Function to determine if a given filename exists.
+
+ @param[in] Name Path to test.
+
+ @retval EFI_SUCCESS The Path represents a file.
+ @retval EFI_NOT_FOUND The Path does not represent a file.
+ @retval other The path failed to open.
+**/
+EFI_STATUS
+EFIAPI
+ShellFileExists(
+ IN CONST CHAR16 *Name
+ )
+{
+ EFI_STATUS Status;
+ EFI_SHELL_FILE_INFO *List;
+
+ ASSERT(Name != NULL);
+
+ List = NULL;
+ Status = ShellOpenFileMetaArg((CHAR16*)Name, EFI_FILE_MODE_READ, &List);
+ if (EFI_ERROR(Status)) {
+ return (Status);
+ }
+
+ ShellCloseFileMetaArg(&List);
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Convert a Unicode character to upper case only if
+ it maps to a valid small-case ASCII character.
+
+ This internal function only deal with Unicode character
+ which maps to a valid small-case ASCII character, i.e.
+ L'a' to L'z'. For other Unicode character, the input character
+ is returned directly.
+
+ @param Char The character to convert.
+
+ @retval LowerCharacter If the Char is with range L'a' to L'z'.
+ @retval Unchanged Otherwise.
+
+**/
+CHAR16
+EFIAPI
+InternalShellCharToUpper (
+ IN CHAR16 Char
+ )
+{
+ if (Char >= L'a' && Char <= L'z') {
+ return (CHAR16) (Char - (L'a' - L'A'));
+ }
+
+ return Char;
+}
+
+/**
+ Convert a Unicode character to numerical value.
+
+ This internal function only deal with Unicode character
+ which maps to a valid hexadecimal ASII character, i.e.
+ L'0' to L'9', L'a' to L'f' or L'A' to L'F'. For other
+ Unicode character, the value returned does not make sense.
+
+ @param Char The character to convert.
+
+ @return The numerical value converted.
+
+**/
+UINTN
+EFIAPI
+InternalShellHexCharToUintn (
+ IN CHAR16 Char
+ )
+{
+ if (ShellIsDecimalDigitCharacter (Char)) {
+ return Char - L'0';
+ }
+
+ return (UINTN) (10 + InternalShellCharToUpper (Char) - L'A');
+}
+
+/**
+ Convert a Null-terminated Unicode hexadecimal string to a value of type UINT64.
+
+ This function returns a value of type UINT64 by interpreting the contents
+ of the Unicode string specified by String as a hexadecimal number.
+ The format of the input Unicode string String is:
+
+ [spaces][zeros][x][hexadecimal digits].
+
+ The valid hexadecimal digit character is in the range [0-9], [a-f] and [A-F].
+ The prefix "0x" is optional. Both "x" and "X" is allowed in "0x" prefix.
+ If "x" appears in the input string, it must be prefixed with at least one 0.
+ The function will ignore the pad space, which includes spaces or tab characters,
+ before [zeros], [x] or [hexadecimal digit]. The running zero before [x] or
+ [hexadecimal digit] will be ignored. Then, the decoding starts after [x] or the
+ first valid hexadecimal digit. Then, the function stops at the first character that is
+ a not a valid hexadecimal character or NULL, whichever one comes first.
+
+ If String has only pad spaces, then zero is returned.
+ If String has no leading pad spaces, leading zeros or valid hexadecimal digits,
+ then zero is returned.
+
+ @param[in] String A pointer to a Null-terminated Unicode string.
+ @param[out] Value Upon a successful return the value of the conversion.
+ @param[in] StopAtSpace FALSE to skip spaces.
+
+ @retval EFI_SUCCESS The conversion was successful.
+ @retval EFI_INVALID_PARAMETER A parameter was NULL or invalid.
+ @retval EFI_DEVICE_ERROR An overflow occured.
+**/
+EFI_STATUS
+EFIAPI
+InternalShellStrHexToUint64 (
+ IN CONST CHAR16 *String,
+ OUT UINT64 *Value,
+ IN CONST BOOLEAN StopAtSpace
+ )
+{
+ UINT64 Result;
+
+ if (String == NULL || StrSize(String) == 0 || Value == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ //
+ // Ignore the pad spaces (space or tab)
+ //
+ while ((*String == L' ') || (*String == L'\t')) {
+ String++;
+ }
+
+ //
+ // Ignore leading Zeros after the spaces
+ //
+ while (*String == L'0') {
+ String++;
+ }
+
+ if (InternalShellCharToUpper (*String) == L'X') {
+ if (*(String - 1) != L'0') {
+ return 0;
+ }
+ //
+ // Skip the 'X'
+ //
+ String++;
+ }
+
+ Result = 0;
+
+ //
+ // there is a space where there should't be
+ //
+ if (*String == L' ') {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ while (ShellIsHexaDecimalDigitCharacter (*String)) {
+ //
+ // If the Hex Number represented by String overflows according
+ // to the range defined by UINT64, then return EFI_DEVICE_ERROR.
+ //
+ if (!(Result <= (RShiftU64((((UINT64) ~0) - InternalShellHexCharToUintn (*String)), 4)))) {
+// if (!(Result <= ((((UINT64) ~0) - InternalShellHexCharToUintn (*String)) >> 4))) {
+ return (EFI_DEVICE_ERROR);
+ }
+
+ Result = (LShiftU64(Result, 4));
+ Result += InternalShellHexCharToUintn (*String);
+ String++;
+
+ //
+ // stop at spaces if requested
+ //
+ if (StopAtSpace && *String == L' ') {
+ break;
+ }
+ }
+
+ *Value = Result;
+ return (EFI_SUCCESS);
+}
+
+/**
+ Convert a Null-terminated Unicode decimal string to a value of
+ type UINT64.
+
+ This function returns a value of type UINT64 by interpreting the contents
+ of the Unicode string specified by String as a decimal number. The format
+ of the input Unicode string String is:
+
+ [spaces] [decimal digits].
+
+ The valid decimal digit character is in the range [0-9]. The
+ function will ignore the pad space, which includes spaces or
+ tab characters, before [decimal digits]. The running zero in the
+ beginning of [decimal digits] will be ignored. Then, the function
+ stops at the first character that is a not a valid decimal character
+ or a Null-terminator, whichever one comes first.
+
+ If String has only pad spaces, then 0 is returned.
+ If String has no pad spaces or valid decimal digits,
+ then 0 is returned.
+
+ @param[in] String A pointer to a Null-terminated Unicode string.
+ @param[out] Value Upon a successful return the value of the conversion.
+ @param[in] StopAtSpace FALSE to skip spaces.
+
+ @retval EFI_SUCCESS The conversion was successful.
+ @retval EFI_INVALID_PARAMETER A parameter was NULL or invalid.
+ @retval EFI_DEVICE_ERROR An overflow occured.
+**/
+EFI_STATUS
+EFIAPI
+InternalShellStrDecimalToUint64 (
+ IN CONST CHAR16 *String,
+ OUT UINT64 *Value,
+ IN CONST BOOLEAN StopAtSpace
+ )
+{
+ UINT64 Result;
+
+ if (String == NULL || StrSize (String) == 0 || Value == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ //
+ // Ignore the pad spaces (space or tab)
+ //
+ while ((*String == L' ') || (*String == L'\t')) {
+ String++;
+ }
+
+ //
+ // Ignore leading Zeros after the spaces
+ //
+ while (*String == L'0') {
+ String++;
+ }
+
+ Result = 0;
+
+ //
+ // Stop upon space if requested
+ // (if the whole value was 0)
+ //
+ if (StopAtSpace && *String == L' ') {
+ *Value = Result;
+ return (EFI_SUCCESS);
+ }
+
+ while (ShellIsDecimalDigitCharacter (*String)) {
+ //
+ // If the number represented by String overflows according
+ // to the range defined by UINT64, then return EFI_DEVICE_ERROR.
+ //
+
+ if (!(Result <= (DivU64x32((((UINT64) ~0) - (*String - L'0')),10)))) {
+ return (EFI_DEVICE_ERROR);
+ }
+
+ Result = MultU64x32(Result, 10) + (*String - L'0');
+ String++;
+
+ //
+ // Stop at spaces if requested
+ //
+ if (StopAtSpace && *String == L' ') {
+ break;
+ }
+ }
+
+ *Value = Result;
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Function to verify and convert a string to its numerical value.
+
+ If Hex it must be preceeded with a 0x, 0X, or has ForceHex set TRUE.
+
+ @param[in] String The string to evaluate.
+ @param[out] Value Upon a successful return the value of the conversion.
+ @param[in] ForceHex TRUE - always assume hex.
+ @param[in] StopAtSpace FALSE to skip spaces.
+
+ @retval EFI_SUCCESS The conversion was successful.
+ @retval EFI_INVALID_PARAMETER String contained an invalid character.
+ @retval EFI_NOT_FOUND String was a number, but Value was NULL.
+**/
+EFI_STATUS
+EFIAPI
+ShellConvertStringToUint64(
+ IN CONST CHAR16 *String,
+ OUT UINT64 *Value,
+ IN CONST BOOLEAN ForceHex,
+ IN CONST BOOLEAN StopAtSpace
+ )
+{
+ UINT64 RetVal;
+ CONST CHAR16 *Walker;
+ EFI_STATUS Status;
+ BOOLEAN Hex;
+
+ Hex = ForceHex;
+
+ if (!InternalShellIsHexOrDecimalNumber(String, Hex, StopAtSpace, FALSE)) {
+ if (!Hex) {
+ Hex = TRUE;
+ if (!InternalShellIsHexOrDecimalNumber(String, Hex, StopAtSpace, FALSE)) {
+ return (EFI_INVALID_PARAMETER);
+ }
+ } else {
+ return (EFI_INVALID_PARAMETER);
+ }
+ }
+
+ //
+ // Chop off leading spaces
+ //
+ for (Walker = String; Walker != NULL && *Walker != CHAR_NULL && *Walker == L' '; Walker++);
+
+ //
+ // make sure we have something left that is numeric.
+ //
+ if (Walker == NULL || *Walker == CHAR_NULL || !InternalShellIsHexOrDecimalNumber(Walker, Hex, StopAtSpace, FALSE)) {
+ return (EFI_INVALID_PARAMETER);
+ }
+
+ //
+ // do the conversion.
+ //
+ if (Hex || StrnCmp(Walker, L"0x", 2) == 0 || StrnCmp(Walker, L"0X", 2) == 0){
+ Status = InternalShellStrHexToUint64(Walker, &RetVal, StopAtSpace);
+ } else {
+ Status = InternalShellStrDecimalToUint64(Walker, &RetVal, StopAtSpace);
+ }
+
+ if (Value == NULL && !EFI_ERROR(Status)) {
+ return (EFI_NOT_FOUND);
+ }
+
+ if (Value != NULL) {
+ *Value = RetVal;
+ }
+
+ return (Status);
+}
+
+/**
+ Function to determin if an entire string is a valid number.
+
+ If Hex it must be preceeded with a 0x or has ForceHex, set TRUE.
+
+ @param[in] String The string to evaluate.
+ @param[in] ForceHex TRUE - always assume hex.
+ @param[in] StopAtSpace TRUE to halt upon finding a space, FALSE to keep going.
+
+ @retval TRUE It is all numeric (dec/hex) characters.
+ @retval FALSE There is a non-numeric character.
+**/
+BOOLEAN
+EFIAPI
+ShellIsHexOrDecimalNumber (
+ IN CONST CHAR16 *String,
+ IN CONST BOOLEAN ForceHex,
+ IN CONST BOOLEAN StopAtSpace
+ )
+{
+ if (ShellConvertStringToUint64(String, NULL, ForceHex, StopAtSpace) == EFI_NOT_FOUND) {
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/**
+ Function to read a single line from a SHELL_FILE_HANDLE. The \n is not included in the returned
+ buffer. The returned buffer must be callee freed.
+
+ If the position upon start is 0, then the Ascii Boolean will be set. This should be
+ maintained and not changed for all operations with the same file.
+
+ @param[in] Handle SHELL_FILE_HANDLE to read from.
+ @param[in, out] Ascii Boolean value for indicating whether the file is
+ Ascii (TRUE) or UCS2 (FALSE).
+
+ @return The line of text from the file.
+ @retval NULL There was not enough memory available.
+
+ @sa ShellFileHandleReadLine
+**/
+CHAR16*
+EFIAPI
+ShellFileHandleReturnLine(
+ IN SHELL_FILE_HANDLE Handle,
+ IN OUT BOOLEAN *Ascii
+ )
+{
+ CHAR16 *RetVal;
+ UINTN Size;
+ EFI_STATUS Status;
+
+ Size = 0;
+ RetVal = NULL;
+
+ Status = ShellFileHandleReadLine(Handle, RetVal, &Size, FALSE, Ascii);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ RetVal = AllocateZeroPool(Size);
+ if (RetVal == NULL) {
+ return (NULL);
+ }
+ Status = ShellFileHandleReadLine(Handle, RetVal, &Size, FALSE, Ascii);
+
+ }
+ if (Status == EFI_END_OF_FILE && RetVal != NULL && *RetVal != CHAR_NULL) {
+ Status = EFI_SUCCESS;
+ }
+ if (EFI_ERROR(Status) && (RetVal != NULL)) {
+ FreePool(RetVal);
+ RetVal = NULL;
+ }
+ return (RetVal);
+}
+
+/**
+ Function to read a single line (up to but not including the \n) from a SHELL_FILE_HANDLE.
+
+ If the position upon start is 0, then the Ascii Boolean will be set. This should be
+ maintained and not changed for all operations with the same file.
+
+ NOTE: LINES THAT ARE RETURNED BY THIS FUNCTION ARE UCS2, EVEN IF THE FILE BEING READ
+ IS IN ASCII FORMAT.
+
+ @param[in] Handle SHELL_FILE_HANDLE to read from.
+ @param[in, out] Buffer The pointer to buffer to read into. If this function
+ returns EFI_SUCCESS, then on output Buffer will
+ contain a UCS2 string, even if the file being
+ read is ASCII.
+ @param[in, out] Size On input, pointer to number of bytes in Buffer.
+ On output, unchanged unless Buffer is too small
+ to contain the next line of the file. In that
+ case Size is set to the number of bytes needed
+ to hold the next line of the file (as a UCS2
+ string, even if it is an ASCII file).
+ @param[in] Truncate If the buffer is large enough, this has no effect.
+ If the buffer is is too small and Truncate is TRUE,
+ the line will be truncated.
+ If the buffer is is too small and Truncate is FALSE,
+ then no read will occur.
+
+ @param[in, out] Ascii Boolean value for indicating whether the file is
+ Ascii (TRUE) or UCS2 (FALSE).
+
+ @retval EFI_SUCCESS The operation was successful. The line is stored in
+ Buffer.
+ @retval EFI_END_OF_FILE There are no more lines in the file.
+ @retval EFI_INVALID_PARAMETER Handle was NULL.
+ @retval EFI_INVALID_PARAMETER Size was NULL.
+ @retval EFI_BUFFER_TOO_SMALL Size was not large enough to store the line.
+ Size was updated to the minimum space required.
+**/
+EFI_STATUS
+EFIAPI
+ShellFileHandleReadLine(
+ IN SHELL_FILE_HANDLE Handle,
+ IN OUT CHAR16 *Buffer,
+ IN OUT UINTN *Size,
+ IN BOOLEAN Truncate,
+ IN OUT BOOLEAN *Ascii
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 CharBuffer;
+ UINTN CharSize;
+ UINTN CountSoFar;
+ UINT64 OriginalFilePosition;
+
+
+ if (Handle == NULL
+ ||Size == NULL
+ ){
+ return (EFI_INVALID_PARAMETER);
+ }
+ if (Buffer == NULL) {
+ ASSERT(*Size == 0);
+ } else {
+ *Buffer = CHAR_NULL;
+ }
+ gEfiShellProtocol->GetFilePosition(Handle, &OriginalFilePosition);
+ if (OriginalFilePosition == 0) {
+ CharSize = sizeof(CHAR16);
+ Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer);
+ ASSERT_EFI_ERROR(Status);
+ if (CharBuffer == gUnicodeFileTag) {
+ *Ascii = FALSE;
+ } else {
+ *Ascii = TRUE;
+ gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);
+ }
+ }
+
+ if (*Ascii) {
+ CharSize = sizeof(CHAR8);
+ } else {
+ CharSize = sizeof(CHAR16);
+ }
+ for (CountSoFar = 0;;CountSoFar++){
+ CharBuffer = 0;
+ Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer);
+ if ( EFI_ERROR(Status)
+ || CharSize == 0
+ || (CharBuffer == L'\n' && !(*Ascii))
+ || (CharBuffer == '\n' && *Ascii)
+ ){
+ if (CharSize == 0) {
+ Status = EFI_END_OF_FILE;
+ }
+ break;
+ }
+ //
+ // if we have space save it...
+ //
+ if ((CountSoFar+1)*sizeof(CHAR16) < *Size){
+ ASSERT(Buffer != NULL);
+ ((CHAR16*)Buffer)[CountSoFar] = CharBuffer;
+ ((CHAR16*)Buffer)[CountSoFar+1] = CHAR_NULL;
+ }
+ }
+
+ //
+ // if we ran out of space tell when...
+ //
+ if ((CountSoFar+1)*sizeof(CHAR16) > *Size){
+ *Size = (CountSoFar+1)*sizeof(CHAR16);
+ if (!Truncate) {
+ gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);
+ } else {
+ DEBUG((DEBUG_WARN, "The line was truncated in ShellFileHandleReadLine"));
+ }
+ return (EFI_BUFFER_TOO_SMALL);
+ }
+ while(Buffer[StrLen(Buffer)-1] == L'\r') {
+ Buffer[StrLen(Buffer)-1] = CHAR_NULL;
+ }
+
+ return (Status);
+}
+
+/**
+ Function to print help file / man page content in the spec from the UEFI Shell protocol GetHelpText function.
+
+ @param[in] CommandToGetHelpOn Pointer to a string containing the command name of help file to be printed.
+ @param[in] SectionToGetHelpOn Pointer to the section specifier(s).
+ @param[in] PrintCommandText If TRUE, prints the command followed by the help content, otherwise prints
+ the help content only.
+ @retval EFI_DEVICE_ERROR The help data format was incorrect.
+ @retval EFI_NOT_FOUND The help data could not be found.
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+ShellPrintHelp (
+ IN CONST CHAR16 *CommandToGetHelpOn,
+ IN CONST CHAR16 *SectionToGetHelpOn,
+ IN BOOLEAN PrintCommandText
+ )
+{
+ EFI_STATUS Status;
+ CHAR16 *OutText;
+
+ OutText = NULL;
+
+ //
+ // Get the string to print based
+ //
+ Status = gEfiShellProtocol->GetHelpText (CommandToGetHelpOn, SectionToGetHelpOn, &OutText);
+
+ //
+ // make sure we got a valid string
+ //
+ if (EFI_ERROR(Status)){
+ return Status;
+ }
+ if (OutText == NULL || StrLen(OutText) == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ //
+ // Chop off trailing stuff we dont need
+ //
+ while (OutText[StrLen(OutText)-1] == L'\r' || OutText[StrLen(OutText)-1] == L'\n' || OutText[StrLen(OutText)-1] == L' ') {
+ OutText[StrLen(OutText)-1] = CHAR_NULL;
+ }
+
+ //
+ // Print this out to the console
+ //
+ if (PrintCommandText) {
+ ShellPrintEx(-1, -1, L"%H%-14s%N- %s\r\n", CommandToGetHelpOn, OutText);
+ } else {
+ ShellPrintEx(-1, -1, L"%N%s\r\n", OutText);
+ }
+
+ SHELL_FREE_NON_NULL(OutText);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Function to delete a file by name
+
+ @param[in] FileName Pointer to file name to delete.
+
+ @retval EFI_SUCCESS the file was deleted sucessfully
+ @retval EFI_WARN_DELETE_FAILURE the handle was closed, but the file was not
+ deleted
+ @retval EFI_INVALID_PARAMETER One of the parameters has an invalid value.
+ @retval EFI_NOT_FOUND The specified file could not be found on the
+ device or the file system could not be found
+ on the device.
+ @retval EFI_NO_MEDIA The device has no medium.
+ @retval EFI_MEDIA_CHANGED The device has a different medium in it or the
+ medium is no longer supported.
+ @retval EFI_DEVICE_ERROR The device reported an error.
+ @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
+ @retval EFI_WRITE_PROTECTED The file or medium is write protected.
+ @retval EFI_ACCESS_DENIED The file was opened read only.
+ @retval EFI_OUT_OF_RESOURCES Not enough resources were available to open the
+ file.
+ @retval other The file failed to open
+**/
+EFI_STATUS
+EFIAPI
+ShellDeleteFileByName(
+ IN CONST CHAR16 *FileName
+ )
+{
+ EFI_STATUS Status;
+ SHELL_FILE_HANDLE FileHandle;
+
+ Status = ShellFileExists(FileName);
+
+ if (Status == EFI_SUCCESS){
+ Status = ShellOpenFileByName(FileName, &FileHandle, EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE | EFI_FILE_MODE_CREATE, 0x0);
+ if (Status == EFI_SUCCESS){
+ Status = ShellDeleteFile(&FileHandle);
+ }
+ }
+
+ return(Status);
+
+}
+
+/**
+ Cleans off all the quotes in the string.
+
+ @param[in] OriginalString pointer to the string to be cleaned.
+ @param[out] CleanString The new string with all quotes removed.
+ Memory allocated in the function and free
+ by caller.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+InternalShellStripQuotes (
+ IN CONST CHAR16 *OriginalString,
+ OUT CHAR16 **CleanString
+ )
+{
+ CHAR16 *Walker;
+
+ if (OriginalString == NULL || CleanString == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ *CleanString = AllocateCopyPool (StrSize (OriginalString), OriginalString);
+ if (*CleanString == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ for (Walker = *CleanString; Walker != NULL && *Walker != CHAR_NULL ; Walker++) {
+ if (*Walker == L'\"') {
+ CopyMem(Walker, Walker+1, StrSize(Walker) - sizeof(Walker[0]));
+ }
+ }
+
+ return EFI_SUCCESS;
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellLib/UefiShellLib.h b/Core/ShellPkg/Library/UefiShellLib/UefiShellLib.h
new file mode 100644
index 0000000000..3596f7b011
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLib/UefiShellLib.h
@@ -0,0 +1,96 @@
+/** @file
+ Provides interface to shell functionality for shell commands and applications.
+
+ Copyright (c) 2006 - 2014, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _UEFI_SHELL_LIB_INTERNAL_H_
+#define _UEFI_SHELL_LIB_INTERNAL_H_
+
+#include <Uefi.h>
+
+#include <Guid/FileInfo.h>
+
+#include <Protocol/SimpleFileSystem.h>
+#include <Protocol/LoadedImage.h>
+#include <Protocol/EfiShellInterface.h>
+#include <Protocol/EfiShellEnvironment2.h>
+#include <Protocol/EfiShell.h>
+#include <Protocol/EfiShellParameters.h>
+
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PcdLib.h>
+#include <Library/FileHandleLib.h>
+#include <Library/PrintLib.h>
+#include <Library/UefiLib.h>
+#include <Library/HiiLib.h>
+#include <Library/ShellLib.h>
+
+typedef struct {
+ EFI_SHELL_GET_FILE_INFO GetFileInfo;
+ EFI_SHELL_SET_FILE_INFO SetFileInfo;
+ EFI_SHELL_READ_FILE ReadFile;
+ EFI_SHELL_WRITE_FILE WriteFile;
+ EFI_SHELL_CLOSE_FILE CloseFile;
+ EFI_SHELL_DELETE_FILE DeleteFile;
+ EFI_SHELL_GET_FILE_POSITION GetFilePosition;
+ EFI_SHELL_SET_FILE_POSITION SetFilePosition;
+ EFI_SHELL_FLUSH_FILE FlushFile;
+ EFI_SHELL_GET_FILE_SIZE GetFileSize;
+} FILE_HANDLE_FUNCTION_MAP;
+
+/**
+ Function to determin if an entire string is a valid number.
+
+ If Hex it must be preceeded with a 0x or has ForceHex, set TRUE.
+
+ @param[in] String The string to evaluate.
+ @param[in] ForceHex TRUE - always assume hex.
+ @param[in] StopAtSpace TRUE to halt upon finding a space, FALSE to keep going.
+ @param[in] TimeNumbers TRUE to allow numbers with ":", FALSE otherwise.
+
+ @retval TRUE It is all numeric (dec/hex) characters.
+ @retval FALSE There is a non-numeric character.
+**/
+BOOLEAN
+EFIAPI
+InternalShellIsHexOrDecimalNumber (
+ IN CONST CHAR16 *String,
+ IN CONST BOOLEAN ForceHex,
+ IN CONST BOOLEAN StopAtSpace,
+ IN CONST BOOLEAN TimeNumbers
+ );
+
+/**
+ Cleans off all the quotes in the string.
+
+ @param[in] OriginalString pointer to the string to be cleaned.
+ @param[out] CleanString The new string with all quotes removed.
+ Memory allocated in the function and free
+ by caller.
+
+ @retval EFI_SUCCESS The operation was successful.
+**/
+EFI_STATUS
+EFIAPI
+InternalShellStripQuotes (
+ IN CONST CHAR16 *OriginalString,
+ OUT CHAR16 **CleanString
+ );
+
+
+#endif
+
diff --git a/Core/ShellPkg/Library/UefiShellLib/UefiShellLib.inf b/Core/ShellPkg/Library/UefiShellLib/UefiShellLib.inf
new file mode 100644
index 0000000000..782649a7a0
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellLib/UefiShellLib.inf
@@ -0,0 +1,69 @@
+## @file
+# Provides interface to shell functionality for shell commands and applications.
+#
+# Copyright (c) 2006 - 2015, Intel Corporation. All rights reserved. <BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = UefiShellLib
+ FILE_GUID = 449D0F00-2148-4a43-9836-F10B3980ECF5
+ MODULE_TYPE = UEFI_DRIVER
+ VERSION_STRING = 1.1
+ LIBRARY_CLASS = ShellLib|UEFI_APPLICATION UEFI_DRIVER DXE_RUNTIME_DRIVER DXE_DRIVER
+ CONSTRUCTOR = ShellLibConstructor
+ DESTRUCTOR = ShellLibDestructor
+
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources.common]
+ UefiShellLib.c
+ UefiShellLib.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+ ShellPkg/ShellPkg.dec
+
+[LibraryClasses]
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ DevicePathLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ FileHandleLib
+ PrintLib
+ UefiLib
+ HiiLib
+ SortLib
+
+[Protocols]
+ gEfiSimpleFileSystemProtocolGuid ## SOMETIMES_CONSUMES
+
+ # shell 2.0
+ gEfiShellProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiShellParametersProtocolGuid ## SOMETIMES_CONSUMES
+
+ # 'old' shell
+ gEfiShellEnvironment2Guid ## SOMETIMES_CONSUMES
+ gEfiShellInterfaceGuid ## SOMETIMES_CONSUMES
+
+[Guids]
+ gEfiFileInfoGuid ## SOMETIMES_CONSUMES ## GUID
+ gEfiShellEnvironment2ExtGuid ## SOMETIMES_CONSUMES ## GUID
+
+[Pcd.common]
+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize ## CONSUMES
+ gEfiShellPkgTokenSpaceGuid.PcdShellPrintBufferSize ## CONSUMES
diff --git a/Core/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c b/Core/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c
new file mode 100644
index 0000000000..5e243d5884
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ifconfig.c
@@ -0,0 +1,1426 @@
+/** @file
+ The implementation for Shell command ifconfig based on IP4Config2 protocol.
+
+ (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellNetwork1CommandsLib.h"
+
+typedef enum {
+ IfConfigOpList = 1,
+ IfConfigOpSet = 2,
+ IfConfigOpClear = 3
+} IFCONFIG_OPCODE;
+
+typedef enum {
+ VarCheckReserved = -1,
+ VarCheckOk = 0,
+ VarCheckDuplicate,
+ VarCheckConflict,
+ VarCheckUnknown,
+ VarCheckLackValue,
+ VarCheckOutOfMem
+} VAR_CHECK_CODE;
+
+typedef enum {
+ FlagTypeSingle = 0,
+ FlagTypeNeedVar,
+ FlagTypeNeedSet,
+ FlagTypeSkipUnknown
+} VAR_CHECK_FLAG_TYPE;
+
+#define MACADDRMAXSIZE 32
+
+typedef struct _IFCONFIG_INTERFACE_CB {
+ EFI_HANDLE NicHandle;
+ LIST_ENTRY Link;
+ EFI_IP4_CONFIG2_PROTOCOL *IfCfg;
+ EFI_IP4_CONFIG2_INTERFACE_INFO *IfInfo;
+ EFI_IP4_CONFIG2_POLICY Policy;
+ UINT32 DnsCnt;
+ EFI_IPv4_ADDRESS DnsAddr[1];
+} IFCONFIG_INTERFACE_CB;
+
+typedef struct _ARG_LIST ARG_LIST;
+
+struct _ARG_LIST {
+ ARG_LIST *Next;
+ CHAR16 *Arg;
+};
+
+typedef struct _IFCONFIG4_PRIVATE_DATA {
+ LIST_ENTRY IfList;
+
+ UINT32 OpCode;
+ CHAR16 *IfName;
+ ARG_LIST *VarArg;
+} IFCONFIG_PRIVATE_DATA;
+
+typedef struct _VAR_CHECK_ITEM{
+ CHAR16 *FlagStr;
+ UINT32 FlagID;
+ UINT32 ConflictMask;
+ VAR_CHECK_FLAG_TYPE FlagType;
+} VAR_CHECK_ITEM;
+
+SHELL_PARAM_ITEM mIfConfigCheckList[] = {
+ {
+ L"-b",
+ TypeFlag
+ },
+ {
+ L"-l",
+ TypeValue
+ },
+ {
+ L"-r",
+ TypeValue
+ },
+ {
+ L"-c",
+ TypeValue
+ },
+ {
+ L"-s",
+ TypeMaxValue
+ },
+ {
+ NULL,
+ TypeMax
+ },
+};
+
+VAR_CHECK_ITEM mSetCheckList[] = {
+ {
+ L"static",
+ 0x00000001,
+ 0x00000001,
+ FlagTypeSingle
+ },
+ {
+ L"dhcp",
+ 0x00000002,
+ 0x00000001,
+ FlagTypeSingle
+ },
+ {
+ L"dns",
+ 0x00000008,
+ 0x00000004,
+ FlagTypeSingle
+ },
+ {
+ NULL,
+ 0x0,
+ 0x0,
+ FlagTypeSkipUnknown
+ },
+};
+
+STATIC CONST CHAR16 PermanentString[10] = L"PERMANENT";
+
+/**
+ Free the ARG_LIST.
+
+ @param List Pointer to ARG_LIST to free.
+**/
+VOID
+FreeArgList (
+ ARG_LIST *List
+)
+{
+ ARG_LIST *Next;
+ while (List->Next != NULL) {
+ Next = List->Next;
+ FreePool (List);
+ List = Next;
+ }
+
+ FreePool (List);
+}
+
+/**
+ Split a string with specified separator and save the substring to a list.
+
+ @param[in] String The pointer of the input string.
+ @param[in] Separator The specified separator.
+
+ @return The pointer of headnode of ARG_LIST.
+
+**/
+ARG_LIST *
+SplitStrToList (
+ IN CONST CHAR16 *String,
+ IN CHAR16 Separator
+ )
+{
+ CHAR16 *Str;
+ CHAR16 *ArgStr;
+ ARG_LIST *ArgList;
+ ARG_LIST *ArgNode;
+
+ if (*String == L'\0') {
+ return NULL;
+ }
+
+ //
+ // Copy the CONST string to a local copy.
+ //
+ Str = AllocateCopyPool (StrSize (String), String);
+ if (Str == NULL) {
+ return NULL;
+ }
+ ArgStr = Str;
+
+ //
+ // init a node for the list head.
+ //
+ ArgNode = (ARG_LIST *) AllocateZeroPool (sizeof (ARG_LIST));
+ if (ArgNode == NULL) {
+ return NULL;
+ }
+ ArgList = ArgNode;
+
+ //
+ // Split the local copy and save in the list node.
+ //
+ while (*Str != L'\0') {
+ if (*Str == Separator) {
+ *Str = L'\0';
+ ArgNode->Arg = ArgStr;
+ ArgStr = Str + 1;
+ ArgNode->Next = (ARG_LIST *) AllocateZeroPool (sizeof (ARG_LIST));
+ if (ArgNode->Next == NULL) {
+ //
+ // Free the local copy of string stored in the first node
+ //
+ FreePool (ArgList->Arg);
+ FreeArgList (ArgList);
+ return NULL;
+ }
+ ArgNode = ArgNode->Next;
+ }
+
+ Str++;
+ }
+
+ ArgNode->Arg = ArgStr;
+ ArgNode->Next = NULL;
+
+ return ArgList;
+}
+
+/**
+ Check the correctness of input Args with '-s' option.
+
+ @param[in] CheckList The pointer of VAR_CHECK_ITEM array.
+ @param[in] Name The pointer of input arg.
+ @param[in] Init The switch to execute the check.
+
+ @return VarCheckOk Valid parameter or Initialize check successfully.
+ @return VarCheckDuplicate Duplicated parameter happened.
+ @return VarCheckConflict Conflicted parameter happened
+ @return VarCheckUnknown Unknown parameter.
+
+**/
+VAR_CHECK_CODE
+IfConfigRetriveCheckListByName(
+ IN VAR_CHECK_ITEM *CheckList,
+ IN CHAR16 *Name,
+ IN BOOLEAN Init
+)
+{
+ STATIC UINT32 CheckDuplicate;
+ STATIC UINT32 CheckConflict;
+ VAR_CHECK_CODE RtCode;
+ UINT32 Index;
+ VAR_CHECK_ITEM Arg;
+
+ if (Init) {
+ CheckDuplicate = 0;
+ CheckConflict = 0;
+ return VarCheckOk;
+ }
+
+ RtCode = VarCheckOk;
+ Index = 0;
+ Arg = CheckList[Index];
+
+ //
+ // Check the Duplicated/Conflicted/Unknown input Args.
+ //
+ while (Arg.FlagStr != NULL) {
+ if (StrCmp (Arg.FlagStr, Name) == 0) {
+
+ if (CheckDuplicate & Arg.FlagID) {
+ RtCode = VarCheckDuplicate;
+ break;
+ }
+
+ if (CheckConflict & Arg.ConflictMask) {
+ RtCode = VarCheckConflict;
+ break;
+ }
+
+ CheckDuplicate |= Arg.FlagID;
+ CheckConflict |= Arg.ConflictMask;
+ break;
+ }
+
+ Arg = CheckList[++Index];
+ }
+
+ if (Arg.FlagStr == NULL) {
+ RtCode = VarCheckUnknown;
+ }
+
+ return RtCode;
+}
+
+/**
+ The notify function of create event when performing a manual config.
+
+ @param[in] Event The event this notify function registered to.
+ @param[in] Context Pointer to the context data registered to the event.
+
+**/
+VOID
+EFIAPI
+IfConfigManualAddressNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ *((BOOLEAN *) Context) = TRUE;
+}
+
+/**
+ Print MAC address.
+
+ @param[in] Node The pointer of MAC address buffer.
+ @param[in] Size The size of MAC address buffer.
+
+**/
+VOID
+IfConfigPrintMacAddr (
+ IN UINT8 *Node,
+ IN UINT32 Size
+ )
+{
+ UINTN Index;
+
+ ASSERT (Size <= MACADDRMAXSIZE);
+
+ for (Index = 0; Index < Size; Index++) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MAC_ADDR_BODY), gShellNetwork1HiiHandle, Node[Index]);
+ if (Index + 1 < Size) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_COLON), gShellNetwork1HiiHandle);
+ }
+ }
+
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_NEWLINE), gShellNetwork1HiiHandle);
+}
+
+
+/**
+ The get current status of all handles.
+
+ @param[in] IfName The pointer of IfName(interface name).
+ @param[in] IfList The pointer of IfList(interface list).
+
+ @retval EFI_SUCCESS The get status processed successfully.
+ @retval others The get status process failed.
+
+**/
+EFI_STATUS
+IfConfigGetInterfaceInfo (
+ IN CHAR16 *IfName,
+ IN LIST_ENTRY *IfList
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleIndex;
+ UINTN HandleNum;
+ EFI_HANDLE *HandleBuffer;
+ EFI_IP4_CONFIG2_PROTOCOL *Ip4Cfg2;
+ EFI_IP4_CONFIG2_INTERFACE_INFO *IfInfo;
+ IFCONFIG_INTERFACE_CB *IfCb;
+ UINTN DataSize;
+
+ HandleBuffer = NULL;
+ HandleNum = 0;
+
+ IfInfo = NULL;
+ IfCb = NULL;
+
+ //
+ // Locate all the handles with ip4 service binding protocol.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiIp4ServiceBindingProtocolGuid,
+ NULL,
+ &HandleNum,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status) || (HandleNum == 0)) {
+ return Status;
+ }
+
+ //
+ // Enumerate all handles that installed with ip4 service binding protocol.
+ //
+ for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) {
+ IfCb = NULL;
+ IfInfo = NULL;
+ DataSize = 0;
+
+ //
+ // Ip4config protocol and ip4 service binding protocol are installed
+ // on the same handle.
+ //
+ ASSERT (HandleBuffer != NULL);
+ Status = gBS->HandleProtocol (
+ HandleBuffer[HandleIndex],
+ &gEfiIp4Config2ProtocolGuid,
+ (VOID **) &Ip4Cfg2
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ //
+ // Get the interface information size.
+ //
+ Status = Ip4Cfg2->GetData (
+ Ip4Cfg2,
+ Ip4Config2DataTypeInterfaceInfo,
+ &DataSize,
+ NULL
+ );
+
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ goto ON_ERROR;
+ }
+
+ IfInfo = AllocateZeroPool (DataSize);
+
+ if (IfInfo == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_ERROR;
+ }
+
+ //
+ // Get the interface info.
+ //
+ Status = Ip4Cfg2->GetData (
+ Ip4Cfg2,
+ Ip4Config2DataTypeInterfaceInfo,
+ &DataSize,
+ IfInfo
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ //
+ // Check the interface name if required.
+ //
+ if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) != 0)) {
+ FreePool (IfInfo);
+ continue;
+ }
+
+ DataSize = 0;
+
+ //
+ // Get the size of dns server list.
+ //
+ Status = Ip4Cfg2->GetData (
+ Ip4Cfg2,
+ Ip4Config2DataTypeDnsServer,
+ &DataSize,
+ NULL
+ );
+
+ if ((Status != EFI_BUFFER_TOO_SMALL) && (Status != EFI_NOT_FOUND)) {
+ goto ON_ERROR;
+ }
+
+ IfCb = AllocateZeroPool (sizeof (IFCONFIG_INTERFACE_CB) + DataSize);
+
+ if (IfCb == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_ERROR;
+ }
+
+ IfCb->NicHandle = HandleBuffer[HandleIndex];
+ IfCb->IfInfo = IfInfo;
+ IfCb->IfCfg = Ip4Cfg2;
+ IfCb->DnsCnt = (UINT32) (DataSize / sizeof (EFI_IPv4_ADDRESS));
+
+ //
+ // Get the dns server list if has.
+ //
+ if (DataSize > 0) {
+ Status = Ip4Cfg2->GetData (
+ Ip4Cfg2,
+ Ip4Config2DataTypeDnsServer,
+ &DataSize,
+ IfCb->DnsAddr
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+ }
+
+ //
+ // Get the config policy.
+ //
+ DataSize = sizeof (EFI_IP4_CONFIG2_POLICY);
+ Status = Ip4Cfg2->GetData (
+ Ip4Cfg2,
+ Ip4Config2DataTypePolicy,
+ &DataSize,
+ &IfCb->Policy
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ InsertTailList (IfList, &IfCb->Link);
+
+ if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) == 0)) {
+ //
+ // Only need the appointed interface, keep the allocated buffer.
+ //
+ IfCb = NULL;
+ IfInfo = NULL;
+ break;
+ }
+ }
+
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+
+ return EFI_SUCCESS;
+
+ON_ERROR:
+
+ if (IfInfo != NULL) {
+ FreePool (IfInfo);
+ }
+
+ if (IfCb != NULL) {
+ FreePool (IfCb);
+ }
+
+ return Status;
+}
+
+/**
+ The list process of the ifconfig command.
+
+ @param[in] IfList The pointer of IfList(interface list).
+
+ @retval SHELL_SUCCESS The ifconfig command list processed successfully.
+ @retval others The ifconfig command list process failed.
+
+**/
+SHELL_STATUS
+IfConfigShowInterfaceInfo (
+ IN LIST_ENTRY *IfList
+ )
+{
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *Next;
+ IFCONFIG_INTERFACE_CB *IfCb;
+ BOOLEAN MediaPresent;
+ EFI_IPv4_ADDRESS Gateway;
+ UINT32 Index;
+
+ MediaPresent = TRUE;
+
+ if (IsListEmpty (IfList)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INVALID_INTERFACE), gShellNetwork1HiiHandle);
+ }
+
+ //
+ // Go through the interface list.
+ //
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, IfList) {
+ IfCb = NET_LIST_USER_STRUCT (Entry, IFCONFIG_INTERFACE_CB, Link);
+
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_BREAK), gShellNetwork1HiiHandle);
+
+ //
+ // Print interface name.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_IF_NAME), gShellNetwork1HiiHandle, IfCb->IfInfo->Name);
+
+ //
+ // Get Media State.
+ //
+ NetLibDetectMedia (IfCb->NicHandle, &MediaPresent);
+ if (!MediaPresent) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MEDIA_STATE), gShellNetwork1HiiHandle, L"Media disconnected");
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MEDIA_STATE), gShellNetwork1HiiHandle, L"Media present");
+ }
+
+ //
+ // Print interface config policy.
+ //
+ if (IfCb->Policy == Ip4Config2PolicyDhcp) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_POLICY_DHCP), gShellNetwork1HiiHandle);
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_POLICY_MAN), gShellNetwork1HiiHandle);
+ }
+
+ //
+ // Print mac address of the interface.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_MAC_ADDR_HEAD), gShellNetwork1HiiHandle);
+
+ IfConfigPrintMacAddr (
+ IfCb->IfInfo->HwAddress.Addr,
+ IfCb->IfInfo->HwAddressSize
+ );
+
+ //
+ // Print IPv4 address list of the interface.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_HEAD), gShellNetwork1HiiHandle);
+
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_BODY),
+ gShellNetwork1HiiHandle,
+ (UINTN)IfCb->IfInfo->StationAddress.Addr[0],
+ (UINTN)IfCb->IfInfo->StationAddress.Addr[1],
+ (UINTN)IfCb->IfInfo->StationAddress.Addr[2],
+ (UINTN)IfCb->IfInfo->StationAddress.Addr[3]
+ );
+
+ //
+ // Print subnet mask list of the interface.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_SUBNET_MASK_HEAD), gShellNetwork1HiiHandle);
+
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_BODY),
+ gShellNetwork1HiiHandle,
+ (UINTN)IfCb->IfInfo->SubnetMask.Addr[0],
+ (UINTN)IfCb->IfInfo->SubnetMask.Addr[1],
+ (UINTN)IfCb->IfInfo->SubnetMask.Addr[2],
+ (UINTN)IfCb->IfInfo->SubnetMask.Addr[3]
+ );
+
+ //
+ // Print default gateway of the interface.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_GATEWAY_HEAD), gShellNetwork1HiiHandle);
+
+ ZeroMem (&Gateway, sizeof (EFI_IPv4_ADDRESS));
+
+ for (Index = 0; Index < IfCb->IfInfo->RouteTableSize; Index++) {
+ if ((CompareMem (&IfCb->IfInfo->RouteTable[Index].SubnetAddress, &mZeroIp4Addr, sizeof (EFI_IPv4_ADDRESS)) == 0) &&
+ (CompareMem (&IfCb->IfInfo->RouteTable[Index].SubnetMask , &mZeroIp4Addr, sizeof (EFI_IPv4_ADDRESS)) == 0) ){
+ CopyMem (&Gateway, &IfCb->IfInfo->RouteTable[Index].GatewayAddress, sizeof (EFI_IPv4_ADDRESS));
+ }
+ }
+
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_IFCONFIG_INFO_IP_ADDR_BODY),
+ gShellNetwork1HiiHandle,
+ (UINTN)Gateway.Addr[0],
+ (UINTN)Gateway.Addr[1],
+ (UINTN)Gateway.Addr[2],
+ (UINTN)Gateway.Addr[3]
+ );
+
+ //
+ // Print route table entry.
+ //
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_ROUTES_SIZE), gShellNetwork1HiiHandle, IfCb->IfInfo->RouteTableSize);
+
+ for (Index = 0; Index < IfCb->IfInfo->RouteTableSize; Index++) {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_ROUTES_ENTRY_INDEX), gShellNetwork1HiiHandle, Index);
+
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR),
+ gShellNetwork1HiiHandle,
+ L"Subnet ",
+ (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[0],
+ (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[1],
+ (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[2],
+ (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetAddress.Addr[3]
+ );
+
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR),
+ gShellNetwork1HiiHandle,
+ L"Netmask",
+ (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[0],
+ (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[1],
+ (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[2],
+ (UINTN)IfCb->IfInfo->RouteTable[Index].SubnetMask.Addr[3]
+ );
+
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_IFCONFIG_SHOW_IP_ADDR),
+ gShellNetwork1HiiHandle,
+ L"Gateway",
+ (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[0],
+ (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[1],
+ (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[2],
+ (UINTN)IfCb->IfInfo->RouteTable[Index].GatewayAddress.Addr[3]
+ );
+ }
+
+ //
+ // Print dns server addresses list of the interface if has.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_DNS_ADDR_HEAD), gShellNetwork1HiiHandle);
+
+ for (Index = 0; Index < IfCb->DnsCnt; Index++) {
+ ShellPrintHiiEx(
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_IFCONFIG_INFO_DNS_ADDR_BODY),
+ gShellNetwork1HiiHandle,
+ (UINTN) IfCb->DnsAddr[Index].Addr[0],
+ (UINTN) IfCb->DnsAddr[Index].Addr[1],
+ (UINTN) IfCb->DnsAddr[Index].Addr[2],
+ (UINTN) IfCb->DnsAddr[Index].Addr[3]
+ );
+
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_NEWLINE), gShellNetwork1HiiHandle);
+ }
+ }
+
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INFO_BREAK), gShellNetwork1HiiHandle);
+
+ return SHELL_SUCCESS;
+}
+
+/**
+ The clean process of the ifconfig command to clear interface info.
+
+ @param[in] IfList The pointer of IfList(interface list).
+ @param[in] IfName The pointer of interface name.
+
+ @retval SHELL_SUCCESS The ifconfig command clean processed successfully.
+ @retval others The ifconfig command clean process failed.
+
+**/
+SHELL_STATUS
+IfConfigClearInterfaceInfo (
+ IN LIST_ENTRY *IfList,
+ IN CHAR16 *IfName
+ )
+{
+ EFI_STATUS Status;
+ SHELL_STATUS ShellStatus;
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *Next;
+ IFCONFIG_INTERFACE_CB *IfCb;
+ EFI_IP4_CONFIG2_POLICY Policy;
+
+ Status = EFI_SUCCESS;
+ ShellStatus = SHELL_SUCCESS;
+
+ if (IsListEmpty (IfList)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INVALID_INTERFACE), gShellNetwork1HiiHandle);
+ }
+
+ //
+ // Go through the interface list.
+ // If the interface name is specified, DHCP DORA process will be
+ // triggered by the policy transition (static -> dhcp).
+ //
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, IfList) {
+ IfCb = NET_LIST_USER_STRUCT (Entry, IFCONFIG_INTERFACE_CB, Link);
+
+ if ((IfName != NULL) && (StrCmp (IfName, IfCb->IfInfo->Name) == 0)) {
+ Policy = Ip4Config2PolicyStatic;
+
+ Status = IfCb->IfCfg->SetData (
+ IfCb->IfCfg,
+ Ip4Config2DataTypePolicy,
+ sizeof (EFI_IP4_CONFIG2_POLICY),
+ &Policy
+ );
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
+ ShellStatus = SHELL_ACCESS_DENIED;
+ break;
+ }
+ }
+
+ Policy = Ip4Config2PolicyDhcp;
+
+ Status = IfCb->IfCfg->SetData (
+ IfCb->IfCfg,
+ Ip4Config2DataTypePolicy,
+ sizeof (EFI_IP4_CONFIG2_POLICY),
+ &Policy
+ );
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
+ ShellStatus = SHELL_ACCESS_DENIED;
+ break;
+ }
+ }
+
+ return ShellStatus;
+}
+
+/**
+ The set process of the ifconfig command.
+
+ @param[in] IfList The pointer of IfList(interface list).
+ @param[in] VarArg The pointer of ARG_LIST(Args with "-s" option).
+
+ @retval SHELL_SUCCESS The ifconfig command set processed successfully.
+ @retval others The ifconfig command set process failed.
+
+**/
+SHELL_STATUS
+IfConfigSetInterfaceInfo (
+ IN LIST_ENTRY *IfList,
+ IN ARG_LIST *VarArg
+ )
+{
+ EFI_STATUS Status;
+ SHELL_STATUS ShellStatus;
+ IFCONFIG_INTERFACE_CB *IfCb;
+ VAR_CHECK_CODE CheckCode;
+ EFI_EVENT TimeOutEvt;
+ EFI_EVENT MappedEvt;
+ BOOLEAN IsAddressOk;
+
+ EFI_IP4_CONFIG2_POLICY Policy;
+ EFI_IP4_CONFIG2_MANUAL_ADDRESS ManualAddress;
+ UINTN DataSize;
+ EFI_IPv4_ADDRESS Gateway;
+ EFI_IPv4_ADDRESS *Dns;
+ ARG_LIST *Tmp;
+ UINTN Index;
+
+ CONST CHAR16* TempString;
+
+ Dns = NULL;
+
+ if (IsListEmpty (IfList)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_INVALID_INTERFACE), gShellNetwork1HiiHandle);
+ return SHELL_INVALID_PARAMETER;
+ }
+
+ //
+ // Make sure to set only one interface each time.
+ //
+ IfCb = NET_LIST_USER_STRUCT (IfList->ForwardLink, IFCONFIG_INTERFACE_CB, Link);
+ Status = EFI_SUCCESS;
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // Initialize check list mechanism.
+ //
+ CheckCode = IfConfigRetriveCheckListByName(
+ NULL,
+ NULL,
+ TRUE
+ );
+
+ //
+ // Create events & timers for asynchronous settings.
+ //
+ Status = gBS->CreateEvent (
+ EVT_TIMER,
+ TPL_CALLBACK,
+ NULL,
+ NULL,
+ &TimeOutEvt
+ );
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ IfConfigManualAddressNotify,
+ &IsAddressOk,
+ &MappedEvt
+ );
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ //
+ // Parse the setting variables.
+ //
+ while (VarArg != NULL) {
+ //
+ // Check invalid parameters (duplication & unknown & conflict).
+ //
+ CheckCode = IfConfigRetriveCheckListByName(
+ mSetCheckList,
+ VarArg->Arg,
+ FALSE
+ );
+
+ if (VarCheckOk != CheckCode) {
+ switch (CheckCode) {
+ case VarCheckDuplicate:
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_DUPLICATE_COMMAND), gShellNetwork1HiiHandle, VarArg->Arg);
+ break;
+
+ case VarCheckConflict:
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_CONFLICT_COMMAND), gShellNetwork1HiiHandle, VarArg->Arg);
+ break;
+
+ case VarCheckUnknown:
+ //
+ // To handle unsupported option.
+ //
+ TempString = PermanentString;
+ if (StringNoCaseCompare(&VarArg->Arg, &TempString) == 0) {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_UNSUPPORTED_OPTION), gShellNetwork1HiiHandle, PermanentString);
+ goto ON_EXIT;
+ }
+
+ //
+ // To handle unknown option.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_UNKNOWN_COMMAND), gShellNetwork1HiiHandle, VarArg->Arg);
+ break;
+
+ default:
+ break;
+ }
+
+ VarArg = VarArg->Next;
+ continue;
+ }
+
+ //
+ // Process valid variables.
+ //
+ if (StrCmp(VarArg->Arg, L"dhcp") == 0) {
+ //
+ // Set dhcp config policy
+ //
+ Policy = Ip4Config2PolicyDhcp;
+ Status = IfCb->IfCfg->SetData (
+ IfCb->IfCfg,
+ Ip4Config2DataTypePolicy,
+ sizeof (EFI_IP4_CONFIG2_POLICY),
+ &Policy
+ );
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ VarArg= VarArg->Next;
+
+ } else if (StrCmp (VarArg->Arg, L"static") == 0) {
+ VarArg= VarArg->Next;
+ if (VarArg == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_COMMAND), gShellNetwork1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ ZeroMem (&ManualAddress, sizeof (ManualAddress));
+
+ //
+ // Get manual IP address.
+ //
+ Status = NetLibStrToIp4 (VarArg->Arg, &ManualAddress.Address);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IPADDRESS), gShellNetwork1HiiHandle, VarArg->Arg);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ //
+ // Get subnetmask.
+ //
+ VarArg = VarArg->Next;
+ if (VarArg == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_COMMAND), gShellNetwork1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ Status = NetLibStrToIp4 (VarArg->Arg, &ManualAddress.SubnetMask);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IPADDRESS), gShellNetwork1HiiHandle, VarArg->Arg);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ //
+ // Get gateway.
+ //
+ VarArg = VarArg->Next;
+ if (VarArg == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_COMMAND), gShellNetwork1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ Status = NetLibStrToIp4 (VarArg->Arg, &Gateway);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IPADDRESS), gShellNetwork1HiiHandle, VarArg->Arg);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ //
+ // Set manual config policy.
+ //
+ Policy = Ip4Config2PolicyStatic;
+ Status = IfCb->IfCfg->SetData (
+ IfCb->IfCfg,
+ Ip4Config2DataTypePolicy,
+ sizeof (EFI_IP4_CONFIG2_POLICY),
+ &Policy
+ );
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ //
+ // Set Manual Address.
+ //
+ IsAddressOk = FALSE;
+
+ Status = IfCb->IfCfg->RegisterDataNotify (
+ IfCb->IfCfg,
+ Ip4Config2DataTypeManualAddress,
+ MappedEvt
+ );
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_SET_ADDR_FAILED), gShellNetwork1HiiHandle, Status);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ DataSize = sizeof (EFI_IP4_CONFIG2_MANUAL_ADDRESS);
+
+ Status = IfCb->IfCfg->SetData (
+ IfCb->IfCfg,
+ Ip4Config2DataTypeManualAddress,
+ DataSize,
+ &ManualAddress
+ );
+
+ if (Status == EFI_NOT_READY) {
+ gBS->SetTimer (TimeOutEvt, TimerRelative, 50000000);
+
+ while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) {
+ if (IsAddressOk) {
+ Status = EFI_SUCCESS;
+ break;
+ }
+ }
+ }
+
+ IfCb->IfCfg->UnregisterDataNotify (
+ IfCb->IfCfg,
+ Ip4Config2DataTypeManualAddress,
+ MappedEvt
+ );
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_SET_ADDR_FAILED), gShellNetwork1HiiHandle, Status);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ //
+ // Set gateway.
+ //
+ DataSize = sizeof (EFI_IPv4_ADDRESS);
+
+ Status = IfCb->IfCfg->SetData (
+ IfCb->IfCfg,
+ Ip4Config2DataTypeGateway,
+ DataSize,
+ &Gateway
+ );
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_SET_ADDR_FAILED), gShellNetwork1HiiHandle, Status);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ VarArg = VarArg->Next;
+
+ } else if (StrCmp (VarArg->Arg, L"dns") == 0) {
+ //
+ // Get DNS addresses.
+ //
+ VarArg = VarArg->Next;
+ Tmp = VarArg;
+ Index = 0;
+ while (Tmp != NULL) {
+ Index ++;
+ Tmp = Tmp->Next;
+ }
+
+ Dns = AllocatePool (Index * sizeof (EFI_IPv4_ADDRESS));
+ if (Dns == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork1HiiHandle, L"ifconfig");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+ Tmp = VarArg;
+ Index = 0;
+ while (Tmp != NULL) {
+ Status = NetLibStrToIp4 (Tmp->Arg, Dns + Index);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx(-1, -1, NULL,STRING_TOKEN (STR_IFCONFIG_INVALID_IPADDRESS), gShellNetwork1HiiHandle, Tmp->Arg);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+ Index ++;
+ Tmp = Tmp->Next;
+ }
+
+ VarArg = Tmp;
+
+ //
+ // Set DNS addresses.
+ //
+ DataSize = Index * sizeof (EFI_IPv4_ADDRESS);
+
+ Status = IfCb->IfCfg->SetData (
+ IfCb->IfCfg,
+ Ip4Config2DataTypeDnsServer,
+ DataSize,
+ Dns
+ );
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork1HiiHandle, L"ifconfig");
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+ }
+ }
+
+ON_EXIT:
+ if (Dns != NULL) {
+ FreePool (Dns);
+ }
+
+ return ShellStatus;
+
+}
+
+/**
+ The ifconfig command main process.
+
+ @param[in] Private The pointer of IFCONFIG_PRIVATE_DATA.
+
+ @retval SHELL_SUCCESS ifconfig command processed successfully.
+ @retval others The ifconfig command process failed.
+
+**/
+SHELL_STATUS
+IfConfig (
+ IN IFCONFIG_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status;
+ SHELL_STATUS ShellStatus;
+
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // Get configure information of all interfaces.
+ //
+ Status = IfConfigGetInterfaceInfo (
+ Private->IfName,
+ &Private->IfList
+ );
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_NOT_FOUND;
+ goto ON_EXIT;
+ }
+
+ switch (Private->OpCode) {
+ case IfConfigOpList:
+ ShellStatus = IfConfigShowInterfaceInfo (&Private->IfList);
+ break;
+
+ case IfConfigOpClear:
+ ShellStatus = IfConfigClearInterfaceInfo (&Private->IfList, Private->IfName);
+ break;
+
+ case IfConfigOpSet:
+ ShellStatus = IfConfigSetInterfaceInfo (&Private->IfList, Private->VarArg);
+ break;
+
+ default:
+ ShellStatus = SHELL_UNSUPPORTED;
+ }
+
+ON_EXIT:
+ return ShellStatus;
+}
+
+/**
+ The ifconfig command cleanup process, free the allocated memory.
+
+ @param[in] Private The pointer of IFCONFIG_PRIVATE_DATA.
+
+**/
+VOID
+IfConfigCleanup (
+ IN IFCONFIG_PRIVATE_DATA *Private
+ )
+{
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *NextEntry;
+ IFCONFIG_INTERFACE_CB *IfCb;
+
+ ASSERT (Private != NULL);
+
+ //
+ // Clean the list which save the set config Args.
+ //
+ if (Private->VarArg != NULL) {
+ FreeArgList (Private->VarArg);
+ }
+
+ if (Private->IfName != NULL) {
+ FreePool (Private->IfName);
+ }
+
+ //
+ // Clean the IFCONFIG_INTERFACE_CB list.
+ //
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->IfList) {
+ IfCb = NET_LIST_USER_STRUCT (Entry, IFCONFIG_INTERFACE_CB, Link);
+
+ RemoveEntryList (&IfCb->Link);
+
+ if (IfCb->IfInfo != NULL) {
+
+ FreePool (IfCb->IfInfo);
+ }
+
+ FreePool (IfCb);
+ }
+
+ FreePool (Private);
+}
+
+/**
+ Function for 'ifconfig' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+
+ @retval EFI_SUCCESS ifconfig command processed successfully.
+ @retval others The ifconfig command process failed.
+
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunIfconfig (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ IFCONFIG_PRIVATE_DATA *Private;
+ LIST_ENTRY *ParamPackage;
+ SHELL_STATUS ShellStatus;
+ CONST CHAR16 *ValueStr;
+ ARG_LIST *ArgList;
+ CHAR16 *ProblemParam;
+ CHAR16 *Str;
+
+ Status = EFI_INVALID_PARAMETER;
+ Private = NULL;
+ ShellStatus = SHELL_SUCCESS;
+
+ Status = ShellCommandLineParseEx (mIfConfigCheckList, &ParamPackage, &ProblemParam, TRUE, FALSE);
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_VOLUME_CORRUPTED && ProblemParam != NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ifconfig", ProblemParam);
+ FreePool(ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ } else {
+ ASSERT(FALSE);
+ }
+
+ goto ON_EXIT;
+ }
+
+ //
+ // To handle unsupported option.
+ //
+ if (ShellCommandLineGetFlag (ParamPackage, L"-c")) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_UNSUPPORTED_OPTION), gShellNetwork1HiiHandle,L"-c");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ //
+ // To handle no option.
+ //
+ if (!ShellCommandLineGetFlag (ParamPackage, L"-r") && !ShellCommandLineGetFlag (ParamPackage, L"-s") &&
+ !ShellCommandLineGetFlag (ParamPackage, L"-l")) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_OPTION), gShellNetwork1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ //
+ // To handle conflict options.
+ //
+ if (((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-s"))) ||
+ ((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-l"))) ||
+ ((ShellCommandLineGetFlag (ParamPackage, L"-s")) && (ShellCommandLineGetFlag (ParamPackage, L"-l")))) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_CON), gShellNetwork1HiiHandle, L"ifconfig");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ Private = AllocateZeroPool (sizeof (IFCONFIG_PRIVATE_DATA));
+ if (Private == NULL) {
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ InitializeListHead (&Private->IfList);
+
+ //
+ // To get interface name for the list option.
+ //
+ if (ShellCommandLineGetFlag (ParamPackage, L"-l")) {
+ Private->OpCode = IfConfigOpList;
+ ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l");
+ if (ValueStr != NULL) {
+ Str = AllocateCopyPool (StrSize (ValueStr), ValueStr);
+ if (Str == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork1HiiHandle, L"ifconfig");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+ Private->IfName = Str;
+ }
+ }
+
+ //
+ // To get interface name for the clear option.
+ //
+ if (ShellCommandLineGetFlag (ParamPackage, L"-r")) {
+ Private->OpCode = IfConfigOpClear;
+ ValueStr = ShellCommandLineGetValue (ParamPackage, L"-r");
+ if (ValueStr != NULL) {
+ Str = AllocateCopyPool (StrSize (ValueStr), ValueStr);
+ if (Str == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork1HiiHandle, L"ifconfig");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+ Private->IfName = Str;
+ }
+ }
+
+ //
+ // To get interface name and corresponding Args for the set option.
+ //
+ if (ShellCommandLineGetFlag (ParamPackage, L"-s")) {
+ ValueStr = ShellCommandLineGetValue (ParamPackage, L"-s");
+ if (ValueStr == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_INTERFACE), gShellNetwork1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ //
+ // To split the configuration into multi-section.
+ //
+ ArgList = SplitStrToList (ValueStr, L' ');
+ if (ArgList == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork1HiiHandle, L"ifconfig");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ Private->OpCode = IfConfigOpSet;
+ Private->IfName = ArgList->Arg;
+
+ Private->VarArg = ArgList->Next;
+
+ if (Private->IfName == NULL || Private->VarArg == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG_LACK_COMMAND), gShellNetwork1HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+ }
+
+ //
+ // Main process of ifconfig.
+ //
+ ShellStatus = IfConfig (Private);
+
+ON_EXIT:
+
+ ShellCommandLineFreeVarList (ParamPackage);
+
+ if (Private != NULL) {
+ IfConfigCleanup (Private);
+ }
+
+ return ShellStatus;
+}
diff --git a/Core/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c b/Core/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c
new file mode 100644
index 0000000000..e2dc76570a
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellNetwork1CommandsLib/Ping.c
@@ -0,0 +1,1619 @@
+/** @file
+ The implementation for Ping shell command.
+
+ (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+ (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellNetwork1CommandsLib.h"
+
+#define PING_IP4_COPY_ADDRESS(Dest, Src) (CopyMem ((Dest), (Src), sizeof (EFI_IPv4_ADDRESS)))
+
+UINT64 mCurrentTick = 0;
+
+//
+// Function templates to match the IPv4 and IPv6 commands that we use.
+//
+typedef
+EFI_STATUS
+(EFIAPI *PING_IPX_POLL)(
+ IN VOID *This
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *PING_IPX_TRANSMIT)(
+ IN VOID *This,
+ IN VOID *Token
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *PING_IPX_RECEIVE)(
+ IN VOID *This,
+ IN VOID *Token
+ );
+
+typedef
+EFI_STATUS
+(EFIAPI *PING_IPX_CANCEL)(
+ IN VOID *This,
+ IN VOID *Token OPTIONAL
+ );
+
+///
+/// A set of pointers to either IPv6 or IPv4 functions.
+/// Unknown which one to the ping command.
+///
+typedef struct {
+ PING_IPX_TRANSMIT Transmit;
+ PING_IPX_RECEIVE Receive;
+ PING_IPX_CANCEL Cancel;
+ PING_IPX_POLL Poll;
+}PING_IPX_PROTOCOL;
+
+
+typedef union {
+ VOID *RxData;
+ VOID *TxData;
+} PING_PACKET;
+
+//
+// PING_IPX_COMPLETION_TOKEN
+// structures are used for both transmit and receive operations.
+// This version is IP-unaware.
+//
+typedef struct {
+ EFI_EVENT Event;
+ EFI_STATUS Status;
+ PING_PACKET Packet;
+} PING_IPX_COMPLETION_TOKEN;
+
+#pragma pack(1)
+typedef struct _ICMPX_ECHO_REQUEST_REPLY {
+ UINT8 Type;
+ UINT8 Code;
+ UINT16 Checksum;
+ UINT16 Identifier;
+ UINT16 SequenceNum;
+ UINT64 TimeStamp;
+ UINT8 Data[1];
+} ICMPX_ECHO_REQUEST_REPLY;
+#pragma pack()
+
+typedef struct _PING_ICMP_TX_INFO {
+ LIST_ENTRY Link;
+ UINT16 SequenceNum;
+ UINT64 TimeStamp;
+ PING_IPX_COMPLETION_TOKEN *Token;
+} PING_ICMPX_TX_INFO;
+
+#define DEFAULT_TIMEOUT 5000
+#define MAX_SEND_NUMBER 10000
+#define MAX_BUFFER_SIZE 32768
+#define DEFAULT_TIMER_PERIOD 358049
+#define ONE_SECOND 10000000
+#define PING_IP_CHOICE_IP4 1
+#define PING_IP_CHOICE_IP6 2
+#define DEFAULT_SEND_COUNT 10
+#define DEFAULT_BUFFER_SIZE 16
+#define ICMP_V4_ECHO_REQUEST 0x8
+#define ICMP_V4_ECHO_REPLY 0x0
+
+#define PING_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('P', 'i', 'n', 'g')
+typedef struct _PING_PRIVATE_DATA {
+ UINT32 Signature;
+ EFI_HANDLE NicHandle;
+ EFI_HANDLE IpChildHandle;
+ EFI_EVENT Timer;
+
+ EFI_STATUS Status;
+ LIST_ENTRY TxList;
+ UINT16 RxCount;
+ UINT16 TxCount;
+ UINT64 RttSum;
+ UINT64 RttMin;
+ UINT64 RttMax;
+ UINT32 SequenceNum;
+
+ UINT32 SendNum;
+ UINT32 BufferSize;
+ UINT32 IpChoice;
+
+ PING_IPX_PROTOCOL ProtocolPointers;
+ VOID *IpProtocol;
+ UINT8 SrcAddress[MAX(sizeof(EFI_IPv6_ADDRESS) , sizeof(EFI_IPv4_ADDRESS) )];
+ UINT8 DstAddress[MAX(sizeof(EFI_IPv6_ADDRESS) , sizeof(EFI_IPv4_ADDRESS) )];
+ PING_IPX_COMPLETION_TOKEN RxToken;
+ UINT16 FailedCount;
+} PING_PRIVATE_DATA;
+
+/**
+ Calculate the internet checksum (see RFC 1071).
+
+ @param[in] Packet Buffer which contains the data to be checksummed.
+ @param[in] Length Length to be checksummed.
+
+ @retval Checksum Returns the 16 bit ones complement of
+ ones complement sum of 16 bit words
+**/
+UINT16
+EFIAPI
+NetChecksum (
+ IN UINT8 *Buffer,
+ IN UINT32 Length
+ )
+{
+ UINT32 Sum;
+ UINT8 Odd;
+ UINT16 *Packet;
+
+ Packet = (UINT16 *) Buffer;
+
+ Sum = 0;
+ Odd = (UINT8) (Length & 1);
+ Length >>= 1;
+ while ((Length--) != 0) {
+ Sum += *Packet++;
+ }
+
+ if (Odd != 0) {
+ Sum += *(UINT8 *) Packet;
+ }
+
+ Sum = (Sum & 0xffff) + (Sum >> 16);
+
+ //
+ // in case above carried
+ //
+ Sum += Sum >> 16;
+
+ return (UINT16) Sum;
+}
+
+/**
+ Reads and returns the current value of register.
+ In IA64, the register is the Interval Timer Vector (ITV).
+ In X86(IA32/X64), the register is the Time Stamp Counter (TSC)
+
+ @return The current value of the register.
+
+**/
+
+STATIC CONST SHELL_PARAM_ITEM PingParamList[] = {
+ {
+ L"-l",
+ TypeValue
+ },
+ {
+ L"-n",
+ TypeValue
+ },
+ {
+ L"-s",
+ TypeValue
+ },
+ {
+ L"-_s",
+ TypeValue
+ },
+ {
+ L"-_ip6",
+ TypeFlag
+ },
+ {
+ NULL,
+ TypeMax
+ },
+};
+
+//
+// Global Variables in Ping command.
+//
+STATIC CONST CHAR16 *mDstString;
+STATIC CONST CHAR16 *mSrcString;
+STATIC UINT64 mFrequency = 0;
+EFI_CPU_ARCH_PROTOCOL *gCpu = NULL;
+
+/**
+ Read the current time.
+
+ @retval the current tick value.
+**/
+UINT64
+EFIAPI
+ReadTime (
+ VOID
+ )
+{
+ UINT64 TimerPeriod;
+ EFI_STATUS Status;
+
+ ASSERT (gCpu != NULL);
+
+ Status = gCpu->GetTimerValue (gCpu, 0, &mCurrentTick, &TimerPeriod);
+ if (EFI_ERROR (Status)) {
+ //
+ // The WinntGetTimerValue will return EFI_UNSUPPORTED. Set the
+ // TimerPeriod by ourselves.
+ //
+ mCurrentTick += 1000000;
+ }
+
+ return mCurrentTick;
+}
+
+
+/**
+ Get and calculate the frequency in ticks/ms.
+ The result is saved in the global variable mFrequency
+
+ @retval EFI_SUCCESS Calculated the frequency successfully.
+ @retval Others Failed to calculate the frequency.
+
+**/
+EFI_STATUS
+EFIAPI
+GetFrequency (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT64 CurrentTick;
+ UINT64 TimerPeriod;
+
+ Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **) &gCpu);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = gCpu->GetTimerValue (gCpu, 0, &CurrentTick, &TimerPeriod);
+
+ if (EFI_ERROR (Status)) {
+ TimerPeriod = DEFAULT_TIMER_PERIOD;
+ }
+
+ //
+ // The timer period is in femtosecond (1 femtosecond is 1e-15 second).
+ // So 1e+12 is divided by timer period to produce the freq in ticks/ms.
+ //
+ mFrequency = DivU64x64Remainder (1000000000000ULL, TimerPeriod, NULL);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Calculate a duration in ms.
+
+ @param[in] Begin The start point of time.
+ @param[in] End The end point of time.
+
+ @return The duration in ms.
+ @retval 0 The parameters were not valid.
+**/
+UINT64
+EFIAPI
+CalculateTick (
+ IN UINT64 Begin,
+ IN UINT64 End
+ )
+{
+ if (End <= Begin) {
+ return (0);
+ }
+ return DivU64x64Remainder (End - Begin, mFrequency, NULL);
+}
+
+/**
+ Destroy PING_ICMPX_TX_INFO, and recollect the memory.
+
+ @param[in] TxInfo The pointer to PING_ICMPX_TX_INFO.
+ @param[in] IpChoice Whether the token is IPv4 or IPv6
+**/
+VOID
+EFIAPI
+PingDestroyTxInfo (
+ IN PING_ICMPX_TX_INFO *TxInfo,
+ IN UINT32 IpChoice
+ )
+{
+ EFI_IP6_TRANSMIT_DATA *Ip6TxData;
+ EFI_IP4_TRANSMIT_DATA *Ip4TxData;
+ EFI_IP6_FRAGMENT_DATA *FragData;
+ UINTN Index;
+
+ if (TxInfo == NULL) {
+ return;
+ }
+
+ if (TxInfo->Token != NULL) {
+
+ if (TxInfo->Token->Event != NULL) {
+ gBS->CloseEvent (TxInfo->Token->Event);
+ }
+
+ if (TxInfo->Token->Packet.TxData != NULL) {
+ if (IpChoice == PING_IP_CHOICE_IP6) {
+ Ip6TxData = TxInfo->Token->Packet.TxData;
+
+ if (Ip6TxData->OverrideData != NULL) {
+ FreePool (Ip6TxData->OverrideData);
+ }
+
+ if (Ip6TxData->ExtHdrs != NULL) {
+ FreePool (Ip6TxData->ExtHdrs);
+ }
+
+ for (Index = 0; Index < Ip6TxData->FragmentCount; Index++) {
+ FragData = Ip6TxData->FragmentTable[Index].FragmentBuffer;
+ if (FragData != NULL) {
+ FreePool (FragData);
+ }
+ }
+ } else {
+ Ip4TxData = TxInfo->Token->Packet.TxData;
+
+ if (Ip4TxData->OverrideData != NULL) {
+ FreePool (Ip4TxData->OverrideData);
+ }
+
+ for (Index = 0; Index < Ip4TxData->FragmentCount; Index++) {
+ FragData = Ip4TxData->FragmentTable[Index].FragmentBuffer;
+ if (FragData != NULL) {
+ FreePool (FragData);
+ }
+ }
+ }
+ }
+
+ FreePool (TxInfo->Token);
+ }
+
+ FreePool (TxInfo);
+}
+
+/**
+ Match the request, and reply with SequenceNum/TimeStamp.
+
+ @param[in] Private The pointer to PING_PRIVATE_DATA.
+ @param[in] Packet The pointer to ICMPX_ECHO_REQUEST_REPLY.
+
+ @retval EFI_SUCCESS The match is successful.
+ @retval EFI_NOT_FOUND The reply can't be matched with any request.
+
+**/
+EFI_STATUS
+EFIAPI
+Ping6MatchEchoReply (
+ IN PING_PRIVATE_DATA *Private,
+ IN ICMPX_ECHO_REQUEST_REPLY *Packet
+ )
+{
+ PING_ICMPX_TX_INFO *TxInfo;
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *NextEntry;
+
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) {
+ TxInfo = BASE_CR (Entry, PING_ICMPX_TX_INFO, Link);
+
+ if ((TxInfo->SequenceNum == Packet->SequenceNum) && (TxInfo->TimeStamp == Packet->TimeStamp)) {
+ Private->RxCount++;
+ RemoveEntryList (&TxInfo->Link);
+ PingDestroyTxInfo (TxInfo, Private->IpChoice);
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ The original intention is to send a request.
+ Currently, the application retransmits an icmp6 echo request packet
+ per second in sendnumber times that is specified by the user.
+ Because nothing can be done here, all things move to the timer rountine.
+
+ @param[in] Event A EFI_EVENT type event.
+ @param[in] Context The pointer to Context.
+
+**/
+VOID
+EFIAPI
+Ping6OnEchoRequestSent (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+}
+
+/**
+ receive reply, match and print reply infomation.
+
+ @param[in] Event A EFI_EVENT type event.
+ @param[in] Context The pointer to context.
+
+**/
+VOID
+EFIAPI
+Ping6OnEchoReplyReceived (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ PING_PRIVATE_DATA *Private;
+ ICMPX_ECHO_REQUEST_REPLY *Reply;
+ UINT32 PayLoad;
+ UINT64 Rtt;
+ CHAR8 Near;
+
+ Private = (PING_PRIVATE_DATA *) Context;
+
+ if (Private == NULL || Private->Status == EFI_ABORTED || Private->Signature != PING_PRIVATE_DATA_SIGNATURE) {
+ return;
+ }
+
+ if (Private->RxToken.Packet.RxData == NULL) {
+ return;
+ }
+
+ if (Private->IpChoice == PING_IP_CHOICE_IP6) {
+ Reply = ((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->FragmentTable[0].FragmentBuffer;
+ PayLoad = ((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->DataLength;
+ if (((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->Header->NextHeader != IP6_ICMP) {
+ goto ON_EXIT;
+ }
+ if (!IP6_IS_MULTICAST ((EFI_IPv6_ADDRESS*)&Private->DstAddress) &&
+ !EFI_IP6_EQUAL (&((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->Header->SourceAddress, (EFI_IPv6_ADDRESS*)&Private->DstAddress)) {
+ goto ON_EXIT;
+ }
+
+ if ((Reply->Type != ICMP_V6_ECHO_REPLY) || (Reply->Code != 0)) {
+ goto ON_EXIT;
+ }
+ } else {
+ Reply = ((EFI_IP4_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->FragmentTable[0].FragmentBuffer;
+ PayLoad = ((EFI_IP4_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->DataLength;
+ if (!IP4_IS_MULTICAST (EFI_IP4(*(EFI_IPv4_ADDRESS*)Private->DstAddress)) &&
+ !EFI_IP4_EQUAL (&((EFI_IP4_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->Header->SourceAddress, (EFI_IPv4_ADDRESS*)&Private->DstAddress)) {
+ goto ON_EXIT;
+ }
+
+ if ((Reply->Type != ICMP_V4_ECHO_REPLY) || (Reply->Code != 0)) {
+ goto ON_EXIT;
+ }
+ }
+
+
+ if (PayLoad != Private->BufferSize) {
+ goto ON_EXIT;
+ }
+ //
+ // Check whether the reply matches the sent request before.
+ //
+ Status = Ping6MatchEchoReply (Private, Reply);
+ if (EFI_ERROR(Status)) {
+ goto ON_EXIT;
+ }
+ //
+ // Display statistics on this icmp6 echo reply packet.
+ //
+ Rtt = CalculateTick (Reply->TimeStamp, ReadTime ());
+ if (Rtt != 0) {
+ Near = (CHAR8) '=';
+ } else {
+ Near = (CHAR8) '<';
+ }
+
+ Private->RttSum += Rtt;
+ Private->RttMin = Private->RttMin > Rtt ? Rtt : Private->RttMin;
+ Private->RttMax = Private->RttMax < Rtt ? Rtt : Private->RttMax;
+
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_PING_REPLY_INFO),
+ gShellNetwork1HiiHandle,
+ PayLoad,
+ mDstString,
+ Reply->SequenceNum,
+ Private->IpChoice == PING_IP_CHOICE_IP6?((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->Header->HopLimit:0,
+ Near,
+ Rtt
+ );
+
+ON_EXIT:
+
+ if (Private->RxCount < Private->SendNum) {
+ //
+ // Continue to receive icmp echo reply packets.
+ //
+ Private->RxToken.Status = EFI_ABORTED;
+
+ Status = Private->ProtocolPointers.Receive (Private->IpProtocol, &Private->RxToken);
+
+ if (EFI_ERROR (Status)) {
+ Private->Status = EFI_ABORTED;
+ }
+ } else {
+ //
+ // All reply have already been received from the dest host.
+ //
+ Private->Status = EFI_SUCCESS;
+ }
+ //
+ // Singal to recycle the each rxdata here, not at the end of process.
+ //
+ gBS->SignalEvent (Private->IpChoice == PING_IP_CHOICE_IP6?((EFI_IP6_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->RecycleSignal:((EFI_IP4_RECEIVE_DATA*)Private->RxToken.Packet.RxData)->RecycleSignal);
+}
+
+/**
+ Create a PING_IPX_COMPLETION_TOKEN.
+
+ @param[in] Private The pointer of PING_PRIVATE_DATA.
+ @param[in] TimeStamp The TimeStamp of request.
+ @param[in] SequenceNum The SequenceNum of request.
+
+ @return The pointer of PING_IPX_COMPLETION_TOKEN.
+
+**/
+PING_IPX_COMPLETION_TOKEN *
+EFIAPI
+PingGenerateToken (
+ IN PING_PRIVATE_DATA *Private,
+ IN UINT64 TimeStamp,
+ IN UINT16 SequenceNum
+ )
+{
+ EFI_STATUS Status;
+ PING_IPX_COMPLETION_TOKEN *Token;
+ VOID *TxData;
+ ICMPX_ECHO_REQUEST_REPLY *Request;
+ UINT16 HeadSum;
+ UINT16 TempChecksum;
+
+ Request = AllocateZeroPool (Private->BufferSize);
+ if (Request == NULL) {
+ return NULL;
+ }
+ TxData = AllocateZeroPool (Private->IpChoice==PING_IP_CHOICE_IP6?sizeof (EFI_IP6_TRANSMIT_DATA):sizeof (EFI_IP4_TRANSMIT_DATA));
+ if (TxData == NULL) {
+ FreePool (Request);
+ return NULL;
+ }
+ Token = AllocateZeroPool (sizeof (PING_IPX_COMPLETION_TOKEN));
+ if (Token == NULL) {
+ FreePool (Request);
+ FreePool (TxData);
+ return NULL;
+ }
+
+ //
+ // Assembly echo request packet.
+ //
+ Request->Type = (UINT8)(Private->IpChoice==PING_IP_CHOICE_IP6?ICMP_V6_ECHO_REQUEST:ICMP_V4_ECHO_REQUEST);
+ Request->Code = 0;
+ Request->SequenceNum = SequenceNum;
+ Request->Identifier = 0;
+ Request->Checksum = 0;
+
+ //
+ // Assembly token for transmit.
+ //
+ if (Private->IpChoice==PING_IP_CHOICE_IP6) {
+ Request->TimeStamp = TimeStamp;
+ ((EFI_IP6_TRANSMIT_DATA*)TxData)->ExtHdrsLength = 0;
+ ((EFI_IP6_TRANSMIT_DATA*)TxData)->ExtHdrs = NULL;
+ ((EFI_IP6_TRANSMIT_DATA*)TxData)->OverrideData = 0;
+ ((EFI_IP6_TRANSMIT_DATA*)TxData)->DataLength = Private->BufferSize;
+ ((EFI_IP6_TRANSMIT_DATA*)TxData)->FragmentCount = 1;
+ ((EFI_IP6_TRANSMIT_DATA*)TxData)->FragmentTable[0].FragmentBuffer = (VOID *) Request;
+ ((EFI_IP6_TRANSMIT_DATA*)TxData)->FragmentTable[0].FragmentLength = Private->BufferSize;
+ } else {
+ ((EFI_IP4_TRANSMIT_DATA*)TxData)->OptionsLength = 0;
+ ((EFI_IP4_TRANSMIT_DATA*)TxData)->OptionsBuffer = NULL;
+ ((EFI_IP4_TRANSMIT_DATA*)TxData)->OverrideData = 0;
+ ((EFI_IP4_TRANSMIT_DATA*)TxData)->TotalDataLength = Private->BufferSize;
+ ((EFI_IP4_TRANSMIT_DATA*)TxData)->FragmentCount = 1;
+ ((EFI_IP4_TRANSMIT_DATA*)TxData)->FragmentTable[0].FragmentBuffer = (VOID *) Request;
+ ((EFI_IP4_TRANSMIT_DATA*)TxData)->FragmentTable[0].FragmentLength = Private->BufferSize;
+ ((EFI_IP4_TRANSMIT_DATA*)TxData)->DestinationAddress.Addr[0] = Private->DstAddress[0];
+ ((EFI_IP4_TRANSMIT_DATA*)TxData)->DestinationAddress.Addr[1] = Private->DstAddress[1];
+ ((EFI_IP4_TRANSMIT_DATA*)TxData)->DestinationAddress.Addr[2] = Private->DstAddress[2];
+ ((EFI_IP4_TRANSMIT_DATA*)TxData)->DestinationAddress.Addr[3] = Private->DstAddress[3];
+
+ HeadSum = NetChecksum ((UINT8 *) Request, Private->BufferSize);
+ Request->TimeStamp = TimeStamp;
+ TempChecksum = NetChecksum ((UINT8 *) &Request->TimeStamp, sizeof (UINT64));
+ Request->Checksum = (UINT16)(~NetAddChecksum (HeadSum, TempChecksum));
+ }
+
+
+ Token->Status = EFI_ABORTED;
+ Token->Packet.TxData = TxData;
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ Ping6OnEchoRequestSent,
+ Private,
+ &Token->Event
+ );
+
+ if (EFI_ERROR (Status)) {
+ FreePool (Request);
+ FreePool (TxData);
+ FreePool (Token);
+ return NULL;
+ }
+
+ return Token;
+}
+
+/**
+ Transmit the PING_IPX_COMPLETION_TOKEN.
+
+ @param[in] Private The pointer of PING_PRIVATE_DATA.
+
+ @retval EFI_SUCCESS Transmitted successfully.
+ @retval EFI_OUT_OF_RESOURCES No memory is available on the platform.
+ @retval others Transmitted unsuccessfully.
+
+**/
+EFI_STATUS
+EFIAPI
+PingSendEchoRequest (
+ IN PING_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status;
+ PING_ICMPX_TX_INFO *TxInfo;
+
+ TxInfo = AllocateZeroPool (sizeof (PING_ICMPX_TX_INFO));
+
+ if (TxInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ TxInfo->TimeStamp = ReadTime ();
+ TxInfo->SequenceNum = (UINT16) (Private->TxCount + 1);
+ TxInfo->Token = PingGenerateToken (
+ Private,
+ TxInfo->TimeStamp,
+ TxInfo->SequenceNum
+ );
+
+ if (TxInfo->Token == NULL) {
+ PingDestroyTxInfo (TxInfo, Private->IpChoice);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ ASSERT(Private->ProtocolPointers.Transmit != NULL);
+ Status = Private->ProtocolPointers.Transmit (Private->IpProtocol, TxInfo->Token);
+
+ if (EFI_ERROR (Status)) {
+ PingDestroyTxInfo (TxInfo, Private->IpChoice);
+ return Status;
+ }
+
+ InsertTailList (&Private->TxList, &TxInfo->Link);
+ Private->TxCount++;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Place a completion token into the receive packet queue to receive the echo reply.
+
+ @param[in] Private The pointer of PING_PRIVATE_DATA.
+
+ @retval EFI_SUCCESS Put the token into the receive packet queue successfully.
+ @retval others Put the token into the receive packet queue unsuccessfully.
+
+**/
+EFI_STATUS
+EFIAPI
+Ping6ReceiveEchoReply (
+ IN PING_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status;
+
+ ZeroMem (&Private->RxToken, sizeof (PING_IPX_COMPLETION_TOKEN));
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ Ping6OnEchoReplyReceived,
+ Private,
+ &Private->RxToken.Event
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Private->RxToken.Status = EFI_NOT_READY;
+
+ return (Private->ProtocolPointers.Receive (Private->IpProtocol, &Private->RxToken));
+}
+
+/**
+ Remove the timeout request from the list.
+
+ @param[in] Event A EFI_EVENT type event.
+ @param[in] Context The pointer to Context.
+
+**/
+VOID
+EFIAPI
+Ping6OnTimerRoutine (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ PING_PRIVATE_DATA *Private;
+ PING_ICMPX_TX_INFO *TxInfo;
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *NextEntry;
+ UINT64 Time;
+
+ Private = (PING_PRIVATE_DATA *) Context;
+ if (Private->Signature != PING_PRIVATE_DATA_SIGNATURE) {
+ Private->Status = EFI_NOT_FOUND;
+ return;
+ }
+
+ //
+ // Retransmit icmp6 echo request packets per second in sendnumber times.
+ //
+ if (Private->TxCount < Private->SendNum) {
+
+ Status = PingSendEchoRequest (Private);
+ if (Private->TxCount != 0){
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_SEND_REQUEST), gShellNetwork1HiiHandle, Private->TxCount + 1);
+ }
+ }
+ }
+ //
+ // Check whether any icmp6 echo request in the list timeout.
+ //
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) {
+ TxInfo = BASE_CR (Entry, PING_ICMPX_TX_INFO, Link);
+ Time = CalculateTick (TxInfo->TimeStamp, ReadTime ());
+
+ //
+ // Remove the timeout echo request from txlist.
+ //
+ if (Time > DEFAULT_TIMEOUT) {
+
+ if (EFI_ERROR (TxInfo->Token->Status)) {
+ Private->ProtocolPointers.Cancel (Private->IpProtocol, TxInfo->Token);
+ }
+ //
+ // Remove the timeout icmp6 echo request from list.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_TIMEOUT), gShellNetwork1HiiHandle, TxInfo->SequenceNum);
+
+ RemoveEntryList (&TxInfo->Link);
+ PingDestroyTxInfo (TxInfo, Private->IpChoice);
+
+ Private->RxCount++;
+ Private->FailedCount++;
+
+ if (IsListEmpty (&Private->TxList) && (Private->TxCount == Private->SendNum)) {
+ //
+ // All the left icmp6 echo request in the list timeout.
+ //
+ Private->Status = EFI_TIMEOUT;
+ }
+ }
+ }
+}
+
+/**
+ Determine if a IP4 address is Link Local.
+
+ 169.254.1.0 through 169.254.254.255 is link local.
+
+ @param[in] Address The address to test.
+
+ @retval TRUE It is.
+ @retval FALSE It is not.
+**/
+BOOLEAN
+EFIAPI
+PingNetIp4IsLinkLocalAddr (
+ IN CONST EFI_IPv4_ADDRESS *Address
+ )
+{
+ return ((BOOLEAN)(Address->Addr[0] == 169 && Address->Addr[1] == 254 && Address->Addr[2] >= 1 && Address->Addr[2] <= 254));
+}
+
+/**
+ Determine if a IP4 address is unspecified.
+
+ @param[in] Address The address to test.
+
+ @retval TRUE It is.
+ @retval FALSE It is not.
+**/
+BOOLEAN
+EFIAPI
+PingNetIp4IsUnspecifiedAddr (
+ IN CONST EFI_IPv4_ADDRESS *Address
+ )
+{
+ return ((BOOLEAN)((ReadUnaligned32 ((UINT32*)&Address->Addr[0])) == 0x00000000));
+}
+
+/**
+ Create a valid IP instance.
+
+ @param[in] Private The pointer of PING_PRIVATE_DATA.
+
+ @retval EFI_SUCCESS Create a valid IPx instance successfully.
+ @retval EFI_ABORTED Locate handle with ipx service binding protocol unsuccessfully.
+ @retval EFI_INVALID_PARAMETER The source address is unspecified when the destination address is a link-local address.
+ @retval EFI_OUT_OF_RESOURCES No memory is available on the platform.
+ @retval EFI_NOT_FOUND The source address is not found.
+**/
+EFI_STATUS
+EFIAPI
+PingCreateIpInstance (
+ IN PING_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleIndex;
+ UINTN HandleNum;
+ EFI_HANDLE *HandleBuffer;
+ BOOLEAN UnspecifiedSrc;
+ BOOLEAN MediaPresent;
+ EFI_SERVICE_BINDING_PROTOCOL *EfiSb;
+ VOID *IpXCfg;
+ EFI_IP6_CONFIG_DATA Ip6Config;
+ EFI_IP4_CONFIG_DATA Ip4Config;
+ VOID *IpXInterfaceInfo;
+ UINTN IfInfoSize;
+ EFI_IPv6_ADDRESS *Addr;
+ UINTN AddrIndex;
+
+ HandleBuffer = NULL;
+ UnspecifiedSrc = FALSE;
+ MediaPresent = TRUE;
+ EfiSb = NULL;
+ IpXInterfaceInfo = NULL;
+ IfInfoSize = 0;
+
+ //
+ // Locate all the handles with ip6 service binding protocol.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ServiceBindingProtocolGuid:&gEfiIp4ServiceBindingProtocolGuid,
+ NULL,
+ &HandleNum,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status) || (HandleNum == 0) || (HandleBuffer == NULL)) {
+ return EFI_ABORTED;
+ }
+
+ if (Private->IpChoice == PING_IP_CHOICE_IP6 ? NetIp6IsUnspecifiedAddr ((EFI_IPv6_ADDRESS*)&Private->SrcAddress) : \
+ PingNetIp4IsUnspecifiedAddr ((EFI_IPv4_ADDRESS*)&Private->SrcAddress)) {
+ //
+ // SrcAddress is unspecified. So, both connected and configured interface will be automatic selected.
+ //
+ UnspecifiedSrc = TRUE;
+ }
+
+ //
+ // Source address is required when pinging a link-local address.
+ //
+ if (Private->IpChoice == PING_IP_CHOICE_IP6) {
+ if (NetIp6IsLinkLocalAddr ((EFI_IPv6_ADDRESS*)&Private->DstAddress) && UnspecifiedSrc) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_INVALID_SOURCE), gShellNetwork1HiiHandle);
+ Status = EFI_INVALID_PARAMETER;
+ goto ON_ERROR;
+ }
+ } else {
+ ASSERT(Private->IpChoice == PING_IP_CHOICE_IP4);
+ if (PingNetIp4IsLinkLocalAddr ((EFI_IPv4_ADDRESS*)&Private->DstAddress) && UnspecifiedSrc) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_INVALID_SOURCE), gShellNetwork1HiiHandle);
+ Status = EFI_INVALID_PARAMETER;
+ goto ON_ERROR;
+ }
+ }
+
+ //
+ // For each ip6 protocol, check interface addresses list.
+ //
+ for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) {
+ EfiSb = NULL;
+ IpXInterfaceInfo = NULL;
+ IfInfoSize = 0;
+
+ if (UnspecifiedSrc) {
+ //
+ // Check media.
+ //
+ NetLibDetectMedia (HandleBuffer[HandleIndex], &MediaPresent);
+ if (!MediaPresent) {
+ //
+ // Skip this one.
+ //
+ continue;
+ }
+ }
+
+ Status = gBS->HandleProtocol (
+ HandleBuffer[HandleIndex],
+ Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ServiceBindingProtocolGuid:&gEfiIp4ServiceBindingProtocolGuid,
+ (VOID **) &EfiSb
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ //
+ // Ip6config protocol and ip6 service binding protocol are installed
+ // on the same handle.
+ //
+ Status = gBS->HandleProtocol (
+ HandleBuffer[HandleIndex],
+ Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ConfigProtocolGuid:&gEfiIp4Config2ProtocolGuid,
+ (VOID **) &IpXCfg
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+ //
+ // Get the interface information size.
+ //
+ if (Private->IpChoice == PING_IP_CHOICE_IP6) {
+ Status = ((EFI_IP6_CONFIG_PROTOCOL*)IpXCfg)->GetData (
+ IpXCfg,
+ Ip6ConfigDataTypeInterfaceInfo,
+ &IfInfoSize,
+ NULL
+ );
+ } else {
+ Status = ((EFI_IP4_CONFIG2_PROTOCOL*)IpXCfg)->GetData (
+ IpXCfg,
+ Ip4Config2DataTypeInterfaceInfo,
+ &IfInfoSize,
+ NULL
+ );
+ }
+
+ //
+ // Skip the ones not in current use.
+ //
+ if (Status == EFI_NOT_STARTED) {
+ continue;
+ }
+
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_GETDATA), gShellNetwork1HiiHandle, Status);
+ goto ON_ERROR;
+ }
+
+ IpXInterfaceInfo = AllocateZeroPool (IfInfoSize);
+
+ if (IpXInterfaceInfo == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_ERROR;
+ }
+ //
+ // Get the interface info.
+ //
+ if (Private->IpChoice == PING_IP_CHOICE_IP6) {
+ Status = ((EFI_IP6_CONFIG_PROTOCOL*)IpXCfg)->GetData (
+ IpXCfg,
+ Ip6ConfigDataTypeInterfaceInfo,
+ &IfInfoSize,
+ IpXInterfaceInfo
+ );
+ } else {
+ Status = ((EFI_IP4_CONFIG2_PROTOCOL*)IpXCfg)->GetData (
+ IpXCfg,
+ Ip4Config2DataTypeInterfaceInfo,
+ &IfInfoSize,
+ IpXInterfaceInfo
+ );
+ }
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_GETDATA), gShellNetwork1HiiHandle, Status);
+ goto ON_ERROR;
+ }
+ //
+ // Check whether the source address is one of the interface addresses.
+ //
+ if (Private->IpChoice == PING_IP_CHOICE_IP6) {
+ for (AddrIndex = 0; AddrIndex < ((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfoCount; AddrIndex++) {
+ Addr = &(((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfo[AddrIndex].Address);
+
+ if (UnspecifiedSrc) {
+ if (!NetIp6IsUnspecifiedAddr (Addr) && !NetIp6IsLinkLocalAddr (Addr)) {
+ //
+ // Select the interface automatically.
+ //
+ CopyMem(&Private->SrcAddress, Addr, sizeof(Private->SrcAddress));
+ break;
+ }
+ } else if (EFI_IP6_EQUAL (&Private->SrcAddress, Addr)) {
+ //
+ // Match a certain interface address.
+ //
+ break;
+ }
+ }
+
+ if (AddrIndex < ((EFI_IP6_CONFIG_INTERFACE_INFO*)IpXInterfaceInfo)->AddressInfoCount) {
+ //
+ // Found a nic handle with right interface address.
+ //
+ break;
+ }
+ } else {
+ if (UnspecifiedSrc) {
+ if (!PingNetIp4IsUnspecifiedAddr (&((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress) &&
+ !PingNetIp4IsLinkLocalAddr (&((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress)) {
+ //
+ // Select the interface automatically.
+ //
+ break;
+ }
+ } else if (EFI_IP4_EQUAL (&Private->SrcAddress, &((EFI_IP4_CONFIG2_INTERFACE_INFO*)IpXInterfaceInfo)->StationAddress)) {
+ //
+ // Match a certain interface address.
+ //
+ break;
+ }
+ }
+
+ FreePool (IpXInterfaceInfo);
+ IpXInterfaceInfo = NULL;
+ }
+ //
+ // No exact interface address matched.
+ //
+
+ if (HandleIndex == HandleNum) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_CONFIGD_NIC_NF), gShellNetwork1HiiHandle, L"ping");
+ Status = EFI_NOT_FOUND;
+ goto ON_ERROR;
+ }
+
+ Private->NicHandle = HandleBuffer[HandleIndex];
+
+ ASSERT (EfiSb != NULL);
+ Status = EfiSb->CreateChild (EfiSb, &Private->IpChildHandle);
+
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+ if (Private->IpChoice == PING_IP_CHOICE_IP6) {
+ Status = gBS->OpenProtocol (
+ Private->IpChildHandle,
+ &gEfiIp6ProtocolGuid,
+ &Private->IpProtocol,
+ gImageHandle,
+ Private->IpChildHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+
+ ZeroMem (&Ip6Config, sizeof (EFI_IP6_CONFIG_DATA));
+
+ //
+ // Configure the ip6 instance for icmp6 packet exchange.
+ //
+ Ip6Config.DefaultProtocol = 58;
+ Ip6Config.AcceptAnyProtocol = FALSE;
+ Ip6Config.AcceptIcmpErrors = TRUE;
+ Ip6Config.AcceptPromiscuous = FALSE;
+ Ip6Config.TrafficClass = 0;
+ Ip6Config.HopLimit = 128;
+ Ip6Config.FlowLabel = 0;
+ Ip6Config.ReceiveTimeout = 0;
+ Ip6Config.TransmitTimeout = 0;
+
+ IP6_COPY_ADDRESS (&Ip6Config.StationAddress, &Private->SrcAddress);
+ IP6_COPY_ADDRESS (&Ip6Config.DestinationAddress, &Private->DstAddress);
+
+ Status = ((EFI_IP6_PROTOCOL*)(Private->IpProtocol))->Configure (Private->IpProtocol, &Ip6Config);
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_CONFIG), gShellNetwork1HiiHandle, Status);
+ goto ON_ERROR;
+ }
+
+ Private->ProtocolPointers.Transmit = (PING_IPX_TRANSMIT )((EFI_IP6_PROTOCOL*)Private->IpProtocol)->Transmit;
+ Private->ProtocolPointers.Receive = (PING_IPX_RECEIVE )((EFI_IP6_PROTOCOL*)Private->IpProtocol)->Receive;
+ Private->ProtocolPointers.Cancel = (PING_IPX_CANCEL )((EFI_IP6_PROTOCOL*)Private->IpProtocol)->Cancel;
+ Private->ProtocolPointers.Poll = (PING_IPX_POLL )((EFI_IP6_PROTOCOL*)Private->IpProtocol)->Poll;
+ } else {
+ Status = gBS->OpenProtocol (
+ Private->IpChildHandle,
+ &gEfiIp4ProtocolGuid,
+ &Private->IpProtocol,
+ gImageHandle,
+ Private->IpChildHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+
+ ZeroMem (&Ip4Config, sizeof (EFI_IP4_CONFIG_DATA));
+
+ //
+ // Configure the ip4 instance for icmp4 packet exchange.
+ //
+ Ip4Config.DefaultProtocol = 1;
+ Ip4Config.AcceptAnyProtocol = FALSE;
+ Ip4Config.AcceptBroadcast = FALSE;
+ Ip4Config.AcceptIcmpErrors = TRUE;
+ Ip4Config.AcceptPromiscuous = FALSE;
+ Ip4Config.DoNotFragment = FALSE;
+ Ip4Config.RawData = FALSE;
+ Ip4Config.ReceiveTimeout = 0;
+ Ip4Config.TransmitTimeout = 0;
+ Ip4Config.UseDefaultAddress = TRUE;
+ Ip4Config.TimeToLive = 128;
+ Ip4Config.TypeOfService = 0;
+
+ Status = ((EFI_IP4_PROTOCOL*)(Private->IpProtocol))->Configure (Private->IpProtocol, &Ip4Config);
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_CONFIG), gShellNetwork1HiiHandle, Status);
+ goto ON_ERROR;
+ }
+
+ Private->ProtocolPointers.Transmit = (PING_IPX_TRANSMIT )((EFI_IP4_PROTOCOL*)Private->IpProtocol)->Transmit;
+ Private->ProtocolPointers.Receive = (PING_IPX_RECEIVE )((EFI_IP4_PROTOCOL*)Private->IpProtocol)->Receive;
+ Private->ProtocolPointers.Cancel = (PING_IPX_CANCEL )((EFI_IP4_PROTOCOL*)Private->IpProtocol)->Cancel;
+ Private->ProtocolPointers.Poll = (PING_IPX_POLL )((EFI_IP4_PROTOCOL*)Private->IpProtocol)->Poll;
+ }
+
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+
+ return EFI_SUCCESS;
+
+ON_ERROR:
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+
+ if (IpXInterfaceInfo != NULL) {
+ FreePool (IpXInterfaceInfo);
+ }
+
+ if ((EfiSb != NULL) && (Private->IpChildHandle != NULL)) {
+ EfiSb->DestroyChild (EfiSb, Private->IpChildHandle);
+ }
+
+ return Status;
+}
+
+/**
+ Destroy the IP instance.
+
+ @param[in] Private The pointer of PING_PRIVATE_DATA.
+
+**/
+VOID
+EFIAPI
+Ping6DestroyIp6Instance (
+ IN PING_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status;
+ EFI_SERVICE_BINDING_PROTOCOL *IpSb;
+
+ gBS->CloseProtocol (
+ Private->IpChildHandle,
+ Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ProtocolGuid:&gEfiIp4ProtocolGuid,
+ gImageHandle,
+ Private->IpChildHandle
+ );
+
+ Status = gBS->HandleProtocol (
+ Private->NicHandle,
+ Private->IpChoice == PING_IP_CHOICE_IP6?&gEfiIp6ServiceBindingProtocolGuid:&gEfiIp4ServiceBindingProtocolGuid,
+ (VOID **) &IpSb
+ );
+
+ if (!EFI_ERROR(Status)) {
+ IpSb->DestroyChild (IpSb, Private->IpChildHandle);
+ }
+}
+
+/**
+ The Ping Process.
+
+ @param[in] SendNumber The send request count.
+ @param[in] BufferSize The send buffer size.
+ @param[in] SrcAddress The source address.
+ @param[in] DstAddress The destination address.
+ @param[in] IpChoice The choice between IPv4 and IPv6.
+
+ @retval SHELL_SUCCESS The ping processed successfullly.
+ @retval others The ping processed unsuccessfully.
+**/
+SHELL_STATUS
+EFIAPI
+ShellPing (
+ IN UINT32 SendNumber,
+ IN UINT32 BufferSize,
+ IN EFI_IPv6_ADDRESS *SrcAddress,
+ IN EFI_IPv6_ADDRESS *DstAddress,
+ IN UINT32 IpChoice
+ )
+{
+ EFI_STATUS Status;
+ PING_PRIVATE_DATA *Private;
+ PING_ICMPX_TX_INFO *TxInfo;
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *NextEntry;
+ SHELL_STATUS ShellStatus;
+
+ ShellStatus = SHELL_SUCCESS;
+ Private = AllocateZeroPool (sizeof (PING_PRIVATE_DATA));
+
+ if (Private == NULL) {
+ return (SHELL_OUT_OF_RESOURCES);
+ }
+
+ Private->IpChoice = IpChoice;
+ Private->Signature = PING_PRIVATE_DATA_SIGNATURE;
+ Private->SendNum = SendNumber;
+ Private->BufferSize = BufferSize;
+ Private->RttMin = ~((UINT64 )(0x0));
+ Private->Status = EFI_NOT_READY;
+
+ CopyMem(&Private->SrcAddress, SrcAddress, sizeof(Private->SrcAddress));
+ CopyMem(&Private->DstAddress, DstAddress, sizeof(Private->DstAddress));
+
+ InitializeListHead (&Private->TxList);
+
+ //
+ // Open and configure a ip instance for us.
+ //
+ Status = PingCreateIpInstance (Private);
+
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+ //
+ // Print the command line itself.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_START), gShellNetwork1HiiHandle, mDstString, Private->BufferSize);
+ //
+ // Create a ipv6 token to receive the first icmp6 echo reply packet.
+ //
+ Status = Ping6ReceiveEchoReply (Private);
+
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+ //
+ // Create and start timer to send icmp6 echo request packet per second.
+ //
+ Status = gBS->CreateEvent (
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ Ping6OnTimerRoutine,
+ Private,
+ &Private->Timer
+ );
+
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+ //
+ // Create a ipv6 token to send the first icmp6 echo request packet.
+ //
+ Status = PingSendEchoRequest (Private);
+ //
+ // EFI_NOT_READY for IPsec is enable and IKE is not established.
+ //
+ if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ if(Status == EFI_NOT_FOUND) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_NOSOURCE_INDO), gShellNetwork1HiiHandle, mDstString);
+ } else if (Status == RETURN_NO_MAPPING) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_NOROUTE_FOUND), gShellNetwork1HiiHandle, mDstString, mSrcString);
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING_NETWORK_ERROR), gShellNetwork1HiiHandle, L"ping", Status);
+ }
+
+ goto ON_EXIT;
+ }
+
+ Status = gBS->SetTimer (
+ Private->Timer,
+ TimerPeriodic,
+ ONE_SECOND
+ );
+
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+ //
+ // Control the ping6 process by two factors:
+ // 1. Hot key
+ // 2. Private->Status
+ // 2.1. success means all icmp6 echo request packets get reply packets.
+ // 2.2. timeout means the last icmp6 echo reply request timeout to get reply.
+ // 2.3. noready means ping6 process is on-the-go.
+ //
+ while (Private->Status == EFI_NOT_READY) {
+ Status = Private->ProtocolPointers.Poll (Private->IpProtocol);
+ if (ShellGetExecutionBreakFlag()) {
+ Private->Status = EFI_ABORTED;
+ goto ON_STAT;
+ }
+ }
+
+ON_STAT:
+ //
+ // Display the statistics in all.
+ //
+ gBS->SetTimer (Private->Timer, TimerCancel, 0);
+
+ if (Private->TxCount != 0) {
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_PING_STAT),
+ gShellNetwork1HiiHandle,
+ Private->TxCount,
+ (Private->RxCount - Private->FailedCount),
+ (100 - ((100 * (Private->RxCount - Private->FailedCount)) / Private->TxCount)),
+ Private->RttSum
+ );
+ }
+
+ if (Private->RxCount > Private->FailedCount) {
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_PING_RTT),
+ gShellNetwork1HiiHandle,
+ Private->RttMin,
+ Private->RttMax,
+ DivU64x64Remainder (Private->RttSum, (Private->RxCount - Private->FailedCount), NULL)
+ );
+ }
+
+ON_EXIT:
+
+ if (Private != NULL) {
+
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) {
+ TxInfo = BASE_CR (Entry, PING_ICMPX_TX_INFO, Link);
+
+ if (Private->IpProtocol != NULL && Private->ProtocolPointers.Cancel != NULL) {
+ Status = Private->ProtocolPointers.Cancel (Private->IpProtocol, TxInfo->Token);
+ }
+
+ RemoveEntryList (&TxInfo->Link);
+ PingDestroyTxInfo (TxInfo, Private->IpChoice);
+ }
+
+ if (Private->Timer != NULL) {
+ gBS->CloseEvent (Private->Timer);
+ }
+
+ if (Private->IpProtocol != NULL && Private->ProtocolPointers.Cancel != NULL) {
+ Status = Private->ProtocolPointers.Cancel (Private->IpProtocol, &Private->RxToken);
+ }
+
+ if (Private->RxToken.Event != NULL) {
+ gBS->CloseEvent (Private->RxToken.Event);
+ }
+
+ if (Private->IpChildHandle != NULL) {
+ Ping6DestroyIp6Instance (Private);
+ }
+
+ FreePool (Private);
+ }
+
+ return ShellStatus;
+}
+
+/**
+ Function for 'ping' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+
+ @retval SHELL_SUCCESS The ping processed successfullly.
+ @retval others The ping processed unsuccessfully.
+
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunPing (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ SHELL_STATUS ShellStatus;
+ EFI_IPv6_ADDRESS DstAddress;
+ EFI_IPv6_ADDRESS SrcAddress;
+ UINT64 BufferSize;
+ UINTN SendNumber;
+ LIST_ENTRY *ParamPackage;
+ CONST CHAR16 *ValueStr;
+ UINTN NonOptionCount;
+ UINT32 IpChoice;
+ CHAR16 *ProblemParam;
+
+ //
+ // we use IPv6 buffers to hold items...
+ // make sure this is enough space!
+ //
+ ASSERT(sizeof(EFI_IPv4_ADDRESS ) <= sizeof(EFI_IPv6_ADDRESS ));
+ ASSERT(sizeof(EFI_IP4_COMPLETION_TOKEN) <= sizeof(EFI_IP6_COMPLETION_TOKEN ));
+
+ IpChoice = PING_IP_CHOICE_IP4;
+
+ ShellStatus = SHELL_SUCCESS;
+ ProblemParam = NULL;
+
+ Status = ShellCommandLineParseEx (PingParamList, &ParamPackage, &ProblemParam, TRUE, FALSE);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ if (ShellCommandLineGetFlag (ParamPackage, L"-_ip6")) {
+ IpChoice = PING_IP_CHOICE_IP6;
+ }
+
+ //
+ // Parse the paramter of count number.
+ //
+ ValueStr = ShellCommandLineGetValue (ParamPackage, L"-n");
+ if (ValueStr != NULL) {
+ SendNumber = ShellStrToUintn (ValueStr);
+
+ //
+ // ShellStrToUintn will return 0 when input is 0 or an invalid input string.
+ //
+ if ((SendNumber == 0) || (SendNumber > MAX_SEND_NUMBER)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ValueStr);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+ } else {
+ SendNumber = DEFAULT_SEND_COUNT;
+ }
+ //
+ // Parse the paramter of buffer size.
+ //
+ ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l");
+ if (ValueStr != NULL) {
+ BufferSize = ShellStrToUintn (ValueStr);
+
+ //
+ // ShellStrToUintn will return 0 when input is 0 or an invalid input string.
+ //
+ if ((BufferSize < 16) || (BufferSize > MAX_BUFFER_SIZE)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ValueStr);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+ } else {
+ BufferSize = DEFAULT_BUFFER_SIZE;
+ }
+
+ ZeroMem (&SrcAddress, sizeof (EFI_IPv6_ADDRESS));
+ ZeroMem (&DstAddress, sizeof (EFI_IPv6_ADDRESS));
+
+ //
+ // Parse the paramter of source ip address.
+ //
+ ValueStr = ShellCommandLineGetValue (ParamPackage, L"-s");
+ if (ValueStr == NULL) {
+ ValueStr = ShellCommandLineGetValue (ParamPackage, L"-_s");
+ }
+
+ if (ValueStr != NULL) {
+ mSrcString = ValueStr;
+ if (IpChoice == PING_IP_CHOICE_IP6) {
+ Status = NetLibStrToIp6 (ValueStr, &SrcAddress);
+ } else {
+ Status = NetLibStrToIp4 (ValueStr, (EFI_IPv4_ADDRESS*)&SrcAddress);
+ }
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ValueStr);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+ }
+ //
+ // Parse the paramter of destination ip address.
+ //
+ NonOptionCount = ShellCommandLineGetCount(ParamPackage);
+ if (NonOptionCount < 2) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW), gShellNetwork1HiiHandle, L"ping");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+ if (NonOptionCount > 2) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY), gShellNetwork1HiiHandle, L"ping");
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+ ValueStr = ShellCommandLineGetRawValue (ParamPackage, 1);
+ if (ValueStr != NULL) {
+ mDstString = ValueStr;
+ if (IpChoice == PING_IP_CHOICE_IP6) {
+ Status = NetLibStrToIp6 (ValueStr, &DstAddress);
+ } else {
+ Status = NetLibStrToIp4 (ValueStr, (EFI_IPv4_ADDRESS*)&DstAddress);
+ }
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV), gShellNetwork1HiiHandle, L"ping", ValueStr);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+ }
+ //
+ // Get frequency to calculate the time from ticks.
+ //
+ Status = GetFrequency ();
+
+ if (EFI_ERROR(Status)) {
+ goto ON_EXIT;
+ }
+ //
+ // Enter into ping process.
+ //
+ ShellStatus = ShellPing (
+ (UINT32)SendNumber,
+ (UINT32)BufferSize,
+ &SrcAddress,
+ &DstAddress,
+ IpChoice
+ );
+
+ON_EXIT:
+ ShellCommandLineFreeVarList (ParamPackage);
+ return ShellStatus;
+}
diff --git a/Core/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.c b/Core/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.c
new file mode 100644
index 0000000000..49849a6191
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.c
@@ -0,0 +1,90 @@
+/** @file
+ Main file for NULL named library for network1 shell command functions.
+
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "UefiShellNetwork1CommandsLib.h"
+
+CONST CHAR16 gShellNetwork1FileName[] = L"ShellCommands";
+EFI_HANDLE gShellNetwork1HiiHandle = NULL;
+
+/**
+ return the file name of the help text file if not using HII.
+
+ @return The string pointer to the file name.
+**/
+CONST CHAR16*
+EFIAPI
+ShellCommandGetManFileNameNetwork1 (
+ VOID
+ )
+{
+ return (gShellNetwork1FileName);
+}
+
+/**
+ Constructor for the Shell Network1 Commands library.
+
+ Install the handlers for Network1 UEFI Shell 2.0 profile commands.
+
+ @param ImageHandle The image handle of the process.
+ @param SystemTable The EFI System Table pointer.
+
+ @retval EFI_SUCCESS The shell command handlers were installed sucessfully.
+ @retval EFI_UNSUPPORTED The shell level required was not found.
+**/
+EFI_STATUS
+EFIAPI
+ShellNetwork1CommandsLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ gShellNetwork1HiiHandle = NULL;
+
+ //
+ // check our bit of the profiles mask
+ //
+ if ((PcdGet8(PcdShellProfileMask) & BIT3) == 0) {
+ return (EFI_SUCCESS);
+ }
+
+ gShellNetwork1HiiHandle = HiiAddPackages (&gShellNetwork1HiiGuid, gImageHandle, UefiShellNetwork1CommandsLibStrings, NULL);
+ if (gShellNetwork1HiiHandle == NULL) {
+ return (EFI_DEVICE_ERROR);
+ }
+ //
+ // install our shell command handlers
+ //
+ ShellCommandRegisterCommandName(L"ping", ShellCommandRunPing , ShellCommandGetManFileNameNetwork1, 0, L"network1", TRUE , gShellNetwork1HiiHandle, STRING_TOKEN(STR_GET_HELP_PING));
+ ShellCommandRegisterCommandName(L"ifconfig",ShellCommandRunIfconfig , ShellCommandGetManFileNameNetwork1, 0, L"network1", TRUE , gShellNetwork1HiiHandle, STRING_TOKEN(STR_GET_HELP_IFCONFIG));
+
+ return (EFI_SUCCESS);
+}
+
+/**
+ Destructor for the library. free any resources.
+
+ @param ImageHandle The image handle of the process.
+ @param SystemTable The EFI System Table pointer.
+**/
+EFI_STATUS
+EFIAPI
+ShellNetwork1CommandsLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ if (gShellNetwork1HiiHandle != NULL) {
+ HiiRemovePackages(gShellNetwork1HiiHandle);
+ }
+ return (EFI_SUCCESS);
+}
diff --git a/Core/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.h b/Core/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.h
new file mode 100644
index 0000000000..98b40df825
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.h
@@ -0,0 +1,77 @@
+/** @file
+ header file for NULL named library for network1 shell command functions.
+
+ Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved. <BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _UEFI_SHELL_NETWORK1_COMMANDS_LIB_H_
+#define _UEFI_SHELL_NETWORK1_COMMANDS_LIB_H_
+
+#include <Uefi.h>
+#include <ShellBase.h>
+
+#include <Guid/ShellLibHiiGuid.h>
+
+#include <Protocol/Cpu.h>
+#include <Protocol/ServiceBinding.h>
+#include <Protocol/Ip6.h>
+#include <Protocol/Ip6Config.h>
+#include <Protocol/Ip4.h>
+#include <Protocol/Ip4Config2.h>
+#include <Protocol/Arp.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/PcdLib.h>
+#include <Library/ShellCommandLib.h>
+#include <Library/ShellLib.h>
+#include <Library/SortLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HiiLib.h>
+#include <Library/NetLib.h>
+#include <Library/DevicePathLib.h>
+#include <Library/PrintLib.h>
+
+extern EFI_HANDLE gShellNetwork1HiiHandle;
+
+/**
+ Function for 'ping' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunPing (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'ifconfig' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunIfconfig (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+#endif
+
diff --git a/Core/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf b/Core/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf
new file mode 100644
index 0000000000..92d47d114f
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf
@@ -0,0 +1,67 @@
+## @file
+# Provides shell network1 functions
+#
+# Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved. <BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = UefiShellNetwork1CommandsLib
+ FILE_GUID = 9A929F7E-3861-45ce-87AB-7371219AE255
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER
+ CONSTRUCTOR = ShellNetwork1CommandsLibConstructor
+ DESTRUCTOR = ShellNetwork1CommandsLibDestructor
+
+[Sources.common]
+ UefiShellNetwork1CommandsLib.uni
+ UefiShellNetwork1CommandsLib.c
+ UefiShellNetwork1CommandsLib.h
+ Ping.c
+ Ifconfig.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ ShellCommandLib
+ ShellLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ PcdLib
+ HiiLib
+ FileHandleLib
+ NetLib
+
+[Pcd]
+ gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask ## CONSUMES
+
+[Protocols]
+ gEfiCpuArchProtocolGuid ## CONSUMES
+ gEfiIp6ProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiIp6ServiceBindingProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiIp6ConfigProtocolGuid ## SOMETIMES_CONSUMES
+
+ gEfiIp4ProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiIp4ServiceBindingProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiIp4Config2ProtocolGuid ## SOMETIMES_CONSUMES
+
+[Guids]
+ gShellNetwork1HiiGuid ## SOMETIMES_CONSUMES ## HII \ No newline at end of file
diff --git a/Core/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni b/Core/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni
new file mode 100644
index 0000000000..c8ab64fc55
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.uni
@@ -0,0 +1,179 @@
+// /**
+//
+// (C) Copyright 2013-2015 Hewlett-Packard Development Company, L.P.<BR>
+// Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved. <BR>
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// Module Name:
+//
+// UefiShellNetwork1CommandsLib.uni
+//
+// Abstract:
+//
+// String definitions for UEFI Shell 2.0 network 1 commands
+//
+//
+// **/
+
+/=#
+
+#langdef en-US "english"
+
+#string STR_GEN_TOO_MANY #language en-US "%H%s%N: Too many arguments.\r\n"
+#string STR_GEN_TOO_FEW #language en-US "%H%s%N: Too few arguments.\r\n"
+#string STR_GEN_PARAM_INV #language en-US "%H%s%N: Invalid argument - '%H%s%N'\r\n"
+#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n"
+#string STR_GEN_PROBLEM_OP2 #language en-US "%H%s%N: Invalid argument - '%H%s%N'. Expected '%B%s%N' or '%B%s%N'.\r\n"
+#string STR_GEN_PROBLEM_VAL #language en-US "%H%s%N: Bad value - '%H%s%N' for flag - '%H%s%N'\r\n"
+#string STR_GEN_NO_VALUE #language en-US "%H%s%N: Missing argument for flag - '%H%s%N'\r\n"
+#string STR_GEN_ERR_AD #language en-US "%H%s%N: Access denied.\r\n"
+#string STR_GEN_ERR_UK #language en-US "%H%s%N: Status: %r\r\n"
+#string STR_GEN_PARAM_CON #language en-US "%H%s%N: Parameters conflict.\r\n"
+#string STR_GEN_FILE_OPEN_FAIL #language en-US "%H%s%N: Cannot open file - '%H%s%N'\r\n"
+#string STR_GEN_FILE_AD #language en-US "%H%s%N: Access file error - '%H%s%N'\r\n"
+#string STR_GEN_CRLF #language en-US "\r\n"
+#string STR_GEN_NO_FILES #language en-US "%H%s%N: No matching files were found.\r\n"
+#string STR_GEN_DIR_NF #language en-US "%H%s%N: Directory not found - '%H%s%N'\r\n"
+#string STR_GEN_FILE_NF #language en-US "%H%s%N: File not found - '%H%s%N'\r\n"
+#string STR_GEN_IS_DIR #language en-US "%H%s%N: '%H%s%N' is a directory\r\n"
+#string STR_GEN_PROTOCOL_NF #language en-US "%H%s%N: The protocol '%H%s%N' is required and not found (%g).\r\n"
+#string STR_GEN_OUT_MEM #language en-US "%H%s%N: Memory allocation was not successful.\r\n"
+
+#string STR_PING_INVALID_SOURCE #language en-US "%Ping: Require source interface option\r\n"
+#string STR_PING_CONFIG #language en-US "Config %r\r\n"
+#string STR_PING_GETMODE #language en-US "GetModeData %r\r\n"
+#string STR_PING_GETDATA #language en-US "GetData %r\r\n"
+#string STR_PING_SEND_REQUEST #language en-US "Echo request sequence %d did not complete successfully.\r\n"
+#string STR_PING_NOSOURCE_INDO #language en-US "There are no sources in %s's multicast domain.\r\n"
+#string STR_PING_NETWORK_ERROR #language en-US "%H%s%N: Network function failed with %r\r\n"
+#string STR_PING_CONFIGD_NIC_NF #language en-US "%H%s%N: No configured interfaces were found.\r\n"
+#string STR_PING_NOROUTE_FOUND #language en-US "There is no route to the destination '%B%s%N' from the source '%B%s%N' was found.\r\n"
+#string STR_PING_START #language en-US "Ping %s %d data bytes.\r\n"
+#string STR_PING_TIMEOUT #language en-US "Echo request sequence %d timeout.\r\n"
+#string STR_PING_REPLY_INFO #language en-US "%d bytes from %s : icmp_seq=%d ttl=%d time%c%dms\r\n"
+#string STR_PING_STAT #language en-US "\n%d packets transmitted, %d received, %d%% packet loss, time %dms\r\n"
+#string STR_PING_RTT #language en-US "\nRtt(round trip time) min=%dms max=%dms avg=%dms\r\n"
+
+#string STR_IFCONFIG_UNSUPPORTED_OPTION #language en-US "The option '%H%s%N' is unsupported now.\n"
+#string STR_IFCONFIG_LACK_OPTION #language en-US "Flags lack.\n"
+#string STR_IFCONFIG_LACK_INTERFACE #language en-US "Lack interface name.\n"
+#string STR_IFCONFIG_LACK_COMMAND #language en-US "Lack interface config option.\n"
+#string STR_IFCONFIG_INVALID_INTERFACE #language en-US "Invalid interface name.\n"
+#string STR_IFCONFIG_INVALID_IPADDRESS #language en-US "Invalid ipv4 address: '%H%s%N'\n"
+#string STR_IFCONFIG_DUPLICATE_COMMAND #language en-US "Duplicate commands. Bad command %H%s%N is skipped.\n"
+#string STR_IFCONFIG_CONFLICT_COMMAND #language en-US "Conflict commands. Bad command %H%s%N is skipped.\n"
+#string STR_IFCONFIG_UNKNOWN_COMMAND #language en-US "Unknown commands. Bad command %H%s%N is skipped.\n"
+#string STR_IFCONFIG_SET_ADDR_FAILED #language en-US "Failed to set address.\n"
+#string STR_IFCONFIG_ROUTES_SIZE #language en-US "\n%H Routes (%d entries):\n"
+#string STR_IFCONFIG_ROUTES_ENTRY_INDEX #language en-US "%H Entry[%d]\n"
+#string STR_IFCONFIG_SHOW_IP_ADDR #language en-US "%12s: %N%d.%d.%d.%d\n"
+#string STR_IFCONFIG_INFO_NEWLINE #language en-US "\n"
+#string STR_IFCONFIG_INFO_DNS_ADDR_BODY #language en-US "%8d.%d.%d.%d\n"
+#string STR_IFCONFIG_INFO_BREAK #language en-US "\n-----------------------------------------------------------------\n"
+#string STR_IFCONFIG_INFO_COLON #language en-US ":"
+#string STR_IFCONFIG_INFO_IF_NAME #language en-US "\n%Hname : %s%N\n"
+#string STR_IFCONFIG_INFO_MEDIA_STATE #language en-US "%HMedia State : %s%N\n"
+#string STR_IFCONFIG_INFO_POLICY_DHCP #language en-US "%Hpolicy : dhcp%N\n"
+#string STR_IFCONFIG_INFO_POLICY_MAN #language en-US "%Hpolicy : static%N\n"
+#string STR_IFCONFIG_INFO_MAC_ADDR_HEAD #language en-US "%Hmac addr : %N"
+#string STR_IFCONFIG_INFO_MAC_ADDR_BODY #language en-US "%02x"
+#string STR_IFCONFIG_INFO_IP_ADDR_HEAD #language en-US "\n%Hipv4 address : %N"
+#string STR_IFCONFIG_INFO_SUBNET_MASK_HEAD #language en-US "\n%Hsubnet mask : %N"
+#string STR_IFCONFIG_INFO_GATEWAY_HEAD #language en-US "\n%Hdefault gateway: %N"
+#string STR_IFCONFIG_INFO_DNS_ADDR_HEAD #language en-US "\n%HDNS server : %N\n"
+#string STR_IFCONFIG_INFO_IP_ADDR_BODY #language en-US "%d.%d.%d.%d\n"
+
+#string STR_GET_HELP_PING #language en-US ""
+".TH ping 0 "Ping the target host with an IPv4 stack."\r\n"
+".SH NAME\r\n"
+"Ping the target host with an IPv4 stack.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"PING [-n count] [-l size] [-s SourceIp] TargetIp\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -n - Specifies the number of echo request datagrams to be sent.\r\n"
+" -l - Specifies the size of the data buffer in the echo request datagram.\r\n"
+" -s - Specifies the source adapter as IPv4 address.\r\n"
+" SourceIp - Specifies the IPv4 address of the source machine.\r\n"
+" TargetIp - Specifies the IPv4 address of the target machine.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command uses the ICMPv4 ECHO_REQUEST datagram to elicit an\r\n"
+" ECHO_REPLY from a host.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To ping the target host with 64 bytes data:\r\n"
+" fs0:\> ping -l 64 192.168.0.1\r\n"
+" \r\n"
+" * To ping the target host by sending 20 echo request datagrams:\r\n"
+" fs0:\> ping -n 20 202.120.100.1\r\n"
+" \r\n"
+" * To ping the target host by specifying the source adapter as IPv4 address:\r\n"
+" fs0:\> ping -s 202.120.100.12 202.120.100.1\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+
+#string STR_GET_HELP_IFCONFIG #language en-US ""
+".TH ifconfig 0 "Modifies the default IP address of the UEFI IPv4 Network Stack."\r\n"
+".SH NAME\r\n"
+"Modifies the default IP address of the UEFI IPv4 Network Stack.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"IFCONFIG [-r [Name]] [-l [Name]]\r\n"
+"IFCONFIG [-s <Name> dhcp | <static <IP> <Mask> <Gateway>> | <dns <IP>>]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -r - Renew configuration of interface and set dhcp policy.\r\n"
+" -l - Lists the configuration.\r\n"
+" -s - Sets the configuration.\r\n"
+" Name - Specifies an adapter name (for example, eth0).\r\n"
+" IP - Specifies the IPv4 address in four integer values:\r\n"
+" - Example: 192.168.0.10\r\n"
+" SubnetMask - Specifies a subnet mask in four integer values:\r\n"
+" - Example: 255.255.255.0\r\n"
+" GatewayMask - Specifies a default gateway in four integer values:\r\n"
+" - Example: 192.168.0.1\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. This command modifies the default IP address for the UEFI IP4\r\n"
+" network stack.\r\n"
+" 2. Use '-r' to renew configuration of interface and set dhcp policy.\r\n"
+" 3. Use '-l' to list the DNS and other address related settings for all\r\n"
+" interfaces or the specified interface.\r\n"
+" 4. Use '-s <Name> static <IP> <SubnetMask> <GatewayMask>' with \r\n"
+" static IP4 address configuration for specified interface.\r\n"
+" 5. Use '-s <Name> dhcp' for DHCP4 to request the IP4 address\r\n"
+" configuration dynamically for specified interface.\r\n"
+" 6. Use '-s <Name> dns <IP>' must under manual policy.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To list the configuration for the eth0 interface:\r\n"
+" fs0:\> ifconfig -l eth0\r\n"
+" \r\n"
+" * To use DHCP4 to request the IPv4 address configuration dynamically for the\r\n"
+" eth0 interface:\r\n"
+" fs0:\> ifconfig -s eth0 dhcp\r\n"
+" \r\n"
+" * To use the static IPv4 address configuration for the eth0 interface:\r\n"
+" fs0:\> ifconfig -s eth0 static 192.168.0.5 255.255.255.0 192.168.0.1\r\n"
+" \r\n"
+" * To configure DNS server address for the eth0 interface:\r\n"
+" fs0:\> ifconfig -s eth0 dns 192.168.0.8 192.168.0.9\r\n"
+
+
+
diff --git a/Core/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ifconfig6.c b/Core/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ifconfig6.c
new file mode 100644
index 0000000000..32dd2845fc
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ifconfig6.c
@@ -0,0 +1,1894 @@
+/** @file
+ The implementation for Shell command IfConfig6.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "UefiShellNetwork2CommandsLib.h"
+
+enum {
+ IfConfig6OpList = 1,
+ IfConfig6OpSet = 2,
+ IfConfig6OpClear = 3
+};
+
+typedef enum {
+ VarCheckReserved = -1,
+ VarCheckOk = 0,
+ VarCheckDuplicate,
+ VarCheckConflict,
+ VarCheckUnknown,
+ VarCheckLackValue,
+ VarCheckOutOfMem
+} VAR_CHECK_CODE;
+
+typedef enum {
+ FlagTypeSingle = 0,
+ FlagTypeNeedVar,
+ FlagTypeNeedSet,
+ FlagTypeSkipUnknown
+} VAR_CHECK_FLAG_TYPE;
+
+#define MACADDRMAXSIZE 32
+#define PREFIXMAXLEN 16
+
+typedef struct _IFCONFIG6_INTERFACE_CB {
+ EFI_HANDLE NicHandle;
+ LIST_ENTRY Link;
+ EFI_IP6_CONFIG_PROTOCOL *IfCfg;
+ EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo;
+ EFI_IP6_CONFIG_INTERFACE_ID *IfId;
+ EFI_IP6_CONFIG_POLICY Policy;
+ EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS Xmits;
+ UINT32 DnsCnt;
+ EFI_IPv6_ADDRESS DnsAddr[1];
+} IFCONFIG6_INTERFACE_CB;
+
+typedef struct _ARG_LIST ARG_LIST;
+
+struct _ARG_LIST {
+ ARG_LIST *Next;
+ CHAR16 *Arg;
+};
+
+typedef struct _IFCONFIG6_PRIVATE_DATA {
+ EFI_HANDLE ImageHandle;
+ LIST_ENTRY IfList;
+
+ UINT32 OpCode;
+ CHAR16 *IfName;
+ ARG_LIST *VarArg;
+} IFCONFIG6_PRIVATE_DATA;
+
+typedef struct _VAR_CHECK_ITEM{
+ CHAR16 *FlagStr;
+ UINT32 FlagID;
+ UINT32 ConflictMask;
+ VAR_CHECK_FLAG_TYPE FlagType;
+} VAR_CHECK_ITEM;
+
+
+SHELL_PARAM_ITEM mIfConfig6CheckList[] = {
+ {
+ L"-b",
+ TypeFlag
+ },
+ {
+ L"-s",
+ TypeMaxValue
+ },
+ {
+ L"-l",
+ TypeValue
+ },
+ {
+ L"-r",
+ TypeValue
+ },
+ {
+ L"-?",
+ TypeFlag
+ },
+ {
+ NULL,
+ TypeMax
+ },
+};
+
+VAR_CHECK_ITEM mIfConfig6SetCheckList[] = {
+ {
+ L"auto",
+ 0x00000001,
+ 0x00000001,
+ FlagTypeSingle
+ },
+ {
+ L"man",
+ 0x00000002,
+ 0x00000001,
+ FlagTypeSingle
+ },
+ {
+ L"host",
+ 0x00000004,
+ 0x00000002,
+ FlagTypeSingle
+ },
+ {
+ L"dad",
+ 0x00000008,
+ 0x00000004,
+ FlagTypeSingle
+ },
+ {
+ L"gw",
+ 0x00000010,
+ 0x00000008,
+ FlagTypeSingle
+ },
+ {
+ L"dns",
+ 0x00000020,
+ 0x00000010,
+ FlagTypeSingle
+ },
+ {
+ L"id",
+ 0x00000040,
+ 0x00000020,
+ FlagTypeSingle
+ },
+ {
+ NULL,
+ 0x0,
+ 0x0,
+ FlagTypeSkipUnknown
+ },
+};
+
+/**
+ Free the ARG_LIST.
+
+ @param List Pointer to ARG_LIST to free.
+**/
+VOID
+IfConfig6FreeArgList (
+ ARG_LIST *List
+)
+{
+ ARG_LIST *Next;
+ while (List->Next != NULL) {
+ Next = List->Next;
+ FreePool (List);
+ List = Next;
+ }
+
+ FreePool (List);
+}
+
+/**
+ Split a string with specified separator and save the substring to a list.
+
+ @param[in] String The pointer of the input string.
+ @param[in] Separator The specified separator.
+
+ @return The pointer of headnode of ARG_LIST.
+
+**/
+ARG_LIST *
+IfConfig6SplitStrToList (
+ IN CONST CHAR16 *String,
+ IN CHAR16 Separator
+ )
+{
+ CHAR16 *Str;
+ CHAR16 *ArgStr;
+ ARG_LIST *ArgList;
+ ARG_LIST *ArgNode;
+
+ if (String == NULL || *String == L'\0') {
+ return NULL;
+ }
+
+ //
+ // Copy the CONST string to a local copy.
+ //
+ Str = AllocateCopyPool (StrSize (String), String);
+ if (Str == NULL) {
+ return NULL;
+ }
+ ArgStr = Str;
+
+ //
+ // init a node for the list head.
+ //
+ ArgNode = (ARG_LIST *) AllocateZeroPool (sizeof (ARG_LIST));
+ if (ArgNode == NULL) {
+ return NULL;
+ }
+ ArgList = ArgNode;
+
+ //
+ // Split the local copy and save in the list node.
+ //
+ while (*Str != L'\0') {
+ if (*Str == Separator) {
+ *Str = L'\0';
+ ArgNode->Arg = ArgStr;
+ ArgStr = Str + 1;
+ ArgNode->Next = (ARG_LIST *) AllocateZeroPool (sizeof (ARG_LIST));
+ if (ArgNode->Next == NULL) {
+ //
+ // Free the local copy of string stored in the first node
+ //
+ FreePool (ArgList->Arg);
+ IfConfig6FreeArgList (ArgList);
+ return NULL;
+ }
+ ArgNode = ArgNode->Next;
+ }
+
+ Str++;
+ }
+
+ ArgNode->Arg = ArgStr;
+ ArgNode->Next = NULL;
+
+ return ArgList;
+}
+
+/**
+ Check the correctness of input Args with '-s' option.
+
+ @param[in] CheckList The pointer of VAR_CHECK_ITEM array.
+ @param[in] Name The pointer of input arg.
+ @param[in] Init The switch to execute the check.
+
+ @return The value of VAR_CHECK_CODE.
+
+**/
+VAR_CHECK_CODE
+IfConfig6RetriveCheckListByName(
+ IN VAR_CHECK_ITEM *CheckList,
+ IN CHAR16 *Name,
+ IN BOOLEAN Init
+)
+{
+ STATIC UINT32 CheckDuplicate;
+ STATIC UINT32 CheckConflict;
+ VAR_CHECK_CODE RtCode;
+ UINT32 Index;
+ VAR_CHECK_ITEM Arg;
+
+ if (Init) {
+ CheckDuplicate = 0;
+ CheckConflict = 0;
+ return VarCheckOk;
+ }
+
+ RtCode = VarCheckOk;
+ Index = 0;
+ Arg = CheckList[Index];
+
+ //
+ // Check the Duplicated/Conflicted/Unknown input Args.
+ //
+ while (Arg.FlagStr != NULL) {
+ if (StrCmp (Arg.FlagStr, Name) == 0) {
+
+ if (CheckDuplicate & Arg.FlagID) {
+ RtCode = VarCheckDuplicate;
+ break;
+ }
+
+ if (CheckConflict & Arg.ConflictMask) {
+ RtCode = VarCheckConflict;
+ break;
+ }
+
+ CheckDuplicate |= Arg.FlagID;
+ CheckConflict |= Arg.ConflictMask;
+ break;
+ }
+
+ Arg = CheckList[++Index];
+ }
+
+ if (Arg.FlagStr == NULL) {
+ RtCode = VarCheckUnknown;
+ }
+
+ return RtCode;
+}
+
+/**
+ The notify function of create event when performing a manual config.
+
+ @param[in] Event The event this notify function registered to.
+ @param[in] Context Pointer to the context data registered to the event.
+
+**/
+VOID
+EFIAPI
+IfConfig6ManualAddressNotify (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ *((BOOLEAN *) Context) = TRUE;
+}
+
+/**
+ Print MAC address.
+
+ @param[in] Node The pointer of MAC address buffer.
+ @param[in] Size The size of MAC address buffer.
+
+**/
+VOID
+IfConfig6PrintMacAddr (
+ IN UINT8 *Node,
+ IN UINT32 Size
+ )
+{
+ UINTN Index;
+
+ ASSERT (Size <= MACADDRMAXSIZE);
+
+ for (Index = 0; Index < Size; Index++) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_MAC_ADDR_BODY), gShellNetwork2HiiHandle, Node[Index]);
+ if (Index + 1 < Size) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), gShellNetwork2HiiHandle);
+ }
+ }
+
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle);
+}
+
+/**
+ Print IPv6 address.
+
+ @param[in] Ip The pointer of Ip bufffer in EFI_IPv6_ADDRESS format.
+ @param[in] PrefixLen The pointer of PrefixLen that describes the size Prefix.
+
+**/
+VOID
+IfConfig6PrintIpAddr (
+ IN EFI_IPv6_ADDRESS *Ip,
+ IN UINT8 *PrefixLen
+ )
+{
+ UINTN Index;
+ BOOLEAN Short;
+
+ Short = FALSE;
+
+ for (Index = 0; Index < PREFIXMAXLEN; Index = Index + 2) {
+
+ if (!Short && (Index + 1 < PREFIXMAXLEN) && (Index % 2 == 0) && (Ip->Addr[Index] == 0) && (Ip->Addr[Index + 1] == 0)) {
+ //
+ // Deal with the case of ::.
+ //
+ if (Index == 0) {
+ //
+ // :: is at the beginning of the address.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), gShellNetwork2HiiHandle);
+ }
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), gShellNetwork2HiiHandle);
+
+ while ((Ip->Addr[Index] == 0) && (Ip->Addr[Index + 1] == 0) && (Index < PREFIXMAXLEN)) {
+ Index = Index + 2;
+ if (Index > PREFIXMAXLEN - 2) {
+ break;
+ }
+ }
+
+ Short = TRUE;
+
+ if (Index == PREFIXMAXLEN) {
+ //
+ // :: is at the end of the address.
+ //
+ break;
+ }
+ }
+
+ if (Index < PREFIXMAXLEN - 1) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IP_ADDR_BODY), gShellNetwork2HiiHandle, Ip->Addr[Index]);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IP_ADDR_BODY), gShellNetwork2HiiHandle, Ip->Addr[Index + 1]);
+ }
+
+ if (Index + 2 < PREFIXMAXLEN) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_COLON), gShellNetwork2HiiHandle);
+ }
+ }
+
+ if (PrefixLen != NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_PREFIX_LEN), gShellNetwork2HiiHandle, *PrefixLen);
+ }
+}
+
+/**
+ Pick up host IPv6 address in string format from Args with "-s" option and convert it to EFI_IP6_CONFIG_MANUAL_ADDRESS format.
+
+ @param[in, out] Arg The pointer of the address of ARG_LIST which save Args with the "-s" option.
+ @param[out] Buf The pointer of the address of EFI_IP6_CONFIG_MANUAL_ADDRESS.
+ @param[out] BufSize The pointer of BufSize that describes the size of Buf in bytes.
+
+ @retval EFI_SUCCESS The convertion is successful.
+ @retval Others Does't find the host address, or it is an invalid IPv6 address in string format.
+
+**/
+EFI_STATUS
+IfConfig6ParseManualAddressList (
+ IN OUT ARG_LIST **Arg,
+ OUT EFI_IP6_CONFIG_MANUAL_ADDRESS **Buf,
+ OUT UINTN *BufSize
+ )
+{
+ EFI_STATUS Status;
+ EFI_IP6_CONFIG_MANUAL_ADDRESS *AddrBuf;
+ ARG_LIST *VarArg;
+ EFI_IPv6_ADDRESS Address;
+ UINT8 Prefix;
+ UINT8 AddrCnt;
+
+ Prefix = 0;
+ AddrCnt = 0;
+ *BufSize = 0;
+ *Buf = NULL;
+ VarArg = *Arg;
+ Status = EFI_SUCCESS;
+
+ //
+ // Go through the list to check the correctness of input host ip6 address.
+ //
+ while ((!EFI_ERROR (Status)) && (VarArg != NULL)) {
+
+ Status = NetLibStrToIp6andPrefix (VarArg->Arg, &Address, &Prefix);
+
+ if (EFI_ERROR (Status)) {
+ //
+ // host ip ip ... gw
+ //
+ break;
+ }
+
+ VarArg = VarArg->Next;
+ AddrCnt++;
+ }
+
+ if (AddrCnt == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AddrBuf = AllocateZeroPool (AddrCnt * sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS));
+ ASSERT (AddrBuf != NULL);
+
+ AddrCnt = 0;
+ VarArg = *Arg;
+ Status = EFI_SUCCESS;
+
+ //
+ // Go through the list to fill in the EFI_IP6_CONFIG_MANUAL_ADDRESS structure.
+ //
+ while ((!EFI_ERROR (Status)) && (VarArg != NULL)) {
+
+ Status = NetLibStrToIp6andPrefix (VarArg->Arg, &Address, &Prefix);
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ //
+ // If prefix length is not set, set it as Zero here. In the IfConfigSetInterfaceInfo()
+ // Zero prefix, length will be transfered to default prefix length.
+ //
+ if (Prefix == 0xFF) {
+ Prefix = 0;
+ }
+ AddrBuf[AddrCnt].IsAnycast = FALSE;
+ AddrBuf[AddrCnt].PrefixLength = Prefix;
+ IP6_COPY_ADDRESS (&AddrBuf[AddrCnt].Address, &Address);
+ VarArg = VarArg->Next;
+ AddrCnt++;
+ }
+
+ *Arg = VarArg;
+
+ if (EFI_ERROR (Status) && (Status != EFI_INVALID_PARAMETER)) {
+ goto ON_ERROR;
+ }
+
+ *Buf = AddrBuf;
+ *BufSize = AddrCnt * sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS);
+
+ return EFI_SUCCESS;
+
+ON_ERROR:
+
+ FreePool (AddrBuf);
+ return Status;
+}
+
+/**
+ Pick up gw/dns IPv6 address in string format from Args with "-s" option and convert it to EFI_IPv6_ADDRESS format.
+
+ @param[in, out] Arg The pointer of the address of ARG_LIST that save Args with the "-s" option.
+ @param[out] Buf The pointer of the address of EFI_IPv6_ADDRESS.
+ @param[out] BufSize The pointer of BufSize that describes the size of Buf in bytes.
+
+ @retval EFI_SUCCESS The conversion is successful.
+ @retval Others Doesn't find the host address, or it is an invalid IPv6 address in string format.
+
+**/
+EFI_STATUS
+IfConfig6ParseGwDnsAddressList (
+ IN OUT ARG_LIST **Arg,
+ OUT EFI_IPv6_ADDRESS **Buf,
+ OUT UINTN *BufSize
+ )
+{
+ EFI_STATUS Status;
+ EFI_IPv6_ADDRESS *AddrBuf;
+ ARG_LIST *VarArg;
+ EFI_IPv6_ADDRESS Address;
+ UINT8 Prefix;
+ UINT8 AddrCnt;
+
+ AddrCnt = 0;
+ *BufSize = 0;
+ *Buf = NULL;
+ VarArg = *Arg;
+ Status = EFI_SUCCESS;
+
+ //
+ // Go through the list to check the correctness of input gw/dns address.
+ //
+ while ((!EFI_ERROR (Status)) && (VarArg != NULL)) {
+
+ Status = NetLibStrToIp6andPrefix (VarArg->Arg, &Address, &Prefix);
+
+ if (EFI_ERROR (Status)) {
+ //
+ // gw ip ip ... host
+ //
+ break;
+ }
+
+ VarArg = VarArg->Next;
+ AddrCnt++;
+ }
+
+ if (AddrCnt == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ AddrBuf = AllocateZeroPool (AddrCnt * sizeof (EFI_IPv6_ADDRESS));
+ ASSERT (AddrBuf != NULL);
+
+ AddrCnt = 0;
+ VarArg = *Arg;
+ Status = EFI_SUCCESS;
+
+ //
+ // Go through the list to fill in the EFI_IPv6_ADDRESS structure.
+ //
+ while ((!EFI_ERROR (Status)) && (VarArg != NULL)) {
+
+ Status = NetLibStrToIp6andPrefix (VarArg->Arg, &Address, &Prefix);
+
+ if (EFI_ERROR (Status)) {
+ break;
+ }
+
+ IP6_COPY_ADDRESS (&AddrBuf[AddrCnt], &Address);
+
+ VarArg = VarArg->Next;
+ AddrCnt++;
+ }
+
+ *Arg = VarArg;
+
+ if (EFI_ERROR (Status) && (Status != EFI_INVALID_PARAMETER)) {
+ goto ON_ERROR;
+ }
+
+ *Buf = AddrBuf;
+ *BufSize = AddrCnt * sizeof (EFI_IPv6_ADDRESS);
+
+ return EFI_SUCCESS;
+
+ON_ERROR:
+
+ FreePool (AddrBuf);
+ return Status;
+}
+
+/**
+ Parse InterfaceId in string format from Args with the "-s" option and convert it to EFI_IP6_CONFIG_INTERFACE_ID format.
+
+ @param[in, out] Arg The pointer of the address of ARG_LIST that saves Args with the "-s" option.
+ @param[out] IfId The pointer of EFI_IP6_CONFIG_INTERFACE_ID.
+
+ @retval EFI_SUCCESS The get status processed successfullly.
+ @retval EFI_INVALID_PARAMETER The get status process failed.
+
+**/
+EFI_STATUS
+IfConfig6ParseInterfaceId (
+ IN OUT ARG_LIST **Arg,
+ OUT EFI_IP6_CONFIG_INTERFACE_ID **IfId
+ )
+{
+ UINT8 Index;
+ UINT8 NodeVal;
+ CHAR16 *IdStr;
+
+ if (*Arg == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Index = 0;
+ IdStr = (*Arg)->Arg;
+ ASSERT (IfId != NULL);
+ *IfId = AllocateZeroPool (sizeof (EFI_IP6_CONFIG_INTERFACE_ID));
+ ASSERT (*IfId != NULL);
+
+ while ((*IdStr != L'\0') && (Index < 8)) {
+
+ NodeVal = 0;
+ while ((*IdStr != L':') && (*IdStr != L'\0')) {
+
+ if ((*IdStr <= L'F') && (*IdStr >= L'A')) {
+ NodeVal = (UINT8)((NodeVal << 4) + *IdStr - L'A' + 10);
+ } else if ((*IdStr <= L'f') && (*IdStr >= L'a')) {
+ NodeVal = (UINT8)((NodeVal << 4) + *IdStr - L'a' + 10);
+ } else if ((*IdStr <= L'9') && (*IdStr >= L'0')) {
+ NodeVal = (UINT8)((NodeVal << 4) + *IdStr - L'0');
+ } else {
+ FreePool (*IfId);
+ return EFI_INVALID_PARAMETER;
+ }
+
+ IdStr++;
+ }
+
+ (*IfId)->Id[Index++] = NodeVal;
+
+ if (*IdStr == L':') {
+ IdStr++;
+ }
+ }
+
+ *Arg = (*Arg)->Next;
+ return EFI_SUCCESS;
+}
+
+/**
+ Parse dad in string format from Args with the "-s" option and convert it to UINT32 format.
+
+ @param[in, out] Arg The pointer of the address of ARG_LIST that saves Args with the "-s" option.
+ @param[out] Xmits The pointer of Xmits.
+
+ @retval EFI_SUCCESS The get status processed successfully.
+ @retval others The get status process failed.
+
+**/
+EFI_STATUS
+IfConfig6ParseDadXmits (
+ IN OUT ARG_LIST **Arg,
+ OUT UINT32 *Xmits
+ )
+{
+ CHAR16 *ValStr;
+
+ if (*Arg == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ValStr = (*Arg)->Arg;
+ *Xmits = 0;
+
+ while (*ValStr != L'\0') {
+
+ if ((*ValStr <= L'9') && (*ValStr >= L'0')) {
+
+ *Xmits = (*Xmits * 10) + (*ValStr - L'0');
+
+ } else {
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ ValStr++;
+ }
+
+ *Arg = (*Arg)->Next;
+ return EFI_SUCCESS;
+}
+
+/**
+ The get current status of all handles.
+
+ @param[in] ImageHandle The handle of ImageHandle.
+ @param[in] IfName The pointer of IfName(interface name).
+ @param[in] IfList The pointer of IfList(interface list).
+
+ @retval EFI_SUCCESS The get status processed successfully.
+ @retval others The get status process failed.
+
+**/
+EFI_STATUS
+IfConfig6GetInterfaceInfo (
+ IN EFI_HANDLE ImageHandle,
+ IN CHAR16 *IfName,
+ IN LIST_ENTRY *IfList
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleIndex;
+ UINTN HandleNum;
+ EFI_HANDLE *HandleBuffer;
+ EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg;
+ EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo;
+ IFCONFIG6_INTERFACE_CB *IfCb;
+ UINTN DataSize;
+
+ HandleBuffer = NULL;
+ HandleNum = 0;
+
+ IfInfo = NULL;
+ IfCb = NULL;
+
+ //
+ // Locate all the handles with ip6 service binding protocol.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiIp6ServiceBindingProtocolGuid,
+ NULL,
+ &HandleNum,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status) || (HandleNum == 0)) {
+ return Status;
+ }
+
+ //
+ // Enumerate all handles that installed with ip6 service binding protocol.
+ //
+ for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) {
+ IfCb = NULL;
+ IfInfo = NULL;
+ DataSize = 0;
+
+ //
+ // Ip6config protocol and ip6 service binding protocol are installed
+ // on the same handle.
+ //
+ ASSERT (HandleBuffer != NULL);
+ Status = gBS->HandleProtocol (
+ HandleBuffer[HandleIndex],
+ &gEfiIp6ConfigProtocolGuid,
+ (VOID **) &Ip6Cfg
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+ //
+ // Get the interface information size.
+ //
+ Status = Ip6Cfg->GetData (
+ Ip6Cfg,
+ Ip6ConfigDataTypeInterfaceInfo,
+ &DataSize,
+ NULL
+ );
+
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
+ goto ON_ERROR;
+ }
+
+ IfInfo = AllocateZeroPool (DataSize);
+
+ if (IfInfo == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_ERROR;
+ }
+ //
+ // Get the interface info.
+ //
+ Status = Ip6Cfg->GetData (
+ Ip6Cfg,
+ Ip6ConfigDataTypeInterfaceInfo,
+ &DataSize,
+ IfInfo
+ );
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
+ goto ON_ERROR;
+ }
+ //
+ // Check the interface name if required.
+ //
+ if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) != 0)) {
+ FreePool (IfInfo);
+ continue;
+ }
+
+ DataSize = 0;
+ //
+ // Get the size of dns server list.
+ //
+ Status = Ip6Cfg->GetData (
+ Ip6Cfg,
+ Ip6ConfigDataTypeDnsServer,
+ &DataSize,
+ NULL
+ );
+
+ if ((Status != EFI_BUFFER_TOO_SMALL) && (Status != EFI_NOT_FOUND)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
+ goto ON_ERROR;
+ }
+
+ IfCb = AllocateZeroPool (sizeof (IFCONFIG6_INTERFACE_CB) + DataSize);
+
+ if (IfCb == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_ERROR;
+ }
+
+ IfCb->NicHandle = HandleBuffer[HandleIndex];
+ IfCb->IfInfo = IfInfo;
+ IfCb->IfCfg = Ip6Cfg;
+ IfCb->DnsCnt = (UINT32) (DataSize / sizeof (EFI_IPv6_ADDRESS));
+
+ //
+ // Get the dns server list if has.
+ //
+ if (DataSize > 0) {
+
+ Status = Ip6Cfg->GetData (
+ Ip6Cfg,
+ Ip6ConfigDataTypeDnsServer,
+ &DataSize,
+ IfCb->DnsAddr
+ );
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
+ goto ON_ERROR;
+ }
+ }
+ //
+ // Get the interface id if has.
+ //
+ DataSize = sizeof (EFI_IP6_CONFIG_INTERFACE_ID);
+ IfCb->IfId = AllocateZeroPool (DataSize);
+
+ if (IfCb->IfId == NULL) {
+ goto ON_ERROR;
+ }
+
+ Status = Ip6Cfg->GetData (
+ Ip6Cfg,
+ Ip6ConfigDataTypeAltInterfaceId,
+ &DataSize,
+ IfCb->IfId
+ );
+
+ if (EFI_ERROR (Status) && (Status != EFI_NOT_FOUND)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
+ goto ON_ERROR;
+ }
+
+ if (Status == EFI_NOT_FOUND) {
+ FreePool (IfCb->IfId);
+ IfCb->IfId = NULL;
+ }
+ //
+ // Get the config policy.
+ //
+ DataSize = sizeof (EFI_IP6_CONFIG_POLICY);
+ Status = Ip6Cfg->GetData (
+ Ip6Cfg,
+ Ip6ConfigDataTypePolicy,
+ &DataSize,
+ &IfCb->Policy
+ );
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
+ goto ON_ERROR;
+ }
+ //
+ // Get the dad transmits.
+ //
+ DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);
+ Status = Ip6Cfg->GetData (
+ Ip6Cfg,
+ Ip6ConfigDataTypeDupAddrDetectTransmits,
+ &DataSize,
+ &IfCb->Xmits
+ );
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
+ goto ON_ERROR;
+ }
+
+ InsertTailList (IfList, &IfCb->Link);
+
+ if ((IfName != NULL) && (StrCmp (IfName, IfInfo->Name) == 0)) {
+ //
+ // Only need the appointed interface, keep the allocated buffer.
+ //
+ IfCb = NULL;
+ IfInfo = NULL;
+ break;
+ }
+ }
+
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+
+ return EFI_SUCCESS;
+
+ON_ERROR:
+
+ if (IfInfo != NULL) {
+ FreePool (IfInfo);
+ }
+
+ if (IfCb != NULL) {
+ if (IfCb->IfId != NULL) {
+ FreePool (IfCb->IfId);
+ }
+
+ FreePool (IfCb);
+ }
+
+ return Status;
+}
+
+/**
+ The list process of the IfConfig6 application.
+
+ @param[in] IfList The pointer of IfList(interface list).
+
+ @retval SHELL_SUCCESS The IfConfig6 list processed successfully.
+ @retval others The IfConfig6 list process failed.
+
+**/
+SHELL_STATUS
+IfConfig6ShowInterfaceInfo (
+ IN LIST_ENTRY *IfList
+ )
+{
+ LIST_ENTRY *Entry;
+ IFCONFIG6_INTERFACE_CB *IfCb;
+ UINTN Index;
+
+ Entry = IfList->ForwardLink;
+
+ if (IsListEmpty (IfList)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_INTERFACE), gShellNetwork2HiiHandle);
+ }
+
+ //
+ // Go through the interface list.
+ //
+ while (Entry != IfList) {
+
+ IfCb = BASE_CR (Entry, IFCONFIG6_INTERFACE_CB, Link);
+
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_BREAK), gShellNetwork2HiiHandle);
+
+ //
+ // Print interface name.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IF_NAME), gShellNetwork2HiiHandle, IfCb->IfInfo->Name);
+
+ //
+ // Print interface config policy.
+ //
+ if (IfCb->Policy == Ip6ConfigPolicyAutomatic) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_POLICY_AUTO), gShellNetwork2HiiHandle);
+ } else {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_POLICY_MAN), gShellNetwork2HiiHandle);
+ }
+
+ //
+ // Print dad transmit.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_DAD_TRANSMITS), gShellNetwork2HiiHandle, IfCb->Xmits);
+
+ //
+ // Print interface id if has.
+ //
+ if (IfCb->IfId != NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_INTERFACE_ID_HEAD), gShellNetwork2HiiHandle);
+
+ IfConfig6PrintMacAddr (
+ IfCb->IfId->Id,
+ 8
+ );
+ }
+ //
+ // Print mac address of the interface.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_MAC_ADDR_HEAD), gShellNetwork2HiiHandle);
+
+ IfConfig6PrintMacAddr (
+ IfCb->IfInfo->HwAddress.Addr,
+ IfCb->IfInfo->HwAddressSize
+ );
+
+ //
+ // Print ip addresses list of the interface.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_IP_ADDR_HEAD), gShellNetwork2HiiHandle);
+
+ for (Index = 0; Index < IfCb->IfInfo->AddressInfoCount; Index++) {
+ IfConfig6PrintIpAddr (
+ &IfCb->IfInfo->AddressInfo[Index].Address,
+ &IfCb->IfInfo->AddressInfo[Index].PrefixLength
+ );
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle);
+ }
+
+ //
+ // Print dns server addresses list of the interface if has.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_DNS_ADDR_HEAD), gShellNetwork2HiiHandle);
+
+ for (Index = 0; Index < IfCb->DnsCnt; Index++) {
+ IfConfig6PrintIpAddr (
+ &IfCb->DnsAddr[Index],
+ NULL
+ );
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle);
+ }
+
+ //
+ // Print route table of the interface if has.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_ROUTE_HEAD), gShellNetwork2HiiHandle);
+
+ for (Index = 0; Index < IfCb->IfInfo->RouteCount; Index++) {
+ IfConfig6PrintIpAddr (
+ &IfCb->IfInfo->RouteTable[Index].Destination,
+ &IfCb->IfInfo->RouteTable[Index].PrefixLength
+ );
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_JOINT), gShellNetwork2HiiHandle);
+
+ IfConfig6PrintIpAddr (
+ &IfCb->IfInfo->RouteTable[Index].Gateway,
+ NULL
+ );
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle);
+ }
+
+ Entry = Entry->ForwardLink;
+ }
+
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_BREAK), gShellNetwork2HiiHandle);
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_INFO_NEWLINE), gShellNetwork2HiiHandle);
+
+ return SHELL_SUCCESS;
+}
+
+/**
+ The clean process of the IfConfig6 application.
+
+ @param[in] IfList The pointer of IfList(interface list).
+ @param[in] IfName The pointer of interface name.
+
+ @retval SHELL_SUCCESS The IfConfig6 clean processed successfully.
+ @retval others The IfConfig6 clean process failed.
+
+**/
+SHELL_STATUS
+IfConfig6ClearInterfaceInfo (
+ IN LIST_ENTRY *IfList,
+ IN CHAR16 *IfName
+ )
+{
+ EFI_STATUS Status;
+ SHELL_STATUS ShellStatus;
+ LIST_ENTRY *Entry;
+ IFCONFIG6_INTERFACE_CB *IfCb;
+ EFI_IP6_CONFIG_POLICY Policy;
+
+ Entry = IfList->ForwardLink;
+ Status = EFI_SUCCESS;
+ ShellStatus = SHELL_SUCCESS;
+
+ if (IsListEmpty (IfList)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_INTERFACE), gShellNetwork2HiiHandle);
+ }
+
+ //
+ // Go through the interface list.If the interface name is specified, then
+ // need to refresh the configuration.
+ //
+ while (Entry != IfList) {
+
+ IfCb = BASE_CR (Entry, IFCONFIG6_INTERFACE_CB, Link);
+
+ if ((IfName != NULL) && (StrCmp (IfName, IfCb->IfInfo->Name) == 0)) {
+ Policy = Ip6ConfigPolicyManual;
+
+ Status = IfCb->IfCfg->SetData (
+ IfCb->IfCfg,
+ Ip6ConfigDataTypePolicy,
+ sizeof (EFI_IP6_CONFIG_POLICY),
+ &Policy
+ );
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork2HiiHandle, L"ifconfig6");
+ ShellStatus = SHELL_ACCESS_DENIED;
+ break;
+ }
+ }
+
+ Policy = Ip6ConfigPolicyAutomatic;
+
+ Status = IfCb->IfCfg->SetData (
+ IfCb->IfCfg,
+ Ip6ConfigDataTypePolicy,
+ sizeof (EFI_IP6_CONFIG_POLICY),
+ &Policy
+ );
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_ERR_AD), gShellNetwork2HiiHandle, L"ifconfig6");
+ ShellStatus = SHELL_ACCESS_DENIED;
+ break;
+ }
+
+ Entry = Entry->ForwardLink;
+ }
+
+ return ShellStatus;
+}
+
+/**
+ The set process of the IfConfig6 application.
+
+ @param[in] IfList The pointer of IfList(interface list).
+ @param[in] VarArg The pointer of ARG_LIST(Args with "-s" option).
+
+ @retval SHELL_SUCCESS The IfConfig6 set processed successfully.
+ @retval others The IfConfig6 set process failed.
+
+**/
+SHELL_STATUS
+IfConfig6SetInterfaceInfo (
+ IN LIST_ENTRY *IfList,
+ IN ARG_LIST *VarArg
+ )
+{
+ EFI_STATUS Status;
+ SHELL_STATUS ShellStatus;
+ IFCONFIG6_INTERFACE_CB *IfCb;
+ EFI_IP6_CONFIG_MANUAL_ADDRESS *CfgManAddr;
+ EFI_IPv6_ADDRESS *CfgAddr;
+ UINTN AddrSize;
+ EFI_IP6_CONFIG_INTERFACE_ID *InterfaceId;
+ UINT32 DadXmits;
+ UINT32 CurDadXmits;
+ UINTN CurDadXmitsLen;
+ EFI_IP6_CONFIG_POLICY Policy;
+
+ VAR_CHECK_CODE CheckCode;
+ EFI_EVENT TimeOutEvt;
+ EFI_EVENT MappedEvt;
+ BOOLEAN IsAddressOk;
+
+ UINTN DataSize;
+ UINT32 Index;
+ UINT32 Index2;
+ BOOLEAN IsAddressSet;
+ EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo;
+
+ CfgManAddr = NULL;
+ CfgAddr = NULL;
+ TimeOutEvt = NULL;
+ MappedEvt = NULL;
+ IfInfo = NULL;
+ InterfaceId = NULL;
+ CurDadXmits = 0;
+
+ if (IsListEmpty (IfList)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_INTERFACE), gShellNetwork2HiiHandle);
+ return SHELL_INVALID_PARAMETER;
+ }
+ //
+ // Make sure to set only one interface each time.
+ //
+ IfCb = BASE_CR (IfList->ForwardLink, IFCONFIG6_INTERFACE_CB, Link);
+ Status = EFI_SUCCESS;
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // Initialize check list mechanism.
+ //
+ CheckCode = IfConfig6RetriveCheckListByName(
+ NULL,
+ NULL,
+ TRUE
+ );
+
+ //
+ // Create events & timers for asynchronous settings.
+ //
+ Status = gBS->CreateEvent (
+ EVT_TIMER,
+ TPL_CALLBACK,
+ NULL,
+ NULL,
+ &TimeOutEvt
+ );
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ IfConfig6ManualAddressNotify,
+ &IsAddressOk,
+ &MappedEvt
+ );
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+ //
+ // Parse the setting variables.
+ //
+ while (VarArg != NULL) {
+ //
+ // Check invalid parameters (duplication & unknown & conflict).
+ //
+ CheckCode = IfConfig6RetriveCheckListByName(
+ mIfConfig6SetCheckList,
+ VarArg->Arg,
+ FALSE
+ );
+
+ if (VarCheckOk != CheckCode) {
+ switch (CheckCode) {
+ case VarCheckDuplicate:
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_DUPLICATE_COMMAND), gShellNetwork2HiiHandle, VarArg->Arg);
+ break;
+
+ case VarCheckConflict:
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_CONFLICT_COMMAND), gShellNetwork2HiiHandle, VarArg->Arg);
+ break;
+
+ case VarCheckUnknown:
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_UNKNOWN_COMMAND), gShellNetwork2HiiHandle, VarArg->Arg);
+ break;
+
+ default:
+ break;
+ }
+
+ VarArg = VarArg->Next;
+ continue;
+ }
+ //
+ // Process valid variables.
+ //
+ if (StrCmp(VarArg->Arg, L"auto") == 0) {
+ //
+ // Set automaic config policy
+ //
+ Policy = Ip6ConfigPolicyAutomatic;
+ Status = IfCb->IfCfg->SetData (
+ IfCb->IfCfg,
+ Ip6ConfigDataTypePolicy,
+ sizeof (EFI_IP6_CONFIG_POLICY),
+ &Policy
+ );
+
+ if (EFI_ERROR(Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ VarArg= VarArg->Next;
+
+ } else if (StrCmp (VarArg->Arg, L"man") == 0) {
+ //
+ // Set manual config policy.
+ //
+ Policy = Ip6ConfigPolicyManual;
+ Status = IfCb->IfCfg->SetData (
+ IfCb->IfCfg,
+ Ip6ConfigDataTypePolicy,
+ sizeof (EFI_IP6_CONFIG_POLICY),
+ &Policy
+ );
+
+ if (EFI_ERROR(Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ VarArg= VarArg->Next;
+
+ } else if (StrCmp (VarArg->Arg, L"host") == 0) {
+ //
+ // Parse till the next tag or the end of command line.
+ //
+ VarArg = VarArg->Next;
+ Status = IfConfig6ParseManualAddressList (
+ &VarArg,
+ &CfgManAddr,
+ &AddrSize
+ );
+
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_INVALID_PARAMETER) {
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_ARGUMENTS), gShellNetwork2HiiHandle, L"host");
+ continue;
+ } else {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+ }
+ //
+ // Set static host ip6 address list.
+ // This is a asynchronous process.
+ //
+ IsAddressOk = FALSE;
+
+ Status = IfCb->IfCfg->RegisterDataNotify (
+ IfCb->IfCfg,
+ Ip6ConfigDataTypeManualAddress,
+ MappedEvt
+ );
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ Status = IfCb->IfCfg->SetData (
+ IfCb->IfCfg,
+ Ip6ConfigDataTypeManualAddress,
+ AddrSize,
+ CfgManAddr
+ );
+
+ if (Status == EFI_NOT_READY) {
+ //
+ // Get current dad transmits count.
+ //
+ CurDadXmitsLen = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);
+ IfCb->IfCfg->GetData (
+ IfCb->IfCfg,
+ Ip6ConfigDataTypeDupAddrDetectTransmits,
+ &CurDadXmitsLen,
+ &CurDadXmits
+ );
+
+ gBS->SetTimer (TimeOutEvt, TimerRelative, 50000000 + 10000000 * CurDadXmits);
+
+ while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) {
+ if (IsAddressOk) {
+ Status = EFI_SUCCESS;
+ break;
+ }
+ }
+ }
+
+ IfCb->IfCfg->UnregisterDataNotify (
+ IfCb->IfCfg,
+ Ip6ConfigDataTypeManualAddress,
+ MappedEvt
+ );
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_MAN_HOST), gShellNetwork2HiiHandle, Status);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ //
+ // Check whether the address is set successfully.
+ //
+ DataSize = 0;
+
+ Status = IfCb->IfCfg->GetData (
+ IfCb->IfCfg,
+ Ip6ConfigDataTypeInterfaceInfo,
+ &DataSize,
+ NULL
+ );
+
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ IfInfo = AllocateZeroPool (DataSize);
+
+ if (IfInfo == NULL) {
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ Status = IfCb->IfCfg->GetData (
+ IfCb->IfCfg,
+ Ip6ConfigDataTypeInterfaceInfo,
+ &DataSize,
+ IfInfo
+ );
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ for ( Index = 0; Index < (UINTN) (AddrSize / sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS)); Index++) {
+ IsAddressSet = FALSE;
+ //
+ // By default, the prefix length 0 is regarded as 64.
+ //
+ if (CfgManAddr[Index].PrefixLength == 0) {
+ CfgManAddr[Index].PrefixLength = 64;
+ }
+
+ for (Index2 = 0; Index2 < IfInfo->AddressInfoCount; Index2++) {
+ if (EFI_IP6_EQUAL (&IfInfo->AddressInfo[Index2].Address, &CfgManAddr[Index].Address) &&
+ (IfInfo->AddressInfo[Index2].PrefixLength == CfgManAddr[Index].PrefixLength)) {
+ IsAddressSet = TRUE;
+ break;
+ }
+ }
+
+ if (!IsAddressSet) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_ADDRESS_FAILED), gShellNetwork2HiiHandle);
+ IfConfig6PrintIpAddr (
+ &CfgManAddr[Index].Address,
+ &CfgManAddr[Index].PrefixLength
+ );
+ }
+ }
+
+ } else if (StrCmp (VarArg->Arg, L"gw") == 0) {
+ //
+ // Parse till the next tag or the end of command line.
+ //
+ VarArg = VarArg->Next;
+ Status = IfConfig6ParseGwDnsAddressList (
+ &VarArg,
+ &CfgAddr,
+ &AddrSize
+ );
+
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_INVALID_PARAMETER) {
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_ARGUMENTS), gShellNetwork2HiiHandle, L"gw");
+ continue;
+ } else {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+ }
+ //
+ // Set static gateway ip6 address list.
+ //
+ Status = IfCb->IfCfg->SetData (
+ IfCb->IfCfg,
+ Ip6ConfigDataTypeGateway,
+ AddrSize,
+ CfgAddr
+ );
+
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ } else if (StrCmp (VarArg->Arg, L"dns") == 0) {
+ //
+ // Parse till the next tag or the end of command line.
+ //
+ VarArg = VarArg->Next;
+ Status = IfConfig6ParseGwDnsAddressList (
+ &VarArg,
+ &CfgAddr,
+ &AddrSize
+ );
+
+ if (EFI_ERROR (Status)) {
+ if (Status == EFI_INVALID_PARAMETER) {
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_ARGUMENTS), gShellNetwork2HiiHandle, L"dns");
+ continue;
+ } else {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+ }
+ //
+ // Set static DNS server ip6 address list.
+ //
+ Status = IfCb->IfCfg->SetData (
+ IfCb->IfCfg,
+ Ip6ConfigDataTypeDnsServer,
+ AddrSize,
+ CfgAddr
+ );
+
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ } else if (StrCmp (VarArg->Arg, L"id") == 0) {
+ //
+ // Parse till the next tag or the end of command line.
+ //
+ VarArg = VarArg->Next;
+ Status = IfConfig6ParseInterfaceId (&VarArg, &InterfaceId);
+
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+ //
+ // Set alternative interface id.
+ //
+ Status = IfCb->IfCfg->SetData (
+ IfCb->IfCfg,
+ Ip6ConfigDataTypeAltInterfaceId,
+ sizeof (EFI_IP6_CONFIG_INTERFACE_ID),
+ InterfaceId
+ );
+
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+
+ } else if (StrCmp (VarArg->Arg, L"dad") == 0) {
+ //
+ // Parse till the next tag or the end of command line.
+ //
+ VarArg = VarArg->Next;
+ Status = IfConfig6ParseDadXmits (&VarArg, &DadXmits);
+
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+ //
+ // Set dad transmits count.
+ //
+ Status = IfCb->IfCfg->SetData (
+ IfCb->IfCfg,
+ Ip6ConfigDataTypeDupAddrDetectTransmits,
+ sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS),
+ &DadXmits
+ );
+
+ if (EFI_ERROR(Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+ }
+ }
+
+ON_EXIT:
+
+ if (CfgManAddr != NULL) {
+ FreePool (CfgManAddr);
+ }
+
+ if (CfgAddr != NULL) {
+ FreePool (CfgAddr);
+ }
+
+ if (MappedEvt != NULL) {
+ gBS->CloseEvent (MappedEvt);
+ }
+
+ if (TimeOutEvt != NULL) {
+ gBS->CloseEvent (TimeOutEvt);
+ }
+
+ if (IfInfo != NULL) {
+ FreePool (IfInfo);
+ }
+
+ return ShellStatus;
+
+}
+
+/**
+ The IfConfig6 main process.
+
+ @param[in] Private The pointer of IFCONFIG6_PRIVATE_DATA.
+
+ @retval SHELL_SUCCESS IfConfig6 processed successfully.
+ @retval others The IfConfig6 process failed.
+
+**/
+SHELL_STATUS
+IfConfig6 (
+ IN IFCONFIG6_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status;
+ SHELL_STATUS ShellStatus;
+
+ ShellStatus = SHELL_SUCCESS;
+
+ //
+ // Get configure information of all interfaces.
+ //
+ Status = IfConfig6GetInterfaceInfo (
+ Private->ImageHandle,
+ Private->IfName,
+ &Private->IfList
+ );
+
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_NOT_FOUND;
+ goto ON_EXIT;
+ }
+
+ switch (Private->OpCode) {
+ case IfConfig6OpList:
+ ShellStatus = IfConfig6ShowInterfaceInfo (&Private->IfList);
+ break;
+
+ case IfConfig6OpClear:
+ ShellStatus = IfConfig6ClearInterfaceInfo (&Private->IfList, Private->IfName);
+ break;
+
+ case IfConfig6OpSet:
+ ShellStatus = IfConfig6SetInterfaceInfo (&Private->IfList, Private->VarArg);
+ break;
+
+ default:
+ ShellStatus = SHELL_UNSUPPORTED;
+ }
+
+ON_EXIT:
+
+ return ShellStatus;
+}
+
+/**
+ The IfConfig6 cleanup process, free the allocated memory.
+
+ @param[in] Private The pointer of IFCONFIG6_PRIVATE_DATA.
+
+**/
+VOID
+IfConfig6Cleanup (
+ IN IFCONFIG6_PRIVATE_DATA *Private
+ )
+{
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *NextEntry;
+ IFCONFIG6_INTERFACE_CB *IfCb;
+
+ ASSERT (Private != NULL);
+
+ //
+ // Clean the list which save the set config Args.
+ //
+ if (Private->VarArg != NULL) {
+ IfConfig6FreeArgList (Private->VarArg);
+ }
+
+ if (Private->IfName != NULL)
+ FreePool (Private->IfName);
+
+
+ //
+ // Clean the IFCONFIG6_INTERFACE_CB list.
+ //
+ Entry = Private->IfList.ForwardLink;
+ NextEntry = Entry->ForwardLink;
+
+ while (Entry != &Private->IfList) {
+
+ IfCb = BASE_CR (Entry, IFCONFIG6_INTERFACE_CB, Link);
+
+ RemoveEntryList (&IfCb->Link);
+
+ if (IfCb->IfId != NULL) {
+
+ FreePool (IfCb->IfId);
+ }
+
+ if (IfCb->IfInfo != NULL) {
+
+ FreePool (IfCb->IfInfo);
+ }
+
+ FreePool (IfCb);
+
+ Entry = NextEntry;
+ NextEntry = Entry->ForwardLink;
+ }
+
+ FreePool (Private);
+}
+
+/**
+ Function for 'ifconfig6' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+
+ @retval SHELL_SUCCESS ifconfig6 command processed successfully.
+ @retval others The ifconfig6 command process failed.
+
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunIfconfig6 (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ SHELL_STATUS ShellStatus;
+ IFCONFIG6_PRIVATE_DATA *Private;
+ LIST_ENTRY *ParamPackage;
+ CONST CHAR16 *ValueStr;
+ ARG_LIST *ArgList;
+ CHAR16 *ProblemParam;
+ CHAR16 *Str;
+
+ Private = NULL;
+ Status = EFI_INVALID_PARAMETER;
+ ShellStatus = SHELL_SUCCESS;
+
+ Status = ShellCommandLineParseEx (mIfConfig6CheckList, &ParamPackage, &ProblemParam, TRUE, FALSE);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_INVALID_COMMAND), gShellNetwork2HiiHandle, L"ifconfig6", ProblemParam);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ //
+ // To handle no option.
+ //
+ if (!ShellCommandLineGetFlag (ParamPackage, L"-r") && !ShellCommandLineGetFlag (ParamPackage, L"-s") &&
+ !ShellCommandLineGetFlag (ParamPackage, L"-?") && !ShellCommandLineGetFlag (ParamPackage, L"-l")) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_LACK_OPTION), gShellNetwork2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+ //
+ // To handle conflict options.
+ //
+ if (((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-s"))) ||
+ ((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-l"))) ||
+ ((ShellCommandLineGetFlag (ParamPackage, L"-r")) && (ShellCommandLineGetFlag (ParamPackage, L"-?"))) ||
+ ((ShellCommandLineGetFlag (ParamPackage, L"-s")) && (ShellCommandLineGetFlag (ParamPackage, L"-l"))) ||
+ ((ShellCommandLineGetFlag (ParamPackage, L"-s")) && (ShellCommandLineGetFlag (ParamPackage, L"-?"))) ||
+ ((ShellCommandLineGetFlag (ParamPackage, L"-l")) && (ShellCommandLineGetFlag (ParamPackage, L"-?")))) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_CONFLICT_OPTIONS), gShellNetwork2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ Private = AllocateZeroPool (sizeof (IFCONFIG6_PRIVATE_DATA));
+
+ if (Private == NULL) {
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ InitializeListHead (&Private->IfList);
+
+ //
+ // To get interface name for the list option.
+ //
+ if (ShellCommandLineGetFlag (ParamPackage, L"-l")) {
+ Private->OpCode = IfConfig6OpList;
+ ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l");
+ if (ValueStr != NULL) {
+ Str = AllocateCopyPool (StrSize (ValueStr), ValueStr);
+ if (Str == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork2HiiHandle, L"ifconfig6");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+ Private->IfName = Str;
+ }
+ }
+ //
+ // To get interface name for the clear option.
+ //
+ if (ShellCommandLineGetFlag (ParamPackage, L"-r")) {
+ Private->OpCode = IfConfig6OpClear;
+ ValueStr = ShellCommandLineGetValue (ParamPackage, L"-r");
+ if (ValueStr != NULL) {
+ Str = AllocateCopyPool (StrSize (ValueStr), ValueStr);
+ if (Str == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork2HiiHandle, L"ifconfig6");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+ Private->IfName = Str;
+ }
+ }
+ //
+ // To get interface name and corresponding Args for the set option.
+ //
+ if (ShellCommandLineGetFlag (ParamPackage, L"-s")) {
+
+ ValueStr = ShellCommandLineGetValue (ParamPackage, L"-s");
+ if (ValueStr == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_INTERFACE), gShellNetwork2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+ //
+ // To split the configuration into multi-section.
+ //
+ ArgList = IfConfig6SplitStrToList (ValueStr, L' ');
+ if (ArgList == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork2HiiHandle, L"ifconfig6");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ Private->OpCode = IfConfig6OpSet;
+ Private->IfName = ArgList->Arg;
+
+ Private->VarArg = ArgList->Next;
+
+ if (Private->IfName == NULL || Private->VarArg == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_IFCONFIG6_ERR_LACK_COMMAND), gShellNetwork2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+ }
+ //
+ // Main process of ifconfig6.
+ //
+ ShellStatus = IfConfig6 (Private);
+
+ON_EXIT:
+
+ ShellCommandLineFreeVarList (ParamPackage);
+ if (Private != NULL) {
+ IfConfig6Cleanup (Private);
+ }
+ return ShellStatus;
+
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ping6.c b/Core/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ping6.c
new file mode 100644
index 0000000000..90a2604388
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellNetwork2CommandsLib/Ping6.c
@@ -0,0 +1,1275 @@
+/** @file
+ The implementation for Ping6 application.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "UefiShellNetwork2CommandsLib.h"
+
+#define PING6_DEFAULT_TIMEOUT 5000
+#define PING6_MAX_SEND_NUMBER 10000
+#define PING6_MAX_BUFFER_SIZE 32768
+#define PING6_ONE_SECOND 10000000
+
+//
+// A similar amount of time that passes in femtoseconds
+// for each increment of TimerValue. It is for NT32 only.
+//
+#define NTTIMERPERIOD 358049
+
+#pragma pack(1)
+
+typedef struct _ICMP6_ECHO_REQUEST_REPLY {
+ UINT8 Type;
+ UINT8 Code;
+ UINT16 Checksum;
+ UINT16 Identifier;
+ UINT16 SequenceNum;
+ UINT64 TimeStamp;
+ UINT8 Data[1];
+} ICMP6_ECHO_REQUEST_REPLY;
+
+#pragma pack()
+
+typedef struct _PING6_ICMP6_TX_INFO {
+ LIST_ENTRY Link;
+ UINT16 SequenceNum;
+ UINT64 TimeStamp;
+ EFI_IP6_COMPLETION_TOKEN *Token;
+} PING6_ICMP6_TX_INFO;
+
+typedef struct _PING6_PRIVATE_DATA {
+ EFI_HANDLE ImageHandle;
+ EFI_HANDLE NicHandle;
+ EFI_HANDLE Ip6ChildHandle;
+ EFI_IP6_PROTOCOL *Ip6;
+ EFI_EVENT Timer;
+
+ EFI_STATUS Status;
+ LIST_ENTRY TxList;
+ EFI_IP6_COMPLETION_TOKEN RxToken;
+ UINT16 RxCount;
+ UINT16 TxCount;
+ UINT64 RttSum;
+ UINT64 RttMin;
+ UINT64 RttMax;
+ UINT32 SequenceNum;
+
+ EFI_IPv6_ADDRESS SrcAddress;
+ EFI_IPv6_ADDRESS DstAddress;
+ UINT32 SendNum;
+ UINT32 BufferSize;
+} PING6_PRIVATE_DATA;
+
+
+SHELL_PARAM_ITEM Ping6ParamList[] = {
+ {
+ L"-l",
+ TypeValue
+ },
+ {
+ L"-n",
+ TypeValue
+ },
+ {
+ L"-s",
+ TypeValue
+ },
+ {
+ L"-?",
+ TypeFlag
+ },
+ {
+ NULL,
+ TypeMax
+ },
+};
+
+//
+// Global Variables in Ping6 application.
+//
+CONST CHAR16 *mIp6DstString;
+CONST CHAR16 *mIp6SrcString;
+UINT64 mFrequency = 0;
+UINT64 mIp6CurrentTick = 0;
+EFI_CPU_ARCH_PROTOCOL *Cpu = NULL;
+
+
+
+/**
+ Reads and returns the current value of the Time.
+
+ @return The current tick value.
+
+**/
+UINT64
+Ping6ReadTime ()
+{
+ UINT64 TimerPeriod;
+ EFI_STATUS Status;
+
+ ASSERT (Cpu != NULL);
+
+ Status = Cpu->GetTimerValue (Cpu, 0, &mIp6CurrentTick, &TimerPeriod);
+ if (EFI_ERROR (Status)) {
+ //
+ // The WinntGetTimerValue will return EFI_UNSUPPORTED. Set the
+ // TimerPeriod by ourselves.
+ //
+ mIp6CurrentTick += 1000000;
+ }
+
+ return mIp6CurrentTick;
+}
+
+/**
+ Get and calculate the frequency in tick/ms.
+ The result is saved in the globle variable mFrequency
+
+ @retval EFI_SUCCESS Calculated the frequency successfully.
+ @retval Others Failed to calculate the frequency.
+
+**/
+EFI_STATUS
+Ping6GetFrequency (
+ VOID
+ )
+{
+ EFI_STATUS Status;
+ UINT64 CurrentTick;
+ UINT64 TimerPeriod;
+
+ Status = gBS->LocateProtocol (&gEfiCpuArchProtocolGuid, NULL, (VOID **) &Cpu);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = Cpu->GetTimerValue (Cpu, 0, &CurrentTick, &TimerPeriod);
+
+ if (EFI_ERROR (Status)) {
+ //
+ // For NT32 Simulator only. 358049 is a similar value to keep timer granularity.
+ // Set the timer period by ourselves.
+ //
+ TimerPeriod = (UINT64) NTTIMERPERIOD;
+ }
+ //
+ // The timer period is in femtosecond (1 femtosecond is 1e-15 second).
+ // So 1e+12 is divided by timer period to produce the freq in tick/ms.
+ //
+ mFrequency = DivU64x64Remainder (1000000000000ULL, TimerPeriod, NULL);
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Get and calculate the duration in ms.
+
+ @param[in] Begin The start point of time.
+ @param[in] End The end point of time.
+
+ @return The duration in ms.
+
+**/
+UINT64
+Ping6CalculateTick (
+ IN UINT64 Begin,
+ IN UINT64 End
+ )
+{
+ ASSERT (End > Begin);
+ return DivU64x64Remainder (End - Begin, mFrequency, NULL);
+}
+
+/**
+ Destroy IPING6_ICMP6_TX_INFO, and recollect the memory.
+
+ @param[in] TxInfo The pointer to PING6_ICMP6_TX_INFO.
+
+**/
+VOID
+Ping6DestroyTxInfo (
+ IN PING6_ICMP6_TX_INFO *TxInfo
+ )
+{
+ EFI_IP6_TRANSMIT_DATA *TxData;
+ EFI_IP6_FRAGMENT_DATA *FragData;
+ UINTN Index;
+
+ ASSERT (TxInfo != NULL);
+
+ if (TxInfo->Token != NULL) {
+
+ if (TxInfo->Token->Event != NULL) {
+ gBS->CloseEvent (TxInfo->Token->Event);
+ }
+
+ TxData = TxInfo->Token->Packet.TxData;
+ if (TxData != NULL) {
+
+ if (TxData->OverrideData != NULL) {
+ FreePool (TxData->OverrideData);
+ }
+
+ if (TxData->ExtHdrs != NULL) {
+ FreePool (TxData->ExtHdrs);
+ }
+
+ for (Index = 0; Index < TxData->FragmentCount; Index++) {
+ FragData = TxData->FragmentTable[Index].FragmentBuffer;
+ if (FragData != NULL) {
+ FreePool (FragData);
+ }
+ }
+ }
+
+ FreePool (TxInfo->Token);
+ }
+
+ FreePool (TxInfo);
+}
+
+/**
+ Match the request, and reply with SequenceNum/TimeStamp.
+
+ @param[in] Private The pointer to PING6_PRIVATE_DATA.
+ @param[in] Packet The pointer to ICMP6_ECHO_REQUEST_REPLY.
+
+ @retval EFI_SUCCESS The match is successful.
+ @retval EFI_NOT_FOUND The reply can't be matched with any request.
+
+**/
+EFI_STATUS
+Ping6OnMatchEchoReply (
+ IN PING6_PRIVATE_DATA *Private,
+ IN ICMP6_ECHO_REQUEST_REPLY *Packet
+ )
+{
+ PING6_ICMP6_TX_INFO *TxInfo;
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *NextEntry;
+
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) {
+ TxInfo = BASE_CR (Entry, PING6_ICMP6_TX_INFO, Link);
+
+ if ((TxInfo->SequenceNum == Packet->SequenceNum) && (TxInfo->TimeStamp == Packet->TimeStamp)) {
+ Private->RxCount++;
+ RemoveEntryList (&TxInfo->Link);
+ Ping6DestroyTxInfo (TxInfo);
+ return EFI_SUCCESS;
+ }
+ }
+
+ return EFI_NOT_FOUND;
+}
+
+/**
+ The original intention is to send a request.
+ Currently, the application retransmits an icmp6 echo request packet
+ per second in sendnumber times that is specified by the user.
+ Because nothing can be done here, all things move to the timer rountine.
+
+ @param[in] Event A EFI_EVENT type event.
+ @param[in] Context The pointer to Context.
+
+**/
+VOID
+EFIAPI
+Ping6OnEchoRequestSent6 (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+}
+
+/**
+ receive reply, match and print reply infomation.
+
+ @param[in] Event A EFI_EVENT type event.
+ @param[in] Context The pointer to context.
+
+**/
+VOID
+EFIAPI
+Ping6OnEchoReplyReceived6 (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ PING6_PRIVATE_DATA *Private;
+ EFI_IP6_COMPLETION_TOKEN *RxToken;
+ EFI_IP6_RECEIVE_DATA *RxData;
+ ICMP6_ECHO_REQUEST_REPLY *Reply;
+ UINT32 PayLoad;
+ UINT64 Rtt;
+ CHAR8 Near;
+
+ Private = (PING6_PRIVATE_DATA *) Context;
+
+ if (Private->Status == EFI_ABORTED) {
+ return;
+ }
+
+ RxToken = &Private->RxToken;
+ RxData = RxToken->Packet.RxData;
+ Reply = RxData->FragmentTable[0].FragmentBuffer;
+ PayLoad = RxData->DataLength;
+
+ if (RxData->Header->NextHeader != IP6_ICMP) {
+ goto ON_EXIT;
+ }
+
+ if (!IP6_IS_MULTICAST (&Private->DstAddress) &&
+ !EFI_IP6_EQUAL (&RxData->Header->SourceAddress, &Private->DstAddress)) {
+ goto ON_EXIT;
+ }
+
+ if ((Reply->Type != ICMP_V6_ECHO_REPLY) || (Reply->Code != 0)) {
+ goto ON_EXIT;
+ }
+
+ if (PayLoad != Private->BufferSize) {
+ goto ON_EXIT;
+ }
+ //
+ // Check whether the reply matches the sent request before.
+ //
+ Status = Ping6OnMatchEchoReply (Private, Reply);
+ if (EFI_ERROR(Status)) {
+ goto ON_EXIT;
+ }
+ //
+ // Display statistics on this icmp6 echo reply packet.
+ //
+ Rtt = Ping6CalculateTick (Reply->TimeStamp, Ping6ReadTime ());
+ if (Rtt != 0) {
+ Near = (CHAR8) '=';
+ } else {
+ Near = (CHAR8) '<';
+ }
+
+ Private->RttSum += Rtt;
+ Private->RttMin = Private->RttMin > Rtt ? Rtt : Private->RttMin;
+ Private->RttMax = Private->RttMax < Rtt ? Rtt : Private->RttMax;
+
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_PING6_REPLY_INFO),
+ gShellNetwork2HiiHandle,
+ PayLoad,
+ mIp6DstString,
+ Reply->SequenceNum,
+ RxData->Header->HopLimit,
+ Near,
+ Rtt
+ );
+
+ON_EXIT:
+
+ if (Private->RxCount < Private->SendNum) {
+ //
+ // Continue to receive icmp6 echo reply packets.
+ //
+ RxToken->Status = EFI_ABORTED;
+
+ Status = Private->Ip6->Receive (Private->Ip6, RxToken);
+
+ if (EFI_ERROR (Status)) {
+ Private->Status = EFI_ABORTED;
+ }
+ } else {
+ //
+ // All reply have already been received from the dest host.
+ //
+ Private->Status = EFI_SUCCESS;
+ }
+ //
+ // Singal to recycle the each rxdata here, not at the end of process.
+ //
+ gBS->SignalEvent (RxData->RecycleSignal);
+}
+
+/**
+ Initial EFI_IP6_COMPLETION_TOKEN.
+
+ @param[in] Private The pointer of PING6_PRIVATE_DATA.
+ @param[in] TimeStamp The TimeStamp of request.
+ @param[in] SequenceNum The SequenceNum of request.
+
+ @return The pointer of EFI_IP6_COMPLETION_TOKEN.
+
+**/
+EFI_IP6_COMPLETION_TOKEN *
+Ping6GenerateToken (
+ IN PING6_PRIVATE_DATA *Private,
+ IN UINT64 TimeStamp,
+ IN UINT16 SequenceNum
+ )
+{
+ EFI_STATUS Status;
+ EFI_IP6_COMPLETION_TOKEN *Token;
+ EFI_IP6_TRANSMIT_DATA *TxData;
+ ICMP6_ECHO_REQUEST_REPLY *Request;
+
+ Request = AllocateZeroPool (Private->BufferSize);
+
+ if (Request == NULL) {
+ return NULL;
+ }
+ //
+ // Assembly icmp6 echo request packet.
+ //
+ Request->Type = ICMP_V6_ECHO_REQUEST;
+ Request->Code = 0;
+ Request->SequenceNum = SequenceNum;
+ Request->TimeStamp = TimeStamp;
+ Request->Identifier = 0;
+ //
+ // Leave check sum to ip6 layer, since it has no idea of source address
+ // selection.
+ //
+ Request->Checksum = 0;
+
+ TxData = AllocateZeroPool (sizeof (EFI_IP6_TRANSMIT_DATA));
+
+ if (TxData == NULL) {
+ FreePool (Request);
+ return NULL;
+ }
+ //
+ // Assembly ipv6 token for transmit.
+ //
+ TxData->OverrideData = 0;
+ TxData->ExtHdrsLength = 0;
+ TxData->ExtHdrs = NULL;
+ TxData->DataLength = Private->BufferSize;
+ TxData->FragmentCount = 1;
+ TxData->FragmentTable[0].FragmentBuffer = (VOID *) Request;
+ TxData->FragmentTable[0].FragmentLength = Private->BufferSize;
+
+ Token = AllocateZeroPool (sizeof (EFI_IP6_COMPLETION_TOKEN));
+
+ if (Token == NULL) {
+ FreePool (Request);
+ FreePool (TxData);
+ return NULL;
+ }
+
+ Token->Status = EFI_ABORTED;
+ Token->Packet.TxData = TxData;
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ Ping6OnEchoRequestSent6,
+ Private,
+ &Token->Event
+ );
+
+ if (EFI_ERROR (Status)) {
+ FreePool (Request);
+ FreePool (TxData);
+ FreePool (Token);
+ return NULL;
+ }
+
+ return Token;
+}
+
+/**
+ Transmit the EFI_IP6_COMPLETION_TOKEN.
+
+ @param[in] Private The pointer of PING6_PRIVATE_DATA.
+
+ @retval EFI_SUCCESS Transmitted successfully.
+ @retval EFI_OUT_OF_RESOURCES No memory is available on the platform.
+ @retval others Transmitted unsuccessfully.
+
+**/
+EFI_STATUS
+Ping6SendEchoRequest (
+ IN PING6_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status;
+ PING6_ICMP6_TX_INFO *TxInfo;
+
+ TxInfo = AllocateZeroPool (sizeof (PING6_ICMP6_TX_INFO));
+
+ if (TxInfo == NULL) {
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ TxInfo->TimeStamp = Ping6ReadTime ();
+ TxInfo->SequenceNum = (UINT16) (Private->TxCount + 1);
+
+ TxInfo->Token = Ping6GenerateToken (
+ Private,
+ TxInfo->TimeStamp,
+ TxInfo->SequenceNum
+ );
+
+ if (TxInfo->Token == NULL) {
+ Ping6DestroyTxInfo (TxInfo);
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ Status = Private->Ip6->Transmit (Private->Ip6, TxInfo->Token);
+
+ if (EFI_ERROR (Status)) {
+ Ping6DestroyTxInfo (TxInfo);
+ return Status;
+ }
+
+ InsertTailList (&Private->TxList, &TxInfo->Link);
+ Private->TxCount++;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Place a completion token into the receive packet queue to receive the echo reply.
+
+ @param[in] Private The pointer of PING6_PRIVATE_DATA.
+
+ @retval EFI_SUCCESS Put the token into the receive packet queue successfully.
+ @retval others Put the token into the receive packet queue unsuccessfully.
+
+**/
+EFI_STATUS
+Ping6OnReceiveEchoReply (
+ IN PING6_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status;
+
+ ZeroMem (&Private->RxToken, sizeof (EFI_IP6_COMPLETION_TOKEN));
+
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ Ping6OnEchoReplyReceived6,
+ Private,
+ &Private->RxToken.Event
+ );
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Private->RxToken.Status = EFI_NOT_READY;
+
+ return Private->Ip6->Receive (Private->Ip6, &Private->RxToken);
+}
+
+/**
+ Remove the timeout request from the list.
+
+ @param[in] Event A EFI_EVENT type event.
+ @param[in] Context The pointer to Context.
+
+**/
+VOID
+EFIAPI
+Ping6OnTimerRoutine6 (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ EFI_STATUS Status;
+ PING6_PRIVATE_DATA *Private;
+ PING6_ICMP6_TX_INFO *TxInfo;
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *NextEntry;
+ UINT64 Time;
+
+ Private = (PING6_PRIVATE_DATA *) Context;
+
+ //
+ // Retransmit icmp6 echo request packets per second in sendnumber times.
+ //
+ if (Private->TxCount < Private->SendNum) {
+
+ Status = Ping6SendEchoRequest (Private);
+ if (Private->TxCount != 0){
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_SEND_REQUEST), gShellNetwork2HiiHandle, Private->TxCount + 1);
+ }
+ }
+ }
+ //
+ // Check whether any icmp6 echo request in the list timeout.
+ //
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) {
+ TxInfo = BASE_CR (Entry, PING6_ICMP6_TX_INFO, Link);
+ Time = Ping6CalculateTick (TxInfo->TimeStamp, Ping6ReadTime ());
+
+ //
+ // Remove the timeout echo request from txlist.
+ //
+ if (Time > PING6_DEFAULT_TIMEOUT) {
+
+ if (EFI_ERROR (TxInfo->Token->Status)) {
+ Private->Ip6->Cancel (Private->Ip6, TxInfo->Token);
+ }
+ //
+ // Remove the timeout icmp6 echo request from list.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_TIMEOUT), gShellNetwork2HiiHandle, TxInfo->SequenceNum);
+
+ RemoveEntryList (&TxInfo->Link);
+ Ping6DestroyTxInfo (TxInfo);
+
+ if (IsListEmpty (&Private->TxList) && (Private->TxCount == Private->SendNum)) {
+ //
+ // All the left icmp6 echo request in the list timeout.
+ //
+ Private->Status = EFI_TIMEOUT;
+ }
+ }
+ }
+}
+
+/**
+ Create a valid IP6 instance.
+
+ @param[in] Private The pointer of PING6_PRIVATE_DATA.
+
+ @retval EFI_SUCCESS Create a valid IP6 instance successfully.
+ @retval EFI_ABORTED Locate handle with ip6 service binding protocol unsuccessfully.
+ @retval EFI_INVALID_PARAMETER The source address is unspecified when the destination address is a link -ocal address.
+ @retval EFI_OUT_OF_RESOURCES No memory is available on the platform.
+ @retval EFI_NOT_FOUND The source address is not found.
+**/
+EFI_STATUS
+Ping6CreateIpInstance (
+ IN PING6_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status;
+ UINTN HandleIndex;
+ UINTN HandleNum;
+ EFI_HANDLE *HandleBuffer;
+ BOOLEAN UnspecifiedSrc;
+ BOOLEAN MediaPresent;
+ EFI_SERVICE_BINDING_PROTOCOL *Ip6Sb;
+ EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg;
+ EFI_IP6_CONFIG_DATA Ip6Config;
+ EFI_IP6_CONFIG_INTERFACE_INFO *IfInfo;
+ UINTN IfInfoSize;
+ EFI_IPv6_ADDRESS *Addr;
+ UINTN AddrIndex;
+
+ HandleBuffer = NULL;
+ UnspecifiedSrc = FALSE;
+ MediaPresent = TRUE;
+ Ip6Sb = NULL;
+ IfInfo = NULL;
+ IfInfoSize = 0;
+
+ //
+ // Locate all the handles with ip6 service binding protocol.
+ //
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiIp6ServiceBindingProtocolGuid,
+ NULL,
+ &HandleNum,
+ &HandleBuffer
+ );
+ if (EFI_ERROR (Status) || (HandleNum == 0)) {
+ return EFI_ABORTED;
+ }
+
+ if (NetIp6IsUnspecifiedAddr (&Private->SrcAddress)) {
+ //
+ // SrcAddress is unspecified. So, both connected and configured interface will be automatic selected.
+ //
+ UnspecifiedSrc = TRUE;
+ }
+
+ //
+ // Source address is required when pinging a link-local address.
+ //
+ if (NetIp6IsLinkLocalAddr (&Private->DstAddress) && UnspecifiedSrc) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_SOURCE), gShellNetwork2HiiHandle);
+ Status = EFI_INVALID_PARAMETER;
+ goto ON_ERROR;
+ }
+
+ //
+ // For each ip6 protocol, check interface addresses list.
+ //
+ for (HandleIndex = 0; HandleIndex < HandleNum; HandleIndex++) {
+
+ Ip6Sb = NULL;
+ IfInfo = NULL;
+ IfInfoSize = 0;
+
+ if (UnspecifiedSrc) {
+ //
+ // Check media.
+ //
+ NetLibDetectMedia (HandleBuffer[HandleIndex], &MediaPresent);
+ if (!MediaPresent) {
+ //
+ // Skip this one.
+ //
+ continue;
+ }
+ }
+
+ Status = gBS->HandleProtocol (
+ HandleBuffer[HandleIndex],
+ &gEfiIp6ServiceBindingProtocolGuid,
+ (VOID **) &Ip6Sb
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ //
+ // Ip6config protocol and ip6 service binding protocol are installed
+ // on the same handle.
+ //
+ Status = gBS->HandleProtocol (
+ HandleBuffer[HandleIndex],
+ &gEfiIp6ConfigProtocolGuid,
+ (VOID **) &Ip6Cfg
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+ //
+ // Get the interface information size.
+ //
+ Status = Ip6Cfg->GetData (
+ Ip6Cfg,
+ Ip6ConfigDataTypeInterfaceInfo,
+ &IfInfoSize,
+ NULL
+ );
+
+ if (Status != EFI_BUFFER_TOO_SMALL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
+ goto ON_ERROR;
+ }
+
+ IfInfo = AllocateZeroPool (IfInfoSize);
+
+ if (IfInfo == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto ON_ERROR;
+ }
+ //
+ // Get the interface info.
+ //
+ Status = Ip6Cfg->GetData (
+ Ip6Cfg,
+ Ip6ConfigDataTypeInterfaceInfo,
+ &IfInfoSize,
+ IfInfo
+ );
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6CFG_GETDATA), gShellNetwork2HiiHandle, Status);
+ goto ON_ERROR;
+ }
+ //
+ // Check whether the source address is one of the interface addresses.
+ //
+ for (AddrIndex = 0; AddrIndex < IfInfo->AddressInfoCount; AddrIndex++) {
+ Addr = &(IfInfo->AddressInfo[AddrIndex].Address);
+
+ if (UnspecifiedSrc) {
+ if (!NetIp6IsUnspecifiedAddr (Addr) && !NetIp6IsLinkLocalAddr (Addr)) {
+ //
+ // Select the interface automatically.
+ //
+ CopyMem(&Private->SrcAddress, Addr, sizeof(Private->SrcAddress));
+ break;
+ }
+ } else if (EFI_IP6_EQUAL (&Private->SrcAddress, Addr)) {
+ //
+ // Match a certain interface address.
+ //
+ break;
+ }
+ }
+
+ if (AddrIndex < IfInfo->AddressInfoCount) {
+ //
+ // Found a nic handle with right interface address.
+ //
+ break;
+ }
+
+ FreePool (IfInfo);
+ IfInfo = NULL;
+ }
+ //
+ // No exact interface address matched.
+ //
+
+ if (HandleIndex == HandleNum) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_CONFIGD_NIC_NF), gShellNetwork2HiiHandle);
+ Status = EFI_NOT_FOUND;
+ goto ON_ERROR;
+ }
+
+ Private->NicHandle = HandleBuffer[HandleIndex];
+
+ ASSERT (Ip6Sb != NULL);
+ Status = Ip6Sb->CreateChild (Ip6Sb, &Private->Ip6ChildHandle);
+
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ Status = gBS->OpenProtocol (
+ Private->Ip6ChildHandle,
+ &gEfiIp6ProtocolGuid,
+ (VOID **) &Private->Ip6,
+ Private->ImageHandle,
+ Private->Ip6ChildHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ goto ON_ERROR;
+ }
+
+ ZeroMem (&Ip6Config, sizeof (EFI_IP6_CONFIG_DATA));
+
+ //
+ // Configure the ip6 instance for icmp6 packet exchange.
+ //
+ Ip6Config.DefaultProtocol = 58;
+ Ip6Config.AcceptAnyProtocol = FALSE;
+ Ip6Config.AcceptIcmpErrors = TRUE;
+ Ip6Config.AcceptPromiscuous = FALSE;
+ Ip6Config.TrafficClass = 0;
+ Ip6Config.HopLimit = 128;
+ Ip6Config.FlowLabel = 0;
+ Ip6Config.ReceiveTimeout = 0;
+ Ip6Config.TransmitTimeout = 0;
+
+ IP6_COPY_ADDRESS (&Ip6Config.StationAddress, &Private->SrcAddress);
+
+ IP6_COPY_ADDRESS (&Ip6Config.DestinationAddress, &Private->DstAddress);
+
+ Status = Private->Ip6->Configure (Private->Ip6, &Ip6Config);
+
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_IP6_CONFIG), gShellNetwork2HiiHandle, Status);
+ goto ON_ERROR;
+ }
+
+ return EFI_SUCCESS;
+
+ON_ERROR:
+ if (HandleBuffer != NULL) {
+ FreePool (HandleBuffer);
+ }
+
+ if (IfInfo != NULL) {
+ FreePool (IfInfo);
+ }
+
+ if ((Ip6Sb != NULL) && (Private->Ip6ChildHandle != NULL)) {
+ Ip6Sb->DestroyChild (Ip6Sb, Private->Ip6ChildHandle);
+ }
+
+ return Status;
+}
+
+/**
+ Destroy the IP6 instance.
+
+ @param[in] Private The pointer of PING6_PRIVATE_DATA.
+
+**/
+VOID
+Ping6DestroyIpInstance (
+ IN PING6_PRIVATE_DATA *Private
+ )
+{
+ EFI_STATUS Status;
+ EFI_SERVICE_BINDING_PROTOCOL *Ip6Sb;
+
+ gBS->CloseProtocol (
+ Private->Ip6ChildHandle,
+ &gEfiIp6ProtocolGuid,
+ Private->ImageHandle,
+ Private->Ip6ChildHandle
+ );
+
+ Status = gBS->HandleProtocol (
+ Private->NicHandle,
+ &gEfiIp6ServiceBindingProtocolGuid,
+ (VOID **) &Ip6Sb
+ );
+
+ if (!EFI_ERROR(Status)) {
+ Ip6Sb->DestroyChild (Ip6Sb, Private->Ip6ChildHandle);
+ }
+}
+
+/**
+ The Ping6 Process.
+
+ @param[in] ImageHandle The firmware allocated handle for the UEFI image.
+ @param[in] SendNumber The send request count.
+ @param[in] BufferSize The send buffer size.
+ @param[in] SrcAddress The source IPv6 address.
+ @param[in] DstAddress The destination IPv6 address.
+
+ @retval SHELL_SUCCESS The ping6 processed successfullly.
+ @retval others The ping6 processed unsuccessfully.
+
+**/
+SHELL_STATUS
+ShellPing6 (
+ IN EFI_HANDLE ImageHandle,
+ IN UINT32 SendNumber,
+ IN UINT32 BufferSize,
+ IN EFI_IPv6_ADDRESS *SrcAddress,
+ IN EFI_IPv6_ADDRESS *DstAddress
+ )
+{
+ EFI_STATUS Status;
+ EFI_INPUT_KEY Key;
+ PING6_PRIVATE_DATA *Private;
+ PING6_ICMP6_TX_INFO *TxInfo;
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *NextEntry;
+ SHELL_STATUS ShellStatus;
+
+ ShellStatus = SHELL_SUCCESS;
+ Private = AllocateZeroPool (sizeof (PING6_PRIVATE_DATA));
+
+ if (Private == NULL) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_GEN_OUT_MEM), gShellNetwork2HiiHandle, L"Ping6");
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ goto ON_EXIT;
+ }
+
+ Private->ImageHandle = ImageHandle;
+ Private->SendNum = SendNumber;
+ Private->BufferSize = BufferSize;
+ Private->RttMin = ~((UINT64 )(0x0));
+ Private->Status = EFI_NOT_READY;
+
+ InitializeListHead (&Private->TxList);
+
+ IP6_COPY_ADDRESS (&Private->SrcAddress, SrcAddress);
+ IP6_COPY_ADDRESS (&Private->DstAddress, DstAddress);
+
+ //
+ // Open and configure a ip6 instance for ping6.
+ //
+ Status = Ping6CreateIpInstance (Private);
+
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+ //
+ // Print the command line itself.
+ //
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_START), gShellNetwork2HiiHandle, mIp6DstString, Private->BufferSize);
+ //
+ // Create a ipv6 token to receive the first icmp6 echo reply packet.
+ //
+ Status = Ping6OnReceiveEchoReply (Private);
+
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+ //
+ // Create and start timer to send icmp6 echo request packet per second.
+ //
+ Status = gBS->CreateEvent (
+ EVT_TIMER | EVT_NOTIFY_SIGNAL,
+ TPL_CALLBACK,
+ Ping6OnTimerRoutine6,
+ Private,
+ &Private->Timer
+ );
+
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+ //
+ // Create a ipv6 token to send the first icmp6 echo request packet.
+ //
+ Status = Ping6SendEchoRequest (Private);
+ //
+ // EFI_NOT_READY for IPsec is enable and IKE is not established.
+ //
+ if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ if(Status == EFI_NOT_FOUND) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_NOSOURCE_INDOMAIN), gShellNetwork2HiiHandle, mIp6DstString);
+ }
+
+ goto ON_EXIT;
+ }
+
+ Status = gBS->SetTimer (
+ Private->Timer,
+ TimerPeriodic,
+ PING6_ONE_SECOND
+ );
+
+ if (EFI_ERROR (Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+ //
+ // Control the ping6 process by two factors:
+ // 1. Hot key
+ // 2. Private->Status
+ // 2.1. success means all icmp6 echo request packets get reply packets.
+ // 2.2. timeout means the last icmp6 echo reply request timeout to get reply.
+ // 2.3. noready means ping6 process is on-the-go.
+ //
+ while (Private->Status == EFI_NOT_READY) {
+ Private->Ip6->Poll (Private->Ip6);
+
+ //
+ // Terminate the ping6 process by 'esc' or 'ctl-c'.
+ //
+ Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
+
+ if (!EFI_ERROR(Status)) {
+ if ((Key.UnicodeChar == 0x1b) || (Key.UnicodeChar == 0x03) ||
+ ((Key.UnicodeChar == 0) && (Key.ScanCode == SCAN_ESC))) {
+ goto ON_STAT;
+ }
+ }
+ }
+
+ON_STAT:
+ //
+ // Display the statistics in all.
+ //
+ gBS->SetTimer (Private->Timer, TimerCancel, 0);
+
+ if (Private->TxCount != 0) {
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_PING6_STAT),
+ gShellNetwork2HiiHandle,
+ Private->TxCount,
+ Private->RxCount,
+ (100 * (Private->TxCount - Private->RxCount)) / Private->TxCount,
+ Private->RttSum
+ );
+ }
+
+ if (Private->RxCount != 0) {
+ ShellPrintHiiEx (
+ -1,
+ -1,
+ NULL,
+ STRING_TOKEN (STR_PING6_RTT),
+ gShellNetwork2HiiHandle,
+ Private->RttMin,
+ Private->RttMax,
+ DivU64x64Remainder (Private->RttSum, Private->RxCount, NULL)
+ );
+ }
+
+ON_EXIT:
+
+ if (Private != NULL) {
+ Private->Status = EFI_ABORTED;
+
+ NET_LIST_FOR_EACH_SAFE (Entry, NextEntry, &Private->TxList) {
+ TxInfo = BASE_CR (Entry, PING6_ICMP6_TX_INFO, Link);
+
+ Status = Private->Ip6->Cancel (Private->Ip6, TxInfo->Token);
+
+ RemoveEntryList (&TxInfo->Link);
+ Ping6DestroyTxInfo (TxInfo);
+ }
+
+ if (Private->Timer != NULL) {
+ gBS->CloseEvent (Private->Timer);
+ }
+
+ if (Private->Ip6 != NULL) {
+ Status = Private->Ip6->Cancel (Private->Ip6, &Private->RxToken);
+ }
+
+ if (Private->RxToken.Event != NULL) {
+ gBS->CloseEvent (Private->RxToken.Event);
+ }
+
+ if (Private->Ip6ChildHandle != NULL) {
+ Ping6DestroyIpInstance (Private);
+ }
+
+ FreePool (Private);
+ }
+
+ return ShellStatus;
+}
+
+/**
+ Function for 'ping6' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+
+ @retval SHELL_SUCCESS The ping6 processed successfullly.
+ @retval others The ping6 processed unsuccessfully.
+
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunPing6 (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ EFI_STATUS Status;
+ SHELL_STATUS ShellStatus;
+ EFI_IPv6_ADDRESS DstAddress;
+ EFI_IPv6_ADDRESS SrcAddress;
+ UINT64 BufferSize;
+ UINTN SendNumber;
+ LIST_ENTRY *ParamPackage;
+ CONST CHAR16 *ValueStr;
+ CONST CHAR16 *ValueStrPtr;
+ UINTN NonOptionCount;
+ CHAR16 *ProblemParam;
+
+ ProblemParam = NULL;
+ ShellStatus = SHELL_SUCCESS;
+
+ Status = ShellCommandLineParseEx (Ping6ParamList, &ParamPackage, &ProblemParam, TRUE, FALSE);
+ if (EFI_ERROR(Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_INPUT), gShellNetwork2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+
+ SendNumber = 10;
+ BufferSize = 16;
+
+ //
+ // Parse the paramter of count number.
+ //
+ ValueStr = ShellCommandLineGetValue (ParamPackage, L"-n");
+ ValueStrPtr = ValueStr;
+ if (ValueStr != NULL) {
+ SendNumber = ShellStrToUintn (ValueStrPtr);
+
+ //
+ // ShellStrToUintn will return 0 when input is 0 or an invalid input string.
+ //
+ if ((SendNumber == 0) || (SendNumber > PING6_MAX_SEND_NUMBER)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_SEND_NUMBER), gShellNetwork2HiiHandle, ValueStr);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+ }
+ //
+ // Parse the paramter of buffer size.
+ //
+ ValueStr = ShellCommandLineGetValue (ParamPackage, L"-l");
+ ValueStrPtr = ValueStr;
+ if (ValueStr != NULL) {
+ BufferSize = ShellStrToUintn (ValueStrPtr);
+
+ //
+ // ShellStrToUintn will return 0 when input is 0 or an invalid input string.
+ //
+ if ((BufferSize < 16) || (BufferSize > PING6_MAX_BUFFER_SIZE)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_BUFFER_SIZE), gShellNetwork2HiiHandle, ValueStr);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+ }
+
+ ZeroMem (&SrcAddress, sizeof (EFI_IPv6_ADDRESS));
+ ZeroMem (&DstAddress, sizeof (EFI_IPv6_ADDRESS));
+
+ //
+ // Parse the paramter of source ip address.
+ //
+ ValueStr = ShellCommandLineGetValue (ParamPackage, L"-s");
+ ValueStrPtr = ValueStr;
+ if (ValueStr != NULL) {
+ mIp6SrcString = ValueStr;
+ Status = NetLibStrToIp6 (ValueStrPtr, &SrcAddress);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_IP), gShellNetwork2HiiHandle, ValueStr);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+ }
+ //
+ // Parse the paramter of destination ip address.
+ //
+ NonOptionCount = ShellCommandLineGetCount(ParamPackage);
+ ValueStr = ShellCommandLineGetRawValue (ParamPackage, (UINT32)(NonOptionCount-1));
+ if (NonOptionCount != 2) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_INPUT), gShellNetwork2HiiHandle);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+ ValueStrPtr = ValueStr;
+ if (ValueStr != NULL) {
+ mIp6DstString = ValueStr;
+ Status = NetLibStrToIp6 (ValueStrPtr, &DstAddress);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (-1, -1, NULL, STRING_TOKEN (STR_PING6_INVALID_IP), gShellNetwork2HiiHandle, ValueStr);
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ goto ON_EXIT;
+ }
+ }
+ //
+ // Get frequency to calculate the time from ticks.
+ //
+ Status = Ping6GetFrequency ();
+
+ if (EFI_ERROR(Status)) {
+ ShellStatus = SHELL_ACCESS_DENIED;
+ goto ON_EXIT;
+ }
+ //
+ // Enter into ping6 process.
+ //
+ ShellStatus = ShellPing6 (
+ ImageHandle,
+ (UINT32)SendNumber,
+ (UINT32)BufferSize,
+ &SrcAddress,
+ &DstAddress
+ );
+
+ON_EXIT:
+ ShellCommandLineFreeVarList (ParamPackage);
+ return ShellStatus;
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.c b/Core/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.c
new file mode 100644
index 0000000000..6837b3a7d3
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.c
@@ -0,0 +1,91 @@
+/** @file
+ Main file for NULL named library for network2 shell command functions.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials are licensed and made available under
+ the terms and conditions of the BSD License which accompanies this distribution.
+ The full text of the license may be found at http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "UefiShellNetwork2CommandsLib.h"
+
+CONST CHAR16 gShellNetwork2FileName[] = L"ShellCommands";
+EFI_HANDLE gShellNetwork2HiiHandle = NULL;
+
+/**
+ return the file name of the help text file if not using HII.
+
+ @return The string pointer to the file name.
+**/
+CONST CHAR16*
+EFIAPI
+ShellCommandGetManFileNameNetwork2 (
+ VOID
+ )
+{
+ return (gShellNetwork2FileName);
+}
+
+/**
+ Constructor for the Shell Network2 Commands library.
+
+ Install the handlers for Network2 UEFI Shell 2.0 profile commands.
+
+ @param ImageHandle The image handle of the process.
+ @param SystemTable The EFI System Table pointer.
+
+ @retval EFI_SUCCESS The shell command handlers were installed sucessfully.
+ @retval EFI_UNSUPPORTED The shell level required was not found.
+**/
+EFI_STATUS
+EFIAPI
+ShellNetwork2CommandsLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ gShellNetwork2HiiHandle = NULL;
+
+ //
+ // check our bit of the profiles mask
+ //
+ if ((PcdGet8(PcdShellProfileMask) & BIT4) == 0) {
+ return (EFI_SUCCESS);
+ }
+
+ gShellNetwork2HiiHandle = HiiAddPackages (&gShellNetwork2HiiGuid, gImageHandle, UefiShellNetwork2CommandsLibStrings, NULL);
+ if (gShellNetwork2HiiHandle == NULL) {
+ return (EFI_DEVICE_ERROR);
+ }
+ //
+ // install our shell command handlers
+ //
+ ShellCommandRegisterCommandName(L"ping6", ShellCommandRunPing6 , ShellCommandGetManFileNameNetwork2, 0, L"network2", TRUE , gShellNetwork2HiiHandle, STRING_TOKEN(STR_GET_HELP_PING6));
+ ShellCommandRegisterCommandName(L"ifconfig6",ShellCommandRunIfconfig6 , ShellCommandGetManFileNameNetwork2, 0, L"network2", TRUE , gShellNetwork2HiiHandle, STRING_TOKEN(STR_GET_HELP_IFCONFIG6));
+
+ return EFI_SUCCESS;
+
+}
+
+/**
+ Destructor for the library. free any resources.
+
+ @param ImageHandle The image handle of the process.
+ @param SystemTable The EFI System Table pointer.
+**/
+EFI_STATUS
+EFIAPI
+ShellNetwork2CommandsLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ if (gShellNetwork2HiiHandle != NULL) {
+ HiiRemovePackages(gShellNetwork2HiiHandle);
+ }
+ return EFI_SUCCESS;
+}
+
diff --git a/Core/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.h b/Core/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.h
new file mode 100644
index 0000000000..138cc8c8d4
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.h
@@ -0,0 +1,72 @@
+/** @file
+ Main file for NULL named library for network2 shell command functions.
+
+ Copyright (c) 2016, Intel Corporation. All rights reserved. <BR>
+ This program and the accompanying materials are licensed and made available under
+ the terms and conditions of the BSD License which accompanies this distribution.
+ The full text of the license may be found at http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _UEFI_SHELL_NETWORK2_COMMANDS_LIB_H_
+#define _UEFI_SHELL_NETWORK2_COMMANDS_LIB_H_
+
+#include <Protocol/Cpu.h>
+#include <Protocol/ServiceBinding.h>
+#include <Protocol/Ip6.h>
+#include <Protocol/Ip6Config.h>
+
+#include <Guid/ShellLibHiiGuid.h>
+
+#include <Library/ShellLib.h>
+#include <Library/ShellCommandLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/BaseLib.h>
+#include <Library/PcdLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/DebugLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HiiLib.h>
+#include <Library/NetLib.h>
+
+extern EFI_HANDLE gShellNetwork2HiiHandle;
+
+/**
+ Function for 'ping6' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+
+ @retval SHELL_SUCCESS The ping6 processed successfullly.
+ @retval others The ping6 processed unsuccessfully.
+
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunPing6 (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+/**
+ Function for 'ifconfig6' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+
+ @retval SHELL_SUCCESS The ifconfig6 command processed successfully.
+ @retval others The ifconfig6 command process failed.
+
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunIfconfig6 (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+#endif
+
diff --git a/Core/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.inf b/Core/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.inf
new file mode 100644
index 0000000000..426efcc655
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.inf
@@ -0,0 +1,63 @@
+## @file
+# Provides shell network2 functions
+#
+# Copyright (c) 2016, Intel Corporation. All rights reserved. <BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = UefiShellNetwork2CommandsLib
+ FILE_GUID = D94E3B82-908E-46bf-A7B9-C7B7F17B1B7D
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER
+ CONSTRUCTOR = ShellNetwork2CommandsLibConstructor
+ DESTRUCTOR = ShellNetwork2CommandsLibDestructor
+
+[Sources.common]
+ UefiShellNetwork2CommandsLib.uni
+ UefiShellNetwork2CommandsLib.c
+ UefiShellNetwork2CommandsLib.h
+ Ping6.c
+ Ifconfig6.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ ShellCommandLib
+ ShellLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ PcdLib
+ HiiLib
+ FileHandleLib
+ NetLib
+
+[Pcd]
+ gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask ## CONSUMES
+
+[Protocols]
+ gEfiCpuArchProtocolGuid ## CONSUMES
+ gEfiIp6ProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiIp6ServiceBindingProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiIp6ConfigProtocolGuid ## SOMETIMES_CONSUMES
+
+[Guids]
+ gShellNetwork2HiiGuid ## SOMETIMES_CONSUMES ## HII
diff --git a/Core/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.uni b/Core/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.uni
new file mode 100644
index 0000000000..8f27e272d4
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.uni
@@ -0,0 +1,154 @@
+/** @file
+
+ String definitions for UEFI Shell network 2 commands
+ Copyright (c) 2016, Intel Corporation. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions
+ of the BSD License which accompanies this distribution. The full
+ text of the license may be found at<BR>
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+ Module Name:
+
+ UefiShellNetwork2CommandsLib.uni
+
+ Abstract:
+
+ String definitions for UEFI Shell 2.0 network 2 commands
+**/
+
+#langdef en-US "english"
+
+#string STR_GEN_ERR_AD #language en-US "%H%s%N: Access denied.\r\n"
+#string STR_GEN_OUT_MEM #language en-US "%H%s%N: Memory allocation was not successful.\r\n"
+
+#string STR_PING6_INVALID_IP #language en-US "%Ping6: Invalid IP6 address, %s\r\n"
+#string STR_PING6_INVALID_INPUT #language en-US "%Ping6: Invalid input, please type 'Ping6 -?'for help\r\n"
+#string STR_PING6_INVALID_SEND_NUMBER #language en-US "%Ping6: Invalid send number, %s\r\n"
+#string STR_PING6_INVALID_BUFFER_SIZE #language en-US "%Ping6: Invalid buffer size, %s\r\n"
+#string STR_PING6_INVALID_SOURCE #language en-US "%Ping6: Require source interface option\r\n"
+#string STR_PING6_IP6_CONFIG #language en-US "%Ping6: The process of Ip6 Configure %r\r\n"
+#string STR_PING6_IP6CFG_GETDATA #language en-US "%Ping6: Get data of the interface information %r\r\n"
+#string STR_PING6_SEND_REQUEST #language en-US "Echo request sequence %d fails.\r\n"
+#string STR_PING6_CONFIGD_NIC_NF #language en-US "%Ping6: No configured interfaces were found.\r\n"
+#string STR_PING6_NOSOURCE_INDOMAIN #language en-US "No sources in %s's multicast domain.\r\n"
+#string STR_PING6_START #language en-US "Ping %s %d data bytes\r\n"
+#string STR_PING6_TIMEOUT #language en-US "Echo request sequence %d timeout.\r\n"
+#string STR_PING6_REPLY_INFO #language en-US "%d bytes from %s : icmp_seq=%d ttl=%d time%c%dms\r\n"
+#string STR_PING6_STAT #language en-US "\n%d packets transmitted, %d received, %d%% packet loss, time %dms\r\n"
+#string STR_PING6_RTT #language en-US "\nRtt(round trip time) min=%dms max=%dms avg=%dms\r\n"
+
+#string STR_IFCONFIG6_ERR_IP6CFG_GETDATA #language en-US "Get data of the interface information %hr\r\n"
+#string STR_IFCONFIG6_INFO_BREAK #language en-US "-----------------------------------------------------------------"
+#string STR_IFCONFIG6_INFO_COLON #language en-US ":"
+#string STR_IFCONFIG6_INFO_JOINT #language en-US " >> "
+#string STR_IFCONFIG6_INFO_NEWLINE #language en-US "\r\n"
+#string STR_IFCONFIG6_INFO_IF_NAME #language en-US "\n%Hname : %s%N\r\n"
+#string STR_IFCONFIG6_INFO_POLICY_AUTO #language en-US "%Hpolicy : automatic%N\r\n"
+#string STR_IFCONFIG6_INFO_POLICY_MAN #language en-US "%Hpolicy : manual%N\r\n"
+#string STR_IFCONFIG6_INFO_DAD_TRANSMITS #language en-US "%Hdad xmits : %d%N\r\n"
+#string STR_IFCONFIG6_INFO_INTERFACE_ID_HEAD #language en-US "%Hinterface id : %N"
+#string STR_IFCONFIG6_INFO_MAC_ADDR_HEAD #language en-US "%Hmac addr : %N"
+#string STR_IFCONFIG6_INFO_MAC_ADDR_BODY #language en-US "%02x"
+#string STR_IFCONFIG6_INFO_IP_ADDR_HEAD #language en-US "\n%Hhost addr : %N\r\n"
+#string STR_IFCONFIG6_INFO_DNS_ADDR_HEAD #language en-US "\n%Hdns server : %N\r\n"
+#string STR_IFCONFIG6_INFO_IP_ADDR_BODY #language en-US "%02x"
+#string STR_IFCONFIG6_INFO_IP_ADDR_BODY4BIT #language en-US "%x"
+#string STR_IFCONFIG6_INFO_ROUTE_HEAD #language en-US "\n%Hroute table : %N\r\n"
+#string STR_IFCONFIG6_INFO_PREFIX_LEN #language en-US "/%d"
+#string STR_IFCONFIG6_LINE_HELP #language en-US "Displays or modifies the IPv6 configuration"
+#string STR_IFCONFIG6_ERR_LACK_INTERFACE #language en-US "Lack interface name.\r\n"
+ "Usage: IfConfig6 -s <Name> \r\n"
+ "Example: IfConfig6 -s eth0 auto\r\n"
+#string STR_IFCONFIG6_LACK_OPTION #language en-US "Flags lack. Please type 'IfConfig6 -?' for help info.\r\n"
+#string STR_IFCONFIG6_CONFLICT_OPTIONS #language en-US "Flags conflict. Please type 'IfConfig6 -?' for help info.\r\n"
+#string STR_IFCONFIG6_ERR_LACK_COMMAND #language en-US "Lack interface config option.\r\n"
+ "Hint: Please type 'IfConfig6 -?' for help info.\r\n"
+#string STR_IFCONFIG6_ERR_INVALID_INTERFACE #language en-US "Invalid interface name.\r\n"
+ "Hint: Use {IfConfig6 -l} to check existing interface names.\r\n"
+#string STR_IFCONFIG6_ERR_INVALID_COMMAND #language en-US "Invalid command. Bad command %H%s%N is skipped.\r\n"
+ "Hint: Incorrect option or arguments. Please type 'IfConfig6 -?' for help info.\r\n"
+#string STR_IFCONFIG6_ERR_LACK_ARGUMENTS #language en-US "Lack arguments. Bad command %H%s%N is skipped.\r\n"
+ "Hint: Please type 'IfConfig6 -?' for help info.\r\n"
+#string STR_IFCONFIG6_ERR_LACK_OPTION #language en-US "Lack options.\r\n"
+ "Hint: Please type 'IfConfig6 -?' for help info.\r\n"
+#string STR_IFCONFIG6_ERR_MAN_HOST #language en-US "Manual address configuration failed. Please retry.\r\n"
+#string STR_IFCONFIG6_ERR_DUPLICATE_COMMAND #language en-US "Duplicate commands. Bad command %H%s%N is skipped.\r\n"
+ "Hint: Please type 'IfConfig6 -?' for help info.\r\n"
+#string STR_IFCONFIG6_ERR_CONFLICT_COMMAND #language en-US "Conflict commands. Bad command %H%s%N is skipped.\r\n"
+ "Hint: Please type 'IfConfig6 -?' for help info.\r\n"
+#string STR_IFCONFIG6_ERR_UNKNOWN_COMMAND #language en-US "Unknown commands. Bad command %H%s%N is skipped.\r\n"
+ "Hint: Please type 'IfConfig6 -?' for help info.\r\n"
+#string STR_IFCONFIG6_ERR_ADDRESS_FAILED #language en-US "It failed to set .\r\n"
+
+
+#string STR_GET_HELP_PING6 #language en-US ""
+".TH ping6 0 "Ping a target machine with UEFI IPv6 network stack."\r\n"
+".SH NAME\r\n"
+"Ping a target machine with UEFI IPv6 network stack.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"Ping6 [-l size] [-n count] [-s SourceIp] TargetIp\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -l size Send buffer size, in bytes(default=16, min=16, max=32768).\r\n"
+" -n count Send request count, (default=10, min=1, max=10000).\r\n"
+" -s SourceIp Source IPv6 address.\r\n"
+" TargetIp Target IPv6 address.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"Examples:\r\n"
+" * To ping the target host by sending 5 request with 1000 bytes from 2002::1\r\n"
+" Shell:\> Ping6 -s 2002::1 2002::2 -l 1000 -n 5\r\n"
+" \r\n"
+" * To ping the target host with 1000 bytes\r\n"
+" Shell:\> Ping6 2002::2 -l 1000\r\n"
+
+#string STR_GET_HELP_IFCONFIG6 #language en-US ""
+".TH ifconfig6 0 "Displays or modifies IPv6 configuration for network interface."\r\n"
+".SH NAME\r\n"
+"Displays or modifies IPv6 configuration for network interface.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"IfConfig6 -r [Name] | -l [Name] \r\n"
+"IfConfig6 -s <Name> [dad <Num>] [auto | [man [id <mac>] [host <IPv6> gw <IPv6>]\r\n"
+" [dns <IPv6>]]]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" Name Adapter name, i.e., eth0\r\n"
+" -r [Name] Reconfigure all or specified interface, and set\r\n"
+" automatic policy. If specified interface is already\r\n"
+" set to automatic,then refresh the IPv6 configuration.\r\n"
+" -l [Name] List the configuration of the specified interface.\r\n"
+" -s <Name> dad <Num> Set dad transmits count of the specified interface.\r\n"
+" -s <Name> auto Set automatic policy of the specified interface.\r\n"
+" -s <Name> man id <Mac> Set alternative interface id of the specified \r\n"
+" interface. Must under manual policy.\r\n"
+" -s <Name> man host <IPv6> gw <IPv6>\r\n"
+" Set static host IP and gateway address of the\r\n"
+" specified interface. Must under manual policy.\r\n"
+" -s <Name> man dns <IPv6> Set DNS server IP addresses of the specified\r\n"
+" interface.Must under manual policy.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To list the configuration for the interface eth0:\r\n"
+" Shell:\> ifConfig6 -l eth0\r\n"
+" \r\n"
+" * To use automatic configuration to request the IPv6 address configuration\r\n"
+" dynamically for the interface eth0:\r\n"
+" Shell:\> ifconfig6 -s eth0 auto\r\n"
+" \r\n"
+" * To set the dad transmits count for eth0 under automatic policy:\r\n"
+" Shell:\> ifconfig6 -s eth0 auto dad 10\r\n"
+" \r\n"
+" * To set the alternative interface id of eth0 under manual policy:\r\n"
+" Shell:\> ifconfig6 -s eth0 man id ff:dd:aa:88:66:cc\r\n"
+" \r\n"
+" * To use the static IP6 addresses configuration for the interface eth0,\r\n"
+" and this configuration survives the network reload:\r\n"
+" Shell:\> ifconfig6 -s eth0 man host 2002::1/64 2002::2/64 gw 2002::3/64\r\n"
diff --git a/Core/ShellPkg/Library/UefiShellTftpCommandLib/Tftp.c b/Core/ShellPkg/Library/UefiShellTftpCommandLib/Tftp.c
new file mode 100644
index 0000000000..666ee9d8ea
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellTftpCommandLib/Tftp.c
@@ -0,0 +1,1051 @@
+/** @file
+ The implementation for the 'tftp' Shell command.
+
+ Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>
+ Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved. <BR>
+ (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php.
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+**/
+
+#include "UefiShellTftpCommandLib.h"
+
+#define IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH 32
+
+/*
+ Constant strings and definitions related to the message indicating the amount of
+ progress in the dowloading of a TFTP file.
+*/
+
+// Frame for the progression slider
+STATIC CONST CHAR16 mTftpProgressFrame[] = L"[ ]";
+
+// Number of steps in the progression slider
+#define TFTP_PROGRESS_SLIDER_STEPS ((sizeof (mTftpProgressFrame) / sizeof (CHAR16)) - 3)
+
+// Size in number of characters plus one (final zero) of the message to
+// indicate the progress of a TFTP download. The format is "[(progress slider:
+// 40 characters)] (nb of KBytes downloaded so far: 7 characters) Kb". There
+// are thus the number of characters in mTftpProgressFrame[] plus 11 characters
+// (2 // spaces, "Kb" and seven characters for the number of KBytes).
+#define TFTP_PROGRESS_MESSAGE_SIZE ((sizeof (mTftpProgressFrame) / sizeof (CHAR16)) + 12)
+
+// String to delete the TFTP progress message to be able to update it :
+// (TFTP_PROGRESS_MESSAGE_SIZE-1) '\b'
+STATIC CONST CHAR16 mTftpProgressDelete[] = L"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";
+
+/**
+ Check and convert the UINT16 option values of the 'tftp' command
+
+ @param[in] ValueStr Value as an Unicode encoded string
+ @param[out] Value UINT16 value
+
+ @return TRUE The value was returned.
+ @return FALSE A parsing error occured.
+**/
+STATIC
+BOOLEAN
+StringToUint16 (
+ IN CONST CHAR16 *ValueStr,
+ OUT UINT16 *Value
+ );
+
+/**
+ Get the name of the NIC.
+
+ @param[in] ControllerHandle The network physical device handle.
+ @param[in] NicNumber The network physical device number.
+ @param[out] NicName Address where to store the NIC name.
+ The memory area has to be at least
+ IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH
+ double byte wide.
+
+ @return EFI_SUCCESS The name of the NIC was returned.
+ @return Others The creation of the child for the Managed
+ Network Service failed or the opening of
+ the Managed Network Protocol failed or
+ the operational parameters for the
+ Managed Network Protocol could not be
+ read.
+**/
+STATIC
+EFI_STATUS
+GetNicName (
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NicNumber,
+ OUT CHAR16 *NicName
+ );
+
+/**
+ Create a child for the service identified by its service binding protocol GUID
+ and get from the child the interface of the protocol identified by its GUID.
+
+ @param[in] ControllerHandle Controller handle.
+ @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the
+ service to be created.
+ @param[in] ProtocolGuid GUID of the protocol to be open.
+ @param[out] ChildHandle Address where the handler of the
+ created child is returned. NULL is
+ returned in case of error.
+ @param[out] Interface Address where a pointer to the
+ protocol interface is returned in
+ case of success.
+
+ @return EFI_SUCCESS The child was created and the protocol opened.
+ @return Others Either the creation of the child or the opening
+ of the protocol failed.
+**/
+STATIC
+EFI_STATUS
+CreateServiceChildAndOpenProtocol (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_GUID *ServiceBindingProtocolGuid,
+ IN EFI_GUID *ProtocolGuid,
+ OUT EFI_HANDLE *ChildHandle,
+ OUT VOID **Interface
+ );
+
+/**
+ Close the protocol identified by its GUID on the child handle of the service
+ identified by its service binding protocol GUID, then destroy the child
+ handle.
+
+ @param[in] ControllerHandle Controller handle.
+ @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the
+ service to be destroyed.
+ @param[in] ProtocolGuid GUID of the protocol to be closed.
+ @param[in] ChildHandle Handle of the child to be destroyed.
+
+**/
+STATIC
+VOID
+CloseProtocolAndDestroyServiceChild (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_GUID *ServiceBindingProtocolGuid,
+ IN EFI_GUID *ProtocolGuid,
+ IN EFI_HANDLE ChildHandle
+ );
+
+/**
+ Worker function that gets the size in numbers of bytes of a file from a TFTP
+ server before to download the file.
+
+ @param[in] Mtftp4 MTFTP4 protocol interface
+ @param[in] FilePath Path of the file, ASCII encoded
+ @param[out] FileSize Address where to store the file size in number of
+ bytes.
+
+ @retval EFI_SUCCESS The size of the file was returned.
+ @retval EFI_UNSUPPORTED The server does not support the "tsize" option.
+ @retval Others Error when retrieving the information from the server
+ (see EFI_MTFTP4_PROTOCOL.GetInfo() status codes)
+ or error when parsing the response of the server.
+**/
+STATIC
+EFI_STATUS
+GetFileSize (
+ IN EFI_MTFTP4_PROTOCOL *Mtftp4,
+ IN CONST CHAR8 *FilePath,
+ OUT UINTN *FileSize
+ );
+
+/**
+ Worker function that download the data of a file from a TFTP server given
+ the path of the file and its size.
+
+ @param[in] Mtftp4 MTFTP4 protocol interface
+ @param[in] FilePath Path of the file, Unicode encoded
+ @param[in] AsciiFilePath Path of the file, ASCII encoded
+ @param[in] FileSize Size of the file in number of bytes
+ @param[in] BlockSize Value of the TFTP blksize option
+ @param[out] Data Address where to store the address of the buffer
+ where the data of the file were downloaded in
+ case of success.
+
+ @retval EFI_SUCCESS The file was downloaded.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval Others The downloading of the file from the server failed
+ (see EFI_MTFTP4_PROTOCOL.ReadFile() status codes).
+
+**/
+STATIC
+EFI_STATUS
+DownloadFile (
+ IN EFI_MTFTP4_PROTOCOL *Mtftp4,
+ IN CONST CHAR16 *FilePath,
+ IN CONST CHAR8 *AsciiFilePath,
+ IN UINTN FileSize,
+ IN UINT16 BlockSize,
+ OUT VOID **Data
+ );
+
+/**
+ Update the progress of a file download
+ This procedure is called each time a new TFTP packet is received.
+
+ @param[in] This MTFTP4 protocol interface
+ @param[in] Token Parameters for the download of the file
+ @param[in] PacketLen Length of the packet
+ @param[in] Packet Address of the packet
+
+ @retval EFI_SUCCESS All packets are accepted.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+CheckPacket (
+ IN EFI_MTFTP4_PROTOCOL *This,
+ IN EFI_MTFTP4_TOKEN *Token,
+ IN UINT16 PacketLen,
+ IN EFI_MTFTP4_PACKET *Packet
+ );
+
+EFI_MTFTP4_CONFIG_DATA DefaultMtftp4ConfigData = {
+ TRUE, // Use default setting
+ { { 0, 0, 0, 0 } }, // StationIp - Not relevant as UseDefaultSetting=TRUE
+ { { 0, 0, 0, 0 } }, // SubnetMask - Not relevant as UseDefaultSetting=TRUE
+ 0, // LocalPort - Automatically assigned port number.
+ { { 0, 0, 0, 0 } }, // GatewayIp - Not relevant as UseDefaultSetting=TRUE
+ { { 0, 0, 0, 0 } }, // ServerIp - Not known yet
+ 69, // InitialServerPort - Standard TFTP server port
+ 6, // TryCount - Max number of retransmissions.
+ 4 // TimeoutValue - Retransmission timeout in seconds.
+};
+
+STATIC CONST SHELL_PARAM_ITEM ParamList[] = {
+ {L"-i", TypeValue},
+ {L"-l", TypeValue},
+ {L"-r", TypeValue},
+ {L"-c", TypeValue},
+ {L"-t", TypeValue},
+ {L"-s", TypeValue},
+ {NULL , TypeMax}
+ };
+
+///
+/// The default block size (512) of tftp is defined in the RFC1350.
+///
+#define MTFTP_DEFAULT_BLKSIZE 512
+///
+/// The valid range of block size option is defined in the RFC2348.
+///
+#define MTFTP_MIN_BLKSIZE 8
+#define MTFTP_MAX_BLKSIZE 65464
+
+
+/**
+ Function for 'tftp' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+
+ @return SHELL_SUCCESS The 'tftp' command completed successfully.
+ @return SHELL_ABORTED The Shell Library initialization failed.
+ @return SHELL_INVALID_PARAMETER At least one of the command's arguments is
+ not valid.
+ @return SHELL_OUT_OF_RESOURCES A memory allocation failed.
+ @return SHELL_NOT_FOUND Network Interface Card not found or server
+ error or file error.
+
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunTftp (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ SHELL_STATUS ShellStatus;
+ EFI_STATUS Status;
+ LIST_ENTRY *CheckPackage;
+ CHAR16 *ProblemParam;
+ UINTN ParamCount;
+ CONST CHAR16 *UserNicName;
+ BOOLEAN NicFound;
+ CONST CHAR16 *ValueStr;
+ CONST CHAR16 *RemoteFilePath;
+ CHAR8 *AsciiRemoteFilePath;
+ UINTN FilePathSize;
+ CONST CHAR16 *Walker;
+ CONST CHAR16 *LocalFilePath;
+ EFI_MTFTP4_CONFIG_DATA Mtftp4ConfigData;
+ EFI_HANDLE *Handles;
+ UINTN HandleCount;
+ UINTN NicNumber;
+ CHAR16 NicName[IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH];
+ EFI_HANDLE ControllerHandle;
+ EFI_HANDLE Mtftp4ChildHandle;
+ EFI_MTFTP4_PROTOCOL *Mtftp4;
+ UINTN FileSize;
+ VOID *Data;
+ SHELL_FILE_HANDLE FileHandle;
+ UINT16 BlockSize;
+
+ ShellStatus = SHELL_INVALID_PARAMETER;
+ ProblemParam = NULL;
+ NicFound = FALSE;
+ AsciiRemoteFilePath = NULL;
+ Handles = NULL;
+ FileSize = 0;
+ BlockSize = MTFTP_DEFAULT_BLKSIZE;
+
+ //
+ // Initialize the Shell library (we must be in non-auto-init...)
+ //
+ Status = ShellInitialize ();
+ if (EFI_ERROR (Status)) {
+ ASSERT_EFI_ERROR (Status);
+ return SHELL_ABORTED;
+ }
+
+ //
+ // Parse the command line.
+ //
+ Status = ShellCommandLineParse (ParamList, &CheckPackage, &ProblemParam, TRUE);
+ if (EFI_ERROR (Status)) {
+ if ((Status == EFI_VOLUME_CORRUPTED) &&
+ (ProblemParam != NULL) ) {
+ ShellPrintHiiEx (
+ -1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), gShellTftpHiiHandle,
+ L"tftp", ProblemParam
+ );
+ FreePool (ProblemParam);
+ } else {
+ ASSERT (FALSE);
+ }
+ goto Error;
+ }
+
+ //
+ // Check the number of parameters
+ //
+ ParamCount = ShellCommandLineGetCount (CheckPackage);
+ if (ParamCount > 4) {
+ ShellPrintHiiEx (
+ -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY),
+ gShellTftpHiiHandle, L"tftp"
+ );
+ goto Error;
+ }
+ if (ParamCount < 3) {
+ ShellPrintHiiEx (
+ -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW),
+ gShellTftpHiiHandle, L"tftp"
+ );
+ goto Error;
+ }
+
+ Mtftp4ConfigData = DefaultMtftp4ConfigData;
+
+ //
+ // Check the host IPv4 address
+ //
+ ValueStr = ShellCommandLineGetRawValue (CheckPackage, 1);
+ Status = NetLibStrToIp4 (ValueStr, &Mtftp4ConfigData.ServerIp);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (
+ -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),
+ gShellTftpHiiHandle, L"tftp", ValueStr
+ );
+ goto Error;
+ }
+
+ RemoteFilePath = ShellCommandLineGetRawValue (CheckPackage, 2);
+ ASSERT(RemoteFilePath != NULL);
+ FilePathSize = StrLen (RemoteFilePath) + 1;
+ AsciiRemoteFilePath = AllocatePool (FilePathSize);
+ if (AsciiRemoteFilePath == NULL) {
+ ShellStatus = SHELL_OUT_OF_RESOURCES;
+ goto Error;
+ }
+ UnicodeStrToAsciiStrS (RemoteFilePath, AsciiRemoteFilePath, FilePathSize);
+
+ if (ParamCount == 4) {
+ LocalFilePath = ShellCommandLineGetRawValue (CheckPackage, 3);
+ } else {
+ Walker = RemoteFilePath + StrLen (RemoteFilePath);
+ while ((--Walker) >= RemoteFilePath) {
+ if ((*Walker == L'\\') ||
+ (*Walker == L'/' ) ) {
+ break;
+ }
+ }
+ LocalFilePath = Walker + 1;
+ }
+
+ //
+ // Get the name of the Network Interface Card to be used if any.
+ //
+ UserNicName = ShellCommandLineGetValue (CheckPackage, L"-i");
+
+ ValueStr = ShellCommandLineGetValue (CheckPackage, L"-l");
+ if (ValueStr != NULL) {
+ if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.LocalPort)) {
+ goto Error;
+ }
+ }
+
+ ValueStr = ShellCommandLineGetValue (CheckPackage, L"-r");
+ if (ValueStr != NULL) {
+ if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.InitialServerPort)) {
+ goto Error;
+ }
+ }
+
+ ValueStr = ShellCommandLineGetValue (CheckPackage, L"-c");
+ if (ValueStr != NULL) {
+ if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.TryCount)) {
+ goto Error;
+ }
+ }
+
+ ValueStr = ShellCommandLineGetValue (CheckPackage, L"-t");
+ if (ValueStr != NULL) {
+ if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.TimeoutValue)) {
+ goto Error;
+ }
+ if (Mtftp4ConfigData.TimeoutValue == 0) {
+ ShellPrintHiiEx (
+ -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),
+ gShellTftpHiiHandle, L"tftp", ValueStr
+ );
+ goto Error;
+ }
+ }
+
+ ValueStr = ShellCommandLineGetValue (CheckPackage, L"-s");
+ if (ValueStr != NULL) {
+ if (!StringToUint16 (ValueStr, &BlockSize)) {
+ goto Error;
+ }
+ if (BlockSize < MTFTP_MIN_BLKSIZE || BlockSize > MTFTP_MAX_BLKSIZE) {
+ ShellPrintHiiEx (
+ -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),
+ gShellTftpHiiHandle, L"tftp", ValueStr
+ );
+ goto Error;
+ }
+ }
+
+ //
+ // Locate all MTFTP4 Service Binding protocols
+ //
+ ShellStatus = SHELL_NOT_FOUND;
+ Status = gBS->LocateHandleBuffer (
+ ByProtocol,
+ &gEfiManagedNetworkServiceBindingProtocolGuid,
+ NULL,
+ &HandleCount,
+ &Handles
+ );
+ if (EFI_ERROR (Status) || (HandleCount == 0)) {
+ ShellPrintHiiEx (
+ -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NO_NIC),
+ gShellTftpHiiHandle
+ );
+ goto Error;
+ }
+
+ for (NicNumber = 0;
+ (NicNumber < HandleCount) && (ShellStatus != SHELL_SUCCESS);
+ NicNumber++) {
+ ControllerHandle = Handles[NicNumber];
+ Data = NULL;
+
+ Status = GetNicName (ControllerHandle, NicNumber, NicName);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (
+ -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NIC_NAME),
+ gShellTftpHiiHandle, NicNumber, Status
+ );
+ continue;
+ }
+
+ if (UserNicName != NULL) {
+ if (StrCmp (NicName, UserNicName) != 0) {
+ continue;
+ }
+ NicFound = TRUE;
+ }
+
+ Status = CreateServiceChildAndOpenProtocol (
+ ControllerHandle,
+ &gEfiMtftp4ServiceBindingProtocolGuid,
+ &gEfiMtftp4ProtocolGuid,
+ &Mtftp4ChildHandle,
+ (VOID**)&Mtftp4
+ );
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (
+ -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_OPEN_PROTOCOL),
+ gShellTftpHiiHandle, NicName, Status
+ );
+ continue;
+ }
+
+ Status = Mtftp4->Configure (Mtftp4, &Mtftp4ConfigData);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (
+ -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_CONFIGURE),
+ gShellTftpHiiHandle, NicName, Status
+ );
+ goto NextHandle;
+ }
+
+ Status = GetFileSize (Mtftp4, AsciiRemoteFilePath, &FileSize);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (
+ -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_FILE_SIZE),
+ gShellTftpHiiHandle, RemoteFilePath, NicName, Status
+ );
+ goto NextHandle;
+ }
+
+ Status = DownloadFile (Mtftp4, RemoteFilePath, AsciiRemoteFilePath, FileSize, BlockSize, &Data);
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (
+ -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_DOWNLOAD),
+ gShellTftpHiiHandle, RemoteFilePath, NicName, Status
+ );
+ goto NextHandle;
+ }
+
+ if (!EFI_ERROR (ShellFileExists (LocalFilePath))) {
+ ShellDeleteFileByName (LocalFilePath);
+ }
+
+ Status = ShellOpenFileByName (
+ LocalFilePath,
+ &FileHandle,
+ EFI_FILE_MODE_CREATE |
+ EFI_FILE_MODE_WRITE |
+ EFI_FILE_MODE_READ,
+ 0
+ );
+ if (EFI_ERROR (Status)) {
+ ShellPrintHiiEx (
+ -1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL),
+ gShellTftpHiiHandle, L"tftp", LocalFilePath
+ );
+ goto NextHandle;
+ }
+
+ Status = ShellWriteFile (FileHandle, &FileSize, Data);
+ if (!EFI_ERROR (Status)) {
+ ShellStatus = SHELL_SUCCESS;
+ } else {
+ ShellPrintHiiEx (
+ -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_WRITE),
+ gShellTftpHiiHandle, LocalFilePath, Status
+ );
+ }
+ ShellCloseFile (&FileHandle);
+
+ NextHandle:
+
+ if (Data != NULL) {
+ gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)Data, EFI_SIZE_TO_PAGES (FileSize));
+ }
+
+ CloseProtocolAndDestroyServiceChild (
+ ControllerHandle,
+ &gEfiMtftp4ServiceBindingProtocolGuid,
+ &gEfiMtftp4ProtocolGuid,
+ Mtftp4ChildHandle
+ );
+ }
+
+ if ((UserNicName != NULL) && (!NicFound)) {
+ ShellPrintHiiEx (
+ -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NIC_NOT_FOUND),
+ gShellTftpHiiHandle, UserNicName
+ );
+ }
+
+ Error:
+
+ ShellCommandLineFreeVarList (CheckPackage);
+ if (AsciiRemoteFilePath != NULL) {
+ FreePool (AsciiRemoteFilePath);
+ }
+ if (Handles != NULL) {
+ FreePool (Handles);
+ }
+
+ return ShellStatus;
+}
+
+/**
+ Check and convert the UINT16 option values of the 'tftp' command
+
+ @param[in] ValueStr Value as an Unicode encoded string
+ @param[out] Value UINT16 value
+
+ @return TRUE The value was returned.
+ @return FALSE A parsing error occured.
+**/
+STATIC
+BOOLEAN
+StringToUint16 (
+ IN CONST CHAR16 *ValueStr,
+ OUT UINT16 *Value
+ )
+{
+ UINTN Val;
+
+ Val = ShellStrToUintn (ValueStr);
+ if (Val > MAX_UINT16) {
+ ShellPrintHiiEx (
+ -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),
+ gShellTftpHiiHandle, L"tftp", ValueStr
+ );
+ return FALSE;
+ }
+
+ *Value = (UINT16)Val;
+ return TRUE;
+}
+
+/**
+ Get the name of the NIC.
+
+ @param[in] ControllerHandle The network physical device handle.
+ @param[in] NicNumber The network physical device number.
+ @param[out] NicName Address where to store the NIC name.
+ The memory area has to be at least
+ IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH
+ double byte wide.
+
+ @return EFI_SUCCESS The name of the NIC was returned.
+ @return Others The creation of the child for the Managed
+ Network Service failed or the opening of
+ the Managed Network Protocol failed or
+ the operational parameters for the
+ Managed Network Protocol could not be
+ read.
+**/
+STATIC
+EFI_STATUS
+GetNicName (
+ IN EFI_HANDLE ControllerHandle,
+ IN UINTN NicNumber,
+ OUT CHAR16 *NicName
+ )
+{
+ EFI_STATUS Status;
+ EFI_HANDLE MnpHandle;
+ EFI_MANAGED_NETWORK_PROTOCOL *Mnp;
+ EFI_SIMPLE_NETWORK_MODE SnpMode;
+
+ Status = CreateServiceChildAndOpenProtocol (
+ ControllerHandle,
+ &gEfiManagedNetworkServiceBindingProtocolGuid,
+ &gEfiManagedNetworkProtocolGuid,
+ &MnpHandle,
+ (VOID**)&Mnp
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ Status = Mnp->GetModeData (Mnp, NULL, &SnpMode);
+ if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {
+ goto Error;
+ }
+
+ UnicodeSPrint (
+ NicName,
+ IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH,
+ SnpMode.IfType == NET_IFTYPE_ETHERNET ?
+ L"eth%d" :
+ L"unk%d" ,
+ NicNumber
+ );
+
+ Status = EFI_SUCCESS;
+
+Error:
+
+ if (MnpHandle != NULL) {
+ CloseProtocolAndDestroyServiceChild (
+ ControllerHandle,
+ &gEfiManagedNetworkServiceBindingProtocolGuid,
+ &gEfiManagedNetworkProtocolGuid,
+ MnpHandle
+ );
+ }
+
+ return Status;
+}
+
+/**
+ Create a child for the service identified by its service binding protocol GUID
+ and get from the child the interface of the protocol identified by its GUID.
+
+ @param[in] ControllerHandle Controller handle.
+ @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the
+ service to be created.
+ @param[in] ProtocolGuid GUID of the protocol to be open.
+ @param[out] ChildHandle Address where the handler of the
+ created child is returned. NULL is
+ returned in case of error.
+ @param[out] Interface Address where a pointer to the
+ protocol interface is returned in
+ case of success.
+
+ @return EFI_SUCCESS The child was created and the protocol opened.
+ @return Others Either the creation of the child or the opening
+ of the protocol failed.
+**/
+STATIC
+EFI_STATUS
+CreateServiceChildAndOpenProtocol (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_GUID *ServiceBindingProtocolGuid,
+ IN EFI_GUID *ProtocolGuid,
+ OUT EFI_HANDLE *ChildHandle,
+ OUT VOID **Interface
+ )
+{
+ EFI_STATUS Status;
+
+ *ChildHandle = NULL;
+ Status = NetLibCreateServiceChild (
+ ControllerHandle,
+ gImageHandle,
+ ServiceBindingProtocolGuid,
+ ChildHandle
+ );
+ if (!EFI_ERROR (Status)) {
+ Status = gBS->OpenProtocol (
+ *ChildHandle,
+ ProtocolGuid,
+ Interface,
+ gImageHandle,
+ ControllerHandle,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ if (EFI_ERROR (Status)) {
+ NetLibDestroyServiceChild (
+ ControllerHandle,
+ gImageHandle,
+ ServiceBindingProtocolGuid,
+ *ChildHandle
+ );
+ *ChildHandle = NULL;
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Close the protocol identified by its GUID on the child handle of the service
+ identified by its service binding protocol GUID, then destroy the child
+ handle.
+
+ @param[in] ControllerHandle Controller handle.
+ @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the
+ service to be destroyed.
+ @param[in] ProtocolGuid GUID of the protocol to be closed.
+ @param[in] ChildHandle Handle of the child to be destroyed.
+
+**/
+STATIC
+VOID
+CloseProtocolAndDestroyServiceChild (
+ IN EFI_HANDLE ControllerHandle,
+ IN EFI_GUID *ServiceBindingProtocolGuid,
+ IN EFI_GUID *ProtocolGuid,
+ IN EFI_HANDLE ChildHandle
+ )
+{
+ gBS->CloseProtocol (
+ ChildHandle,
+ ProtocolGuid,
+ gImageHandle,
+ ControllerHandle
+ );
+
+ NetLibDestroyServiceChild (
+ ControllerHandle,
+ gImageHandle,
+ ServiceBindingProtocolGuid,
+ ChildHandle
+ );
+}
+
+/**
+ Worker function that gets the size in numbers of bytes of a file from a TFTP
+ server before to download the file.
+
+ @param[in] Mtftp4 MTFTP4 protocol interface
+ @param[in] FilePath Path of the file, ASCII encoded
+ @param[out] FileSize Address where to store the file size in number of
+ bytes.
+
+ @retval EFI_SUCCESS The size of the file was returned.
+ @retval EFI_UNSUPPORTED The server does not support the "tsize" option.
+ @retval Others Error when retrieving the information from the server
+ (see EFI_MTFTP4_PROTOCOL.GetInfo() status codes)
+ or error when parsing the response of the server.
+**/
+STATIC
+EFI_STATUS
+GetFileSize (
+ IN EFI_MTFTP4_PROTOCOL *Mtftp4,
+ IN CONST CHAR8 *FilePath,
+ OUT UINTN *FileSize
+ )
+{
+ EFI_STATUS Status;
+ EFI_MTFTP4_OPTION ReqOpt[1];
+ EFI_MTFTP4_PACKET *Packet;
+ UINT32 PktLen;
+ EFI_MTFTP4_OPTION *TableOfOptions;
+ EFI_MTFTP4_OPTION *Option;
+ UINT32 OptCnt;
+ UINT8 OptBuf[128];
+
+ ReqOpt[0].OptionStr = (UINT8*)"tsize";
+ OptBuf[0] = '0';
+ OptBuf[1] = 0;
+ ReqOpt[0].ValueStr = OptBuf;
+
+ Status = Mtftp4->GetInfo (
+ Mtftp4,
+ NULL,
+ (UINT8*)FilePath,
+ NULL,
+ 1,
+ ReqOpt,
+ &PktLen,
+ &Packet
+ );
+
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ Status = Mtftp4->ParseOptions (
+ Mtftp4,
+ PktLen,
+ Packet,
+ (UINT32 *) &OptCnt,
+ &TableOfOptions
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+
+ Option = TableOfOptions;
+ while (OptCnt != 0) {
+ if (AsciiStrnCmp ((CHAR8 *)Option->OptionStr, "tsize", 5) == 0) {
+ *FileSize = AsciiStrDecimalToUintn ((CHAR8 *)Option->ValueStr);
+ break;
+ }
+ OptCnt--;
+ Option++;
+ }
+ FreePool (TableOfOptions);
+
+ if (OptCnt == 0) {
+ Status = EFI_UNSUPPORTED;
+ }
+
+Error :
+
+ return Status;
+}
+
+/**
+ Worker function that download the data of a file from a TFTP server given
+ the path of the file and its size.
+
+ @param[in] Mtftp4 MTFTP4 protocol interface
+ @param[in] FilePath Path of the file, Unicode encoded
+ @param[in] AsciiFilePath Path of the file, ASCII encoded
+ @param[in] FileSize Size of the file in number of bytes
+ @param[in] BlockSize Value of the TFTP blksize option
+ @param[out] Data Address where to store the address of the buffer
+ where the data of the file were downloaded in
+ case of success.
+
+ @retval EFI_SUCCESS The file was downloaded.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+ @retval Others The downloading of the file from the server failed
+ (see EFI_MTFTP4_PROTOCOL.ReadFile() status codes).
+
+**/
+STATIC
+EFI_STATUS
+DownloadFile (
+ IN EFI_MTFTP4_PROTOCOL *Mtftp4,
+ IN CONST CHAR16 *FilePath,
+ IN CONST CHAR8 *AsciiFilePath,
+ IN UINTN FileSize,
+ IN UINT16 BlockSize,
+ OUT VOID **Data
+ )
+{
+ EFI_STATUS Status;
+ EFI_PHYSICAL_ADDRESS PagesAddress;
+ VOID *Buffer;
+ DOWNLOAD_CONTEXT *TftpContext;
+ EFI_MTFTP4_TOKEN Mtftp4Token;
+ EFI_MTFTP4_OPTION ReqOpt;
+ UINT8 OptBuf[10];
+
+ // Downloaded file can be large. BS.AllocatePages() is more faster
+ // than AllocatePool() and avoid fragmentation.
+ // The downloaded file could be an EFI application. Marking the
+ // allocated page as EfiBootServicesCode would allow to execute a
+ // potential downloaded EFI application.
+ Status = gBS->AllocatePages (
+ AllocateAnyPages,
+ EfiBootServicesCode,
+ EFI_SIZE_TO_PAGES (FileSize),
+ &PagesAddress
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Buffer = (VOID*)(UINTN)PagesAddress;
+ TftpContext = AllocatePool (sizeof (DOWNLOAD_CONTEXT));
+ if (TftpContext == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+ TftpContext->FileSize = FileSize;
+ TftpContext->DownloadedNbOfBytes = 0;
+ TftpContext->LastReportedNbOfBytes = 0;
+
+ ZeroMem (&Mtftp4Token, sizeof (EFI_MTFTP4_TOKEN));
+ Mtftp4Token.Filename = (UINT8*)AsciiFilePath;
+ Mtftp4Token.BufferSize = FileSize;
+ Mtftp4Token.Buffer = Buffer;
+ Mtftp4Token.CheckPacket = CheckPacket;
+ Mtftp4Token.Context = (VOID*)TftpContext;
+ if (BlockSize != MTFTP_DEFAULT_BLKSIZE) {
+ ReqOpt.OptionStr = (UINT8 *) "blksize";
+ AsciiSPrint ((CHAR8 *)OptBuf, sizeof (OptBuf), "%d", BlockSize);
+ ReqOpt.ValueStr = OptBuf;
+
+ Mtftp4Token.OptionCount = 1;
+ Mtftp4Token.OptionList = &ReqOpt;
+ }
+
+ ShellPrintHiiEx (
+ -1, -1, NULL, STRING_TOKEN (STR_TFTP_DOWNLOADING),
+ gShellTftpHiiHandle, FilePath
+ );
+
+ Status = Mtftp4->ReadFile (Mtftp4, &Mtftp4Token);
+ ShellPrintHiiEx (
+ -1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF),
+ gShellTftpHiiHandle
+ );
+
+Error :
+
+ if (TftpContext == NULL) {
+ FreePool (TftpContext);
+ }
+
+ if (EFI_ERROR (Status)) {
+ gBS->FreePages (PagesAddress, EFI_SIZE_TO_PAGES (FileSize));
+ return Status;
+ }
+
+ *Data = Buffer;
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Update the progress of a file download
+ This procedure is called each time a new TFTP packet is received.
+
+ @param[in] This MTFTP4 protocol interface
+ @param[in] Token Parameters for the download of the file
+ @param[in] PacketLen Length of the packet
+ @param[in] Packet Address of the packet
+
+ @retval EFI_SUCCESS All packets are accepted.
+
+**/
+STATIC
+EFI_STATUS
+EFIAPI
+CheckPacket (
+ IN EFI_MTFTP4_PROTOCOL *This,
+ IN EFI_MTFTP4_TOKEN *Token,
+ IN UINT16 PacketLen,
+ IN EFI_MTFTP4_PACKET *Packet
+ )
+{
+ DOWNLOAD_CONTEXT *Context;
+ CHAR16 Progress[TFTP_PROGRESS_MESSAGE_SIZE];
+ UINTN NbOfKb;
+ UINTN Index;
+ UINTN LastStep;
+ UINTN Step;
+ EFI_STATUS Status;
+
+ if ((NTOHS (Packet->OpCode)) != EFI_MTFTP4_OPCODE_DATA) {
+ return EFI_SUCCESS;
+ }
+
+ Context = (DOWNLOAD_CONTEXT*)Token->Context;
+ if (Context->DownloadedNbOfBytes == 0) {
+ ShellPrintEx (-1, -1, L"%s 0 Kb", mTftpProgressFrame);
+ }
+
+ //
+ // The data in the packet are prepended with two UINT16 :
+ // . OpCode = EFI_MTFTP4_OPCODE_DATA
+ // . Block = the number of this block of data
+ //
+ Context->DownloadedNbOfBytes += PacketLen - sizeof (Packet->OpCode)
+ - sizeof (Packet->Data.Block);
+ NbOfKb = Context->DownloadedNbOfBytes / 1024;
+
+ Progress[0] = L'\0';
+ LastStep = (Context->LastReportedNbOfBytes * TFTP_PROGRESS_SLIDER_STEPS) / Context->FileSize;
+ Step = (Context->DownloadedNbOfBytes * TFTP_PROGRESS_SLIDER_STEPS) / Context->FileSize;
+
+ if (Step <= LastStep) {
+ return EFI_SUCCESS;
+ }
+
+ ShellPrintEx (-1, -1, L"%s", mTftpProgressDelete);
+
+ Status = StrCpyS (Progress, TFTP_PROGRESS_MESSAGE_SIZE, mTftpProgressFrame);
+ if (EFI_ERROR(Status)) {
+ return Status;
+ }
+ for (Index = 1; Index < Step; Index++) {
+ Progress[Index] = L'=';
+ }
+ Progress[Step] = L'>';
+
+ UnicodeSPrint (
+ Progress + (sizeof (mTftpProgressFrame) / sizeof (CHAR16)) - 1,
+ sizeof (Progress) - sizeof (mTftpProgressFrame),
+ L" %7d Kb",
+ NbOfKb
+ );
+ Context->LastReportedNbOfBytes = Context->DownloadedNbOfBytes;
+
+ ShellPrintEx (-1, -1, L"%s", Progress);
+
+ return EFI_SUCCESS;
+}
diff --git a/Core/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.c b/Core/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.c
new file mode 100644
index 0000000000..22c81b8d2a
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.c
@@ -0,0 +1,97 @@
+/** @file
+ Main file for NULL named library for 'tftp' Shell command functions.
+
+ Copyright (c) 2010 - 2011, Intel Corporation. All rights reserved. <BR>
+ Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+#include "UefiShellTftpCommandLib.h"
+
+CONST CHAR16 gShellTftpFileName[] = L"ShellCommand";
+EFI_HANDLE gShellTftpHiiHandle = NULL;
+
+/**
+ Return the file name of the help text file if not using HII.
+
+ @return The string pointer to the file name.
+**/
+CONST CHAR16*
+EFIAPI
+ShellCommandGetManFileNameTftp (
+ VOID
+ )
+{
+ return gShellTftpFileName;
+}
+
+/**
+ Constructor for the Shell Tftp Command library.
+
+ Install the handlers for Tftp UEFI Shell command.
+
+ @param ImageHandle The image handle of the process.
+ @param SystemTable The EFI System Table pointer.
+
+ @retval EFI_SUCCESS The Shell command handlers were installed sucessfully.
+ @retval EFI_UNSUPPORTED The Shell level required was not found.
+**/
+EFI_STATUS
+EFIAPI
+ShellTftpCommandLibConstructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ gShellTftpHiiHandle = NULL;
+
+ //
+ // check our bit of the profiles mask
+ //
+ if ((PcdGet8 (PcdShellProfileMask) & BIT3) == 0) {
+ return EFI_SUCCESS;
+ }
+
+ gShellTftpHiiHandle = HiiAddPackages (
+ &gShellTftpHiiGuid, gImageHandle,
+ UefiShellTftpCommandLibStrings, NULL
+ );
+ if (gShellTftpHiiHandle == NULL) {
+ return EFI_DEVICE_ERROR;
+ }
+ //
+ // Install our Shell command handler
+ //
+ ShellCommandRegisterCommandName (
+ L"tftp", ShellCommandRunTftp, ShellCommandGetManFileNameTftp, 0,
+ L"tftp", TRUE , gShellTftpHiiHandle, STRING_TOKEN (STR_GET_HELP_TFTP)
+ );
+
+ return EFI_SUCCESS;
+}
+
+/**
+ Destructor for the library. free any resources.
+
+ @param ImageHandle The image handle of the process.
+ @param SystemTable The EFI System Table pointer.
+**/
+EFI_STATUS
+EFIAPI
+ShellTftpCommandLibDestructor (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ )
+{
+ if (gShellTftpHiiHandle != NULL) {
+ HiiRemovePackages (gShellTftpHiiHandle);
+ }
+ return EFI_SUCCESS;
+}
diff --git a/Core/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.h b/Core/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.h
new file mode 100644
index 0000000000..bef1e1d9f7
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.h
@@ -0,0 +1,62 @@
+/** @file
+ header file for NULL named library for 'tftp' Shell command functions.
+
+ Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved. <BR>
+ Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>
+
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#ifndef _UEFI_SHELL_TFTP_COMMAND_LIB_H_
+#define _UEFI_SHELL_TFTP_COMMAND_LIB_H_
+
+#include <Uefi.h>
+#include <ShellBase.h>
+
+#include <Guid/ShellLibHiiGuid.h>
+
+#include <Protocol/ServiceBinding.h>
+#include <Protocol/Mtftp4.h>
+
+#include <Library/BaseLib.h>
+#include <Library/BaseMemoryLib.h>
+#include <Library/DebugLib.h>
+#include <Library/MemoryAllocationLib.h>
+#include <Library/ShellCommandLib.h>
+#include <Library/ShellLib.h>
+#include <Library/UefiLib.h>
+#include <Library/UefiRuntimeServicesTableLib.h>
+#include <Library/UefiBootServicesTableLib.h>
+#include <Library/HiiLib.h>
+#include <Library/NetLib.h>
+#include <Library/PrintLib.h>
+
+extern EFI_HANDLE gShellTftpHiiHandle;
+
+typedef struct {
+ UINTN FileSize;
+ UINTN DownloadedNbOfBytes;
+ UINTN LastReportedNbOfBytes;
+} DOWNLOAD_CONTEXT;
+
+/**
+ Function for 'tftp' command.
+
+ @param[in] ImageHandle Handle to the Image (NULL if Internal).
+ @param[in] SystemTable Pointer to the System Table (NULL if Internal).
+**/
+SHELL_STATUS
+EFIAPI
+ShellCommandRunTftp (
+ IN EFI_HANDLE ImageHandle,
+ IN EFI_SYSTEM_TABLE *SystemTable
+ );
+
+#endif /* _UEFI_SHELL_TFTP_COMMAND_LIB_H_ */
diff --git a/Core/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.inf b/Core/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.inf
new file mode 100644
index 0000000000..96db258920
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.inf
@@ -0,0 +1,61 @@
+## @file
+# Provides Shell 'tftp' command functions
+#
+# Copyright (c) 2010 - 2015, Intel Corporation. All rights reserved. <BR>
+# Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010006
+ BASE_NAME = UefiShellTftpCommandLib
+ FILE_GUID = D2B61A25-9835-4E5D-906A-15615E1FF668
+ MODULE_TYPE = UEFI_APPLICATION
+ VERSION_STRING = 1.0
+ LIBRARY_CLASS = NULL|UEFI_APPLICATION UEFI_DRIVER
+ CONSTRUCTOR = ShellTftpCommandLibConstructor
+ DESTRUCTOR = ShellTftpCommandLibDestructor
+
+[Sources.common]
+ UefiShellTftpCommandLib.uni
+ UefiShellTftpCommandLib.c
+ UefiShellTftpCommandLib.h
+ Tftp.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ ShellPkg/ShellPkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ MemoryAllocationLib
+ BaseLib
+ BaseMemoryLib
+ DebugLib
+ ShellCommandLib
+ ShellLib
+ UefiLib
+ UefiRuntimeServicesTableLib
+ UefiBootServicesTableLib
+ PcdLib
+ HiiLib
+ FileHandleLib
+ NetLib
+
+[Pcd]
+ gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask ## CONSUMES
+
+[Protocols]
+ gEfiManagedNetworkServiceBindingProtocolGuid ## CONSUMES
+ gEfiMtftp4ServiceBindingProtocolGuid ## CONSUMES
+
+[Guids]
+ gShellTftpHiiGuid ## CONSUMES ## HII
diff --git a/Core/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.uni b/Core/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.uni
new file mode 100644
index 0000000000..a16265c16e
--- /dev/null
+++ b/Core/ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.uni
@@ -0,0 +1,97 @@
+// /**
+//
+// (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>
+// Copyright (c) 2010 - 2016, Intel Corporation. All rights reserved. <BR>
+// This program and the accompanying materials
+// are licensed and made available under the terms and conditions of the BSD License
+// which accompanies this distribution. The full text of the license may be found at
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// Module Name:
+//
+// UefiShellTftpCommandLib.uni
+//
+// Abstract:
+//
+// String definitions for UEFI Shell TFTP command
+//
+//
+// **/
+
+/=#
+
+#langdef en-US "english"
+
+#string STR_GEN_TOO_MANY #language en-US "%H%s%N: Too many arguments\r\n"
+#string STR_GEN_TOO_FEW #language en-US "%H%s%N: Too few arguments\r\n"
+#string STR_GEN_PARAM_INV #language en-US "%H%s%N: Invalid argument - '%H%s%N'\r\n"
+#string STR_GEN_PROBLEM #language en-US "%H%s%N: Unknown flag - '%H%s%N'\r\n"
+#string STR_GEN_FILE_OPEN_FAIL #language en-US "%H%s%N: Cannot open file - '%H%s%N'\r\n"
+#string STR_GEN_CRLF #language en-US "\r\n"
+
+#string STR_TFTP_ERR_NO_NIC #language en-US "No network interface card found.\r\n"
+#string STR_TFTP_ERR_NIC_NAME #language en-US "Failed to get the name of the network interface card number %d - %r\r\n"
+#string STR_TFTP_ERR_OPEN_PROTOCOL #language en-US "Unable to open MTFTP4 protocol on '%H%s%N' - %r\r\n"
+#string STR_TFTP_ERR_CONFIGURE #language en-US "Unable to configure MTFTP4 protocol on '%H%s%N' - %r\r\n"
+#string STR_TFTP_ERR_FILE_SIZE #language en-US "Unable to get the size of the file '%H%s%N' on '%H%s%N' - %r\r\n"
+#string STR_TFTP_ERR_DOWNLOAD #language en-US "Unable to download the file '%H%s%N' on '%H%s%N' - %r\r\n"
+#string STR_TFTP_ERR_WRITE #language en-US "Unable to write into file '%H%s%N' - %r\r\n"
+#string STR_TFTP_ERR_NIC_NOT_FOUND #language en-US "Network Interface Card '%H%s%N' not found.\r\n"
+#string STR_TFTP_DOWNLOADING #language en-US "Downloading the file '%H%s%N'\r\n"
+#string STR_TFTP_STRING #language en-US "%s"
+
+#string STR_GET_HELP_TFTP #language en-US ""
+".TH tftp 0 "Download a file from TFTP server."\r\n"
+".SH NAME\r\n"
+"Download a file from TFTP server.\r\n"
+".SH SYNOPSIS\r\n"
+" \r\n"
+"TFTP [-i interface] [-l <port>] [-r <port>] [-c <retry count>] [-t <timeout>]\r\n"
+" [-s <block size>] host remotefilepath [localfilepath]\r\n"
+".SH OPTIONS\r\n"
+" \r\n"
+" -i interface - Specifies an adapter name, i.e., eth0.\r\n"
+" -l port - Specifies the local port number. Default value is 0\r\n"
+" and the port number is automatically assigned.\r\n"
+" -r port - Specifies the remote port number. Default value is 69.\r\n"
+" -c <retry count> - The number of times to transmit request packets and\r\n"
+" wait for a response. The default value is 6.\r\n"
+" -t <timeout> - The number of seconds to wait for a response after\r\n"
+" sending a request packet. Default value is 4s.\r\n"
+" -s <block size> - Specifies the TFTP blksize option as defined in RFC 2348.\r\n"
+" Valid range is between 8 and 65464, default value is 512.\r\n"
+" host - Specify TFTP Server IPv4 address.\r\n"
+" remotefilepath - TFTP server file path to download the file.\r\n"
+" localfilepath - Local destination file path.\r\n"
+".SH DESCRIPTION\r\n"
+" \r\n"
+"NOTES:\r\n"
+" 1. The TFTP command allows to get the file specified by its 'remotefilepath'\r\n"
+" path from the TFTP server specified by its 'host' IPv4 address. If the\r\n"
+" optional 'localfilepath' parameter is provided, the downloaded file is\r\n"
+" stored locally using the provided file path. If the local file path is\r\n"
+" not specified, the file is stored in the current directory using the file\r\n"
+" server's name.\r\n"
+" 2. Prior to invoke the TFTP command, the network interface intended to be\r\n"
+" used to retrieve the file as to be configured. This configuration may be\r\n"
+" done by means of the 'ifconfig' command.\r\n"
+" 3. If a network interface is defined with the '-i' option then only this\r\n"
+" interface is used to access to the remote file. Otherwise, all network\r\n"
+" interfaces are tried in the order they have been discovered during the\r\n"
+" DXE phase.\r\n"
+".SH EXAMPLES\r\n"
+" \r\n"
+"EXAMPLES:\r\n"
+" * To get the file "dir1/file1.dat" from the TFTP server 192.168.1.1 and\r\n"
+" store it as file2.dat in the current directory :\r\n"
+" fs0:\> tftp 192.168.1.1 dir1/file1.dat file2.dat\r\n"
+".SH RETURNVALUES\r\n"
+" \r\n"
+"RETURN VALUES:\r\n"
+" SHELL_SUCCESS The action was completed as requested.\r\n"
+" SHELL_INVALID_PARAMETER One of the passed-in parameters was incorrectly\r\n"
+" formatted or its value was out of bounds.\r\n"
+
diff --git a/Core/ShellPkg/License.txt b/Core/ShellPkg/License.txt
new file mode 100644
index 0000000000..be68999be6
--- /dev/null
+++ b/Core/ShellPkg/License.txt
@@ -0,0 +1,25 @@
+Copyright (c) 2012, Intel Corporation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/Core/ShellPkg/Readme.txt b/Core/ShellPkg/Readme.txt
new file mode 100644
index 0000000000..77841c0a2a
--- /dev/null
+++ b/Core/ShellPkg/Readme.txt
@@ -0,0 +1,29 @@
+============================================================================
+ OVERVIEW
+============================================================================
+The UEFI 2.0 shell provides a standard pre-boot command line processor.
+It is similar to the EDK EFI Shell or a *nix command line parser.
+
+============================================================================
+ HOW TO INCORPORATE THIS SHELL INTO NT32
+============================================================================
+The instructions below are included as a sample and template on how a
+developer may integrate this code into an existing platform:
+
+1. Add this shell build to the NT32 build:
+ Add the shell.inf to the [components] section as it is in the ShellPkg.dsc.
+
+2. Update system PCDs to support this new module
+ Update the PCD as follows using the Shell's PCD:
+ gEfiIntelFrameworkModulePkgTokenSpaceGuid.PcdShellFile|{ 0x83, 0xA5, 0x04, 0x7C, 0x3E, 0x9E, 0x1C, 0x4F, 0xAD, 0x65, 0xE0, 0x52, 0x68, 0xD0, 0xB4, 0xD1 }
+
+3. Remove the old shell from the NT32 Firmware list
+ Remove the FILE APPLICATION section for the old shell.
+
+4. Add this shell to the NT32 firmware list
+ Add the Shell.INF to the end of the list of DXE modules.
+
+5. Build NT32
+
+
+============================================================================
diff --git a/Core/ShellPkg/ShellPkg.dec b/Core/ShellPkg/ShellPkg.dec
new file mode 100644
index 0000000000..39f8012b98
--- /dev/null
+++ b/Core/ShellPkg/ShellPkg.dec
@@ -0,0 +1,138 @@
+## @file ShellPkg.dec
+# This Package provides all definitions for EFI and UEFI Shell
+#
+# (C) Copyright 2013-2014 Hewlett-Packard Development Company, L.P.<BR>
+# Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials are licensed and made available under
+# the terms and conditions of the BSD License which accompanies this distribution.
+# The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ DEC_SPECIFICATION = 0x00010005
+ PACKAGE_NAME = ShellPkg
+ PACKAGE_GUID = C1014BB7-4092-43D4-984F-0738EB424DBF
+ PACKAGE_VERSION = 1.0
+
+[Includes]
+ Include
+
+[LibraryClasses]
+ ## @libraryclass Provides most Shell APIs. Only available for Shell applications
+ ShellLib|Include/Library/ShellLib.h
+
+ ## @libraryclass Provides shell internal support Only available for shell internal commands
+ ShellCommandLib|Include/Library/ShellCommandLib.h
+
+ ## @libraryclass Allows for a shell application to have a C style entry point
+ ShellCEntryLib|Include/Library/ShellCEntryLib.h
+
+ ## @libraryclass Provides advanced parsing functions
+ HandleParsingLib|Include/Library/HandleParsingLib.h
+
+ ## @libraryclass provides BCFG command
+ BcfgCommandLib|Include/Library/BcfgCommandLib.h
+
+[Guids]
+ gEfiShellEnvironment2ExtGuid = {0xd2c18636, 0x40e5, 0x4eb5, {0xa3, 0x1b, 0x36, 0x69, 0x5f, 0xd4, 0x2c, 0x87}}
+ gEfiShellPkgTokenSpaceGuid = {0x171e9188, 0x31d3, 0x40f5, {0xb1, 0x0c, 0x53, 0x9b, 0x2d, 0xb9, 0x40, 0xcd}}
+ gShellVariableGuid = {0x158def5a, 0xf656, 0x419c, {0xb0, 0x27, 0x7a, 0x31, 0x92, 0xc0, 0x79, 0xd2}}
+ gShellMapGuid = {0x51271e13, 0x7de3, 0x43af, {0x8b, 0xc2, 0x71, 0xad, 0x3b, 0x82, 0x43, 0x25}}
+ gShellAliasGuid = {0x0053d9d6, 0x2659, 0x4599, {0xa2, 0x6b, 0xef, 0x45, 0x36, 0xe6, 0x31, 0xa9}}
+ gHandleParsingHiiGuid = {0xb8969637, 0x81de, 0x43af, {0xbc, 0x9a, 0x24, 0xd9, 0x89, 0x13, 0xf2, 0xf6}}
+ gShellDebug1HiiGuid = {0x25f200aa, 0xd3cb, 0x470a, {0xbf, 0x51, 0xe7, 0xd1, 0x62, 0xd2, 0x2e, 0x6f}}
+ gShellDriver1HiiGuid = {0xaf0b742, 0x63ec, 0x45bd, {0x8d, 0xb6, 0x71, 0xad, 0x7f, 0x2f, 0xe8, 0xe8}}
+ gShellInstall1HiiGuid = {0x7d574d54, 0xd364, 0x4d4a, {0x95, 0xe3, 0x49, 0x45, 0xdb, 0x7a, 0xd3, 0xee}}
+ gShellLevel1HiiGuid = {0xdec5daa4, 0x6781, 0x4820, {0x9c, 0x63, 0xa7, 0xb0, 0xe4, 0xf1, 0xdb, 0x31}}
+ gShellLevel2HiiGuid = {0xf95a7ccc, 0x4c55, 0x4426, {0xa7, 0xb4, 0xdc, 0x89, 0x61, 0x95, 0xb, 0xae}}
+ gShellLevel3HiiGuid = {0x4344558d, 0x4ef9, 0x4725, {0xb1, 0xe4, 0x33, 0x76, 0xe8, 0xd6, 0x97, 0x4f}}
+ gShellNetwork1HiiGuid = {0xf3d301bb, 0xf4a5, 0x45a8, {0xb0, 0xb7, 0xfa, 0x99, 0x9c, 0x62, 0x37, 0xae}}
+ gShellNetwork2HiiGuid = {0x174b2b5, 0xf505, 0x4b12, {0xaa, 0x60, 0x59, 0xdf, 0xf8, 0xd6, 0xea, 0x37}}
+ gShellTftpHiiGuid = {0x738a9314, 0x82c1, 0x4592, {0x8f, 0xf7, 0xc1, 0xbd, 0xf1, 0xb2, 0x0e, 0xd4}}
+ gShellBcfgHiiGuid = {0x5f5f605d, 0x1583, 0x4a2d, {0xa6, 0xb2, 0xeb, 0x12, 0xda, 0xb4, 0xa2, 0xb6}}
+
+[Protocols]
+ gEfiShellProtocolGuid = {0x6302d008, 0x7f9b, 0x4f30, {0x87, 0xac, 0x60, 0xc9, 0xfe, 0xf5, 0xda, 0x4e}}
+ gEfiShellParametersProtocolGuid = {0x752f3136, 0x4e16, 0x4fdc, {0xa2, 0x2a, 0xe5, 0xf4, 0x68, 0x12, 0xf4, 0xca}}
+ gEfiShellEnvironment2Guid = {0x47c7b221, 0xc42a, 0x11d2, {0x8e, 0x57, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b}}
+ gEfiShellInterfaceGuid = {0x47c7b223, 0xc42a, 0x11d2, {0x8e, 0x57, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b}}
+ gEfiShellDynamicCommandProtocolGuid = {0x3c7200e9, 0x005f, 0x4ea4, {0x87, 0xde, 0xa3, 0xdf, 0xac, 0x8a, 0x27, 0xc3}}
+
+[PcdsFeatureFlag]
+ ## This flag is used to control whether the shell includes NT32 platform Guids
+ # and thereby prevents dependancy on that Pkg
+ gEfiShellPkgTokenSpaceGuid.PcdShellIncludeNtGuids|TRUE|BOOLEAN|0x0000000E
+
+ ## This flag is used to control HII required by the shell
+ gEfiShellPkgTokenSpaceGuid.PcdShellRequireHiiPlatform|TRUE|BOOLEAN|0x00000003
+
+ ## This flag is used to control HII required by the shell
+ gEfiShellPkgTokenSpaceGuid.PcdShellSupportFrameworkHii|FALSE|BOOLEAN|0x00000004
+
+ ## This flag forces the shell to present a user console. Allows for earlier debugging of platforms.
+ gEfiShellPkgTokenSpaceGuid.PcdShellForceConsole|FALSE|BOOLEAN|0x0000000F
+
+[PcdsFixedAtBuild]
+ ## This flag is used to control initialization of the shell library
+ # This should be FALSE for compiling the shell application itself only.
+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|TRUE|BOOLEAN|0x00000005
+
+ ## This is the max buffer for ShellLib and internal Shell printings.
+ gEfiShellPkgTokenSpaceGuid.PcdShellPrintBufferSize|16000|UINT16|0x0000000C
+
+ ## This flag is used to control the commands available in the shell
+ gEfiShellPkgTokenSpaceGuid.PcdShellSupportLevel|3|UINT8|0x00000001
+
+ ## This flag is used to control the profiles available in the shell
+ # don't forget to update the text file if you change this.
+ # bit 0 = Drivers1
+ # bit 1 = Debug1
+ # bit 2 = Install1
+ # bit 3 = Network1
+ # bit 4 = Network2
+ gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask|0xFF|UINT8|0x0000000D
+
+ ## This is the character count for allocation for consistent mappings
+ gEfiShellPkgTokenSpaceGuid.PcdShellMapNameLength|50|UINT8|0x00000009
+
+ ## This determines how many bytes are read out of files at a time for file operations (type, copy, etc...)
+ gEfiShellPkgTokenSpaceGuid.PcdShellFileOperationSize|0x1000|UINT32|0x0000000A
+
+ ## This determines the max count of history commands
+ gEfiShellPkgTokenSpaceGuid.PcdShellMaxHistoryCommandCount|0x0020|UINT16|0x00000014
+
+[PcdsFixedAtBuild, PcdsPatchableInModule, PcdsDynamic, PcdsDynamicEx]
+ ## This flag is used to control the protocols produced by the shell
+ # If TRUE the shell will produce EFI_SHELL_ENVIRONMENT2 and EFI_SHELL_INTERFACE
+ gEfiShellPkgTokenSpaceGuid.PcdShellSupportOldProtocols|FALSE|BOOLEAN|0x00000002
+
+ ## this flag determines whether Page Break (-b) defaults to on or off in the shell
+ gEfiShellPkgTokenSpaceGuid.PcdShellPageBreakDefault|FALSE|BOOLEAN|0x00000006
+
+ ## this flag determines whether insert mode for typing is default (FALSE means typeover)
+ gEfiShellPkgTokenSpaceGuid.PcdShellInsertModeDefault|TRUE|BOOLEAN|0x00000007
+
+ ## this flag determines the default number of screens kept for history log.
+ # the spec defines 3 as the minimum
+ gEfiShellPkgTokenSpaceGuid.PcdShellScreenLogCount|3|UINT8|0x00000008
+
+ ## Unicode string of the shell supplier
+ gEfiShellPkgTokenSpaceGuid.PcdShellSupplier|L"EDK II"|VOID*|0x00000010
+
+ ## Do extended decode of USB for determining media type
+ gEfiShellPkgTokenSpaceGuid.PcdUsbExtendedDecode|TRUE|BOOLEAN|0x00000011
+
+ ## Do iSCSI decode for map names.
+ # This is disabled by default due to the length of generated strings
+ gEfiShellPkgTokenSpaceGuid.PcdShellDecodeIScsiMapNames|FALSE|BOOLEAN|0x00000012
+
+ ## Controls Extended decode for Vendor device path nodes for map names.
+ # Up to this many bytes of vendor specific data will be used. Default is 0
+ # (disabled).
+ gEfiShellPkgTokenSpaceGuid.PcdShellVendorExtendedDecode|0|UINT32|0x00000013
diff --git a/Core/ShellPkg/ShellPkg.dsc b/Core/ShellPkg/ShellPkg.dsc
new file mode 100644
index 0000000000..25c4fadc61
--- /dev/null
+++ b/Core/ShellPkg/ShellPkg.dsc
@@ -0,0 +1,124 @@
+## @file
+# Shell Package
+#
+# Copyright (c) 2007 - 2016, Intel Corporation. All rights reserved.<BR>
+#
+# This program and the accompanying materials
+# are licensed and made available under the terms and conditions of the BSD License
+# which accompanies this distribution. The full text of the license may be found at
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ PLATFORM_NAME = Shell
+ PLATFORM_GUID = E1DC9BF8-7013-4c99-9437-795DAA45F3BD
+ PLATFORM_VERSION = 1.0
+ DSC_SPECIFICATION = 0x00010006
+ OUTPUT_DIRECTORY = Build/Shell
+ SUPPORTED_ARCHITECTURES = IA32|IPF|X64|EBC|ARM|AARCH64
+ BUILD_TARGETS = DEBUG|RELEASE|NOOPT
+ SKUID_IDENTIFIER = DEFAULT
+
+[LibraryClasses.common]
+ UefiApplicationEntryPoint|MdePkg/Library/UefiApplicationEntryPoint/UefiApplicationEntryPoint.inf
+ UefiBootServicesTableLib|MdePkg/Library/UefiBootServicesTableLib/UefiBootServicesTableLib.inf
+ DevicePathLib|MdePkg/Library/UefiDevicePathLib/UefiDevicePathLibOptionalDevicePathProtocol.inf
+!if $(TARGET) == RELEASE
+ DebugLib|MdePkg/Library/BaseDebugLibNull/BaseDebugLibNull.inf
+!else
+ DebugLib|MdePkg/Library/UefiDebugLibConOut/UefiDebugLibConOut.inf
+!endif
+ DebugPrintErrorLevelLib|MdePkg/Library/BaseDebugPrintErrorLevelLib/BaseDebugPrintErrorLevelLib.inf
+ PcdLib|MdePkg/Library/BasePcdLibNull/BasePcdLibNull.inf
+ MemoryAllocationLib|MdePkg/Library/UefiMemoryAllocationLib/UefiMemoryAllocationLib.inf
+ UefiLib|MdePkg/Library/UefiLib/UefiLib.inf
+ BaseLib|MdePkg/Library/BaseLib/BaseLib.inf
+ BaseMemoryLib|MdePkg/Library/BaseMemoryLib/BaseMemoryLib.inf
+ PrintLib|MdePkg/Library/BasePrintLib/BasePrintLib.inf
+ FileHandleLib|MdePkg/Library/UefiFileHandleLib/UefiFileHandleLib.inf
+ SortLib|MdeModulePkg/Library/UefiSortLib/UefiSortLib.inf
+ UefiRuntimeServicesTableLib|MdePkg/Library/UefiRuntimeServicesTableLib/UefiRuntimeServicesTableLib.inf
+ UefiHiiServicesLib|MdeModulePkg/Library/UefiHiiServicesLib/UefiHiiServicesLib.inf
+ HiiLib|MdeModulePkg/Library/UefiHiiLib/UefiHiiLib.inf
+ NetLib|MdeModulePkg/Library/DxeNetLib/DxeNetLib.inf
+
+ ShellLib|ShellPkg/Library/UefiShellLib/UefiShellLib.inf
+ ShellCommandLib|ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
+ ShellCEntryLib|ShellPkg/Library/UefiShellCEntryLib/UefiShellCEntryLib.inf
+ HandleParsingLib|ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
+
+ PeCoffGetEntryPointLib|MdePkg/Library/BasePeCoffGetEntryPointLib/BasePeCoffGetEntryPointLib.inf
+ BcfgCommandLib|ShellPkg/Library/UefiShellBcfgCommandLib/UefiShellBcfgCommandLib.inf
+ IoLib|MdePkg/Library/BaseIoLibIntrinsic/BaseIoLibIntrinsic.inf
+
+[LibraryClasses.ARM]
+ #
+ # It is not possible to prevent the ARM compiler for generic intrinsic functions.
+ # This library provides the instrinsic functions generate by a given compiler.
+ # [LibraryClasses.ARM] and NULL mean link this library into all ARM images.
+ #
+ NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
+
+ # Add support for GCC stack protector
+ NULL|MdePkg/Library/BaseStackCheckLib/BaseStackCheckLib.inf
+
+[LibraryClasses.AARCH64]
+ NULL|ArmPkg/Library/CompilerIntrinsicsLib/CompilerIntrinsicsLib.inf
+
+[PcdsFixedAtBuild]
+ gEfiMdePkgTokenSpaceGuid.PcdDebugPropertyMask|0xFF
+ gEfiShellPkgTokenSpaceGuid.PcdShellLibAutoInitialize|FALSE
+ gEfiMdePkgTokenSpaceGuid.PcdUefiLibMaxPrintBufferSize|16000
+!ifdef $(NO_SHELL_PROFILES)
+ gEfiShellPkgTokenSpaceGuid.PcdShellProfileMask|0x00
+!endif #$(NO_SHELL_PROFILES)
+
+[Components]
+ #
+ # Build all the libraries when building this package.
+ # This helps developers test changes and how they affect the package.
+ #
+ ShellPkg/Library/UefiShellLib/UefiShellLib.inf
+ ShellPkg/Library/UefiShellCommandLib/UefiShellCommandLib.inf
+ ShellPkg/Library/UefiHandleParsingLib/UefiHandleParsingLib.inf
+ ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf
+ ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf
+ ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf
+ ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf
+ ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf
+ ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf
+ ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf
+ ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.inf
+ ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.inf
+
+ ShellPkg/Library/UefiDpLib/UefiDpLib.inf {
+ <LibraryClasses>
+ TimerLib|MdePkg/Library/BaseTimerLibNullTemplate/BaseTimerLibNullTemplate.inf
+ PerformanceLib|MdePkg/Library/BasePerformanceLibNull/BasePerformanceLibNull.inf
+ DxeServicesLib|MdePkg/Library/DxeServicesLib/DxeServicesLib.inf
+ }
+
+ ShellPkg/Application/Shell/Shell.inf {
+ <LibraryClasses>
+ NULL|ShellPkg/Library/UefiShellLevel2CommandsLib/UefiShellLevel2CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellLevel1CommandsLib/UefiShellLevel1CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellLevel3CommandsLib/UefiShellLevel3CommandsLib.inf
+!ifndef $(NO_SHELL_PROFILES)
+ NULL|ShellPkg/Library/UefiShellDriver1CommandsLib/UefiShellDriver1CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellInstall1CommandsLib/UefiShellInstall1CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellDebug1CommandsLib/UefiShellDebug1CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellNetwork1CommandsLib/UefiShellNetwork1CommandsLib.inf
+ NULL|ShellPkg/Library/UefiShellNetwork2CommandsLib/UefiShellNetwork2CommandsLib.inf
+!ifdef $(INCLUDE_DP)
+ NULL|ShellPkg/Library/UefiDpLib/UefiDpLib.inf
+!endif #$(INCLUDE_DP)
+!ifdef $(INCLUDE_TFTP_COMMAND)
+ NULL|ShellPkg/Library/UefiShellTftpCommandLib/UefiShellTftpCommandLib.inf
+!endif #$(INCLUDE_TFTP_COMMAND)
+!endif #$(NO_SHELL_PROFILES)
+ }
+