coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
oem_s3.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <spi-generic.h>
4 #include <spi_flash.h>
5 #include <string.h>
6 #include <cbmem.h>
7 #include <console/console.h>
9 #include <AGESA.h>
11 
12 typedef enum {
13  S3DataTypeNonVolatile = 0, ///< NonVolatile Data Type
14  S3DataTypeMTRR ///< MTRR storage
16 
17 /* The size needs to be 4k aligned, which is the sector size of most flashes. */
18 #define S3_DATA_MTRR_SIZE 0x1000
19 #define S3_DATA_NONVOLATILE_SIZE 0x1000
20 
21 #if CONFIG(HAVE_ACPI_RESUME) && \
22  (S3_DATA_MTRR_SIZE + S3_DATA_NONVOLATILE_SIZE) > CONFIG_S3_DATA_SIZE
23 #error "Please increase the value of S3_DATA_SIZE"
24 #endif
25 
26 static void get_s3nv_data(S3_DATA_TYPE S3DataType, uintptr_t *pos, uintptr_t *len)
27 {
28  /* FIXME: Find file from CBFS. */
29  u32 s3_data = CONFIG_S3_DATA_POS;
30 
31  switch (S3DataType) {
32  case S3DataTypeMTRR:
33  *pos = s3_data;
34  *len = S3_DATA_MTRR_SIZE;
35  break;
37  *pos = s3_data + S3_DATA_MTRR_SIZE;
39  break;
40  default:
41  *pos = 0;
42  *len = 0;
43  break;
44  }
45 }
46 
47 AGESA_STATUS OemInitResume(AMD_S3_PARAMS *dataBlock)
48 {
49  uintptr_t pos, size;
51 
52  u32 len = *(u32*)pos;
53 
54  /* Test for uninitialized s3nv data in SPI. */
55  if (len == 0 || len == (u32)-1ULL)
56  return AGESA_FATAL;
57 
58  dataBlock->NvStorageSize = len;
59  dataBlock->NvStorage = (void *) (pos + sizeof(u32));
60  return AGESA_SUCCESS;
61 }
62 
63 AGESA_STATUS OemS3LateRestore(AMD_S3_PARAMS *dataBlock)
64 {
65  char *heap = cbmem_find(CBMEM_ID_RESUME_SCRATCH);
66  if (heap == NULL)
67  return AGESA_FATAL;
68 
69  printk(BIOS_DEBUG, "Using resume HEAP at %08x\n",
70  (unsigned int)(uintptr_t) heap);
71 
72  /* Return allocated CBMEM size, we do not keep track of
73  * how much was actually used.
74  */
75  dataBlock->VolatileStorageSize = HIGH_MEMORY_SCRATCH;
76  dataBlock->VolatileStorage = heap;
77  return AGESA_SUCCESS;
78 }
79 
80 #if ENV_RAMSTAGE
81 
82 static int spi_SaveS3info(u32 pos, u32 size, u8 *buf, u32 len)
83 {
84 #if CONFIG(SPI_FLASH)
85  struct spi_flash flash;
86 
87  spi_init();
88  if (spi_flash_probe(0, 0, &flash))
89  return -1;
90 
92 
93  spi_flash_erase(&flash, pos, size);
94  spi_flash_write(&flash, pos, sizeof(len), &len);
95  spi_flash_write(&flash, pos + sizeof(len), len, buf);
96 
98  return 0;
99 #else
100  return -1;
101 #endif
102 }
103 
104 static u8 MTRRStorage[S3_DATA_MTRR_SIZE];
105 
106 AGESA_STATUS OemS3Save(AMD_S3_PARAMS *dataBlock)
107 {
108  u32 MTRRStorageSize = 0;
109  uintptr_t pos, size;
110 
111  /* To be consumed in AmdInitResume. */
113  if (size && dataBlock->NvStorageSize)
114  spi_SaveS3info(pos, size, dataBlock->NvStorage,
115  dataBlock->NvStorageSize);
116  else
118  "Error: Cannot store memory training results in SPI.\n"
119  "Error: S3 resume will not be possible.\n"
120  );
121 
122  /* To be consumed in AmdS3LateRestore. */
124  if (heap) {
125  memset(heap, 0, HIGH_MEMORY_SCRATCH);
126  memcpy(heap, dataBlock->VolatileStorage, dataBlock->VolatileStorageSize);
127  }
128 
129  /* Collect MTRR setup. */
130  backup_mtrr(MTRRStorage, &MTRRStorageSize);
131 
132  /* To be consumed in restore_mtrr, CPU enumeration in ramstage. */
134  if (size && MTRRStorageSize)
135  spi_SaveS3info(pos, size, MTRRStorage, MTRRStorageSize);
136 
137  return AGESA_SUCCESS;
138 }
139 
140 #endif /* ENV_RAMSTAGE */
141 
142 const void *OemS3Saved_MTRR_Storage(void)
143 {
144  uintptr_t pos, size;
146  if (!size)
147  return NULL;
148 
149  return (void *)(pos + sizeof(UINT32));
150 }
#define AGESA_SUCCESS
Definition: Amd.h:38
#define AGESA_FATAL
Definition: Amd.h:44
unsigned int AGESA_STATUS
Definition: Amd.h:36
#define HIGH_MEMORY_SCRATCH
Definition: agesa_helper.h:36
void * memcpy(void *dest, const void *src, size_t n)
Definition: memcpy.c:7
void * memset(void *dstpp, int c, size_t len)
Definition: memset.c:12
void * cbmem_add(u32 id, u64 size)
Definition: imd_cbmem.c:144
void * cbmem_find(u32 id)
Definition: imd_cbmem.c:166
#define CBMEM_ID_RESUME_SCRATCH
Definition: cbmem_id.h:50
#define printk(level,...)
Definition: stdlib.h:16
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_EMERG
BIOS_EMERG - Emergency / Fatal.
Definition: loglevel.h:25
static uint8_t * buf
Definition: uart.c:7
#define S3_DATA_MTRR_SIZE
Definition: oem_s3.c:18
S3_DATA_TYPE
Definition: oem_s3.c:12
@ S3DataTypeNonVolatile
NonVolatile Data Type.
Definition: oem_s3.c:13
@ S3DataTypeMTRR
MTRR storage.
Definition: oem_s3.c:14
AGESA_STATUS OemS3LateRestore(AMD_S3_PARAMS *dataBlock)
Definition: oem_s3.c:63
const void * OemS3Saved_MTRR_Storage(void)
Definition: oem_s3.c:142
AGESA_STATUS OemInitResume(AMD_S3_PARAMS *dataBlock)
Definition: oem_s3.c:47
#define S3_DATA_NONVOLATILE_SIZE
Definition: oem_s3.c:19
static void get_s3nv_data(S3_DATA_TYPE S3DataType, uintptr_t *pos, uintptr_t *len)
Definition: oem_s3.c:26
void backup_mtrr(void *mtrr_store, u32 *mtrr_store_size)
Definition: s3_mtrr.c:20
void __weak spi_init(void)
Definition: spi-generic.c:117
int spi_flash_probe(unsigned int bus, unsigned int cs, struct spi_flash *flash)
Definition: spi_flash.c:486
int spi_flash_volatile_group_begin(const struct spi_flash *flash)
Definition: spi_flash.c:647
int spi_flash_write(const struct spi_flash *flash, u32 offset, size_t len, const void *buf)
Definition: spi_flash.c:537
int spi_flash_volatile_group_end(const struct spi_flash *flash)
Definition: spi_flash.c:664
int spi_flash_erase(const struct spi_flash *flash, u32 offset, size_t len)
Definition: spi_flash.c:553
AGESA_STATUS OemS3Save(AMD_S3_PARAMS *dataBlock)
#define NULL
Definition: stddef.h:19
uint32_t u32
Definition: stdint.h:51
unsigned long uintptr_t
Definition: stdint.h:21
uint8_t u8
Definition: stdint.h:45
u32 size
Definition: spi_flash.h:95