• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /** @file
2   Interpret and execute the S3 data in S3 boot script.
3 
4   Copyright (c) 2006 - 2015, 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 read operation
643 
644   @param  Width   Width of the operation.
645   @param  Address Address of the operation.
646   @param  Count   Count of the number of accesses to perform.
647   @param  Buffer  Pointer to the buffer read from PCI config space
648 
649   @retval EFI_SUCCESS The read succeed.
650   @retval EFI_INVALID_PARAMETER if Width is not defined
651   @note  A known Limitations in the implementation which is 64bits operations are not supported.
652 
653 **/
654 EFI_STATUS
ScriptPciCfgRead(IN S3_BOOT_SCRIPT_LIB_WIDTH Width,IN UINT64 Address,IN UINTN Count,OUT VOID * Buffer)655 ScriptPciCfgRead (
656   IN  S3_BOOT_SCRIPT_LIB_WIDTH    Width,
657   IN  UINT64                       Address,
658   IN  UINTN                        Count,
659   OUT VOID                        *Buffer
660   )
661 {
662   EFI_STATUS  Status;
663   UINTN       AddressStride;
664   UINTN       BufferStride;
665   PTR         Out;
666   UINTN       PciAddress;
667 
668   Out.Buf = (UINT8 *) Buffer;
669 
670   PciAddress = PCI_ADDRESS_ENCODE (Address);
671 
672   Status = BuildLoopData (Width, PciAddress, &AddressStride, &BufferStride);
673   if (EFI_ERROR (Status)) {
674     return Status;
675   }
676   //
677   // Loop for each iteration and move the data
678   //
679   for (; Count > 0; Count--, PciAddress += AddressStride, Out.Buf += BufferStride) {
680     switch (Width) {
681     case S3BootScriptWidthUint8:
682       DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%08x\n", PciAddress));
683       *Out.Uint8 = PciRead8 (PciAddress);
684       break;
685     case S3BootScriptWidthFifoUint8:
686       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%08x\n", PciAddress));
687       *Out.Uint8 = PciRead8 (PciAddress);
688       break;
689     case S3BootScriptWidthFillUint8:
690       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%08x\n", PciAddress));
691       *Out.Uint8 = PciRead8 (PciAddress);
692       break;
693 
694     case S3BootScriptWidthUint16:
695       DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%08x\n", PciAddress));
696       *Out.Uint16 = PciRead16 (PciAddress);
697       break;
698     case S3BootScriptWidthFifoUint16:
699       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%08x\n", PciAddress));
700       *Out.Uint16 = PciRead16 (PciAddress);
701       break;
702     case S3BootScriptWidthFillUint16:
703       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%08x\n", PciAddress));
704       *Out.Uint16 = PciRead16 (PciAddress);
705       break;
706 
707     case S3BootScriptWidthUint32:
708       DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%08x\n", PciAddress));
709       *Out.Uint32 = PciRead32 (PciAddress);
710       break;
711     case S3BootScriptWidthFifoUint32:
712       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%08x\n", PciAddress));
713       *Out.Uint32 = PciRead32 (PciAddress);
714       break;
715     case S3BootScriptWidthFillUint32:
716       DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%08x\n", PciAddress));
717       *Out.Uint32 = PciRead32 (PciAddress);
718       break;
719 
720     default:
721       return EFI_INVALID_PARAMETER;
722     }
723   }
724   return EFI_SUCCESS;
725 }
726 
727 /**
728   Performance PCI configuration write operation
729 
730   @param  Width   Width of the operation.
731   @param  Address Address of the operation.
732   @param  Count   Count of the number of accesses to perform.
733   @param  Buffer  Pointer to the buffer write to PCI config space
734 
735   @retval EFI_SUCCESS The write succeed.
736   @retval EFI_INVALID_PARAMETER if Width is not defined
737   @note  A known Limitations in the implementation which is 64bits operations are not supported.
738 
739 **/
740 EFI_STATUS
ScriptPciCfgWrite(IN S3_BOOT_SCRIPT_LIB_WIDTH Width,IN UINT64 Address,IN UINTN Count,IN VOID * Buffer)741 ScriptPciCfgWrite (
742   IN  S3_BOOT_SCRIPT_LIB_WIDTH     Width,
743   IN  UINT64                       Address,
744   IN  UINTN                        Count,
745   IN  VOID                         *Buffer
746   )
747 {
748   EFI_STATUS  Status;
749   UINTN       AddressStride;
750   UINTN       BufferStride;
751   UINTN       OriginalPciAddress;
752   PTR         In;
753   PTR         OriginalIn;
754   UINTN       PciAddress;
755 
756   In.Buf = (UINT8 *) Buffer;
757 
758   PciAddress = PCI_ADDRESS_ENCODE (Address);
759 
760   Status = BuildLoopData (Width, PciAddress, &AddressStride, &BufferStride);
761   if (EFI_ERROR (Status)) {
762     return Status;
763   }
764   //
765   // Loop for each iteration and move the data
766   //
767   OriginalPciAddress = PciAddress;
768   OriginalIn.Buf = In.Buf;
769   for (; Count > 0; Count--, PciAddress += AddressStride, In.Buf += BufferStride) {
770     switch (Width) {
771       case S3BootScriptWidthUint8:
772         DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint8 - 0x%08x (0x%02x)\n", PciAddress, (UINTN)*In.Uint8));
773         PciWrite8 (PciAddress, *In.Uint8);
774         break;
775       case S3BootScriptWidthFifoUint8:
776         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint8 - 0x%08x (0x%02x)\n", OriginalPciAddress, (UINTN)*In.Uint8));
777         PciWrite8 (OriginalPciAddress, *In.Uint8);
778         break;
779       case S3BootScriptWidthFillUint8:
780         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint8 - 0x%08x (0x%02x)\n", PciAddress, (UINTN)*OriginalIn.Uint8));
781         PciWrite8 (PciAddress, *OriginalIn.Uint8);
782         break;
783       case S3BootScriptWidthUint16:
784         DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint16 - 0x%08x (0x%04x)\n", PciAddress, (UINTN)*In.Uint16));
785         PciWrite16 (PciAddress, *In.Uint16);
786         break;
787       case S3BootScriptWidthFifoUint16:
788         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint16 - 0x%08x (0x%04x)\n", OriginalPciAddress, (UINTN)*In.Uint16));
789         PciWrite16 (OriginalPciAddress, *In.Uint16);
790         break;
791       case S3BootScriptWidthFillUint16:
792         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint16 - 0x%08x (0x%04x)\n", PciAddress, (UINTN)*OriginalIn.Uint16));
793         PciWrite16 (PciAddress, *OriginalIn.Uint16);
794         break;
795       case S3BootScriptWidthUint32:
796         DEBUG ((EFI_D_INFO, "S3BootScriptWidthUint32 - 0x%08x (0x%08x)\n", PciAddress, (UINTN)*In.Uint32));
797         PciWrite32 (PciAddress, *In.Uint32);
798         break;
799       case S3BootScriptWidthFifoUint32:
800         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFifoUint32 - 0x%08x (0x%08x)\n", OriginalPciAddress, (UINTN)*In.Uint32));
801         PciWrite32 (OriginalPciAddress, *In.Uint32);
802         break;
803       case S3BootScriptWidthFillUint32:
804         DEBUG ((EFI_D_INFO, "S3BootScriptWidthFillUint32 - 0x%08x (0x%08x)\n", (UINTN)PciAddress, (UINTN)*OriginalIn.Uint32));
805         PciWrite32 (PciAddress, *OriginalIn.Uint32);
806         break;
807       default:
808         return EFI_INVALID_PARAMETER;
809     }
810   }
811   return EFI_SUCCESS;
812 }
813 /**
814   Performance PCI configuration 2 read operation
815 
816   @param     Width                      Width of the operation.
817   @param     Segment                    Pci segment number
818   @param     Address                    Address of the operation.
819   @param     Count                      Count of the number of accesses to perform.
820   @param     Buffer                     Pointer to the buffer to read from PCI config space.
821 
822   @retval    EFI_SUCCESS                The data was written to the EFI System.
823   @retval    EFI_INVALID_PARAMETER      Width is invalid for this EFI System.
824                                         Buffer is NULL.
825                                         The Buffer is not aligned for the given Width.
826                                         Address is outside the legal range of I/O ports.
827   @note  A known Limitations in the implementation which is the 'Segment' parameter is assumed as
828          Zero, or else, assert.
829 **/
830 EFI_STATUS
ScriptPciCfg2Read(IN S3_BOOT_SCRIPT_LIB_WIDTH Width,IN UINT16 Segment,IN UINT64 Address,IN UINTN Count,OUT VOID * Buffer)831 ScriptPciCfg2Read (
832   IN  S3_BOOT_SCRIPT_LIB_WIDTH    Width,
833   IN  UINT16                   Segment,
834   IN  UINT64                   Address,
835   IN  UINTN                    Count,
836   OUT VOID                     *Buffer
837   )
838 {
839   ASSERT (Segment==0);
840 
841   return ScriptPciCfgRead (Width, Address, Count, Buffer);
842 }
843 /**
844   Performance PCI configuration 2 write operation
845 
846   @param     Width                      Width of the operation.
847   @param     Segment                    Pci segment number
848   @param     Address                    Address of the operation.
849   @param     Count                      Count of the number of accesses to perform.
850   @param     Buffer                     Pointer to the buffer to write to PCI config space.
851 
852   @retval    EFI_SUCCESS                The data was written to the EFI System.
853   @retval    EFI_INVALID_PARAMETER      Width is invalid for this EFI System.
854                                         Buffer is NULL.
855                                         The Buffer is not aligned for the given Width.
856                                         Address is outside the legal range of I/O ports.
857   @note  A known Limitations in the implementation which is the 'Segment' parameter is assumed as
858          Zero, or else, assert.
859 
860 **/
861 EFI_STATUS
862 EFIAPI
ScriptPciCfg2Write(IN S3_BOOT_SCRIPT_LIB_WIDTH Width,IN UINT16 Segment,IN UINT64 Address,IN UINTN Count,IN VOID * Buffer)863 ScriptPciCfg2Write (
864   IN  S3_BOOT_SCRIPT_LIB_WIDTH    Width,
865   IN  UINT16                   Segment,
866   IN  UINT64                   Address,
867   IN  UINTN                    Count,
868   IN  VOID                     *Buffer
869   )
870 {
871   ASSERT (Segment==0);
872   return ScriptPciCfgWrite (Width, Address, Count, Buffer);
873 }
874 /**
875   Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE OP code.
876 
877   @param  Script        The pointer of typed node in boot script table
878 
879   @retval EFI_SUCCESS  The operation was executed successfully
880 **/
881 EFI_STATUS
BootScriptExecutePciCfgWrite(IN UINT8 * Script)882 BootScriptExecutePciCfgWrite (
883   IN UINT8                    *Script
884   )
885 {
886   VOID                              *Buffer;
887   S3_BOOT_SCRIPT_LIB_WIDTH          Width;
888   UINT64                            Address;
889   UINTN                             Count;
890   EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE  PciCfgWrite;
891 
892   CopyMem ((VOID*)&PciCfgWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE));
893 
894   Width   = (S3_BOOT_SCRIPT_LIB_WIDTH)PciCfgWrite.Width;
895   Address = PciCfgWrite.Address;
896   Count   = PciCfgWrite.Count;
897   Buffer  = Script + sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE);
898 
899   DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfgWrite - 0x%08x, 0x%08x, 0x%08x\n", PCI_ADDRESS_ENCODE (Address), Count, (UINTN)Width));
900   return ScriptPciCfgWrite (Width, Address, Count, Buffer);
901 }
902 /**
903   Interprete the boot script node with EFI_BOOT_SCRIPT_IO_READ_WRITE OP code.
904 
905   @param Script   The pointer of typed node in boot script table
906   @param AndMask  Mask value for 'and' operation
907   @param OrMask   Mask value for 'or' operation
908 
909   @retval EFI_SUCCESS    The operation was executed successfully
910 **/
911 EFI_STATUS
BootScriptExecuteIoReadWrite(IN UINT8 * Script,IN UINT64 AndMask,IN UINT64 OrMask)912 BootScriptExecuteIoReadWrite (
913   IN  UINT8                        *Script,
914   IN  UINT64                       AndMask,
915   IN  UINT64                        OrMask
916   )
917 
918 {
919   EFI_STATUS  Status;
920   UINT64      Data;
921   EFI_BOOT_SCRIPT_IO_READ_WRITE IoReadWrite;
922 
923   Data = 0;
924 
925   CopyMem((VOID*)&IoReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_IO_READ_WRITE));
926 
927   DEBUG ((EFI_D_INFO, "BootScriptExecuteIoReadWrite - 0x%08x, 0x%016lx, 0x%016lx\n", (UINTN)IoReadWrite.Address, AndMask, OrMask));
928 
929   Status = ScriptIoRead (
930              (S3_BOOT_SCRIPT_LIB_WIDTH) IoReadWrite.Width,
931              IoReadWrite.Address,
932              1,
933              &Data
934              );
935   if (!EFI_ERROR (Status)) {
936     Data = (Data & AndMask) | OrMask;
937     Status = ScriptIoWrite (
938                (S3_BOOT_SCRIPT_LIB_WIDTH) IoReadWrite.Width,
939                IoReadWrite.Address,
940                1,
941                &Data
942                );
943   }
944   return Status;
945 }
946 /**
947   Interprete the boot script node with EFI_BOOT_SCRIPT_MEM_READ_WRITE OP code.
948 
949   @param Script    The pointer of typed node in boot script table
950   @param AndMask   Mask value for 'and' operation
951   @param OrMask    Mask value for 'or' operation
952 
953   @retval EFI_SUCCESS The operation was executed successfully
954 **/
955 EFI_STATUS
BootScriptExecuteMemoryReadWrite(IN UINT8 * Script,IN UINT64 AndMask,IN UINT64 OrMask)956 BootScriptExecuteMemoryReadWrite (
957   IN UINT8                        *Script,
958   IN UINT64                        AndMask,
959   IN UINT64                        OrMask
960   )
961 
962 {
963   EFI_STATUS  Status;
964   UINT64      Data;
965   EFI_BOOT_SCRIPT_MEM_READ_WRITE  MemReadWrite;
966 
967   Data = 0;
968 
969   CopyMem((VOID*)&MemReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_MEM_READ_WRITE));
970 
971   DEBUG ((EFI_D_INFO, "BootScriptExecuteMemoryReadWrite - 0x%08x, 0x%016lx, 0x%016lx\n", (UINTN)MemReadWrite.Address, AndMask, OrMask));
972 
973   Status = ScriptMemoryRead (
974              (S3_BOOT_SCRIPT_LIB_WIDTH) MemReadWrite.Width,
975              MemReadWrite.Address,
976              1,
977              &Data
978              );
979   if (!EFI_ERROR (Status)) {
980     Data = (Data & AndMask) | OrMask;
981     Status = ScriptMemoryWrite (
982                (S3_BOOT_SCRIPT_LIB_WIDTH) MemReadWrite.Width,
983                MemReadWrite.Address,
984                1,
985                &Data
986                );
987   }
988   return Status;
989 }
990 /**
991   Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CFG_READ_WRITE OP code.
992 
993   @param Script   The pointer of typed node in boot script table
994   @param AndMask  Mask value for 'and' operation
995   @param OrMask   Mask value for 'or' operation
996 
997   @retval EFI_SUCCESS   The operation was executed successfully
998 **/
999 EFI_STATUS
BootScriptExecutePciCfgReadWrite(IN UINT8 * Script,IN UINT64 AndMask,IN UINT64 OrMask)1000 BootScriptExecutePciCfgReadWrite (
1001   IN UINT8                     *Script,
1002   IN UINT64                    AndMask,
1003   IN UINT64                    OrMask
1004   )
1005 
1006 {
1007   EFI_STATUS  Status;
1008   UINT64      Data;
1009   EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE  PciCfgReadWrite;
1010 
1011   Data = 0;
1012 
1013   CopyMem((VOID*)&PciCfgReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE));
1014 
1015   DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfgReadWrite - 0x%08x, 0x%016lx, 0x%016lx\n", PCI_ADDRESS_ENCODE (PciCfgReadWrite.Address), AndMask, OrMask));
1016 
1017   Status = ScriptPciCfgRead (
1018              (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgReadWrite.Width,
1019              PciCfgReadWrite.Address,
1020              1,
1021              &Data
1022              );
1023   if (EFI_ERROR (Status)) {
1024     return Status;
1025   }
1026 
1027   Data = (Data & AndMask) | OrMask;
1028 
1029   Status = ScriptPciCfgWrite (
1030              (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgReadWrite.Width,
1031              PciCfgReadWrite.Address,
1032              1,
1033              &Data
1034              );
1035 
1036   return Status;
1037 }
1038 /**
1039   Interprete the boot script node with EFI_BOOT_SCRIPT_SMBUS_EXECUTE OP code.
1040 
1041   @param Script  The pointer of typed node in boot script table
1042 
1043   @retval EFI_SUCCESS      The operation was executed successfully
1044   @retval EFI_UNSUPPORTED  Cannot locate smbus ppi or occur error of script execution
1045   @retval Others           Result of script execution
1046 **/
1047 EFI_STATUS
BootScriptExecuteSmbusExecute(IN UINT8 * Script)1048 BootScriptExecuteSmbusExecute (
1049   IN UINT8                     *Script
1050   )
1051 {
1052   UINTN                    SmBusAddress;
1053   UINTN                    DataSize;
1054   EFI_BOOT_SCRIPT_SMBUS_EXECUTE SmbusExecuteEntry;
1055 
1056   CopyMem ((VOID*)&SmbusExecuteEntry, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_SMBUS_EXECUTE ));
1057 
1058   DEBUG ((EFI_D_INFO, "BootScriptExecuteSmbusExecute - 0x%08x, 0x%08x\n", (UINTN)SmbusExecuteEntry.SmBusAddress, (UINTN)SmbusExecuteEntry.Operation));
1059 
1060   SmBusAddress = (UINTN)SmbusExecuteEntry.SmBusAddress;
1061   DataSize = (UINTN) SmbusExecuteEntry.DataSize;
1062   return SmbusExecute (
1063            SmBusAddress,
1064            (EFI_SMBUS_OPERATION) SmbusExecuteEntry.Operation,
1065            &DataSize,
1066            Script + sizeof (EFI_BOOT_SCRIPT_SMBUS_EXECUTE)
1067            );
1068 }
1069 /**
1070   Interprete the boot script node with EFI_BOOT_SCRIPT_STALL OP code.
1071 
1072   @param Script      The pointer of typed node in boot script table
1073 
1074   @retval EFI_SUCCESS The operation was executed successfully
1075 **/
1076 EFI_STATUS
BootScriptExecuteStall(IN UINT8 * Script)1077 BootScriptExecuteStall (
1078   IN UINT8                 *Script
1079   )
1080 {
1081   EFI_BOOT_SCRIPT_STALL    Stall;
1082 
1083   CopyMem ((VOID*)&Stall, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_STALL));
1084 
1085   DEBUG ((EFI_D_INFO, "BootScriptExecuteStall - 0x%08x\n", (UINTN)Stall.Duration));
1086 
1087   MicroSecondDelay ((UINTN) Stall.Duration);
1088   return EFI_SUCCESS;
1089 }
1090 /**
1091   Interprete the boot script node with EFI_BOOT_SCRIPT_DISPATCH OP code.
1092 
1093   @param Script  The pointer of typed node in boot script table
1094   @retval EFI_SUCCESS  The operation was executed successfully
1095 **/
1096 EFI_STATUS
BootScriptExecuteDispatch(IN UINT8 * Script)1097 BootScriptExecuteDispatch (
1098   IN UINT8                  *Script
1099   )
1100 {
1101   EFI_STATUS                Status;
1102   DISPATCH_ENTRYPOINT_FUNC  EntryFunc;
1103   EFI_BOOT_SCRIPT_DISPATCH  ScriptDispatch;
1104 
1105   CopyMem ((VOID*)&ScriptDispatch, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_DISPATCH));
1106   EntryFunc = (DISPATCH_ENTRYPOINT_FUNC) (UINTN) (ScriptDispatch.EntryPoint);
1107 
1108   DEBUG ((EFI_D_INFO, "BootScriptExecuteDispatch - 0x%08x\n", (UINTN)ScriptDispatch.EntryPoint));
1109 
1110   Status    = EntryFunc (NULL, NULL);
1111 
1112   return Status;
1113 }
1114 /**
1115   Interprete the boot script node with EFI_BOOT_SCRIPT_DISPATCH_2 OP code.
1116 
1117   @param  Script       The pointer of typed node in boot script table
1118   @retval EFI_SUCCESS  The operation was executed successfully
1119 **/
1120 EFI_STATUS
BootScriptExecuteDispatch2(IN UINT8 * Script)1121 BootScriptExecuteDispatch2 (
1122   IN UINT8                  *Script
1123   )
1124 {
1125   EFI_STATUS                Status;
1126   DISPATCH_ENTRYPOINT_FUNC  EntryFunc;
1127   EFI_BOOT_SCRIPT_DISPATCH_2  ScriptDispatch2;
1128 
1129   CopyMem ((VOID*)&ScriptDispatch2, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_DISPATCH_2));
1130 
1131   DEBUG ((EFI_D_INFO, "BootScriptExecuteDispatch2 - 0x%08x(0x%08x)\n", (UINTN)ScriptDispatch2.EntryPoint, (UINTN)ScriptDispatch2.Context));
1132 
1133   EntryFunc = (DISPATCH_ENTRYPOINT_FUNC) (UINTN) (ScriptDispatch2.EntryPoint);
1134 
1135   Status    = EntryFunc (NULL, (VOID *) (UINTN) ScriptDispatch2.Context);
1136 
1137   return Status;
1138 }
1139 /**
1140   Interprete the boot script node with EFI_BOOT_SCRIPT_MEM_POLL OP code.
1141 
1142   @param  Script  The pointer of typed node in boot script table
1143   @param  AndMask  Mask value for 'and' operation
1144   @param  OrMask   Mask value for 'or' operation
1145 
1146   @retval EFI_DEVICE_ERROR Data polled from memory does not equal to
1147                            the epecting data within the Loop Times.
1148   @retval EFI_SUCCESS      The operation was executed successfully
1149 **/
1150 EFI_STATUS
BootScriptExecuteMemPoll(IN UINT8 * Script,IN UINT64 AndMask,IN UINT64 OrMask)1151 BootScriptExecuteMemPoll (
1152   IN UINT8                        *Script,
1153   IN UINT64                        AndMask,
1154   IN UINT64                        OrMask
1155   )
1156 {
1157 
1158   UINT64        Data;
1159   UINT64        LoopTimes;
1160   EFI_STATUS    Status;
1161   EFI_BOOT_SCRIPT_MEM_POLL       MemPoll;
1162 
1163   CopyMem ((VOID*)&MemPoll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_MEM_POLL));
1164 
1165   DEBUG ((EFI_D_INFO, "BootScriptExecuteMemPoll - 0x%08x, 0x%016lx, 0x%016lx\n", (UINTN)MemPoll.Address, AndMask, OrMask));
1166 
1167   Data = 0;
1168   Status = ScriptMemoryRead (
1169                (S3_BOOT_SCRIPT_LIB_WIDTH) MemPoll.Width,
1170                MemPoll.Address,
1171                1,
1172                &Data
1173                );
1174   if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
1175     return EFI_SUCCESS;
1176   }
1177 
1178   for (LoopTimes = 0; LoopTimes < MemPoll.LoopTimes; LoopTimes++) {
1179     MicroSecondDelay ((UINTN)MemPoll.Duration);
1180 
1181     Data = 0;
1182     Status = ScriptMemoryRead (
1183                (S3_BOOT_SCRIPT_LIB_WIDTH) MemPoll.Width,
1184                MemPoll.Address,
1185                1,
1186                &Data
1187                );
1188    if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
1189     return EFI_SUCCESS;
1190    }
1191   }
1192 
1193   if (LoopTimes < MemPoll.LoopTimes) {
1194     return EFI_SUCCESS;
1195   } else {
1196     return EFI_DEVICE_ERROR;
1197   }
1198 }
1199 /**
1200   Execute the boot script to interpret the Store arbitrary information.
1201   This opcode is a no-op on dispatch and is only used for debugging script issues.
1202 
1203   @param Script       The pointer of node in boot script table
1204 
1205 **/
1206 VOID
BootScriptExecuteInformation(IN UINT8 * Script)1207 BootScriptExecuteInformation (
1208   IN UINT8       *Script
1209   )
1210 
1211 {
1212   UINT32                        Index;
1213   EFI_BOOT_SCRIPT_INFORMATION   Information;
1214   UINT8                         *InformationData;
1215 
1216   CopyMem ((VOID*)&Information, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_INFORMATION));
1217 
1218   InformationData = Script + sizeof (EFI_BOOT_SCRIPT_INFORMATION);
1219   DEBUG ((EFI_D_INFO, "BootScriptExecuteInformation - 0x%08x\n", (UINTN) InformationData));
1220 
1221   DEBUG ((EFI_D_INFO, "BootScriptInformation: "));
1222   for (Index = 0; Index < Information.InformationLength; Index++) {
1223     DEBUG ((EFI_D_INFO, "%02x ", InformationData[Index]));
1224   }
1225   DEBUG ((EFI_D_INFO, "\n"));
1226 }
1227 
1228 /**
1229   Execute the boot script to interpret the Label information.
1230 
1231   @param Script       The pointer of node in boot script table
1232 
1233 **/
1234 VOID
BootScriptExecuteLabel(IN UINT8 * Script)1235 BootScriptExecuteLabel (
1236   IN UINT8       *Script
1237   )
1238 
1239 {
1240   UINT32                        Index;
1241   EFI_BOOT_SCRIPT_INFORMATION   Information;
1242   UINT8                         *InformationData;
1243 
1244   CopyMem ((VOID*)&Information, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_INFORMATION));
1245 
1246   InformationData = Script + sizeof (EFI_BOOT_SCRIPT_INFORMATION);
1247   DEBUG ((EFI_D_INFO, "BootScriptExecuteLabel - 0x%08x\n", (UINTN) InformationData));
1248 
1249   DEBUG ((EFI_D_INFO, "BootScriptLabel: "));
1250   for (Index = 0; Index < Information.InformationLength; Index++) {
1251     DEBUG ((EFI_D_INFO, "%02x ", InformationData[Index]));
1252   }
1253   DEBUG ((EFI_D_INFO, "\n"));
1254 }
1255 
1256 /**
1257   calculate the mask value for 'and' and 'or' operation
1258   @param ScriptHeader   The pointer of header of node in boot script table
1259   @param AndMask  The Mask value for 'and' operation
1260   @param OrMask   The Mask value for 'or' operation
1261   @param Script   Pointer to the entry.
1262 
1263 **/
1264 VOID
CheckAndOrMask(IN EFI_BOOT_SCRIPT_COMMON_HEADER * ScriptHeader,OUT UINT64 * AndMask,OUT UINT64 * OrMask,IN UINT8 * Script)1265 CheckAndOrMask (
1266   IN   EFI_BOOT_SCRIPT_COMMON_HEADER  *ScriptHeader,
1267   OUT UINT64                      *AndMask,
1268   OUT UINT64                      *OrMask,
1269   IN  UINT8                       *Script
1270   )
1271 {
1272   UINT8 *DataPtr;
1273   UINTN Size;
1274 
1275   switch (ScriptHeader->OpCode) {
1276   case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE:
1277     Size = sizeof (EFI_BOOT_SCRIPT_IO_READ_WRITE);
1278     break;
1279 
1280   case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE:
1281     Size = sizeof (EFI_BOOT_SCRIPT_MEM_READ_WRITE);
1282     break;
1283 
1284   case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE:
1285     Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE);
1286     break;
1287   case EFI_BOOT_SCRIPT_MEM_POLL_OPCODE:
1288     Size = sizeof (EFI_BOOT_SCRIPT_MEM_POLL);
1289     break;
1290 
1291   case EFI_BOOT_SCRIPT_IO_POLL_OPCODE:
1292     Size = sizeof (EFI_BOOT_SCRIPT_IO_POLL);
1293     break;
1294 
1295   case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE:
1296     Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE);
1297     break;
1298 
1299   case EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE:
1300     Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL);
1301     break;
1302 
1303   case EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE:
1304     Size = sizeof (EFI_BOOT_SCRIPT_PCI_CONFIG_POLL);
1305     break;
1306 
1307   default:
1308     return;
1309   }
1310 
1311   DataPtr = Script + Size;
1312 
1313   switch (ScriptHeader->Width) {
1314   case S3BootScriptWidthUint8:
1315     *AndMask  = (UINT64) (*(UINT8*) (DataPtr + 1));
1316     *OrMask   = (UINT64) (*DataPtr);
1317     break;
1318 
1319   case S3BootScriptWidthUint16:
1320     *AndMask  = (UINT64) (*(UINT16 *) (DataPtr + 2));
1321     *OrMask   = (UINT64) (*(UINT16 *) DataPtr);
1322     break;
1323 
1324   case S3BootScriptWidthUint32:
1325     *AndMask  = (UINT64) (*(UINT32 *) (DataPtr + 4));
1326     *OrMask   = (UINT64) (*(UINT32 *) DataPtr);
1327     break;
1328 
1329   case S3BootScriptWidthUint64:
1330     *AndMask  = (UINT64) (*(UINT64 *) (DataPtr + 8));
1331     *OrMask   = (UINT64) (*(UINT64 *) DataPtr);
1332     break;
1333 
1334   default:
1335     break;
1336   }
1337 
1338   return;
1339 }
1340 /**
1341   Interprete the boot script node with EFI_BOOT_SCRIPT_IO_POLL OP code.
1342 
1343   @param  Script  The pointer of typed node in boot script table
1344   @param  AndMask  Mask value for 'and' operation
1345   @param  OrMask   Mask value for 'or' operation
1346 
1347   @retval EFI_DEVICE_ERROR Data polled from memory does not equal to
1348                            the epecting data within the Loop Times.
1349   @retval EFI_SUCCESS      The operation was executed successfully
1350 **/
1351 EFI_STATUS
BootScriptExecuteIoPoll(IN UINT8 * Script,IN UINT64 AndMask,IN UINT64 OrMask)1352 BootScriptExecuteIoPoll (
1353   IN UINT8       *Script,
1354   IN UINT64      AndMask,
1355   IN UINT64      OrMask
1356   )
1357 {
1358   EFI_STATUS    Status;
1359   UINT64        Data;
1360   UINT64        LoopTimes;
1361   EFI_BOOT_SCRIPT_IO_POLL       IoPoll;
1362 
1363   CopyMem ((VOID*)&IoPoll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_IO_POLL));
1364 
1365   DEBUG ((EFI_D_INFO, "BootScriptExecuteIoPoll - 0x%08x, 0x%016lx, 0x%016lx\n", (UINTN)IoPoll.Address, AndMask, OrMask));
1366 
1367   Data = 0;
1368   Status = ScriptIoRead (
1369              (S3_BOOT_SCRIPT_LIB_WIDTH) IoPoll.Width,
1370              IoPoll.Address,
1371              1,
1372              &Data
1373              );
1374   if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
1375     return EFI_SUCCESS;
1376   }
1377   for (LoopTimes = 0; LoopTimes < IoPoll.Delay; LoopTimes++) {
1378     NanoSecondDelay (100);
1379     Data = 0;
1380     Status = ScriptIoRead (
1381                (S3_BOOT_SCRIPT_LIB_WIDTH) IoPoll.Width,
1382                IoPoll.Address,
1383                1,
1384                &Data
1385                );
1386     if ((!EFI_ERROR (Status)) &&(Data & AndMask) == OrMask) {
1387       return EFI_SUCCESS;
1388     }
1389   }
1390 
1391   if (LoopTimes < IoPoll.Delay) {
1392     return EFI_SUCCESS;
1393   } else {
1394     return EFI_DEVICE_ERROR;
1395   }
1396 }
1397 /**
1398   Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE OP code.
1399 
1400   @param    Script              The pointer of S3 boot script
1401 
1402   @retval   EFI_SUCCESS         The operation was executed successfully
1403 
1404 **/
1405 EFI_STATUS
BootScriptExecutePciCfg2Write(IN UINT8 * Script)1406 BootScriptExecutePciCfg2Write (
1407   IN UINT8             *Script
1408   )
1409 {
1410   VOID                              *Buffer;
1411   S3_BOOT_SCRIPT_LIB_WIDTH          Width;
1412   UINT16                            Segment;
1413   UINT64                            Address;
1414   UINTN                             Count;
1415   EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE PciCfg2Write;
1416 
1417   CopyMem ((VOID*)&PciCfg2Write, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE));
1418 
1419   Width   = (S3_BOOT_SCRIPT_LIB_WIDTH)PciCfg2Write.Width;
1420   Segment = PciCfg2Write.Segment;
1421   Address = PciCfg2Write.Address;
1422   Count   = PciCfg2Write.Count;
1423   Buffer  = Script + sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE);
1424 
1425   DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfg2Write - 0x%04x, 0x%08x, 0x%08x, 0x%08x\n", Segment, PCI_ADDRESS_ENCODE (Address), Count, (UINTN)Width));
1426   return ScriptPciCfg2Write (Width, Segment, Address, Count, Buffer);
1427 }
1428 
1429 
1430 /**
1431   Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE OP code.
1432 
1433   @param     Script                     The pointer of S3 boot script
1434   @param     AndMask                    Mask value for 'and' operation
1435   @param     OrMask                     Mask value for 'or' operation
1436 
1437   @retval    EFI_SUCCESS                The operation was executed successfully
1438 
1439 **/
1440 EFI_STATUS
BootScriptExecutePciCfg2ReadWrite(IN UINT8 * Script,IN UINT64 AndMask,IN UINT64 OrMask)1441 BootScriptExecutePciCfg2ReadWrite (
1442   IN UINT8                        *Script,
1443   IN UINT64                        AndMask,
1444   IN UINT64                        OrMask
1445   )
1446 {
1447   UINT64      Data;
1448   EFI_STATUS  Status;
1449   EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE PciCfg2ReadWrite;
1450 
1451   Data = 0;
1452 
1453   CopyMem ((VOID*)&PciCfg2ReadWrite, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE));
1454 
1455   DEBUG ((EFI_D_INFO, "BootScriptExecutePciCfg2ReadWrite - 0x%04x, 0x%08x, 0x%016lx, 0x%016lx\n", PciCfg2ReadWrite.Segment, PCI_ADDRESS_ENCODE (PciCfg2ReadWrite.Address), AndMask, OrMask));
1456 
1457   Status = ScriptPciCfg2Read (
1458              (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2ReadWrite.Width,
1459              PciCfg2ReadWrite.Segment,
1460              PciCfg2ReadWrite.Address,
1461              1,
1462              &Data
1463              );
1464   if (EFI_ERROR (Status)) {
1465     return Status;
1466   }
1467 
1468   Data = (Data & AndMask) | OrMask;
1469   Status = ScriptPciCfg2Write (
1470              (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2ReadWrite.Width,
1471              PciCfg2ReadWrite.Segment,
1472              PciCfg2ReadWrite.Address,
1473              1,
1474              &Data
1475              );
1476   return Status;
1477 }
1478 /**
1479   Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG_POLL OP code.
1480 
1481   @param     Script                     The pointer of S3 boot script
1482   @param     AndMask                    Mask value for 'and' operation
1483   @param     OrMask                     Mask value for 'or' operation
1484 
1485   @retval    EFI_SUCCESS                The operation was executed successfully
1486   @retval    EFI_DEVICE_ERROR           Data polled from Pci configuration space does not equal to
1487                                         epecting data within the Loop Times.
1488 **/
1489 EFI_STATUS
BootScriptPciCfgPoll(IN UINT8 * Script,IN UINT64 AndMask,IN UINT64 OrMask)1490 BootScriptPciCfgPoll (
1491   IN UINT8                         *Script,
1492   IN UINT64                        AndMask,
1493   IN UINT64                        OrMask
1494   )
1495 {
1496   UINT64        Data;
1497   UINT64        LoopTimes;
1498   EFI_STATUS    Status;
1499   EFI_BOOT_SCRIPT_PCI_CONFIG_POLL PciCfgPoll;
1500   CopyMem ((VOID*)&PciCfgPoll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG_POLL));
1501 
1502   DEBUG ((EFI_D_INFO, "BootScriptPciCfgPoll - 0x%08x, 0x%016lx, 0x%016lx\n", PCI_ADDRESS_ENCODE (PciCfgPoll.Address), AndMask, OrMask));
1503 
1504   Data = 0;
1505   Status = ScriptPciCfgRead (
1506              (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgPoll.Width,
1507              PciCfgPoll.Address,
1508              1,
1509              &Data
1510              );
1511   if ((!EFI_ERROR (Status)) &&(Data & AndMask) == OrMask) {
1512     return EFI_SUCCESS;
1513   }
1514 
1515   for (LoopTimes = 0; LoopTimes < PciCfgPoll.Delay; LoopTimes++) {
1516     NanoSecondDelay (100);
1517     Data = 0;
1518     Status = ScriptPciCfgRead (
1519                (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfgPoll.Width,
1520                PciCfgPoll.Address,
1521                1,
1522                &Data
1523                );
1524     if ((!EFI_ERROR (Status)) &&
1525        (Data & AndMask) == OrMask) {
1526       return EFI_SUCCESS;
1527     }
1528   }
1529 
1530   if (LoopTimes < PciCfgPoll.Delay) {
1531     return EFI_SUCCESS;
1532   } else {
1533     return EFI_DEVICE_ERROR;
1534   }
1535 }
1536 
1537 /**
1538   Interprete the boot script node with EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL OP code.
1539 
1540   @param     Script                     The pointer of S3 Boot Script
1541   @param     AndMask                    Mask value for 'and' operation
1542   @param     OrMask                     Mask value for 'or' operation
1543 
1544   @retval    EFI_SUCCESS                The operation was executed successfully
1545   @retval    EFI_DEVICE_ERROR           Data polled from Pci configuration space does not equal to
1546                                         epecting data within the Loop Times.
1547 
1548 **/
1549 EFI_STATUS
BootScriptPciCfg2Poll(IN UINT8 * Script,IN UINT64 AndMask,IN UINT64 OrMask)1550 BootScriptPciCfg2Poll (
1551   IN UINT8                        *Script,
1552   IN UINT64                        AndMask,
1553   IN UINT64                        OrMask
1554   )
1555 {
1556   EFI_STATUS    Status;
1557   UINT64        Data;
1558   UINT64        LoopTimes;
1559   EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL PciCfg2Poll;
1560 
1561   Data = 0;
1562   CopyMem ((VOID*)&PciCfg2Poll, (VOID*)Script, sizeof(EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL));
1563 
1564   DEBUG ((EFI_D_INFO, "BootScriptPciCfg2Poll - 0x%04x, 0x%08x, 0x%016lx, 0x%016lx\n", PciCfg2Poll.Segment, PCI_ADDRESS_ENCODE (PciCfg2Poll.Address), AndMask, OrMask));
1565 
1566   Status = ScriptPciCfg2Read (
1567              (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2Poll.Width,
1568              PciCfg2Poll.Segment,
1569              PciCfg2Poll.Address,
1570              1,
1571              &Data
1572              );
1573   if ((!EFI_ERROR (Status)) && (Data & AndMask) == OrMask) {
1574     return EFI_SUCCESS;
1575   }
1576 
1577   for (LoopTimes = 0; LoopTimes < PciCfg2Poll.Delay; LoopTimes++) {
1578     NanoSecondDelay (100);
1579 
1580     Data = 0;
1581     Status = ScriptPciCfg2Read (
1582                (S3_BOOT_SCRIPT_LIB_WIDTH) PciCfg2Poll.Width,
1583                PciCfg2Poll.Segment,
1584                PciCfg2Poll.Address,
1585                1,
1586                &Data
1587                );
1588     if ((!EFI_ERROR (Status)) &&  (Data & AndMask) == OrMask) {
1589       return EFI_SUCCESS;
1590     }
1591   }
1592 
1593   if (LoopTimes < PciCfg2Poll.Delay) {
1594     return EFI_SUCCESS;
1595   } else {
1596     return EFI_DEVICE_ERROR;
1597   }
1598 
1599 }
1600 
1601 /**
1602   Executes the S3 boot script table.
1603 
1604   @retval RETURN_SUCCESS           The boot script table was executed successfully.
1605   @retval RETURN_UNSUPPORTED       Invalid script table or opcode.
1606 
1607   @note  A known Limitations in the implementation: When interpreting the opcode  EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE
1608          EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE and EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE, the 'Segment' parameter is assumed as
1609          Zero, or else, assert.
1610 **/
1611 RETURN_STATUS
1612 EFIAPI
S3BootScriptExecute(VOID)1613 S3BootScriptExecute (
1614   VOID
1615   )
1616 {
1617   EFI_STATUS            Status;
1618   UINT8*                Script;
1619   UINTN                 StartAddress;
1620   UINT32                TableLength;
1621   UINT64                AndMask;
1622   UINT64                OrMask;
1623   EFI_BOOT_SCRIPT_COMMON_HEADER  ScriptHeader;
1624   EFI_BOOT_SCRIPT_TABLE_HEADER   TableHeader;
1625   Script = mS3BootScriptTablePtr->TableBase;
1626   if (Script != 0) {
1627     CopyMem ((VOID*)&TableHeader, Script, sizeof(EFI_BOOT_SCRIPT_TABLE_HEADER));
1628   } else {
1629     return EFI_INVALID_PARAMETER;
1630   }
1631 
1632   DEBUG ((EFI_D_INFO, "S3BootScriptExecute:\n"));
1633   if (TableHeader.OpCode != S3_BOOT_SCRIPT_LIB_TABLE_OPCODE) {
1634     return EFI_UNSUPPORTED;
1635   }
1636 
1637   DEBUG ((EFI_D_INFO, "TableHeader - 0x%08x\n", Script));
1638 
1639   StartAddress  = (UINTN) Script;
1640   TableLength   = TableHeader.TableLength;
1641   Script    =    Script + TableHeader.Length;
1642   Status        = EFI_SUCCESS;
1643   AndMask       = 0;
1644   OrMask        = 0;
1645 
1646   DEBUG ((EFI_D_INFO, "TableHeader.Version - 0x%04x\n", (UINTN)TableHeader.Version));
1647   DEBUG ((EFI_D_INFO, "TableHeader.TableLength - 0x%08x\n", (UINTN)TableLength));
1648 
1649   while ((UINTN) Script < (UINTN) (StartAddress + TableLength)) {
1650     DEBUG ((EFI_D_INFO, "ExecuteBootScript - %08x\n", (UINTN)Script));
1651 
1652     CopyMem ((VOID*)&ScriptHeader, Script, sizeof(EFI_BOOT_SCRIPT_COMMON_HEADER));
1653     switch (ScriptHeader.OpCode) {
1654 
1655     case EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE:
1656       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_MEM_WRITE_OPCODE\n"));
1657       Status = BootScriptExecuteMemoryWrite (Script);
1658       break;
1659 
1660     case EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE:
1661       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_MEM_READ_WRITE_OPCODE\n"));
1662       CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1663       Status = BootScriptExecuteMemoryReadWrite (
1664                  Script,
1665                  AndMask,
1666                  OrMask
1667                  );
1668       break;
1669 
1670     case EFI_BOOT_SCRIPT_IO_WRITE_OPCODE:
1671       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_IO_WRITE_OPCODE\n"));
1672       Status = BootScriptExecuteIoWrite (Script);
1673       break;
1674 
1675     case EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE:
1676       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG_WRITE_OPCODE\n"));
1677       Status = BootScriptExecutePciCfgWrite (Script);
1678       break;
1679 
1680     case EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE:
1681       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG_READ_WRITE_OPCODE\n"));
1682       CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1683       Status = BootScriptExecutePciCfgReadWrite (
1684                  Script,
1685                  AndMask,
1686                  OrMask
1687                  );
1688       break;
1689     case EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE:
1690       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG2_WRITE_OPCODE\n"));
1691       Status = BootScriptExecutePciCfg2Write (Script);
1692       break;
1693 
1694     case EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE:
1695       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG2_READ_WRITE_OPCODE\n"));
1696       CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1697       Status = BootScriptExecutePciCfg2ReadWrite (
1698                  Script,
1699                  AndMask,
1700                  OrMask
1701                  );
1702       break;
1703     case EFI_BOOT_SCRIPT_DISPATCH_OPCODE:
1704       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_DISPATCH_OPCODE\n"));
1705       Status = BootScriptExecuteDispatch (Script);
1706       break;
1707 
1708     case EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE:
1709       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_DISPATCH_2_OPCODE\n"));
1710       Status = BootScriptExecuteDispatch2 (Script);
1711       break;
1712 
1713     case EFI_BOOT_SCRIPT_INFORMATION_OPCODE:
1714       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_INFORMATION_OPCODE\n"));
1715       BootScriptExecuteInformation (Script);
1716       break;
1717 
1718     case S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE:
1719       DEBUG ((EFI_D_INFO, "S3_BOOT_SCRIPT_LIB_TERMINATE_OPCODE\n"));
1720       DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", EFI_SUCCESS));
1721       return EFI_SUCCESS;
1722 
1723     case EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE:
1724       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_IO_READ_WRITE_OPCODE\n"));
1725       CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1726       Status = BootScriptExecuteIoReadWrite (
1727                 Script,
1728                 AndMask,
1729                 OrMask
1730                 );
1731       break;
1732 
1733     case EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE:
1734       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_SMBUS_EXECUTE_OPCODE\n"));
1735       Status = BootScriptExecuteSmbusExecute (Script);
1736       break;
1737 
1738     case EFI_BOOT_SCRIPT_STALL_OPCODE:
1739       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_STALL_OPCODE\n"));
1740       Status = BootScriptExecuteStall (Script);
1741       break;
1742 
1743     case EFI_BOOT_SCRIPT_MEM_POLL_OPCODE:
1744       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_MEM_POLL_OPCODE\n"));
1745       CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1746       Status = BootScriptExecuteMemPoll (Script, AndMask, OrMask);
1747 
1748       break;
1749 
1750     case EFI_BOOT_SCRIPT_IO_POLL_OPCODE:
1751       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_IO_POLL_OPCODE\n"));
1752       CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1753       Status = BootScriptExecuteIoPoll (Script, AndMask, OrMask);
1754       break;
1755 
1756     case EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE:
1757       DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG_POLL_OPCODE\n"));
1758       CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1759       Status = BootScriptPciCfgPoll (Script, AndMask, OrMask);
1760       break;
1761 
1762     case EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE:
1763      DEBUG ((EFI_D_INFO, "EFI_BOOT_SCRIPT_PCI_CONFIG2_POLL_OPCODE\n"));
1764      CheckAndOrMask (&ScriptHeader, &AndMask, &OrMask, Script);
1765      Status = BootScriptPciCfg2Poll (Script, AndMask, OrMask);
1766      break;
1767 
1768     case S3_BOOT_SCRIPT_LIB_LABEL_OPCODE:
1769       //
1770       // For label
1771       //
1772       DEBUG ((EFI_D_INFO, "S3_BOOT_SCRIPT_LIB_LABEL_OPCODE\n"));
1773       BootScriptExecuteLabel (Script);
1774       break;
1775     default:
1776       DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", EFI_UNSUPPORTED));
1777       return EFI_UNSUPPORTED;
1778     }
1779 
1780     if (EFI_ERROR (Status)) {
1781       DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", Status));
1782       return Status;
1783     }
1784 
1785     Script  = Script + ScriptHeader.Length;
1786   }
1787 
1788   DEBUG ((EFI_D_INFO, "S3BootScriptDone - %r\n", Status));
1789 
1790   return Status;
1791 }
1792 
1793