1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 #include <acpi/acpi_device.h>
4 #include <acpi/acpigen.h>
5 #include <amdblocks/graphics.h>
6 #include <amdblocks/vbios_cache.h>
7 #include <boot/coreboot_tables.h>
10 #include <console/console.h>
11 #include <device/device.h>
12 #include <device/pci.h>
14 #include <security/vboot/vbios_cache_hash_tpm.h>
15 #include <soc/intel/common/vbt.h>
16 #include <timestamp.h>
18 static bool vbios_loaded_from_cache
= false;
19 static uint8_t vbios_data
[VBIOS_CACHE_FMAP_SIZE
];
21 #define ATIF_FUNCTION_VERIFY_INTERFACE 0x0
22 struct atif_verify_interface_output
{
23 uint16_t size
; /* Size of this object, including size field */
25 uint32_t supported_notifications
;
26 uint32_t supported_functions
; /* Bit n set if function n+1 supported. */
29 #define ATIF_FUNCTION_QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS 0x10
30 # define ATIF_QBTC_REQUEST_LCD1 0
32 # define ATIF_QBTC_ERROR_CODE_SUCCESS 0
33 # define ATIF_QBTC_ERROR_CODE_FAILURE 1
34 # define ATIF_QBTC_ERROR_CODE_DEVICE_NOT_SUPPORTED 2
35 struct atif_brightness_input
{
37 /* ATIF doc indicates this field is a word, but the kernel drivers uses a byte. */
38 uint8_t requested_display
;
40 struct atif_brightness_output
{
41 uint16_t size
; /* Size of this object, including size field. */
42 uint16_t flags
; /* Currently all reserved. */
44 /* default brightness fields currently ignored by Linux driver. */
45 uint8_t default_brightness_ac
; /* Percentage brightness when connected to AC. */
46 uint8_t default_brightness_dc
; /* Percentage brightness when connected to DC. */
47 /* The following 2 fields are the only ones honored by Linux driver currently. */
48 uint8_t min_input_signal_level
; /* 0-255 corresponding to 0% */
49 uint8_t max_input_signal_level
; /* 0-255 corresponding to 100% */
50 /* Array of data points consisting of:
51 * { uint8_t luminance_level; (percent)
52 * uint8_t input_signal_level; (0-255 in value) }
53 * Linux ignores these fields so no support currently. */
54 uint8_t count_data_points
; /* Count of data points. */
57 static void generate_atif(const struct device
*dev
)
59 struct atif_verify_interface_output verify_output
= {
60 .size
= sizeof(verify_output
),
62 .supported_functions
=
63 BIT(ATIF_FUNCTION_QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS
- 1),
65 struct atif_brightness_output brightness_error
= {
66 .size
= sizeof(brightness_error
),
67 .error_code
= ATIF_QBTC_ERROR_CODE_DEVICE_NOT_SUPPORTED
,
69 struct atif_brightness_output brightness_out
= {
70 .size
= sizeof(brightness_out
),
71 .error_code
= ATIF_QBTC_ERROR_CODE_SUCCESS
,
72 .min_input_signal_level
= 0,
73 .max_input_signal_level
= 255,
76 /* Scope (\_SB.PCI0.PBRA.IGFX) */
77 acpigen_write_scope(acpi_device_path(dev
));
78 /* Method (ATIF, 2, NotSerialized) */
79 acpigen_write_method("ATIF", 2);
80 /* ToInteger (Arg0, Local0) */
81 acpigen_write_to_integer(ARG0_OP
, LOCAL0_OP
);
83 /* If ((Local0 == Zero)) */
84 acpigen_write_if_lequal_op_int(LOCAL0_OP
, ATIF_FUNCTION_VERIFY_INTERFACE
);
85 /* Return (Buffer (0x0C) { ... } */
86 acpigen_write_return_byte_buffer((uint8_t *)(void *)&verify_output
,
87 sizeof(verify_output
));
89 /* ElseIf ((Local0 == 0x10)) */
91 acpigen_write_if_lequal_op_int(LOCAL0_OP
,
92 ATIF_FUNCTION_QUERY_BRIGHTNESS_TRANSFER_CHARACTERISTICS
);
93 /* CreateByteField (Arg1, 0x02, DISP) */
94 acpigen_write_create_byte_field(ARG1_OP
,
95 offsetof(struct atif_brightness_input
, requested_display
), "DISP");
96 /* ToInteger (DISP, Local1) */
97 acpigen_write_to_integer_from_namestring("DISP", LOCAL1_OP
);
98 /* If ((Local1 == Zero)) */
99 acpigen_write_if_lequal_op_int(LOCAL1_OP
, ATIF_QBTC_REQUEST_LCD1
);
100 /* Return (Buffer (0x0A) { ... } */
101 acpigen_write_return_byte_buffer((uint8_t *)(void *)&brightness_out
,
102 sizeof(brightness_out
));
104 acpigen_write_else();
105 /* Return (Buffer (0x0A) */
106 acpigen_write_return_byte_buffer((uint8_t *)(void *)&brightness_error
,
107 sizeof(brightness_error
));
108 acpigen_pop_len(); /* else */
110 acpigen_pop_len(); /* if (LEqual(Local0, 0x10) */
111 acpigen_pop_len(); /* else */
113 acpigen_pop_len(); /* Method */
114 acpigen_pop_len(); /* Scope */
117 static void generate_acp(const struct device
*dev
)
119 /* Scope (\_SB.PCI0.IGFX) */
120 acpigen_write_scope(acpi_device_path(dev
));
121 acpigen_write_device("ACP");
123 acpigen_write_name_string("_HID", "BOOT0003");
125 acpigen_pop_len(); /* Device */
126 acpigen_pop_len(); /* Scope */
129 static void graphics_fill_ssdt(const struct device
*dev
)
131 acpi_device_write_pci_dev(dev
);
133 /* Use the VFCT copy when using GOP */
134 if (!CONFIG(RUN_FSP_GOP
))
137 if (CONFIG(SOC_AMD_COMMON_BLOCK_GRAPHICS_ATIF
))
140 if (CONFIG(SOC_AMD_COMMON_BLOCK_GRAPHICS_ACP
))
144 static const char *graphics_acpi_name(const struct device
*dev
)
150 * Even though AMD does not need VBT we still need to implement the
151 * vbt_get() function to not break the build with GOP driver enabled
152 * (see fsps_return_value_handler() in fsp2_0/silicon_init.c
159 static void graphics_set_resources(struct device
*const dev
)
161 struct rom_header
*rom
, *ram
;
163 pci_dev_set_resources(dev
);
165 if (!CONFIG(RUN_FSP_GOP
))
168 timestamp_add_now(TS_OPROM_INITIALIZE
);
169 if (CONFIG(USE_SELECTIVE_GOP_INIT
) && vbios_cache_is_valid() &&
170 !display_init_required()) {
171 vbios_load_from_cache();
172 timestamp_add_now(TS_OPROM_COPY_END
);
175 rom
= pci_rom_probe(dev
);
177 printk(BIOS_ERR
, "%s: Unable to find ROM for %s\n",
178 __func__
, dev_path(dev
));
179 timestamp_add_now(TS_OPROM_COPY_END
);
183 ram
= pci_rom_load(dev
, rom
);
185 printk(BIOS_ERR
, "%s: Unable to load ROM for %s\n",
186 __func__
, dev_path(dev
));
191 timestamp_add_now(TS_OPROM_COPY_END
);
194 static void graphics_dev_init(struct device
*const dev
)
196 if (CONFIG(RUN_FSP_GOP
))
197 fsp_graphics_init(dev
);
199 /* Initialize PCI device, load/execute BIOS Option ROM */
203 static void read_vbios_cache_from_fmap(void *unused
)
205 struct region_device rw_vbios_cache
;
208 if (!CONFIG(SOC_AMD_GFX_CACHE_VBIOS_IN_FMAP
))
211 if (fmap_locate_area_as_rdev(VBIOS_CACHE_FMAP_NAME
, &rw_vbios_cache
)) {
212 printk(BIOS_ERR
, "%s: No %s FMAP section.\n", __func__
, VBIOS_CACHE_FMAP_NAME
);
216 region_size
= region_device_sz(&rw_vbios_cache
);
218 if (region_size
!= VBIOS_CACHE_FMAP_SIZE
) {
219 printk(BIOS_ERR
, "%s: %s FMAP size mismatch for VBIOS cache (%d vs %d).\n",
220 __func__
, VBIOS_CACHE_FMAP_NAME
, VBIOS_CACHE_FMAP_SIZE
, region_size
);
224 /* Read cached VBIOS data into buffer */
225 if (rdev_readat(&rw_vbios_cache
, &vbios_data
, 0, VBIOS_CACHE_FMAP_SIZE
) != VBIOS_CACHE_FMAP_SIZE
) {
226 printk(BIOS_ERR
, "Failed to read vbios data from flash; rdev_readat() failed.\n");
230 printk(BIOS_SPEW
, "VBIOS cache successfully read from FMAP.\n");
233 static void write_vbios_cache_to_fmap(void *unused
)
235 if (!CONFIG(SOC_AMD_GFX_CACHE_VBIOS_IN_FMAP
))
238 /* Don't save if VBIOS loaded from cache / data unchanged */
239 if (vbios_loaded_from_cache
== true) {
240 printk(BIOS_SPEW
, "VBIOS data loaded from cache; not saving\n");
244 struct region_device rw_vbios_cache
;
246 if (fmap_locate_area_as_rdev_rw(VBIOS_CACHE_FMAP_NAME
, &rw_vbios_cache
)) {
247 printk(BIOS_ERR
, "%s: No %s FMAP section.\n", __func__
, VBIOS_CACHE_FMAP_NAME
);
251 /* copy from PCI_VGA_RAM_IMAGE_START to rdev */
252 if (rdev_writeat(&rw_vbios_cache
, (void *)PCI_VGA_RAM_IMAGE_START
, 0,
253 VBIOS_CACHE_FMAP_SIZE
) != VBIOS_CACHE_FMAP_SIZE
)
254 printk(BIOS_ERR
, "Failed to save vbios data to flash; rdev_writeat() failed.\n");
256 /* copy modified vbios data from PCI_VGA_RAM_IMAGE_START to buffer before hashing */
257 memcpy(vbios_data
, (void *)PCI_VGA_RAM_IMAGE_START
, VBIOS_CACHE_FMAP_SIZE
);
259 /* save data hash to TPM NVRAM for validation on subsequent boots */
260 vbios_cache_update_hash(vbios_data
, VBIOS_CACHE_FMAP_SIZE
);
262 printk(BIOS_SPEW
, "VBIOS cache successfully written to FMAP.\n");
266 * Loads cached VBIOS data into legacy oprom location.
268 * Assumes user has called vbios_cache_is_valid() and checked for success
270 void vbios_load_from_cache(void)
272 /* copy cached vbios data from buffer to PCI_VGA_RAM_IMAGE_START */
273 memcpy((void *)PCI_VGA_RAM_IMAGE_START
, vbios_data
, VBIOS_CACHE_FMAP_SIZE
);
275 /* mark cache as used so we know not to write it later */
276 vbios_loaded_from_cache
= true;
280 * Return true if VBIOS cache data is valid
282 * Compare first 2 bytes of data with known signature
283 * and hash of data with hash stored in TPM NVRAM
285 bool vbios_cache_is_valid(void)
287 bool sig_valid
= vbios_data
[0] == 0x55 && vbios_data
[1] == 0xaa;
288 return sig_valid
&& vbios_cache_verify_hash(vbios_data
, VBIOS_CACHE_FMAP_SIZE
) == CB_SUCCESS
;
291 BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE
, BS_ON_EXIT
, read_vbios_cache_from_fmap
, NULL
);
292 BOOT_STATE_INIT_ENTRY(BS_OS_RESUME_CHECK
, BS_ON_ENTRY
, write_vbios_cache_to_fmap
, NULL
);
294 const struct device_operations amd_graphics_ops
= {
295 .read_resources
= pci_dev_read_resources
,
296 .set_resources
= graphics_set_resources
,
297 .enable_resources
= pci_dev_enable_resources
,
298 .init
= graphics_dev_init
,
299 .scan_bus
= scan_static_bus
,
300 .ops_pci
= &pci_dev_ops_pci
,
301 .write_acpi_tables
= pci_rom_write_acpi_tables
,
302 .acpi_fill_ssdt
= graphics_fill_ssdt
,
303 .acpi_name
= graphics_acpi_name
,