1/** @file 2 3 Copyright (c) 2004 - 2014, Intel Corporation. All rights reserved.<BR> 4 5 6 This program and the accompanying materials are licensed and made available under 7 8 the terms and conditions of the BSD License that accompanies this distribution. 9 10 The full text of the license may be found at 11 12 http://opensource.org/licenses/bsd-license.php. 13 14 15 16 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 17 18 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 19 20 21 22 23 24Module Name: 25 26 27 SmmScriptSave.c 28 29Abstract: 30 31 ScriptTableSave module at run time 32 33--*/ 34 35#include "SmmScriptSave.h" 36 37// 38// internal functions 39// 40 41EFI_STATUS 42BootScriptIoWrite ( 43 IN EFI_SMM_SCRIPT_TABLE *ScriptTable, 44 IN VA_LIST Marker 45 ); 46 47EFI_STATUS 48BootScriptPciCfgWrite ( 49 IN EFI_SMM_SCRIPT_TABLE *ScriptTable, 50 IN VA_LIST Marker 51 ); 52 53VOID 54SmmCopyMem ( 55 IN UINT8 *Destination, 56 IN UINT8 *Source, 57 IN UINTN ByteCount 58 ); 59 60// 61// Function implementations 62// 63EFI_STATUS 64SmmBootScriptWrite ( 65 IN OUT EFI_SMM_SCRIPT_TABLE *ScriptTable, 66 IN UINTN Type, 67 IN UINT16 OpCode, 68 ... 69 ) 70{ 71 EFI_STATUS Status; 72 VA_LIST Marker; 73 74 if (ScriptTable == NULL) { 75 return EFI_INVALID_PARAMETER; 76 } 77 78 // 79 // Build script according to opcode 80 // 81 switch ( OpCode ) { 82 83 case EFI_BOOT_SCRIPT_IO_WRITE_OPCODE: 84 VA_START(Marker, OpCode); 85 Status = BootScriptIoWrite (ScriptTable, Marker); 86 VA_END(Marker); 87 break; 88 89 case EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE: 90 VA_START(Marker, OpCode); 91 Status = BootScriptPciCfgWrite(ScriptTable, Marker); 92 VA_END(Marker); 93 break; 94 95 default: 96 Status = EFI_SUCCESS; 97 break; 98 } 99 100 return Status; 101} 102 103 104EFI_STATUS 105SmmBootScriptCreateTable ( 106 IN OUT EFI_SMM_SCRIPT_TABLE *ScriptTable, 107 IN UINTN Type 108 ) 109{ 110 BOOT_SCRIPT_POINTERS Script; 111 UINT8 *Buffer; 112 113 if (ScriptTable == NULL) { 114 return EFI_INVALID_PARAMETER; 115 } 116 117 Buffer = (UINT8*) ((UINTN)(*ScriptTable)); 118 119 // 120 // Fill Table Header 121 // 122 Script.Raw = Buffer; 123 Script.TableInfo->OpCode = EFI_BOOT_SCRIPT_TABLE_OPCODE; 124 Script.TableInfo->Length = sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER); 125 Script.TableInfo->TableLength = sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER); 126 127 // 128 // Update current table pointer 129 // 130 *ScriptTable = *ScriptTable + sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER); 131 return EFI_SUCCESS; 132} 133 134 135EFI_STATUS 136SmmBootScriptCloseTable ( 137 IN EFI_SMM_SCRIPT_TABLE ScriptTableBase, 138 IN EFI_SMM_SCRIPT_TABLE ScriptTablePtr, 139 IN UINTN Type 140 ) 141{ 142 BOOT_SCRIPT_POINTERS Script; 143 144 // 145 // Add final "termination" node to script table 146 // 147 Script.Raw = (UINT8*) ((UINTN)ScriptTablePtr); 148 Script.Terminate->OpCode = EFI_BOOT_SCRIPT_TERMINATE_OPCODE; 149 Script.Terminate->Length = sizeof (EFI_BOOT_SCRIPT_TERMINATE); 150 ScriptTablePtr += sizeof (EFI_BOOT_SCRIPT_TERMINATE); 151 152 153 // 154 // Update Table Header 155 // 156 Script.Raw = (UINT8*) ((UINTN)ScriptTableBase); 157 Script.TableInfo->OpCode = EFI_BOOT_SCRIPT_TABLE_OPCODE; 158 Script.TableInfo->Length = sizeof (EFI_BOOT_SCRIPT_TABLE_HEADER); 159 Script.TableInfo->TableLength = (UINT32)(ScriptTablePtr - ScriptTableBase); 160 161 return EFI_SUCCESS; 162} 163 164 165EFI_STATUS 166BootScriptIoWrite ( 167 IN EFI_SMM_SCRIPT_TABLE *ScriptTable, 168 IN VA_LIST Marker 169 ) 170{ 171 BOOT_SCRIPT_POINTERS Script; 172 EFI_BOOT_SCRIPT_WIDTH Width; 173 UINTN Address; 174 UINTN Count; 175 UINT8 *Buffer; 176 UINTN NodeLength; 177 UINT8 WidthInByte; 178 179 Width = VA_ARG(Marker, EFI_BOOT_SCRIPT_WIDTH); 180 Address = VA_ARG(Marker, UINTN); 181 Count = VA_ARG(Marker, UINTN); 182 Buffer = VA_ARG(Marker, UINT8*); 183 184 WidthInByte = (UINT8)(0x01 << (Width & 0x03)); 185 Script.Raw = (UINT8*) ((UINTN)(*ScriptTable)); 186 NodeLength = sizeof (EFI_BOOT_SCRIPT_IO_WRITE) + (WidthInByte * Count); 187 188 // 189 // Build script data 190 // 191 Script.IoWrite->OpCode = EFI_BOOT_SCRIPT_IO_WRITE_OPCODE; 192 Script.IoWrite->Length = (UINT8)(NodeLength); 193 Script.IoWrite->Width = Width; 194 Script.IoWrite->Address = Address; 195 Script.IoWrite->Count = (UINT32)Count; 196 SmmCopyMem ( 197 (UINT8*)(Script.Raw + sizeof (EFI_BOOT_SCRIPT_IO_WRITE)), 198 Buffer, 199 WidthInByte * Count 200 ); 201 202 // 203 // Update Script table pointer 204 // 205 *ScriptTable = *ScriptTable + NodeLength; 206 return EFI_SUCCESS; 207} 208 209 210EFI_STATUS 211BootScriptPciCfgWrite ( 212 IN EFI_SMM_SCRIPT_TABLE *ScriptTable, 213 IN VA_LIST Marker 214 ) 215{ 216 BOOT_SCRIPT_POINTERS Script; 217 EFI_BOOT_SCRIPT_WIDTH Width; 218 UINT64 Address; 219 UINTN Count; 220 UINT8 *Buffer; 221 UINTN NodeLength; 222 UINT8 WidthInByte; 223 224 Width = VA_ARG(Marker, EFI_BOOT_SCRIPT_WIDTH); 225 Address = VA_ARG(Marker, UINT64); 226 Count = VA_ARG(Marker, UINTN); 227 Buffer = VA_ARG(Marker, UINT8*); 228 229 WidthInByte = (UINT8)(0x01 << (Width & 0x03)); 230 Script.Raw = (UINT8*) ((UINTN)(*ScriptTable)); 231 NodeLength = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE) + (WidthInByte * Count); 232 233 // 234 // Build script data 235 // 236 Script.PciWrite->OpCode = EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE; 237 Script.PciWrite->Length = (UINT8)(NodeLength); 238 Script.PciWrite->Width = Width; 239 Script.PciWrite->Address = Address; 240 Script.PciWrite->Count = (UINT32)Count; 241 SmmCopyMem ( 242 (UINT8*)(Script.Raw + sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE)), 243 Buffer, 244 WidthInByte * Count 245 ); 246 247 // 248 // Update Script table pointer 249 // 250 *ScriptTable = *ScriptTable + NodeLength; 251 return EFI_SUCCESS; 252} 253 254VOID 255SmmCopyMem ( 256 IN UINT8 *Destination, 257 IN UINT8 *Source, 258 IN UINTN ByteCount 259 ) 260{ 261 UINTN Index; 262 263 for (Index = 0; Index < ByteCount; Index++, Destination++, Source++) { 264 *Destination = *Source; 265 } 266} 267