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