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