• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Interpret and execute the S3 data in S3 boot script.
3 
4   Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
5 
6   This program and the accompanying materials
7   are licensed and made available under the terms and conditions
8   of the BSD License which accompanies this distribution.  The
9   full text of the license may be found at
10   http://opensource.org/licenses/bsd-license.php
11 
12   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 
15 **/
16 #include "InternalBootScriptLib.h"
17 
18 /**
19   Executes an SMBus operation to an SMBus controller. Returns when either the command has been
20   executed or an error is encountered in doing the operation.
21 
22   The SmbusExecute() function provides a standard way to execute an operation as defined in the System
23   Management Bus (SMBus) Specification. The resulting transaction will be either that the SMBus
24   slave devices accept this transaction or that this function returns with error.
25 
26   @param  SmbusAddress            Address that encodes the SMBUS Slave Address, SMBUS Command, SMBUS Data Length,
27                                   and PEC.
28   @param  Operation               Signifies which particular SMBus hardware protocol instance that
29                                   it will use to execute the SMBus transactions. This SMBus
30                                   hardware protocol is defined by the SMBus Specification and is
31                                   not related to EFI.
32   @param  Length                  Signifies the number of bytes that this operation will do. The
33                                   maximum number of bytes can be revision specific and operation
34                                   specific. This field will contain the actual number of bytes that
35                                   are executed for this operation. Not all operations require this
36                                   argument.
37   @param  Buffer                  Contains the value of data to execute to the SMBus slave device.
38                                   Not all operations require this argument. The length of this
39                                   buffer is identified by Length.
40 
41   @retval EFI_SUCCESS             The last data that was returned from the access matched the poll
42                                   exit criteria.
43   @retval EFI_CRC_ERROR           Checksum is not correct (PEC is incorrect).
44   @retval EFI_TIMEOUT             Timeout expired before the operation was completed. Timeout is
45                                   determined by the SMBus host controller device.
46   @retval EFI_OUT_OF_RESOURCES    The request could not be completed due to a lack of resources.
47   @retval EFI_DEVICE_ERROR        The request was not completed because a failure that was
48                                   reflected in the Host Status Register bit. Device errors are a
49                                   result of a transaction collision, illegal command field,
50                                   unclaimed cycle (host initiated), or bus errors (collisions).
51   @retval EFI_INVALID_PARAMETER   Operation is not defined in EFI_SMBUS_OPERATION.
52   @retval EFI_INVALID_PARAMETER   Length/Buffer is NULL for operations except for EfiSmbusQuickRead
53                                   and EfiSmbusQuickWrite. Length is outside the range of valid
54                                   values.
55   @retval EFI_UNSUPPORTED         The SMBus operation or PEC is not supported.
56   @retval EFI_BUFFER_TOO_SMALL    Buffer is not sufficient for this operation.
57 
58 **/
59 EFI_STATUS
SmbusExecute(IN UINTN SmbusAddress,IN EFI_SMBUS_OPERATION Operation,IN OUT UINTN * Length,IN OUT VOID * Buffer)60 SmbusExecute (
61   IN     UINTN                    SmbusAddress,
62   IN     EFI_SMBUS_OPERATION      Operation,
63   IN OUT UINTN                    *Length,
64   IN OUT VOID                     *Buffer
65   )
66 {
67   EFI_STATUS                      Status;
68   UINT8                           WorkBuffer[MAX_SMBUS_BLOCK_LEN];
69 
70   switch (Operation) {
71     case EfiSmbusQuickRead:
72       DEBUG ((EFI_D_INFO, "EfiSmbusQuickRead - 0x%08x\n", SmbusAddress));
73       SmBusQuickRead (SmbusAddress, &Status);
74       break;
75     case EfiSmbusQuickWrite:
76       DEBUG ((EFI_D_INFO, "EfiSmbusQuickWrite - 0x%08x\n", SmbusAddress));
77       SmBusQuickWrite (SmbusAddress, &Status);
78       break;
79     case EfiSmbusReceiveByte:
80       DEBUG ((EFI_D_INFO, "EfiSmbusReceiveByte - 0x%08x\n", SmbusAddress));
81       SmBusReceiveByte (SmbusAddress, &Status);
82       break;
83     case EfiSmbusSendByte:
84       DEBUG ((EFI_D_INFO, "EfiSmbusSendByte - 0x%08x (0x%02x)\n", SmbusAddress, (UINTN)*(UINT8 *) Buffer));
85       SmBusSendByte (SmbusAddress, *(UINT8 *) Buffer, &Status);
86       break;
87     case EfiSmbusReadByte:
88       DEBUG ((EFI_D_INFO, "EfiSmbusReadByte - 0x%08x\n", SmbusAddress));
89       SmBusReadDataByte (SmbusAddress, &Status);
90       break;
91     case EfiSmbusWriteByte:
92       DEBUG ((EFI_D_INFO, "EfiSmbusWriteByte - 0x%08x (0x%02x)\n", SmbusAddress, (UINTN)*(UINT8 *) Buffer));
93       SmBusWriteDataByte (SmbusAddress, *(UINT8 *) Buffer, &Status);
94       break;
95     case EfiSmbusReadWord:
96       DEBUG ((EFI_D_INFO, "EfiSmbusReadWord - 0x%08x\n", SmbusAddress));
97       SmBusReadDataWord (SmbusAddress, &Status);
98       break;
99     case EfiSmbusWriteWord:
100       DEBUG ((EFI_D_INFO, "EfiSmbusWriteWord - 0x%08x (0x%04x)\n", SmbusAddress, (UINTN)*(UINT16 *) Buffer));
101       SmBusWriteDataWord (SmbusAddress, *(UINT16 *) Buffer, &Status);
102       break;
103     case EfiSmbusProcessCall:
104       DEBUG ((EFI_D_INFO, "EfiSmbusProcessCall - 0x%08x (0x%04x)\n", SmbusAddress, (UINTN)*(UINT16 *) Buffer));
105       SmBusProcessCall (SmbusAddress, *(UINT16 *) Buffer, &Status);
106       break;
107     case EfiSmbusReadBlock:
108       DEBUG ((EFI_D_INFO, "EfiSmbusReadBlock - 0x%08x\n", SmbusAddress));
109       SmBusReadBlock (SmbusAddress, WorkBuffer, &Status);
110       break;
111     case EfiSmbusWriteBlock:
112       DEBUG ((EFI_D_INFO, "EfiSmbusWriteBlock - 0x%08x\n", SmbusAddress));
113       SmBusWriteBlock ((SmbusAddress + SMBUS_LIB_ADDRESS (0, 0, (*Length), FALSE)), Buffer, &Status);
114       break;
115     case EfiSmbusBWBRProcessCall:
116       DEBUG ((EFI_D_INFO, "EfiSmbusBWBRProcessCall - 0x%08x\n", SmbusAddress));
117       SmBusBlockProcessCall ((SmbusAddress + SMBUS_LIB_ADDRESS (0, 0, (*Length), FALSE)), Buffer, WorkBuffer, &Status);
118       break;
119     default:
120       return EFI_INVALID_PARAMETER;
121   }
122 
123   return Status;
124 }
125 
126 /**
127   Translates boot script width and address stride to MDE library interface.
128 
129 
130   @param Width          Width of the operation.
131   @param Address        Address of the operation.
132   @param AddressStride  Instride for stepping input buffer.
133   @param BufferStride   Outstride for stepping output buffer.
134 
135   @retval EFI_SUCCESS  Successful translation.
136   @retval EFI_INVALID_PARAMETER Width or Address is invalid.
137 **/
138 EFI_STATUS
BuildLoopData(IN S3_BOOT_SCRIPT_LIB_WIDTH Width,IN UINT64 Address,OUT UINTN * AddressStride,OUT UINTN * BufferStride)139 BuildLoopData (
140   IN  S3_BOOT_SCRIPT_LIB_WIDTH      Width,
141   IN  UINT64                    Address,
142   OUT UINTN                     *AddressStride,
143   OUT UINTN                     *BufferStride
144   )
145 {
146   UINTN AlignMask;
147 
148   if (Width >= S3BootScriptWidthMaximum) {
149     return EFI_INVALID_PARAMETER;
150   }
151 
152   *AddressStride  = (UINT32)(1 << (Width & 0x03));
153   *BufferStride   = *AddressStride;
154 
155   AlignMask       = *AddressStride - 1;
156   if ((Address & AlignMask) != 0) {
157     return EFI_INVALID_PARAMETER;
158   }
159 
160   if (Width >= S3BootScriptWidthFifoUint8 && Width <= S3BootScriptWidthFifoUint64) {
161     *AddressStride = 0;
162   }
163 
164   if (Width >= S3BootScriptWidthFillUint8 && Width <= S3BootScriptWidthFillUint64) {
165     *BufferStride = 0;
166   }
167 
168   return EFI_SUCCESS;
169 }
170 
171 /**
172   Perform IO read operation
173 
174   @param[in]  Width   Width of the operation.
175   @param[in]  Address Address of the operation.
176   @param[in]  Count   Count of the number of accesses to perform.
177   @param[out] Buffer  Pointer to the buffer to read from I/O space.
178 
179   @retval EFI_SUCCESS The data was written to the EFI System.
180   @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
181                                 Buffer is NULL.
182                                 The Buffer is not aligned for the given Width.
183                                 Address is outside the legal range of I/O ports.
184 
185 **/
186 EFI_STATUS
ScriptIoRead(IN S3_BOOT_SCRIPT_LIB_WIDTH Width,IN UINT64 Address,IN UINTN Count,OUT VOID * Buffer)187 ScriptIoRead (
188   IN      S3_BOOT_SCRIPT_LIB_WIDTH Width,
189   IN      UINT64                   Address,
190   IN      UINTN                    Count,
191   OUT     VOID                     *Buffer
192   )
193 {
194   EFI_STATUS  Status;
195   UINTN       AddressStride;
196   UINTN       BufferStride;
197   PTR         Out;
198 
199   Out.Buf = (UINT8 *) Buffer;
200 
201   if (Address > MAX_IO_ADDRESS) {
202     return EFI_INVALID_PARAMETER;
203   }
204 
205   Status = BuildLoopData (Width, Address, &AddressStride, &BufferStride);
206   if (EFI_ERROR (Status)) {
207     return Status;
208   }
209   //
210   // Loop for each iteration and move the data
211   //
212   for (; Count > 0; Count--, Address += AddressStride, Out.Buf += BufferStride) {
213     switch (Width) {
214 
215     case S3BootScriptWidthUint8:
216       DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%08x\n", (UINTN) Address));
217       *Out.Uint8 = IoRead8 ((UINTN) Address);
218       break;
219     case S3BootScriptWidthFifoUint8:
220       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%08x\n", (UINTN) Address));
221       *Out.Uint8 = IoRead8 ((UINTN) Address);
222       break;
223     case S3BootScriptWidthFillUint8:
224       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%08x\n", (UINTN) Address));
225       *Out.Uint8 = IoRead8 ((UINTN) Address);
226       break;
227 
228     case S3BootScriptWidthUint16:
229       DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%08x\n", (UINTN) Address));
230       *Out.Uint16 = IoRead16 ((UINTN) Address);
231       break;
232     case S3BootScriptWidthFifoUint16:
233       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%08x\n", (UINTN) Address));
234       *Out.Uint16 = IoRead16 ((UINTN) Address);
235       break;
236     case S3BootScriptWidthFillUint16:
237       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%08x\n", (UINTN) Address));
238       *Out.Uint16 = IoRead16 ((UINTN) Address);
239       break;
240 
241     case S3BootScriptWidthUint32:
242       DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%08x\n", (UINTN) Address));
243       *Out.Uint32 = IoRead32 ((UINTN) Address);
244       break;
245     case S3BootScriptWidthFifoUint32:
246       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%08x\n", (UINTN) Address));
247       *Out.Uint32 = IoRead32 ((UINTN) Address);
248       break;
249     case S3BootScriptWidthFillUint32:
250       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%08x\n", (UINTN) Address));
251       *Out.Uint32 = IoRead32 ((UINTN) Address);
252       break;
253 
254     case S3BootScriptWidthUint64:
255       DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint64 - 0x%08x\n", (UINTN) Address));
256       *Out.Uint64 = IoRead64 ((UINTN) Address);
257       break;
258     case S3BootScriptWidthFifoUint64:
259       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint64 - 0x%08x\n", (UINTN) Address));
260       *Out.Uint64 = IoRead64 ((UINTN) Address);
261       break;
262     case S3BootScriptWidthFillUint64:
263       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint64 - 0x%08x\n", (UINTN) Address));
264       *Out.Uint64 = IoRead64 ((UINTN) Address);
265       break;
266 
267     default:
268       return EFI_INVALID_PARAMETER;
269     }
270   }
271 
272   return EFI_SUCCESS;
273 }
274 
275 /**
276   Perform IO write operation
277 
278   @param[in]  Width Width of the operation.
279   @param[in]  Address Address of the operation.
280   @param[in]  Count Count of the number of accesses to perform.
281   @param[in]  Buffer Pointer to the buffer to write to I/O space.
282 
283   @retval EFI_SUCCESS The data was written to the EFI System.
284   @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
285                                 Buffer is NULL.
286                                 The Buffer is not aligned for the given Width.
287                                 Address is outside the legal range of I/O ports.
288 
289 **/
290 EFI_STATUS
ScriptIoWrite(IN S3_BOOT_SCRIPT_LIB_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN VOID * Buffer)291 ScriptIoWrite (
292   IN      S3_BOOT_SCRIPT_LIB_WIDTH  Width,
293   IN      UINT64                 Address,
294   IN      UINTN                  Count,
295   IN      VOID                   *Buffer
296   )
297 {
298   EFI_STATUS  Status;
299   UINTN       AddressStride;
300   UINTN       BufferStride;
301   UINT64      OriginalAddress;
302   PTR         In;
303   PTR         OriginalIn;
304 
305   In.Buf = (UINT8 *) Buffer;
306 
307   if (Address > MAX_IO_ADDRESS) {
308     return EFI_INVALID_PARAMETER;
309   }
310 
311   Status = BuildLoopData (Width, Address, &AddressStride, &BufferStride);
312   if (EFI_ERROR (Status)) {
313     return Status;
314   }
315   //
316   // Loop for each iteration and move the data
317   //
318   OriginalAddress = Address;
319   OriginalIn.Buf = In.Buf;
320   for (; Count > 0; Count--, Address += AddressStride, In.Buf += BufferStride) {
321     switch (Width) {
322       case S3BootScriptWidthUint8:
323         DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%08x (0x%02x)\n", (UINTN)Address, (UINTN)*In.Uint8));
324         IoWrite8 ((UINTN) Address, *In.Uint8);
325         break;
326       case S3BootScriptWidthFifoUint8:
327         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%08x (0x%02x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint8));
328         IoWrite8 ((UINTN) OriginalAddress, *In.Uint8);
329         break;
330       case S3BootScriptWidthFillUint8:
331         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%08x (0x%02x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint8));
332         IoWrite8 ((UINTN) Address, *OriginalIn.Uint8);
333         break;
334       case S3BootScriptWidthUint16:
335         DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%08x (0x%04x)\n", (UINTN)Address, (UINTN)*In.Uint16));
336         IoWrite16 ((UINTN) Address, *In.Uint16);
337         break;
338       case S3BootScriptWidthFifoUint16:
339         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%08x (0x%04x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint16));
340         IoWrite16 ((UINTN) OriginalAddress, *In.Uint16);
341         break;
342       case S3BootScriptWidthFillUint16:
343         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%08x (0x%04x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint16));
344         IoWrite16 ((UINTN) Address, *OriginalIn.Uint16);
345         break;
346       case S3BootScriptWidthUint32:
347         DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%08x (0x%08x)\n", (UINTN)Address, (UINTN)*In.Uint32));
348         IoWrite32 ((UINTN) Address, *In.Uint32);
349         break;
350       case S3BootScriptWidthFifoUint32:
351         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%08x (0x%08x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint32));
352         IoWrite32 ((UINTN) OriginalAddress, *In.Uint32);
353         break;
354       case S3BootScriptWidthFillUint32:
355         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%08x (0x%08x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint32));
356         IoWrite32 ((UINTN) Address, *OriginalIn.Uint32);
357         break;
358       case S3BootScriptWidthUint64:
359         DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint64 - 0x%08x (0x%016lx)\n", (UINTN)Address, *In.Uint64));
360         IoWrite64 ((UINTN) Address, *In.Uint64);
361         break;
362       case S3BootScriptWidthFifoUint64:
363         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint64 - 0x%08x (0x%016lx)\n", (UINTN)OriginalAddress, *In.Uint64));
364         IoWrite64 ((UINTN) OriginalAddress, *In.Uint64);
365         break;
366       case S3BootScriptWidthFillUint64:
367         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint64 - 0x%08x (0x%016lx)\n", (UINTN)Address, *OriginalIn.Uint64));
368         IoWrite64 ((UINTN) Address, *OriginalIn.Uint64);
369         break;
370       default:
371         return EFI_INVALID_PARAMETER;
372     }
373   }
374 
375 
376   return EFI_SUCCESS;
377 }
378 /**
379   Interprete the boot script node with EFI_BOOT_SCRIPT_IO_WRITE OP code.
380 
381   @param Script       Pointer to the node which is to be interpreted.
382 
383   @retval EFI_SUCCESS The data was written to the EFI System.
384   @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
385                                 Buffer is NULL.
386                                 The Buffer is not aligned for the given Width.
387                                 Address is outside the legal range of I/O ports.
388 
389 **/
390 EFI_STATUS
BootScriptExecuteIoWrite(IN UINT8 * Script)391 BootScriptExecuteIoWrite (
392   IN UINT8                    *Script
393   )
394 {
395   S3_BOOT_SCRIPT_LIB_WIDTH   Width;
396   UINT64                     Address;
397   UINTN                      Count;
398   VOID                      *Buffer;
399   EFI_BOOT_SCRIPT_IO_WRITE   IoWrite;
400 
401   CopyMem ((VOID*)&IoWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_IO_WRITE));
402   Width = (S3_BOOT_SCRIPT_LIB_WIDTH) IoWrite.Width;
403   Address = IoWrite.Address;
404   Count = IoWrite.Count;
405   Buffer = Script + sizeof (EFI_BOOT_SCRIPT_IO_WRITE);
406 
407   DEBUG ((EFI_D_INFO, "BootScriptExecuteIoWrite - 0x%08x, 0x%08x, 0x%08x\n", (UINTN)Address, Count, (UINTN)Width));
408   return ScriptIoWrite(Width, Address, Count, Buffer);
409 }
410 /**
411   Perform memory read operation
412 
413   @param  Width Width of the operation.
414   @param  Address Address of the operation.
415   @param  Count Count of the number of accesses to perform.
416   @param  Buffer Pointer to the buffer read from memory.
417 
418   @retval EFI_SUCCESS The data was written to the EFI System.
419   @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
420                                 Buffer is NULL.
421                                 The Buffer is not aligned for the given Width.
422   @retval EFI_UNSUPPORTED The address range specified by Address, Width, and Count
423                           is not valid for this EFI System.
424 
425 **/
426 EFI_STATUS
ScriptMemoryRead(IN S3_BOOT_SCRIPT_LIB_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)427 ScriptMemoryRead (
428   IN       S3_BOOT_SCRIPT_LIB_WIDTH    Width,
429   IN       UINT64                   Address,
430   IN       UINTN                    Count,
431   IN OUT   VOID                     *Buffer
432   )
433 {
434   EFI_STATUS  Status;
435   UINTN       AddressStride;
436   UINTN       BufferStride;
437   PTR         Out;
438 
439   Out.Buf = Buffer;
440 
441   Status  = BuildLoopData (Width, Address, &AddressStride, &BufferStride);
442   if (EFI_ERROR (Status)) {
443     return Status;
444   }
445   //
446   // Loop for each iteration and move the data
447   //
448   for (; Count > 0; Count--, Address += AddressStride, Out.Buf += BufferStride) {
449     switch (Width) {
450     case S3BootScriptWidthUint8:
451       DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%08x\n", (UINTN)Address));
452       *Out.Uint8 = MmioRead8 ((UINTN) Address);
453       break;
454     case S3BootScriptWidthFifoUint8:
455       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%08x\n", (UINTN)Address));
456       *Out.Uint8 = MmioRead8 ((UINTN) Address);
457       break;
458     case S3BootScriptWidthFillUint8:
459       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%08x\n", (UINTN)Address));
460       *Out.Uint8 = MmioRead8 ((UINTN) Address);
461       break;
462 
463     case S3BootScriptWidthUint16:
464       DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%08x\n", (UINTN)Address));
465       *Out.Uint16 = MmioRead16 ((UINTN) Address);
466       break;
467     case S3BootScriptWidthFifoUint16:
468       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%08x\n", (UINTN)Address));
469       *Out.Uint16 = MmioRead16 ((UINTN) Address);
470       break;
471     case S3BootScriptWidthFillUint16:
472       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%08x\n", (UINTN)Address));
473       *Out.Uint16 = MmioRead16 ((UINTN) Address);
474       break;
475 
476     case S3BootScriptWidthUint32:
477       DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%08x\n", (UINTN)Address));
478       *Out.Uint32 = MmioRead32 ((UINTN) Address);
479       break;
480     case S3BootScriptWidthFifoUint32:
481       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%08x\n", (UINTN)Address));
482       *Out.Uint32 = MmioRead32 ((UINTN) Address);
483       break;
484     case S3BootScriptWidthFillUint32:
485       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%08x\n", (UINTN)Address));
486       *Out.Uint32 = MmioRead32 ((UINTN) Address);
487       break;
488 
489     case S3BootScriptWidthUint64:
490       DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint64 - 0x%08x\n", (UINTN)Address));
491       *Out.Uint64 = MmioRead64 ((UINTN) Address);
492       break;
493     case S3BootScriptWidthFifoUint64:
494       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint64 - 0x%08x\n", (UINTN)Address));
495       *Out.Uint64 = MmioRead64 ((UINTN) Address);
496       break;
497     case S3BootScriptWidthFillUint64:
498       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint64 - 0x%08x\n", (UINTN)Address));
499       *Out.Uint64 = MmioRead64 ((UINTN) Address);
500       break;
501 
502     default:
503       return EFI_UNSUPPORTED;
504     }
505   }
506 
507   return EFI_SUCCESS;
508 }
509 /**
510   Perform memory write operation
511 
512   @param   Width   Width of the operation.
513   @param   Address Address of the operation.
514   @param   Count   Count of the number of accesses to perform.
515   @param   Buffer  Pointer to the buffer write to memory.
516 
517   @retval EFI_SUCCESS The data was written to the EFI System.
518   @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
519                                 Buffer is NULL.
520                                 The Buffer is not aligned for the given Width.
521   @retval EFI_UNSUPPORTED The address range specified by Address, Width, and Count
522                           is not valid for this EFI System.
523 
524 **/
525 EFI_STATUS
ScriptMemoryWrite(IN S3_BOOT_SCRIPT_LIB_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN OUT VOID * Buffer)526 ScriptMemoryWrite (
527   IN      S3_BOOT_SCRIPT_LIB_WIDTH Width,
528   IN      UINT64                Address,
529   IN      UINTN                 Count,
530   IN OUT  VOID                 *Buffer
531   )
532 {
533   EFI_STATUS  Status;
534   UINTN       AddressStride;
535   UINT64      OriginalAddress;
536   UINTN       BufferStride;
537   PTR         In;
538   PTR         OriginalIn;
539 
540   In.Buf  = Buffer;
541 
542   Status  = BuildLoopData (Width, Address, &AddressStride, &BufferStride);
543   if (EFI_ERROR (Status)) {
544     return Status;
545   }
546   //
547   // Loop for each iteration and move the data
548   //
549   OriginalAddress = Address;
550   OriginalIn.Buf = In.Buf;
551   for (; Count > 0; Count--, Address += AddressStride, In.Buf += BufferStride) {
552     switch (Width) {
553       case S3BootScriptWidthUint8:
554         DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%08x (0x%02x)\n", (UINTN)Address, (UINTN)*In.Uint8));
555         MmioWrite8 ((UINTN) Address, *In.Uint8);
556         break;
557       case S3BootScriptWidthFifoUint8:
558         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%08x (0x%02x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint8));
559         MmioWrite8 ((UINTN) OriginalAddress, *In.Uint8);
560         break;
561       case S3BootScriptWidthFillUint8:
562         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%08x (0x%02x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint8));
563         MmioWrite8 ((UINTN) Address, *OriginalIn.Uint8);
564         break;
565       case S3BootScriptWidthUint16:
566         DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%08x (0x%04x)\n", (UINTN)Address, (UINTN)*In.Uint16));
567         MmioWrite16 ((UINTN) Address, *In.Uint16);
568         break;
569       case S3BootScriptWidthFifoUint16:
570         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%08x (0x%04x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint16));
571         MmioWrite16 ((UINTN) OriginalAddress, *In.Uint16);
572         break;
573       case S3BootScriptWidthFillUint16:
574         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%08x (0x%04x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint16));
575         MmioWrite16 ((UINTN) Address, *OriginalIn.Uint16);
576         break;
577       case S3BootScriptWidthUint32:
578         DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%08x (0x%08x)\n", (UINTN)Address, (UINTN)*In.Uint32));
579         MmioWrite32 ((UINTN) Address, *In.Uint32);
580         break;
581       case S3BootScriptWidthFifoUint32:
582         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%08x (0x%08x)\n", (UINTN)OriginalAddress, (UINTN)*In.Uint32));
583         MmioWrite32 ((UINTN) OriginalAddress, *In.Uint32);
584         break;
585       case S3BootScriptWidthFillUint32:
586         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%08x (0x%08x)\n", (UINTN)Address, (UINTN)*OriginalIn.Uint32));
587         MmioWrite32 ((UINTN) Address, *OriginalIn.Uint32);
588         break;
589       case S3BootScriptWidthUint64:
590         DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint64 - 0x%08x (0x%016lx)\n", (UINTN)Address, *In.Uint64));
591         MmioWrite64 ((UINTN) Address, *In.Uint64);
592         break;
593       case S3BootScriptWidthFifoUint64:
594         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint64 - 0x%08x (0x%016lx)\n", (UINTN)OriginalAddress, *In.Uint64));
595         MmioWrite64 ((UINTN) OriginalAddress, *In.Uint64);
596         break;
597       case S3BootScriptWidthFillUint64:
598         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint64 - 0x%08x (0x%016lx)\n", (UINTN)Address, *OriginalIn.Uint64));
599         MmioWrite64 ((UINTN) Address, *OriginalIn.Uint64);
600         break;
601       default:
602         return EFI_UNSUPPORTED;
603     }
604   }
605   return EFI_SUCCESS;
606 }
607 /**
608   Interprete the boot script node with EFI_BOOT_SCRIPT_MEM_WRITE OP code.
609 
610   @param[in]  Script Pointer to the node which is to be interpreted.
611 
612   @retval EFI_SUCCESS The data was written to the EFI System.
613   @retval EFI_INVALID_PARAMETER Width is invalid for this EFI System.
614                                 Buffer is NULL.
615                                 The Buffer is not aligned for the given Width.
616   @retval EFI_UNSUPPORTED The address range specified by Address, Width, and Count
617                           is not valid for this EFI System.
618 
619 **/
620 EFI_STATUS
BootScriptExecuteMemoryWrite(IN UINT8 * Script)621 BootScriptExecuteMemoryWrite (
622   IN UINT8             *Script
623   )
624 {
625   VOID            *Buffer;
626   S3_BOOT_SCRIPT_LIB_WIDTH Width;
627   UINT64           Address;
628   UINTN            Count;
629   EFI_BOOT_SCRIPT_MEM_WRITE  MemWrite;
630 
631   CopyMem((VOID*)&MemWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_MEM_WRITE));
632   Width   = (S3_BOOT_SCRIPT_LIB_WIDTH)MemWrite.Width;
633   Address = MemWrite.Address;
634   Count   = MemWrite.Count;
635   Buffer  = Script + sizeof(EFI_BOOT_SCRIPT_MEM_WRITE);
636 
637   DEBUG ((EFI_D_INFO, "BootScriptExecuteMemoryWrite - 0x%08x, 0x%08x, 0x%08x\n", (UINTN)Address, Count, (UINTN)Width));
638   return ScriptMemoryWrite (Width,Address, Count,  Buffer);
639 
640 }
641 /**
642   Performance PCI configuration 2 read operation
643 
644   @param  Width   Width of the operation.
645   @param  Segment Pci segment number
646   @param  Address Address of the operation.
647   @param  Count   Count of the number of accesses to perform.
648   @param  Buffer  Pointer to the buffer read from PCI config space
649 
650   @retval EFI_SUCCESS The read succeed.
651   @retval EFI_INVALID_PARAMETER if Width is not defined
652   @note  A known Limitations in the implementation which is 64bits operations are not supported.
653 
654 **/
655 EFI_STATUS
ScriptPciCfg2Read(IN S3_BOOT_SCRIPT_LIB_WIDTH Width,IN UINT16 Segment,IN UINT64 Address,IN UINTN Count,OUT VOID * Buffer)656 ScriptPciCfg2Read (
657   IN  S3_BOOT_SCRIPT_LIB_WIDTH    Width,
658   IN  UINT16                       Segment,
659   IN  UINT64                       Address,
660   IN  UINTN                        Count,
661   OUT VOID                        *Buffer
662   )
663 {
664   EFI_STATUS  Status;
665   UINTN       AddressStride;
666   UINTN       BufferStride;
667   PTR         Out;
668   UINT64      PciAddress;
669 
670   Out.Buf = (UINT8 *) Buffer;
671 
672   PciAddress = PCI_ADDRESS_ENCODE (Segment, Address);
673 
674   Status = BuildLoopData (Width, PciAddress, &AddressStride, &BufferStride);
675   if (EFI_ERROR (Status)) {
676     return Status;
677   }
678   //
679   // Loop for each iteration and move the data
680   //
681   for (; Count > 0; Count--, PciAddress += AddressStride, Out.Buf += BufferStride) {
682     switch (Width) {
683     case S3BootScriptWidthUint8:
684       DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%016lx\n", PciAddress));
685       *Out.Uint8 = PciSegmentRead8 (PciAddress);
686       break;
687     case S3BootScriptWidthFifoUint8:
688       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%016lx\n", PciAddress));
689       *Out.Uint8 = PciSegmentRead8 (PciAddress);
690       break;
691     case S3BootScriptWidthFillUint8:
692       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%016lx\n", PciAddress));
693       *Out.Uint8 = PciSegmentRead8 (PciAddress);
694       break;
695 
696     case S3BootScriptWidthUint16:
697       DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%016lx\n", PciAddress));
698       *Out.Uint16 = PciSegmentRead16 (PciAddress);
699       break;
700     case S3BootScriptWidthFifoUint16:
701       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%016lx\n", PciAddress));
702       *Out.Uint16 = PciSegmentRead16 (PciAddress);
703       break;
704     case S3BootScriptWidthFillUint16:
705       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%016lx\n", PciAddress));
706       *Out.Uint16 = PciSegmentRead16 (PciAddress);
707       break;
708 
709     case S3BootScriptWidthUint32:
710       DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%016lx\n", PciAddress));
711       *Out.Uint32 = PciSegmentRead32 (PciAddress);
712       break;
713     case S3BootScriptWidthFifoUint32:
714       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%016lx\n", PciAddress));
715       *Out.Uint32 = PciSegmentRead32 (PciAddress);
716       break;
717     case S3BootScriptWidthFillUint32:
718       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%016lx\n", PciAddress));
719       *Out.Uint32 = PciSegmentRead32 (PciAddress);
720       break;
721 
722     default:
723       return EFI_INVALID_PARAMETER;
724     }
725   }
726   return EFI_SUCCESS;
727 }
728 
729 /**
730   Performance PCI configuration 2 write operation
731 
732   @param  Width   Width of the operation.
733   @param  Segment Pci segment number
734   @param  Address Address of the operation.
735   @param  Count   Count of the number of accesses to perform.
736   @param  Buffer  Pointer to the buffer write to PCI config space
737 
738   @retval EFI_SUCCESS The write succeed.
739   @retval EFI_INVALID_PARAMETER if Width is not defined
740   @note  A known Limitations in the implementation which is 64bits operations are not supported.
741 
742 **/
743 EFI_STATUS
ScriptPciCfg2Write(IN S3_BOOT_SCRIPT_LIB_WIDTH Width,IN UINT16 Segment,IN UINT64 Address,IN UINTN Count,IN VOID * Buffer)744 ScriptPciCfg2Write (
745   IN  S3_BOOT_SCRIPT_LIB_WIDTH     Width,
746   IN  UINT16                       Segment,
747   IN  UINT64                       Address,
748   IN  UINTN                        Count,
749   IN  VOID                         *Buffer
750   )
751 {
752   EFI_STATUS  Status;
753   UINTN       AddressStride;
754   UINTN       BufferStride;
755   UINT64      OriginalPciAddress;
756   PTR         In;
757   PTR         OriginalIn;
758   UINT64      PciAddress;
759 
760   In.Buf = (UINT8 *) Buffer;
761 
762   PciAddress = PCI_ADDRESS_ENCODE (Segment, Address);
763 
764   Status = BuildLoopData (Width, PciAddress, &AddressStride, &BufferStride);
765   if (EFI_ERROR (Status)) {
766     return Status;
767   }
768   //
769   // Loop for each iteration and move the data
770   //
771   OriginalPciAddress = PciAddress;
772   OriginalIn.Buf = In.Buf;
773   for (; Count > 0; Count--, PciAddress += AddressStride, In.Buf += BufferStride) {
774     switch (Width) {
775       case S3BootScriptWidthUint8:
776         DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%016lx (0x%02x)\n", PciAddress, (UINTN)*In.Uint8));
777         PciSegmentWrite8 (PciAddress, *In.Uint8);
778         break;
779       case S3BootScriptWidthFifoUint8:
780         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%016lx (0x%02x)\n", OriginalPciAddress, (UINTN)*In.Uint8));
781         PciSegmentWrite8 (OriginalPciAddress, *In.Uint8);
782         break;
783       case S3BootScriptWidthFillUint8:
784         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%016lx (0x%02x)\n", PciAddress, (UINTN)*OriginalIn.Uint8));
785         PciSegmentWrite8 (PciAddress, *OriginalIn.Uint8);
786         break;
787       case S3BootScriptWidthUint16:
788         DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%016lx (0x%04x)\n", PciAddress, (UINTN)*In.Uint16));
789         PciSegmentWrite16 (PciAddress, *In.Uint16);
790         break;
791       case S3BootScriptWidthFifoUint16:
792         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%016lx (0x%04x)\n", OriginalPciAddress, (UINTN)*In.Uint16));
793         PciSegmentWrite16 (OriginalPciAddress, *In.Uint16);
794         break;
795       case S3BootScriptWidthFillUint16:
796         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%016lx (0x%04x)\n", PciAddress, (UINTN)*OriginalIn.Uint16));
797         PciSegmentWrite16 (PciAddress, *OriginalIn.Uint16);
798         break;
799       case S3BootScriptWidthUint32:
800         DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%016lx (0x%08x)\n", PciAddress, (UINTN)*In.Uint32));
801         PciSegmentWrite32 (PciAddress, *In.Uint32);
802         break;
803       case S3BootScriptWidthFifoUint32:
804         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%016lx (0x%08x)\n", OriginalPciAddress, (UINTN)*In.Uint32));
805         PciSegmentWrite32 (OriginalPciAddress, *In.Uint32);
806         break;
807       case S3BootScriptWidthFillUint32:
808         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%016lx (0x%08x)\n", (UINTN)PciAddress, (UINTN)*OriginalIn.Uint32));
809         PciSegmentWrite32 (PciAddress, *OriginalIn.Uint32);
810         break;
811       default:
812         return EFI_INVALID_PARAMETER;
813     }
814   }
815   return EFI_SUCCESS;
816 }
817 /**
818   Performance PCI configuration read operation
819 
820   @param     Width                      Width of the operation.
821   @param     Address                    Address of the operation.
822   @param     Count                      Count of the number of accesses to perform.
823   @param     Buffer                     Pointer to the buffer to read from PCI config space.
824 
825   @retval    EFI_SUCCESS                The data was written to the EFI System.
826   @retval    EFI_INVALID_PARAMETER      Width is invalid for this EFI System.
827                                         Buffer is NULL.
828                                         The Buffer is not aligned for the given Width.
829                                         Address is outside the legal range of I/O ports.
830 
831 **/
832 EFI_STATUS
ScriptPciCfgRead(IN S3_BOOT_SCRIPT_LIB_WIDTH Width,IN UINT64 Address,IN UINTN Count,OUT VOID * Buffer)833 ScriptPciCfgRead (
834   IN  S3_BOOT_SCRIPT_LIB_WIDTH    Width,
835   IN  UINT64                   Address,
836   IN  UINTN                    Count,
837   OUT VOID                     *Buffer
838   )
839 {
840   return ScriptPciCfg2Read (Width, 0, Address, Count, Buffer);
841 }
842 /**
843   Performance PCI configuration write operation
844 
845   @param     Width                      Width of the operation.
846   @param     Address                    Address of the operation.
847   @param     Count                      Count of the number of accesses to perform.
848   @param     Buffer                     Pointer to the buffer to write to PCI config space.
849 
850   @retval    EFI_SUCCESS                The data was written to the EFI System.
851   @retval    EFI_INVALID_PARAMETER      Width is invalid for this EFI System.
852                                         Buffer is NULL.
853                                         The Buffer is not aligned for the given Width.
854                                         Address is outside the legal range of I/O ports.
855 
856 **/
857 EFI_STATUS
858 EFIAPI
ScriptPciCfgWrite(IN S3_BOOT_SCRIPT_LIB_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN VOID * Buffer)859 ScriptPciCfgWrite (
860   IN  S3_BOOT_SCRIPT_LIB_WIDTH    Width,
861   IN  UINT64                   Address,
862   IN  UINTN                    Count,
863   IN  VOID                     *Buffer
864   )
865 {
866   return ScriptPciCfg2Write (Width, 0, Address, Count, Buffer);
867 }
868 /**
869   Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE OP code.
870 
871   @param  Script        The pointer of typed node in boot script table
872 
873   @retval EFI_SUCCESS  The operation was executed successfully
874 **/
875 EFI_STATUS
BootScriptExecutePciCfgWrite(IN UINT8 * Script)876 BootScriptExecutePciCfgWrite (
877   IN UINT8                    *Script
878   )
879 {
880   VOID                              *Buffer;
881   S3_BOOT_SCRIPT_LIB_WIDTH          Width;
882   UINT64                            Address;
883   UINTN                             Count;
884   EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE  PciCfgWrite;
885 
886   CopyMem ((VOID*)&PciCfgWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE));
887 
888   Width   = (S3_BOOT_SCRIPT_LIB_WIDTH)PciCfgWrite.Width;
889   Address = PciCfgWrite.Address;
890   Count   = PciCfgWrite.Count;
891   Buffer  = Script + sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE);
892 
893   DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfgWrite - 0x%016lx, 0x%08x, 0x%08x\n", PCI_ADDRESS_ENCODE (0, Address), Count, (UINTN)Width));
894   return ScriptPciCfgWrite (Width, Address, Count, Buffer);
895 }
896 /**
897   Interprete the boot script node with EFI_BOOT_SCRIPT_IO_READ_WRITE OP code.
898 
899   @param Script   The pointer of typed node in boot script table
900   @param AndMask  Mask value for 'and' operation
901   @param OrMask   Mask value for 'or' operation
902 
903   @retval EFI_SUCCESS    The operation was executed successfully
904 **/
905 EFI_STATUS
BootScriptExecuteIoReadWrite(IN UINT8 * Script,IN UINT64 AndMask,IN UINT64 OrMask)906 BootScriptExecuteIoReadWrite (
907   IN  UINT8                        *Script,
908   IN  UINT64                       AndMask,
909   IN  UINT64                        OrMask
910   )
911 
912 {
913   EFI_STATUS  Status;
914   UINT64      Data;
915   EFI_BOOT_SCRIPT_IO_READ_WRITE IoReadWrite;
916 
917   Data = 0;
918 
919   CopyMem((VOID*)&IoReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_IO_READ_WRITE));
920 
921   DEBUG ((EFI_D_INFO, "BootScriptExecuteIoReadWrite - 0x%08x, 0x%016lx, 0x%016lx\n", (UINTN)IoReadWrite.Address, AndMask, OrMask));
922 
923   Status = ScriptIoRead (
924              (S3_BOOT_SCRIPT_LIB_WIDTH) IoReadWrite.Width,
925              IoReadWrite.Address,
926              1,
927              &Data
928              );
929   if (!EFI_ERROR (Status)) {
930     Data = (Data & AndMask) | OrMask;
931     Status = ScriptIoWrite (
932                (S3_BOOT_SCRIPT_LIB_WIDTH) IoReadWrite.Width,
933                IoReadWrite.Address,
934                1,
935                &Data
936                );
937   }
938   return Status;
939 }
940 /**
941   Interprete the boot script node with EFI_BOOT_SCRIPT_MEM_READ_WRITE OP code.
942 
943   @param Script    The pointer of typed node in boot script table
944   @param AndMask   Mask value for 'and' operation
945   @param OrMask    Mask value for 'or' operation
946 
947   @retval EFI_SUCCESS The operation was executed successfully
948 **/
949 EFI_STATUS
BootScriptExecuteMemoryReadWrite(IN UINT8 * Script,IN UINT64 AndMask,IN UINT64 OrMask)950 BootScriptExecuteMemoryReadWrite (
951   IN UINT8                        *Script,
952   IN UINT64                        AndMask,
953   IN UINT64                        OrMask
954   )
955 
956 {
957   EFI_STATUS  Status;
958   UINT64      Data;
959   EFI_BOOT_SCRIPT_MEM_READ_WRITE  MemReadWrite;
960 
961   Data = 0;
962 
963   CopyMem((VOID*)&MemReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_MEM_READ_WRITE));
964 
965   DEBUG ((EFI_D_INFO, "BootScriptExecuteMemoryReadWrite - 0x%08x, 0x%016lx, 0x%016lx\n", (UINTN)MemReadWrite.Address, AndMask, OrMask));
966 
967   Status = ScriptMemoryRead (
968              (S3_BOOT_SCRIPT_LIB_WIDTH) MemReadWrite.Width,
969              MemReadWrite.Address,
970              1,
971              &Data
972              );
973   if (!EFI_ERROR (Status)) {
974     Data = (Data & AndMask) | OrMask;
975     Status = ScriptMemoryWrite (
976                (S3_BOOT_SCRIPT_LIB_WIDTH) MemReadWrite.Width,
977                MemReadWrite.Address,
978                1,
979                &Data
980                );
981   }
982   return Status;
983 }
984 /**
985   Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CFG_READ_WRITE OP code.
986 
987   @param Script   The pointer of typed node in boot script table
988   @param AndMask  Mask value for 'and' operation
989   @param OrMask   Mask value for 'or' operation
990 
991   @retval EFI_SUCCESS   The operation was executed successfully
992 **/
993 EFI_STATUS
BootScriptExecutePciCfgReadWrite(IN UINT8 * Script,IN UINT64 AndMask,IN UINT64 OrMask)994 BootScriptExecutePciCfgReadWrite (
995   IN UINT8                     *Script,
996   IN UINT64                    AndMask,
997   IN UINT64                    OrMask
998   )
999 
1000 {
1001   EFI_STATUS  Status;
1002   UINT64      Data;
1003   EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE  PciCfgReadWrite;
1004 
1005   Data = 0;
1006 
1007   CopyMem((VOID*)&PciCfgReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE));
1008 
1009   DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfgReadWrite - 0x%016lx, 0x%016lx, 0x%016lx\n", PCI_ADDRESS_ENCODE (0, PciCfgReadWrite.Address), AndMask, OrMask));
1010 
1011   Status = ScriptPciCfgRead (
1012              (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgReadWrite.Width,
1013              PciCfgReadWrite.Address,
1014              1,
1015              &Data
1016              );
1017   if (EFI_ERROR (Status)) {
1018     return Status;
1019   }
1020 
1021   Data = (Data & AndMask) | OrMask;
1022 
1023   Status = ScriptPciCfgWrite (
1024              (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgReadWrite.Width,
1025              PciCfgReadWrite.Address,
1026              1,
1027              &Data
1028              );
1029 
1030   return Status;
1031 }
1032 /**
1033   Interprete the boot script node with EFI_BOOT_SCRIPT_SMBUS_EXECUTE OP code.
1034 
1035   @param Script  The pointer of typed node in boot script table
1036 
1037   @retval EFI_SUCCESS      The operation was executed successfully
1038   @retval EFI_UNSUPPORTED  Cannot locate smbus ppi or occur error of script execution
1039   @retval Others           Result of script execution
1040 **/
1041 EFI_STATUS
BootScriptExecuteSmbusExecute(IN UINT8 * Script)1042 BootScriptExecuteSmbusExecute (
1043   IN UINT8                     *Script
1044   )
1045 {
1046   UINTN                    SmBusAddress;
1047   UINTN                    DataSize;
1048   EFI_BOOT_SCRIPT_SMBUS_EXECUTE SmbusExecuteEntry;
1049 
1050   CopyMem ((VOID*)&SmbusExecuteEntry, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_SMBUS_EXECUTE ));
1051 
1052   DEBUG ((EFI_D_INFO, "BootScriptExecuteSmbusExecute - 0x%08x, 0x%08x\n", (UINTN)SmbusExecuteEntry.SmBusAddress, (UINTN)SmbusExecuteEntry.Operation));
1053 
1054   SmBusAddress = (UINTN)SmbusExecuteEntry.SmBusAddress;
1055   DataSize = (UINTN) SmbusExecuteEntry.DataSize;
1056   return SmbusExecute (
1057            SmBusAddress,
1058            (EFI_SMBUS_OPERATION) SmbusExecuteEntry.Operation,
1059            &DataSize,
1060            Script + sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE)
1061            );
1062 }
1063 /**
1064   Interprete the boot script node with EFI_BOOT_SCRIPT_STALL OP code.
1065 
1066   @param Script      The pointer of typed node in boot script table
1067 
1068   @retval EFI_SUCCESS The operation was executed successfully
1069 **/
1070 EFI_STATUS
BootScriptExecuteStall(IN UINT8 * Script)1071 BootScriptExecuteStall (
1072   IN UINT8                 *Script
1073   )
1074 {
1075   EFI_BOOT_SCRIPT_STALL    Stall;
1076 
1077   CopyMem ((VOID*)&Stall, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_STALL));
1078 
1079   DEBUG ((EFI_D_INFO, "BootScriptExecuteStall - 0x%08x\n", (UINTN)Stall.Duration));
1080 
1081   MicroSecondDelay ((UINTN) Stall.Duration);
1082   return EFI_SUCCESS;
1083 }
1084 /**
1085   Interprete the boot script node with EFI_BOOT_SCRIPT_DISPATCH OP code.
1086 
1087   @param Script  The pointer of typed node in boot script table
1088   @retval EFI_SUCCESS  The operation was executed successfully
1089 **/
1090 EFI_STATUS
BootScriptExecuteDispatch(IN UINT8 * Script)1091 BootScriptExecuteDispatch (
1092   IN UINT8                  *Script
1093   )
1094 {
1095   EFI_STATUS                Status;
1096   DISPATCH_ENTRYPOINT_FUNC  EntryFunc;
1097   EFI_BOOT_SCRIPT_DISPATCH  ScriptDispatch;
1098 
1099   CopyMem ((VOID*)&ScriptDispatch, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_DISPATCH));
1100   EntryFunc = (DISPATCH_ENTRYPOINT_FUNC) (UINTN) (ScriptDispatch.EntryPoint);
1101 
1102   DEBUG ((EFI_D_INFO, "BootScriptExecuteDispatch - 0x%08x\n", (UINTN)ScriptDispatch.EntryPoint));
1103 
1104   Status    = EntryFunc (NULL, NULL);
1105 
1106   return Status;
1107 }
1108 /**
1109   Interprete the boot script node with EFI_BOOT_SCRIPT_DISPATCH_2 OP code.
1110 
1111   @param  Script       The pointer of typed node in boot script table
1112   @retval EFI_SUCCESS  The operation was executed successfully
1113 **/
1114 EFI_STATUS
BootScriptExecuteDispatch2(IN UINT8 * Script)1115 BootScriptExecuteDispatch2 (
1116   IN UINT8                  *Script
1117   )
1118 {
1119   EFI_STATUS                Status;
1120   DISPATCH_ENTRYPOINT_FUNC  EntryFunc;
1121   EFI_BOOT_SCRIPT_DISPATCH_2  ScriptDispatch2;
1122 
1123   CopyMem ((VOID*)&ScriptDispatch2, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_DISPATCH_2));
1124 
1125   DEBUG ((EFI_D_INFO, "BootScriptExecuteDispatch2 - 0x%08x(0x%08x)\n", (UINTN)ScriptDispatch2.EntryPoint, (UINTN)ScriptDispatch2.Context));
1126 
1127   EntryFunc = (DISPATCH_ENTRYPOINT_FUNC) (UINTN) (ScriptDispatch2.EntryPoint);
1128 
1129   Status    = EntryFunc (NULL, (VOID *) (UINTN) ScriptDispatch2.Context);
1130 
1131   return Status;
1132 }
1133 /**
1134   Interprete the boot script node with EFI_BOOT_SCRIPT_MEM_POLL OP code.
1135 
1136   @param  Script  The pointer of typed node in boot script table
1137   @param  AndMask  Mask value for 'and' operation
1138   @param  OrMask   Mask value for 'or' operation
1139 
1140   @retval EFI_DEVICE_ERROR Data polled from memory does not equal to
1141                            the epecting data within the Loop Times.
1142   @retval EFI_SUCCESS      The operation was executed successfully
1143 **/
1144 EFI_STATUS
BootScriptExecuteMemPoll(IN UINT8 * Script,IN UINT64 AndMask,IN UINT64 OrMask)1145 BootScriptExecuteMemPoll (
1146   IN UINT8                        *Script,
1147   IN UINT64                        AndMask,
1148   IN UINT64                        OrMask
1149   )
1150 {
1151 
1152   UINT64        Data;
1153   UINT64        LoopTimes;
1154   EFI_STATUS    Status;
1155   EFI_BOOT_SCRIPT_MEM_POLL       MemPoll;
1156 
1157   CopyMem ((VOID*)&MemPoll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_MEM_POLL));
1158 
1159   DEBUG ((EFI_D_INFO, "BootScriptExecuteMemPoll - 0x%08x, 0x%016lx, 0x%016lx\n", (UINTN)MemPoll.Address, AndMask, OrMask));
1160 
1161   Data = 0;
1162   Status = ScriptMemoryRead (
1163                (S3_BOOT_SCRIPT_LIB_WIDTH) MemPoll.Width,
1164                MemPoll.Address,
1165                1,
1166                &Data
1167                );
1168   if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
1169     return EFI_SUCCESS;
1170   }
1171 
1172   for (LoopTimes = 0; LoopTimes < MemPoll.LoopTimes; LoopTimes++) {
1173     MicroSecondDelay ((UINTN)MemPoll.Duration);
1174 
1175     Data = 0;
1176     Status = ScriptMemoryRead (
1177                (S3_BOOT_SCRIPT_LIB_WIDTH) MemPoll.Width,
1178                MemPoll.Address,
1179                1,
1180                &Data
1181                );
1182    if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
1183     return EFI_SUCCESS;
1184    }
1185   }
1186 
1187   if (LoopTimes < MemPoll.LoopTimes) {
1188     return EFI_SUCCESS;
1189   } else {
1190     return EFI_DEVICE_ERROR;
1191   }
1192 }
1193 /**
1194   Execute the boot script to interpret the Store arbitrary information.
1195   This opcode is a no-op on dispatch and is only used for debugging script issues.
1196 
1197   @param Script       The pointer of node in boot script table
1198 
1199 **/
1200 VOID
BootScriptExecuteInformation(IN UINT8 * Script)1201 BootScriptExecuteInformation (
1202   IN UINT8       *Script
1203   )
1204 
1205 {
1206   UINT32                        Index;
1207   EFI_BOOT_SCRIPT_INFORMATION   Information;
1208   UINT8                         *InformationData;
1209 
1210   CopyMem ((VOID*)&Information, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_INFORMATION));
1211 
1212   InformationData = Script + sizeof (EFI_BOOT_SCRIPT_INFORMATION);
1213   DEBUG ((EFI_D_INFO, "BootScriptExecuteInformation - 0x%08x\n", (UINTN) InformationData));
1214 
1215   DEBUG ((EFI_D_INFO, "BootScriptInformation: "));
1216   for (Index = 0; Index < Information.InformationLength; Index++) {
1217     DEBUG ((EFI_D_INFO, "%02x ", InformationData[Index]));
1218   }
1219   DEBUG ((EFI_D_INFO, "\n"));
1220 }
1221 
1222 /**
1223   Execute the boot script to interpret the Label information.
1224 
1225   @param Script       The pointer of node in boot script table
1226 
1227 **/
1228 VOID
BootScriptExecuteLabel(IN UINT8 * Script)1229 BootScriptExecuteLabel (
1230   IN UINT8       *Script
1231   )
1232 
1233 {
1234   UINT32                        Index;
1235   EFI_BOOT_SCRIPT_INFORMATION   Information;
1236   UINT8                         *InformationData;
1237 
1238   CopyMem ((VOID*)&Information, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_INFORMATION));
1239 
1240   InformationData = Script + sizeof (EFI_BOOT_SCRIPT_INFORMATION);
1241   DEBUG ((EFI_D_INFO, "BootScriptExecuteLabel - 0x%08x\n", (UINTN) InformationData));
1242 
1243   DEBUG ((EFI_D_INFO, "BootScriptLabel: "));
1244   for (Index = 0; Index < Information.InformationLength; Index++) {
1245     DEBUG ((EFI_D_INFO, "%02x ", InformationData[Index]));
1246   }
1247   DEBUG ((EFI_D_INFO, "\n"));
1248 }
1249 
1250 /**
1251   calculate the mask value for 'and' and 'or' operation
1252   @param ScriptHeader   The pointer of header of node in boot script table
1253   @param AndMask  The Mask value for 'and' operation
1254   @param OrMask   The Mask value for 'or' operation
1255   @param Script   Pointer to the entry.
1256 
1257 **/
1258 VOID
CheckAndOrMask(IN EFI_BOOT_SCRIPT_COMMON_HEADER * ScriptHeader,OUT UINT64 * AndMask,OUT UINT64 * OrMask,IN UINT8 * Script)1259 CheckAndOrMask (
1260   IN   EFI_BOOT_SCRIPT_COMMON_HEADER  *ScriptHeader,
1261   OUT UINT64                      *AndMask,
1262   OUT UINT64                      *OrMask,
1263   IN  UINT8                       *Script
1264   )
1265 {
1266   UINT8 *DataPtr;
1267   UINTN Size;
1268 
1269   switch (ScriptHeader->OpCode) {
1270   case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE:
1271     Size = sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE);
1272     break;
1273 
1274   case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE:
1275     Size = sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE);
1276     break;
1277 
1278   case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE:
1279     Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE);
1280     break;
1281   case EFI_BOOT_SCRIPT_MEM_POLL_OPCODE:
1282     Size = sizeof (EFI_BOOT_SCRIPT_MEM_POLL);
1283     break;
1284 
1285   case EFI_BOOT_SCRIPT_IO_POLL_OPCODE:
1286     Size = sizeof (EFI_BOOT_SCRIPT_IO_POLL);
1287     break;
1288 
1289   case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE:
1290     Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE);
1291     break;
1292 
1293   case EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE:
1294     Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL);
1295     break;
1296 
1297   case EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE:
1298     Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL);
1299     break;
1300 
1301   default:
1302     return;
1303   }
1304 
1305   DataPtr = Script + Size;
1306 
1307   switch (ScriptHeader->Width) {
1308   case S3BootScriptWidthUint8:
1309     *AndMask  = (UINT64) (*(UINT8*) (DataPtr + 1));
1310     *OrMask   = (UINT64) (*DataPtr);
1311     break;
1312 
1313   case S3BootScriptWidthUint16:
1314     *AndMask  = (UINT64) (*(UINT16 *) (DataPtr + 2));
1315     *OrMask   = (UINT64) (*(UINT16 *) DataPtr);
1316     break;
1317 
1318   case S3BootScriptWidthUint32:
1319     *AndMask  = (UINT64) (*(UINT32 *) (DataPtr + 4));
1320     *OrMask   = (UINT64) (*(UINT32 *) DataPtr);
1321     break;
1322 
1323   case S3BootScriptWidthUint64:
1324     *AndMask  = (UINT64) (*(UINT64 *) (DataPtr + 8));
1325     *OrMask   = (UINT64) (*(UINT64 *) DataPtr);
1326     break;
1327 
1328   default:
1329     break;
1330   }
1331 
1332   return;
1333 }
1334 /**
1335   Interprete the boot script node with EFI_BOOT_SCRIPT_IO_POLL OP code.
1336 
1337   @param  Script  The pointer of typed node in boot script table
1338   @param  AndMask  Mask value for 'and' operation
1339   @param  OrMask   Mask value for 'or' operation
1340 
1341   @retval EFI_DEVICE_ERROR Data polled from memory does not equal to
1342                            the epecting data within the Loop Times.
1343   @retval EFI_SUCCESS      The operation was executed successfully
1344 **/
1345 EFI_STATUS
BootScriptExecuteIoPoll(IN UINT8 * Script,IN UINT64 AndMask,IN UINT64 OrMask)1346 BootScriptExecuteIoPoll (
1347   IN UINT8       *Script,
1348   IN UINT64      AndMask,
1349   IN UINT64      OrMask
1350   )
1351 {
1352   EFI_STATUS    Status;
1353   UINT64        Data;
1354   UINT64        LoopTimes;
1355   EFI_BOOT_SCRIPT_IO_POLL       IoPoll;
1356 
1357   CopyMem ((VOID*)&IoPoll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_IO_POLL));
1358 
1359   DEBUG ((EFI_D_INFO, "BootScriptExecuteIoPoll - 0x%08x, 0x%016lx, 0x%016lx\n", (UINTN)IoPoll.Address, AndMask, OrMask));
1360 
1361   Data = 0;
1362   Status = ScriptIoRead (
1363              (S3_BOOT_SCRIPT_LIB_WIDTH) IoPoll.Width,
1364              IoPoll.Address,
1365              1,
1366              &Data
1367              );
1368   if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
1369     return EFI_SUCCESS;
1370   }
1371   for (LoopTimes = 0; LoopTimes < IoPoll.Delay; LoopTimes++) {
1372     NanoSecondDelay (100);
1373     Data = 0;
1374     Status = ScriptIoRead (
1375                (S3_BOOT_SCRIPT_LIB_WIDTH) IoPoll.Width,
1376                IoPoll.Address,
1377                1,
1378                &Data
1379                );
1380     if ((!EFI_ERROR (Status)) &&(Data & AndMask) == OrMask) {
1381       return EFI_SUCCESS;
1382     }
1383   }
1384 
1385   if (LoopTimes < IoPoll.Delay) {
1386     return EFI_SUCCESS;
1387   } else {
1388     return EFI_DEVICE_ERROR;
1389   }
1390 }
1391 /**
1392   Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE OP code.
1393 
1394   @param    Script              The pointer of S3 boot script
1395 
1396   @retval   EFI_SUCCESS         The operation was executed successfully
1397 
1398 **/
1399 EFI_STATUS
BootScriptExecutePciCfg2Write(IN UINT8 * Script)1400 BootScriptExecutePciCfg2Write (
1401   IN UINT8             *Script
1402   )
1403 {
1404   VOID                              *Buffer;
1405   S3_BOOT_SCRIPT_LIB_WIDTH          Width;
1406   UINT16                            Segment;
1407   UINT64                            Address;
1408   UINTN                             Count;
1409   EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE PciCfg2Write;
1410 
1411   CopyMem ((VOID*)&PciCfg2Write, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE));
1412 
1413   Width   = (S3_BOOT_SCRIPT_LIB_WIDTH)PciCfg2Write.Width;
1414   Segment = PciCfg2Write.Segment;
1415   Address = PciCfg2Write.Address;
1416   Count   = PciCfg2Write.Count;
1417   Buffer  = Script + sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE);
1418 
1419   DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfg2Write - 0x%016lx, 0x%08x, 0x%08x\n", PCI_ADDRESS_ENCODE (Segment, Address), Count, (UINTN)Width));
1420   return ScriptPciCfg2Write (Width, Segment, Address, Count, Buffer);
1421 }
1422 
1423 
1424 /**
1425   Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE OP code.
1426 
1427   @param     Script                     The pointer of S3 boot script
1428   @param     AndMask                    Mask value for 'and' operation
1429   @param     OrMask                     Mask value for 'or' operation
1430 
1431   @retval    EFI_SUCCESS                The operation was executed successfully
1432 
1433 **/
1434 EFI_STATUS
BootScriptExecutePciCfg2ReadWrite(IN UINT8 * Script,IN UINT64 AndMask,IN UINT64 OrMask)1435 BootScriptExecutePciCfg2ReadWrite (
1436   IN UINT8                        *Script,
1437   IN UINT64                        AndMask,
1438   IN UINT64                        OrMask
1439   )
1440 {
1441   UINT64      Data;
1442   EFI_STATUS  Status;
1443   EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE PciCfg2ReadWrite;
1444 
1445   Data = 0;
1446 
1447   CopyMem ((VOID*)&PciCfg2ReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE));
1448 
1449   DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfg2ReadWrite - 0x%016lx, 0x%016lx, 0x%016lx\n", PCI_ADDRESS_ENCODE (PciCfg2ReadWrite.Segment, PciCfg2ReadWrite.Address), AndMask, OrMask));
1450 
1451   Status = ScriptPciCfg2Read (
1452              (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2ReadWrite.Width,
1453              PciCfg2ReadWrite.Segment,
1454              PciCfg2ReadWrite.Address,
1455              1,
1456              &Data
1457              );
1458   if (EFI_ERROR (Status)) {
1459     return Status;
1460   }
1461 
1462   Data = (Data & AndMask) | OrMask;
1463   Status = ScriptPciCfg2Write (
1464              (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2ReadWrite.Width,
1465              PciCfg2ReadWrite.Segment,
1466              PciCfg2ReadWrite.Address,
1467              1,
1468              &Data
1469              );
1470   return Status;
1471 }
1472 /**
1473   Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG_POLL OP code.
1474 
1475   @param     Script                     The pointer of S3 boot script
1476   @param     AndMask                    Mask value for 'and' operation
1477   @param     OrMask                     Mask value for 'or' operation
1478 
1479   @retval    EFI_SUCCESS                The operation was executed successfully
1480   @retval    EFI_DEVICE_ERROR           Data polled from Pci configuration space does not equal to
1481                                         epecting data within the Loop Times.
1482 **/
1483 EFI_STATUS
BootScriptPciCfgPoll(IN UINT8 * Script,IN UINT64 AndMask,IN UINT64 OrMask)1484 BootScriptPciCfgPoll (
1485   IN UINT8                         *Script,
1486   IN UINT64                        AndMask,
1487   IN UINT64                        OrMask
1488   )
1489 {
1490   UINT64        Data;
1491   UINT64        LoopTimes;
1492   EFI_STATUS    Status;
1493   EFI_BOOT_SCRIPT_PCI_CONFIG_POLL PciCfgPoll;
1494   CopyMem ((VOID*)&PciCfgPoll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG_POLL));
1495 
1496   DEBUG ((EFI_D_INFO, "BootScriptPciCfgPoll - 0x%016lx, 0x%016lx, 0x%016lx\n", PCI_ADDRESS_ENCODE (0, PciCfgPoll.Address), AndMask, OrMask));
1497 
1498   Data = 0;
1499   Status = ScriptPciCfgRead (
1500              (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgPoll.Width,
1501              PciCfgPoll.Address,
1502              1,
1503              &Data
1504              );
1505   if ((!EFI_ERROR (Status)) &&(Data & AndMask) == OrMask) {
1506     return EFI_SUCCESS;
1507   }
1508 
1509   for (LoopTimes = 0; LoopTimes < PciCfgPoll.Delay; LoopTimes++) {
1510     NanoSecondDelay (100);
1511     Data = 0;
1512     Status = ScriptPciCfgRead (
1513                (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgPoll.Width,
1514                PciCfgPoll.Address,
1515                1,
1516                &Data
1517                );
1518     if ((!EFI_ERROR (Status)) &&
1519        (Data & AndMask) == OrMask) {
1520       return EFI_SUCCESS;
1521     }
1522   }
1523 
1524   if (LoopTimes < PciCfgPoll.Delay) {
1525     return EFI_SUCCESS;
1526   } else {
1527     return EFI_DEVICE_ERROR;
1528   }
1529 }
1530 
1531 /**
1532   Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL OP code.
1533 
1534   @param     Script                     The pointer of S3 Boot Script
1535   @param     AndMask                    Mask value for 'and' operation
1536   @param     OrMask                     Mask value for 'or' operation
1537 
1538   @retval    EFI_SUCCESS                The operation was executed successfully
1539   @retval    EFI_DEVICE_ERROR           Data polled from Pci configuration space does not equal to
1540                                         epecting data within the Loop Times.
1541 
1542 **/
1543 EFI_STATUS
BootScriptPciCfg2Poll(IN UINT8 * Script,IN UINT64 AndMask,IN UINT64 OrMask)1544 BootScriptPciCfg2Poll (
1545   IN UINT8                        *Script,
1546   IN UINT64                        AndMask,
1547   IN UINT64                        OrMask
1548   )
1549 {
1550   EFI_STATUS    Status;
1551   UINT64        Data;
1552   UINT64        LoopTimes;
1553   EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL PciCfg2Poll;
1554 
1555   Data = 0;
1556   CopyMem ((VOID*)&PciCfg2Poll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL));
1557 
1558   DEBUG ((EFI_D_INFO, "BootScriptPciCfg2Poll - 0x%016lx, 0x%016lx, 0x%016lx\n", PCI_ADDRESS_ENCODE (PciCfg2Poll.Segment, PciCfg2Poll.Address), AndMask, OrMask));
1559 
1560   Status = ScriptPciCfg2Read (
1561              (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2Poll.Width,
1562              PciCfg2Poll.Segment,
1563              PciCfg2Poll.Address,
1564              1,
1565              &Data
1566              );
1567   if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
1568     return EFI_SUCCESS;
1569   }
1570 
1571   for (LoopTimes = 0; LoopTimes < PciCfg2Poll.Delay; LoopTimes++) {
1572     NanoSecondDelay (100);
1573 
1574     Data = 0;
1575     Status = ScriptPciCfg2Read (
1576                (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2Poll.Width,
1577                PciCfg2Poll.Segment,
1578                PciCfg2Poll.Address,
1579                1,
1580                &Data
1581                );
1582     if ((!EFI_ERROR (Status)) &&  (Data & AndMask) == OrMask) {
1583       return EFI_SUCCESS;
1584     }
1585   }
1586 
1587   if (LoopTimes < PciCfg2Poll.Delay) {
1588     return EFI_SUCCESS;
1589   } else {
1590     return EFI_DEVICE_ERROR;
1591   }
1592 
1593 }
1594 
1595 /**
1596   Executes the S3 boot script table.
1597 
1598   @retval RETURN_SUCCESS           The boot script table was executed successfully.
1599   @retval RETURN_UNSUPPORTED       Invalid script table or opcode.
1600 
1601 **/
1602 RETURN_STATUS
1603 EFIAPI
S3BootScriptExecute(VOID)1604 S3BootScriptExecute (
1605   VOID
1606   )
1607 {
1608   EFI_STATUS            Status;
1609   UINT8*                Script;
1610   UINTN                 StartAddress;
1611   UINT32                TableLength;
1612   UINT64                AndMask;
1613   UINT64                OrMask;
1614   EFI_BOOT_SCRIPT_COMMON_HEADER  ScriptHeader;
1615   EFI_BOOT_SCRIPT_TABLE_HEADER   TableHeader;
1616   Script = mS3BootScriptTablePtr->TableBase;
1617   if (Script != 0) {
1618     CopyMem ((VOID*)&TableHeader, Script, sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER));
1619   } else {
1620     return EFI_INVALID_PARAMETER;
1621   }
1622 
1623   DEBUG ((EFI_D_INFO, "S3BootScriptExecute:\n"));
1624   if (TableHeader.OpCode != S3_BOOT_SCRIPT_LIB_TABLE_OPCODE) {
1625     return EFI_UNSUPPORTED;
1626   }
1627 
1628   DEBUG ((EFI_D_INFO, "TableHeader - 0x%08x\n", Script));
1629 
1630   StartAddress  = (UINTN) Script;
1631   TableLength   = TableHeader.TableLength;
1632   Script    =    Script + TableHeader.Length;
1633   Status        = EFI_SUCCESS;
1634   AndMask       = 0;
1635   OrMask        = 0;
1636 
1637   DEBUG ((EFI_D_INFO, "TableHeader.Version - 0x%04x\n", (UINTN)TableHeader.Version));
1638   DEBUG ((EFI_D_INFO, "TableHeader.TableLength - 0x%08x\n", (UINTN)TableLength));
1639 
1640   while ((UINTN) Script < (UINTN) (StartAddress + TableLength)) {
1641     DEBUG ((EFI_D_INFO, "ExecuteBootScript - %08x\n", (UINTN)Script));
1642 
1643     CopyMem ((VOID*)&ScriptHeader, Script, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER));
1644     switch (ScriptHeader.OpCode) {
1645 
1646     case EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE:
1647       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE\n"));
1648       Status = BootScriptExecuteMemoryWrite (Script);
1649       break;
1650 
1651     case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE:
1652       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE\n"));
1653       CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1654       Status = BootScriptExecuteMemoryReadWrite (
1655                  Script,
1656                  AndMask,
1657                  OrMask
1658                  );
1659       break;
1660 
1661     case EFI_BOOT_SCRIPT_IO_WRITE_OPCODE:
1662       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_IO_WRITE_OPCODE\n"));
1663       Status = BootScriptExecuteIoWrite (Script);
1664       break;
1665 
1666     case EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE:
1667       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE\n"));
1668       Status = BootScriptExecutePciCfgWrite (Script);
1669       break;
1670 
1671     case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE:
1672       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE\n"));
1673       CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1674       Status = BootScriptExecutePciCfgReadWrite (
1675                  Script,
1676                  AndMask,
1677                  OrMask
1678                  );
1679       break;
1680     case EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE:
1681       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE\n"));
1682       Status = BootScriptExecutePciCfg2Write (Script);
1683       break;
1684 
1685     case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE:
1686       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE\n"));
1687       CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1688       Status = BootScriptExecutePciCfg2ReadWrite (
1689                  Script,
1690                  AndMask,
1691                  OrMask
1692                  );
1693       break;
1694     case EFI_BOOT_SCRIPT_DISPATCH_OPCODE:
1695       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_DISPATCH_OPCODE\n"));
1696       Status = BootScriptExecuteDispatch (Script);
1697       break;
1698 
1699     case EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE:
1700       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE\n"));
1701       Status = BootScriptExecuteDispatch2 (Script);
1702       break;
1703 
1704     case EFI_BOOT_SCRIPT_INFORMATION_OPCODE:
1705       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_INFORMATION_OPCODE\n"));
1706       BootScriptExecuteInformation (Script);
1707       break;
1708 
1709     case S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE:
1710       DEBUG ((EFI_D_INFO, "S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE\n"));
1711       DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", EFI_SUCCESS));
1712       return EFI_SUCCESS;
1713 
1714     case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE:
1715       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE\n"));
1716       CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1717       Status = BootScriptExecuteIoReadWrite (
1718                 Script,
1719                 AndMask,
1720                 OrMask
1721                 );
1722       break;
1723 
1724     case EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE:
1725       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE\n"));
1726       Status = BootScriptExecuteSmbusExecute (Script);
1727       break;
1728 
1729     case EFI_BOOT_SCRIPT_STALL_OPCODE:
1730       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_STALL_OPCODE\n"));
1731       Status = BootScriptExecuteStall (Script);
1732       break;
1733 
1734     case EFI_BOOT_SCRIPT_MEM_POLL_OPCODE:
1735       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_MEM_POLL_OPCODE\n"));
1736       CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1737       Status = BootScriptExecuteMemPoll (Script, AndMask, OrMask);
1738 
1739       break;
1740 
1741     case EFI_BOOT_SCRIPT_IO_POLL_OPCODE:
1742       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_IO_POLL_OPCODE\n"));
1743       CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1744       Status = BootScriptExecuteIoPoll (Script, AndMask, OrMask);
1745       break;
1746 
1747     case EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE:
1748       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE\n"));
1749       CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1750       Status = BootScriptPciCfgPoll (Script, AndMask, OrMask);
1751       break;
1752 
1753     case EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE:
1754      DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE\n"));
1755      CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1756      Status = BootScriptPciCfg2Poll (Script, AndMask, OrMask);
1757      break;
1758 
1759     case S3_BOOT_SCRIPT_LIB_LABEL_OPCODE:
1760       //
1761       // For label
1762       //
1763       DEBUG ((EFI_D_INFO, "S3_BOOT_SCRIPT_LIB_LABEL_OPCODE\n"));
1764       BootScriptExecuteLabel (Script);
1765       break;
1766     default:
1767       DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", EFI_UNSUPPORTED));
1768       return EFI_UNSUPPORTED;
1769     }
1770 
1771     if (EFI_ERROR (Status)) {
1772       DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", Status));
1773       return Status;
1774     }
1775 
1776     Script  = Script + ScriptHeader.Length;
1777   }
1778 
1779   DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", Status));
1780 
1781   return Status;
1782 }
1783 
1784