mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 10:40:03 +01:00
rombios: Obtain S3 wake vector from >1MB.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
This commit is contained in:
1 parent
3c1221fce3
commit
b5ee8eb3d6
8 files changed
+112
-96
No files matched your search
@@ -47,5 +47,7 @@ uint32_t jumptable[IDX_LAST+1] __attribute__((section (".biosjumptable"))) =
|
||||
|
||||
TABLE_ENTRY(IDX_TCPA_INITIALIZE_TPM, tcpa_initialize_tpm),
|
||||
|
||||
TABLE_ENTRY(IDX_GET_S3_WAKING_VECTOR, get_s3_waking_vector),
|
||||
|
||||
TABLE_ENTRY(IDX_LAST , 0) /* keep last */
|
||||
};
|
||||
@@ -24,10 +24,9 @@
|
||||
#include "rombios_compat.h"
|
||||
#include "tpm_drivers.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "tcgbios.h"
|
||||
#include "32bitprotos.h"
|
||||
#include "util.h"
|
||||
|
||||
|
||||
/* local structure and variables */
|
||||
struct ptti_cust {
|
||||
@@ -135,7 +134,7 @@ static inline uint32_t bswap(uint32_t a)
|
||||
*******************************************************/
|
||||
|
||||
typedef struct {
|
||||
struct acpi_20_tcpa *tcpa_ptr;
|
||||
struct acpi_20_tcpa_clisrv *tcpa_ptr;
|
||||
unsigned char *lasa_last_ptr;
|
||||
uint16_t entry_count;
|
||||
uint16_t flags;
|
||||
@@ -260,45 +259,19 @@ uint8_t acpi_validate_entry(struct acpi_header *hdr)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Search for the RSDP ACPI table in the memory starting at addr and
|
||||
* ending at addr + len - 1.
|
||||
*/
|
||||
static struct acpi_20_rsdp *find_rsdp(const void *start, unsigned int len)
|
||||
{
|
||||
char *rsdp = (char *)start;
|
||||
char *end = rsdp + len;
|
||||
/* scan memory in steps of 16 bytes */
|
||||
while (rsdp < end) {
|
||||
/* check for expected string */
|
||||
if (!strncmp( rsdp, "RSD PTR ", 8))
|
||||
return (struct acpi_20_rsdp *)rsdp;
|
||||
rsdp += 0x10;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tcpa_acpi_init(void)
|
||||
{
|
||||
struct acpi_20_rsdt *rsdt;
|
||||
struct acpi_20_tcpa *tcpa = (void *)0;
|
||||
struct acpi_20_tcpa_clisrv *tcpa = (void *)0;
|
||||
struct acpi_20_rsdp *rsdp;
|
||||
uint32_t length;
|
||||
uint16_t off;
|
||||
int found = 0;
|
||||
uint16_t ebda_seg;
|
||||
|
||||
if (MA_IsTPMPresent() == 0) {
|
||||
if (MA_IsTPMPresent() == 0)
|
||||
return;
|
||||
}
|
||||
|
||||
/* RSDP in EBDA? */
|
||||
ebda_seg = *(uint16_t *)ADDR_FROM_SEG_OFF(0x40, 0xe);
|
||||
rsdp = find_rsdp((void *)(ebda_seg << 16), 1024);
|
||||
|
||||
if (!rsdp)
|
||||
rsdp = find_rsdp((void *)(ACPI_SEGMENT << 4), 0x20000);
|
||||
|
||||
rsdp = find_rsdp();
|
||||
if (rsdp) {
|
||||
uint32_t ctr = 0;
|
||||
/* get RSDT from RSDP */
|
||||
@@ -307,7 +280,7 @@ void tcpa_acpi_init(void)
|
||||
off = 36;
|
||||
while ((off + 3) < length) {
|
||||
/* try all pointers to structures */
|
||||
tcpa = (struct acpi_20_tcpa *)rsdt->entry[ctr];
|
||||
tcpa = (struct acpi_20_tcpa_clisrv *)rsdt->entry[ctr];
|
||||
/* valid TCPA ACPI table ? */
|
||||
if (ACPI_2_0_TCPA_SIGNATURE == tcpa->header.signature
|
||||
&& acpi_validate_entry(&tcpa->header) == 0) {
|
||||
@@ -398,7 +371,7 @@ static
|
||||
unsigned char *tcpa_get_lasa_base_ptr(void)
|
||||
{
|
||||
unsigned char *lasa = 0;
|
||||
struct acpi_20_tcpa *tcpa = tcpa_acpi.tcpa_ptr;
|
||||
struct acpi_20_tcpa_clisrv *tcpa = tcpa_acpi.tcpa_ptr;
|
||||
if (tcpa != 0) {
|
||||
uint32_t class = tcpa->platform_class;
|
||||
if (class == TCPA_ACPI_CLASS_CLIENT) {
|
||||
@@ -416,7 +389,7 @@ static
|
||||
uint32_t tcpa_get_laml(void)
|
||||
{
|
||||
uint32_t laml = 0;
|
||||
struct acpi_20_tcpa *tcpa = tcpa_acpi.tcpa_ptr;
|
||||
struct acpi_20_tcpa_clisrv *tcpa = tcpa_acpi.tcpa_ptr;
|
||||
if (tcpa != 0) {
|
||||
uint32_t class = tcpa->platform_class;
|
||||
if (class == TCPA_ACPI_CLASS_CLIENT) {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#ifndef TCGBIOS_H
|
||||
#define TCGBIOS_H
|
||||
|
||||
|
||||
/* TCPA ACPI definitions */
|
||||
#define TCPA_ACPI_CLASS_CLIENT 0
|
||||
#define TCPA_ACPI_CLASS_SERVER 1
|
||||
@@ -117,15 +116,8 @@
|
||||
/* address of locality 0 (TIS) */
|
||||
#define TPM_TIS_BASE_ADDRESS 0xfed40000
|
||||
|
||||
#define ASCII32(a,b,c,d) ((((Bit32u)a) << 0) | (((Bit32u)b) << 8) | \
|
||||
(((Bit32u)c) << 16) | (((Bit32u)d) << 24) )
|
||||
#define ACPI_2_0_TCPA_SIGNATURE ASCII32('T','C','P','A') /* "TCPA" */
|
||||
|
||||
|
||||
#define STATUS_FLAG_SHUTDOWN (1 << 0)
|
||||
|
||||
#define ACPI_SEGMENT 0xE000
|
||||
|
||||
/* Input and Output blocks for the TCG BIOS commands */
|
||||
|
||||
struct hleei_short
|
||||
@@ -232,37 +224,6 @@ struct pcpes
|
||||
uint32_t event;
|
||||
} __attribute__((packed));
|
||||
|
||||
|
||||
struct acpi_header
|
||||
{
|
||||
uint32_t signature;
|
||||
uint32_t length;
|
||||
uint8_t revision;
|
||||
uint8_t checksum;
|
||||
uint8_t oem_id[6];
|
||||
uint64_t oem_table_id;
|
||||
uint32_t oem_revision;
|
||||
uint32_t creator_id;
|
||||
uint32_t creator_revision;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct acpi_20_rsdt {
|
||||
struct acpi_header header;
|
||||
uint32_t entry[1];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct acpi_20_rsdp {
|
||||
uint64_t signature;
|
||||
uint8_t checksum;
|
||||
uint8_t oem_id[6];
|
||||
uint8_t revision;
|
||||
uint32_t rsdt_address;
|
||||
uint32_t length;
|
||||
uint64_t xsdt_address;
|
||||
uint8_t extended_checksum;
|
||||
uint8_t reserved[3];
|
||||
} __attribute__((packed));
|
||||
|
||||
struct acpi_20_tcpa_client {
|
||||
uint32_t laml;
|
||||
uint64_t lasa;
|
||||
@@ -275,7 +236,7 @@ struct acpi_20_tcpa_server {
|
||||
/* more here */
|
||||
} __attribute__((packed));
|
||||
|
||||
struct acpi_20_tcpa {
|
||||
struct acpi_20_tcpa_clisrv {
|
||||
struct acpi_header header;
|
||||
uint16_t platform_class;
|
||||
union {
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
*/
|
||||
#include <stdarg.h>
|
||||
#include <stdint.h>
|
||||
#include "rombios_compat.h"
|
||||
#include "util.h"
|
||||
|
||||
static void putchar(char c);
|
||||
@@ -92,11 +93,11 @@ int strcmp(const char *cs, const char *ct)
|
||||
|
||||
int strncmp(const char *s1, const char *s2, uint32_t n)
|
||||
{
|
||||
uint32_t ctr;
|
||||
for (ctr = 0; ctr < n; ctr++)
|
||||
if (s1[ctr] != s2[ctr])
|
||||
return (int)(s1[ctr] - s2[ctr]);
|
||||
return 0;
|
||||
uint32_t ctr;
|
||||
for (ctr = 0; ctr < n; ctr++)
|
||||
if (s1[ctr] != s2[ctr])
|
||||
return (int)(s1[ctr] - s2[ctr]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void *memcpy(void *dest, const void *src, unsigned n)
|
||||
@@ -402,3 +403,64 @@ void mssleep(uint32_t waittime)
|
||||
y = x;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Search for the RSDP ACPI table in the memory starting at addr and
|
||||
* ending at addr + len - 1.
|
||||
*/
|
||||
static struct acpi_20_rsdp *__find_rsdp(const void *start, unsigned int len)
|
||||
{
|
||||
char *rsdp = (char *)start;
|
||||
char *end = rsdp + len;
|
||||
/* scan memory in steps of 16 bytes */
|
||||
while (rsdp < end) {
|
||||
/* check for expected string */
|
||||
if (!strncmp(rsdp, "RSD PTR ", 8))
|
||||
return (struct acpi_20_rsdp *)rsdp;
|
||||
rsdp += 0x10;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct acpi_20_rsdp *find_rsdp(void)
|
||||
{
|
||||
struct acpi_20_rsdp *rsdp;
|
||||
uint16_t ebda_seg;
|
||||
|
||||
ebda_seg = *(uint16_t *)ADDR_FROM_SEG_OFF(0x40, 0xe);
|
||||
rsdp = __find_rsdp((void *)(ebda_seg << 16), 1024);
|
||||
if (!rsdp)
|
||||
rsdp = __find_rsdp((void *)0xE0000, 0x20000);
|
||||
|
||||
return rsdp;
|
||||
}
|
||||
|
||||
uint32_t get_s3_waking_vector(void)
|
||||
{
|
||||
struct acpi_20_rsdp *rsdp = find_rsdp();
|
||||
struct acpi_20_xsdt *xsdt;
|
||||
struct acpi_20_fadt *fadt;
|
||||
struct acpi_20_facs *facs;
|
||||
uint32_t vector;
|
||||
|
||||
if (!rsdp)
|
||||
return 0;
|
||||
|
||||
xsdt = (struct acpi_20_xsdt *)(long)rsdp->xsdt_address;
|
||||
if (!xsdt)
|
||||
return 0;
|
||||
|
||||
fadt = (struct acpi_20_fadt *)(long)xsdt->entry[0];
|
||||
if (!fadt || (fadt->header.signature != ACPI_2_0_FADT_SIGNATURE))
|
||||
return 0;
|
||||
|
||||
facs = (struct acpi_20_facs *)(long)fadt->x_firmware_ctrl;
|
||||
if (!facs)
|
||||
return 0;
|
||||
|
||||
vector = facs->x_firmware_waking_vector;
|
||||
if (!vector)
|
||||
vector = facs->firmware_waking_vector;
|
||||
|
||||
return vector;
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
#ifndef UTIL_H
|
||||
#define UTIL_H
|
||||
|
||||
#include "../hvmloader/acpi/acpi2_0.h"
|
||||
|
||||
void outb(uint16_t addr, uint8_t val);
|
||||
void outw(uint16_t addr, uint16_t val);
|
||||
void outl(uint16_t addr, uint32_t val);
|
||||
@@ -39,5 +41,6 @@ static inline uint32_t mmio_readl(uint32_t *addr)
|
||||
return *(volatile uint32_t *)addr;
|
||||
}
|
||||
|
||||
struct acpi_20_rsdp *find_rsdp(void);
|
||||
|
||||
#endif
|
||||
@@ -356,6 +356,9 @@ Upcall:
|
||||
call _store_returnaddress ; store away
|
||||
pop ax
|
||||
|
||||
; XXX GDT munging requires ROM to be writable!
|
||||
call _enable_rom_write_access
|
||||
|
||||
rol bx, #2
|
||||
mov si, #jmptable
|
||||
seg cs
|
||||
@@ -382,6 +385,8 @@ Upcall:
|
||||
mov bp,sp
|
||||
push eax ; preserve work register
|
||||
|
||||
call _disable_rom_write_access
|
||||
|
||||
call _get_returnaddress
|
||||
mov 2[bp], ax ; 16bit return address onto stack
|
||||
|
||||
@@ -408,3 +413,10 @@ ASM_END
|
||||
#include "32bitgateway.h"
|
||||
|
||||
#include "tcgbios.c"
|
||||
|
||||
Bit32u get_s3_waking_vector()
|
||||
{
|
||||
ASM_START
|
||||
DoUpcall(IDX_GET_S3_WAKING_VECTOR)
|
||||
ASM_END
|
||||
}
|
||||
@@ -17,8 +17,8 @@
|
||||
#define IDX_TCPA_IPL 10
|
||||
#define IDX_TCPA_INITIALIZE_TPM 11
|
||||
#define IDX_TCPA_MEASURE_POST 12
|
||||
|
||||
#define IDX_LAST 13 /* keep last! */
|
||||
#define IDX_GET_S3_WAKING_VECTOR 13
|
||||
#define IDX_LAST 14 /* keep last! */
|
||||
|
||||
#ifdef GCC_PROTOS
|
||||
#define PARMS(x...) x
|
||||
@@ -42,4 +42,6 @@ void tcpa_ipl( PARMS(Bit32u bootcd,Bit32u seg,Bit32u off,Bit32u count) );
|
||||
void tcpa_measure_post( PARMS(Bit32u from, Bit32u to) );
|
||||
Bit32u tcpa_initialize_tpm( PARMS(Bit32u physpres) );
|
||||
|
||||
Bit32u get_s3_waking_vector( PARMS(void) );
|
||||
|
||||
#endif
|
||||
@@ -1482,6 +1482,16 @@ ASM_START
|
||||
out dx,al
|
||||
ASM_END
|
||||
}
|
||||
|
||||
void enable_rom_write_access()
|
||||
{
|
||||
set_rom_write_access(0);
|
||||
}
|
||||
|
||||
void disable_rom_write_access()
|
||||
{
|
||||
set_rom_write_access(PFFLAG_ROM_LOCK);
|
||||
}
|
||||
|
||||
#endif /* HVMASSIST */
|
||||
|
||||
@@ -2378,14 +2388,9 @@ ASM_END
|
||||
if (s3_resume_flag != CMOS_SHUTDOWN_S3)
|
||||
return;
|
||||
|
||||
/* get x_firmware_waking_vector */
|
||||
s3_wakeup_vector = facs_get32(ACPI_FACS_OFFSET+24);
|
||||
if (!s3_wakeup_vector) {
|
||||
/* get firmware_waking_vector */
|
||||
s3_wakeup_vector = facs_get32(ACPI_FACS_OFFSET+12);
|
||||
if (!s3_wakeup_vector)
|
||||
return;
|
||||
}
|
||||
s3_wakeup_vector = get_s3_waking_vector();
|
||||
if (!s3_wakeup_vector)
|
||||
return;
|
||||
|
||||
s3_wakeup_ip = s3_wakeup_vector & 0xF;
|
||||
s3_wakeup_cs = s3_wakeup_vector >> 4;
|
||||
@@ -9927,9 +9932,7 @@ normal_post:
|
||||
call _log_bios_start
|
||||
|
||||
#ifdef HVMASSIST
|
||||
push #0
|
||||
call _set_rom_write_access
|
||||
add sp,#2
|
||||
call _enable_rom_write_access
|
||||
#endif
|
||||
|
||||
call _clobber_entry_point
|
||||
@@ -10128,9 +10131,7 @@ post_default_ints:
|
||||
#ifdef HVMASSIST
|
||||
call _copy_e820_table
|
||||
call smbios_init
|
||||
push #PFFLAG_ROM_LOCK
|
||||
call _set_rom_write_access
|
||||
add sp,#2
|
||||
call _disable_rom_write_access
|
||||
#endif
|
||||
|
||||
call _init_boot_vectors
|
||||
|
||||