Skip to content

Commit 42526e9

Browse files
mintsukiFlyGoat
andcommitted
mcfg tmp
Co-authored-by: Jiaxun Yang <[email protected]>
1 parent 9b4f696 commit 42526e9

File tree

8 files changed

+530
-167
lines changed

8 files changed

+530
-167
lines changed

src/acpi.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,9 @@ bool acpi_init(struct csmwrap_priv *priv) {
9999
return false;
100100
}
101101

102-
void acpi_prepare_exitbs(void) {
102+
void acpi_prepare_exitbs(struct csmwrap_priv *priv) {
103+
(void)priv;
104+
103105
if (early_table_buffer != NULL) {
104106
gBS->FreePool(early_table_buffer);
105107
early_table_buffer = NULL;

src/csmwrap.c

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
#include <csmwrap.h>
33

44
#include <io.h>
5+
#include <pci.h>
56
#include <x86thunk.h>
67
#include <video.h>
78

@@ -100,13 +101,16 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
100101
gBS->RaiseTPL(TPL_NOTIFY);
101102
gBS->SetWatchdogTimer(0, 0, 0, NULL);
102103

103-
if (unlock_bios_region()) {
104+
acpi_init(&priv);
105+
pci_init(&priv);
106+
107+
if (unlock_bios_region(&priv)) {
104108
printf("Unable to unlock BIOS region\n");
105109
return -1;
106110
}
107111
printf("Unlock!\n");
108112

109-
apply_intel_platform_workarounds();
113+
apply_intel_platform_workarounds(&priv);
110114

111115
csm_bin_base = (uintptr_t)BIOSROM_END - sizeof(Csm16_bin);
112116
priv.csm_bin_base = csm_bin_base;
@@ -122,8 +126,6 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
122126
return -1;
123127
}
124128

125-
acpi_init(&priv);
126-
127129
Status = csmwrap_video_init(&priv);
128130

129131
HiPmm = 0xffffffff;
@@ -159,9 +161,9 @@ EFI_STATUS efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable)
159161
printf("CALL16 %x:%x\n", priv.csm_efi_table->Compatibility16CallSegment,
160162
priv.csm_efi_table->Compatibility16CallOffset);
161163

164+
acpi_prepare_exitbs(&priv);
162165
/* WARNING: No EFI Video afterwards */
163166
csmwrap_video_prepare_exitbs(&priv);
164-
acpi_prepare_exitbs();
165167

166168
/* WARNING: No EFI runtime service afterwards */
167169
UINTN efi_mmap_size = 0, efi_desc_size = 0, efi_mmap_key = 0;

src/csmwrap.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ struct csmwrap_priv {
2727
uintptr_t csm_bin_base;
2828
struct low_stub *low_stub;
2929

30+
PCI_DEVICE_INDEPENDENT_REGION hbridge_hdr;
31+
int rootbus_count;
32+
uint8_t rootbus_list[PCI_MAX_BUS + 1];
33+
3034
/* VGA stuff */
3135
enum csmwrap_video_type video_type;
3236
EFI_GRAPHICS_OUTPUT_PROTOCOL *gop;
@@ -37,12 +41,12 @@ struct csmwrap_priv {
3741
struct cb_framebuffer cb_fb;
3842
};
3943

40-
extern int unlock_bios_region();
44+
extern int unlock_bios_region(struct csmwrap_priv *priv);
4145
extern int build_coreboot_table(struct csmwrap_priv *priv);
4246
bool acpi_init(struct csmwrap_priv *priv);
43-
void acpi_prepare_exitbs(void);
47+
void acpi_prepare_exitbs(struct csmwrap_priv *priv);
4448
int build_e820_map(struct csmwrap_priv *priv, EFI_MEMORY_DESCRIPTOR *memory_map, UINTN memory_map_size, UINTN descriptor_size);
45-
int apply_intel_platform_workarounds(void);
49+
int apply_intel_platform_workarounds(struct csmwrap_priv *priv);
4650

4751

4852
static inline int

src/intel_workarounds.c

Lines changed: 64 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,16 @@
11
#include <efi.h>
2-
#include "csmwrap.h"
2+
#include <csmwrap.h>
3+
#include <io.h>
4+
#include <printf.h>
5+
#include <pci.h>
36

4-
#include "io.h"
57

6-
#define PCI_DEVICE_NUMBER_PCH_P2SB 31
7-
#define PCI_FUNCTION_NUMBER_PCH_P2SB 1
8+
// See Silicon/ArrowlakePkg/Include/Register/PchBdfAssignment.h
9+
//
10+
// Primary to Sideband (P2SB) Bridge SOC (D31:F1)
11+
//
12+
#define PCI_DEVICE_NUMBER_PCH_P2SB 31
13+
#define PCI_FUNCTION_NUMBER_PCH_P2SB 1
814

915
#define SBREG_BAR 0x10
1016
#define SBREG_BARH 0x14
@@ -55,46 +61,73 @@
5561
*/
5662
#define B_P2SB_CFG_P2SBC_HIDE (1 << 8) ///< P2SB Hide Bit
5763

58-
static int pit_8254cge_workaround(void)
64+
65+
EFI_STATUS find_p2sb_pci(struct csmwrap_priv *priv, UINT64 *pci_address)
66+
{
67+
PCI_TYPE00 pdev;
68+
69+
for (int pciroot = 0; pciroot < priv->rootbus_count; pciroot++) {
70+
UINT8 bus = priv->rootbus_list[pciroot];
71+
UINT64 d31f0 = EFI_PCI_ADDRESS(bus, 31, 0);
72+
73+
if (PciConfigRead(EfiPciIoWidthUint32, d31f0, sizeof(pdev.Hdr) / 4, &pdev.Hdr) != EFI_SUCCESS) {
74+
continue; // Skip if configuration cannot be read
75+
}
76+
77+
if (pdev.Hdr.VendorId != 0x8086 || !IS_PCI_MULTI_FUNC(&pdev)) {
78+
continue; // Not an Intel multifunc device
79+
}
80+
81+
if (!IS_CLASS2(&pdev, PCI_CLASS_BRIDGE, PCI_CLASS_BRIDGE_ISA)) {
82+
continue; // D31F0 is not a ISA bridge
83+
}
84+
85+
*pci_address = EFI_PCI_ADDRESS(bus, PCI_DEVICE_NUMBER_PCH_P2SB, PCI_FUNCTION_NUMBER_PCH_P2SB);
86+
87+
return EFI_SUCCESS; // Found P2SB
88+
}
89+
90+
return EFI_NOT_FOUND; // No P2SB found
91+
}
92+
93+
static int pit_8254cge_workaround(struct csmwrap_priv *priv)
5994
{
95+
EFI_STATUS Status;
6096
uint32_t reg;
6197
unsigned long base;
6298
bool p2sb_hide = false;
63-
int pch_pci_bus = 0;
99+
UINT64 p2sb_addr;
100+
101+
Status = find_p2sb_pci(priv, &p2sb_addr);
102+
if (EFI_ERROR(Status)) {
103+
DEBUG((DEBUG_INFO, "P2SB Not found %d, skipping 8254CGE workaround\n", Status));
104+
return -1; // P2SB not found, skip workaround
105+
}
64106

65-
reg = pciConfigReadDWord(pch_pci_bus, PCI_DEVICE_NUMBER_PCH_P2SB,
66-
PCI_FUNCTION_NUMBER_PCH_P2SB,
67-
0x0);
107+
DEBUG((DEBUG_INFO, "P2SB Address: %lx\n", p2sb_addr));
108+
109+
Status = PciConfigRead(EfiPciIoWidthUint32, p2sb_addr, 1, &reg);
68110

69111
/* P2SB maybe hidden, try unhide it first */
70112
if ((reg & 0xFFFF) == 0xffff) {
71-
reg = pciConfigReadDWord(pch_pci_bus, PCI_DEVICE_NUMBER_PCH_P2SB,
72-
PCI_FUNCTION_NUMBER_PCH_P2SB,
73-
R_P2SB_CFG_P2SBC);
113+
Status = PciConfigRead(EfiPciIoWidthUint32, p2sb_addr + R_P2SB_CFG_P2SBC, 1, &reg);
74114
reg &= ~B_P2SB_CFG_P2SBC_HIDE;
75-
pciConfigWriteDWord(pch_pci_bus, PCI_DEVICE_NUMBER_PCH_P2SB,
76-
PCI_FUNCTION_NUMBER_PCH_P2SB,
77-
R_P2SB_CFG_P2SBC, reg);
115+
Status = PciConfigWrite(EfiPciIoWidthUint32, p2sb_addr + R_P2SB_CFG_P2SBC, 1, &reg);
78116
p2sb_hide = true;
79117
}
80118

81-
reg = pciConfigReadDWord(pch_pci_bus, PCI_DEVICE_NUMBER_PCH_P2SB,
82-
PCI_FUNCTION_NUMBER_PCH_P2SB,
83-
0x0);
119+
/* Read header again */
120+
Status = PciConfigRead(EfiPciIoWidthUint32, p2sb_addr, 1, &reg);
84121

85122
if ((reg & 0xFFFF) != 0x8086) {
86-
printf("No P2SB found, proceed to PIT test\n");
123+
DEBUG((DEBUG_ERROR, "Unable to unhide P2SB\n"));
87124
goto test_pit;
88125
}
89126

90-
reg = pciConfigReadDWord(pch_pci_bus, PCI_DEVICE_NUMBER_PCH_P2SB,
91-
PCI_FUNCTION_NUMBER_PCH_P2SB,
92-
SBREG_BAR);
127+
Status = PciConfigRead(EfiPciIoWidthUint32, p2sb_addr + SBREG_BAR, 1, &reg);
93128
base = reg & ~0x0F;
94129

95-
reg = pciConfigReadDWord(pch_pci_bus, PCI_DEVICE_NUMBER_PCH_P2SB,
96-
PCI_FUNCTION_NUMBER_PCH_P2SB,
97-
SBREG_BARH);
130+
Status = PciConfigRead(EfiPciIoWidthUint32, p2sb_addr + SBREG_BARH, 1, &reg);
98131
#ifdef __LP64__
99132
base |= ((uint64_t)reg & 0xFFFFFFFF) << 32;
100133
#else
@@ -103,7 +136,6 @@ static int pit_8254cge_workaround(void)
103136
goto test_pit;
104137
}
105138
#endif
106-
107139
/* FIXME: Validate base */
108140
reg = readl(PCH_PCR_ADDRESS(base, PID_ITSS, R_PCH_PCR_ITSS_ITSSPRC));
109141
printf("ITSSPRC = %x, ITSSPRC.8254CGE= %x\n", reg, !!(reg & B_PCH_PCR_ITSS_ITSSPRC_8254CGE));
@@ -113,13 +145,9 @@ static int pit_8254cge_workaround(void)
113145

114146
/* Hide P2SB again */
115147
if (p2sb_hide) {
116-
reg = pciConfigReadDWord(pch_pci_bus, PCI_DEVICE_NUMBER_PCH_P2SB,
117-
PCI_FUNCTION_NUMBER_PCH_P2SB,
118-
R_P2SB_CFG_P2SBC);
148+
Status = PciConfigRead(EfiPciIoWidthUint32, p2sb_addr + R_P2SB_CFG_P2SBC, 1, &reg);
119149
reg |= B_P2SB_CFG_P2SBC_HIDE;
120-
pciConfigWriteDWord(pch_pci_bus, PCI_DEVICE_NUMBER_PCH_P2SB,
121-
PCI_FUNCTION_NUMBER_PCH_P2SB,
122-
R_P2SB_CFG_P2SBC, reg);
150+
Status = PciConfigWrite(EfiPciIoWidthUint32, p2sb_addr + R_P2SB_CFG_P2SBC, 1, &reg);
123151
}
124152

125153
test_pit:
@@ -138,17 +166,13 @@ static int pit_8254cge_workaround(void)
138166
return 0;
139167
}
140168

141-
int apply_intel_platform_workarounds(void)
169+
int apply_intel_platform_workarounds(struct csmwrap_priv *priv)
142170
{
143-
uint16_t vendor_id;
144-
145-
vendor_id = pciConfigReadWord(0, 0, 0, 0x0);
146-
147-
if (vendor_id != 0x8086) {
148-
return 0;
171+
if (priv->hbridge_hdr.VendorId != 0x8086) {
172+
return 0; // Not an Intel platform
149173
}
150174

151-
pit_8254cge_workaround();
175+
pit_8254cge_workaround(priv);
152176

153177
return 0;
154178
}

src/io.h

Lines changed: 4 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ static inline void clflush(void *addr) {
1010
asm volatile ("clflush (%0)" :: "r"(addr) : "memory");
1111
}
1212

13+
static inline void writeq(void *addr, uint64_t val) {
14+
barrier();
15+
*(volatile uint64_t *)addr = val;
16+
}
1317
static inline void writel(void *addr, uint32_t val) {
1418
barrier();
1519
*(volatile uint32_t *)addr = val;
@@ -199,87 +203,6 @@ outsl(int port, const void *addr, int cnt)
199203
: "+S" (addr), "+c" (cnt) : "d" (port) : "cc", "memory");
200204
}
201205

202-
#define PCI_CONFIG_ADDRESS 0xcf8
203-
#define PCI_CONFIG_DATA 0xcfc
204-
205-
static inline void pciSetAddress(unsigned int bus, unsigned int slot,
206-
unsigned int function, unsigned int offset)
207-
{
208-
uint32_t address;
209-
210-
/* Address bits (inclusive):
211-
* 31 Enable bit (must be 1 for it to work)
212-
* 30 - 24 Reserved
213-
* 23 - 16 Bus number
214-
* 15 - 11 Slot number
215-
* 10 - 8 Function number (for multifunction devices)
216-
* 7 - 2 Register number (offset / 4)
217-
* 1 - 0 Must always be 00 */
218-
address = 0x80000000 | ((unsigned long) (bus & 0xff) << 16)
219-
| ((unsigned long) (slot & 0x1f) << 11)
220-
| ((unsigned long) (function & 0x7) << 8)
221-
| ((unsigned long) offset & 0xff);
222-
/* Full DWORD write to port must be used for PCI to detect new address. */
223-
outl(PCI_CONFIG_ADDRESS, address);
224-
}
225-
226-
static inline uint8_t pciConfigReadByte(unsigned int bus, unsigned int slot,
227-
unsigned int function, unsigned int offset)
228-
{
229-
pciSetAddress(bus, slot, function, offset);
230-
/* The PCI registers are little endian,
231-
* so the last byte of DWORD is read
232-
* when offset is 0. */
233-
return (inb(PCI_CONFIG_DATA + (offset & 3)));
234-
}
235-
236-
static inline uint16_t pciConfigReadWord(unsigned int bus, unsigned int slot,
237-
unsigned int function, unsigned int offset)
238-
{
239-
pciSetAddress(bus, slot, function, offset);
240-
/* The PCI registers are little endian,
241-
* so the last word of DWORD is read
242-
* when offset is 0. */
243-
return (inw(PCI_CONFIG_DATA + (offset & 2)));
244-
}
245-
246-
static inline uint32_t pciConfigReadDWord(unsigned int bus, unsigned int slot,
247-
unsigned int function, unsigned int offset)
248-
{
249-
pciSetAddress(bus, slot, function, offset);
250-
return (inl(PCI_CONFIG_DATA));
251-
}
252-
253-
static inline void pciConfigWriteByte(unsigned int bus, unsigned int slot,
254-
unsigned int function, unsigned int offset,
255-
uint8_t data)
256-
{
257-
pciSetAddress(bus, slot, function, offset);
258-
/* The PCI registers are little endian,
259-
* so the last byte of DWORD is written
260-
* when offset is 0. */
261-
outb(PCI_CONFIG_DATA + (offset & 3), data);
262-
}
263-
264-
static inline void pciConfigWriteWord(unsigned int bus, unsigned int slot,
265-
unsigned int function, unsigned int offset,
266-
uint16_t data)
267-
{
268-
pciSetAddress(bus, slot, function, offset);
269-
/* The PCI registers are little endian,
270-
* so the last word of DWORD is written
271-
* when offset is 0. */
272-
outw(PCI_CONFIG_DATA + (offset & 2), data);
273-
}
274-
275-
static inline void pciConfigWriteDWord(unsigned int bus, unsigned int slot,
276-
unsigned int function, unsigned int offset,
277-
uint32_t data)
278-
{
279-
pciSetAddress(bus, slot, function, offset);
280-
outl(PCI_CONFIG_DATA, data);
281-
}
282-
283206
static inline uint64_t rdmsr(uint32_t index) {
284207
uint32_t edx, eax;
285208
asm volatile ("rdmsr" : "=a"(eax), "=d"(edx) : "c"(index) : "memory");

0 commit comments

Comments
 (0)