From be98524ab208be4764c7d79bdcc7c35162210af1 Mon Sep 17 00:00:00 2001 From: Aaron Durbin Date: Wed, 12 Dec 2012 12:40:33 -0600 Subject: [PATCH] lynxpoint: ME to BIOS Payload Updates This commit contains a bevy of updates: - PCI device id is updated to match Lynx Point EDS in the ME driver. - Allocate the memory to store the consumption of the MBP. - me_bios_payload structure is now a structure of pointers that point into the allocated memory. - The ICC profile structure was updated to correctly reflect the documentation. Verfied that output of MBP reading can handle unknown items. Change-Id: I43cc45e6b797444c105e7c842eb5684e9c104687 Signed-off-by: Aaron Durbin Reviewed-on: http://review.coreboot.org/2641 Tested-by: build bot (Jenkins) Reviewed-by: Ronald G. Minnich --- src/southbridge/intel/lynxpoint/me.h | 35 ++--- src/southbridge/intel/lynxpoint/me_9.x.c | 167 +++++++++++------------ 2 files changed, 98 insertions(+), 104 deletions(-) diff --git a/src/southbridge/intel/lynxpoint/me.h b/src/southbridge/intel/lynxpoint/me.h index a57f779ea5..ecd12e4ebf 100644 --- a/src/southbridge/intel/lynxpoint/me.h +++ b/src/southbridge/intel/lynxpoint/me.h @@ -394,12 +394,7 @@ typedef struct { u32 reserved_4 : 1; u32 wlan : 1; u32 reserved_5 : 8; -} __attribute__ ((packed)) mefwcaps_sku; - -typedef struct { - mefwcaps_sku fw_capabilities; - u8 available; -} mbp_fw_caps; +} __attribute__ ((packed)) mbp_mefwcaps; typedef struct { u16 device_id; @@ -430,12 +425,18 @@ typedef struct { u8 available; } mbp_plat_type; +typedef struct { + u16 icc_start_address; + u16 mask; +} __attribute__ ((packed)) icc_address_mask; + typedef struct { u8 num_icc_profiles; u8 icc_profile_soft_strap; u8 icc_profile_index; u8 reserved; - u32 register_lock_mask[3]; + u32 icc_reg_bundles; + icc_address_mask icc_address_mask[0]; } __attribute__ ((packed)) mbp_icc_profile; typedef struct { @@ -451,23 +452,23 @@ typedef struct { u8 state; u8 last_theft_trigger; tdt_state_flag flags; -} __attribute__ ((packed)) tdt_state_info; +} __attribute__ ((packed)) mbp_at_state; typedef struct { - mbp_fw_version_name fw_version_name; - mbp_fw_caps fw_caps_sku; - mbp_rom_bist_data rom_bist_data; - mbp_platform_key platform_key; - mbp_plat_type fw_plat_type; - mbp_icc_profile icc_profile; - tdt_state_info at_state; - u32 mfsintegrity; + mbp_fw_version_name *fw_version_name; + mbp_mefwcaps *fw_capabilities; + mbp_rom_bist_data *rom_bist_data; + mbp_platform_key *platform_key; + mbp_plat_type *fw_plat_type; + mbp_icc_profile *icc_profile; + mbp_at_state *at_state; + u32 *mfsintegrity; } me_bios_payload; struct me_fwcaps { u32 id; u8 length; - mefwcaps_sku caps_sku; + mbp_mefwcaps caps_sku; u8 reserved[3]; } __attribute__ ((packed)); diff --git a/src/southbridge/intel/lynxpoint/me_9.x.c b/src/southbridge/intel/lynxpoint/me_9.x.c index 12f7ab7ed2..f2e928a691 100644 --- a/src/southbridge/intel/lynxpoint/me_9.x.c +++ b/src/southbridge/intel/lynxpoint/me_9.x.c @@ -365,7 +365,7 @@ static inline void print_cap(const char *name, int state) static void me_print_fw_version(mbp_fw_version_name *vers_name) { - if (!vers_name->major_version) { + if (!vers_name) { printk(BIOS_ERR, "ME: mbp missing version report\n"); return; } @@ -376,7 +376,7 @@ static void me_print_fw_version(mbp_fw_version_name *vers_name) } /* Get ME Firmware Capabilities */ -static int mkhi_get_fwcaps(mefwcaps_sku *cap) +static int mkhi_get_fwcaps(mbp_mefwcaps *cap) { u32 rule_id = 0; struct me_fwcaps cap_msg; @@ -402,10 +402,11 @@ static int mkhi_get_fwcaps(mefwcaps_sku *cap) } /* Get ME Firmware Capabilities */ -static void me_print_fwcaps(mbp_fw_caps *caps_section) +static void me_print_fwcaps(mbp_mefwcaps *cap) { - mefwcaps_sku *cap = &caps_section->fw_capabilities; - if (!caps_section->available) { + mbp_mefwcaps local_caps; + if (!cap) { + cap = &local_caps; printk(BIOS_ERR, "ME: mbp missing fwcaps report\n"); if (mkhi_get_fwcaps(cap)) return; @@ -705,6 +706,8 @@ static void intel_me_init(device_t dev) intel_me_extend_valid(dev); } + memset(&mbp_data, 0, sizeof(mbp_data)); + /* * According to the ME9 BWG, BIOS is required to fetch MBP data in * all boot flows except S3 Resume. @@ -718,8 +721,8 @@ static void intel_me_init(device_t dev) return; #if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG) - me_print_fw_version(&mbp_data.fw_version_name); - me_print_fwcaps(&mbp_data.fw_caps_sku); + me_print_fw_version(mbp_data.fw_version_name); + me_print_fwcaps(mbp_data.fw_capabilities); #endif /* @@ -754,7 +757,7 @@ static struct device_operations device_ops = { static const struct pci_driver intel_me __pci_driver = { .ops = &device_ops, .vendor = PCI_VENDOR_ID_INTEL, - .device = 0x1e3a, + .device = 0x8c3a, }; /****************************************************************************** @@ -802,6 +805,11 @@ static void intel_me_mbp_give_up(device_t dev) write_host_csr(&csr); } +struct mbp_payload { + mbp_header header; + u32 data[0]; +}; + /* * mbp seems to be following its own flow, let's retrieve it in a dedicated * function. @@ -809,12 +817,12 @@ static void intel_me_mbp_give_up(device_t dev) static int intel_me_read_mbp(me_bios_payload *mbp_data, device_t dev) { mbp_header mbp_hdr; - mbp_item_header mbp_item_hdr; u32 me2host_pending; - u32 mbp_ident; struct mei_csr host; struct me_hfs2 hfs2; int count; + struct mbp_payload *mbp; + int i; pci_read_dword_ptr(dev, &hfs2, PCI_ME_HFS2); @@ -840,92 +848,25 @@ static int intel_me_read_mbp(me_bios_payload *mbp_data, device_t dev) me2host_pending); goto mbp_failure; } + mbp = malloc(mbp_hdr.mbp_size * sizeof(u32)); + if (!mbp) + goto mbp_failure; + mbp->header = mbp_hdr; me2host_pending--; - memset(mbp_data, 0, sizeof(*mbp_data)); - while (mbp_hdr.num_entries--) { - u32* copy_addr; - u32 copy_size, buffer_room; - void *p; - - if (!me2host_pending) { - printk(BIOS_ERR, "ME: no mbp data %d entries to go!\n", - mbp_hdr.num_entries + 1); - goto mbp_failure; - } - - mei_read_dword_ptr(&mbp_item_hdr, MEI_ME_CB_RW); - - if (mbp_item_hdr.length > me2host_pending) { - printk(BIOS_ERR, "ME: insufficient mbp data %d " - "entries to go!\n", - mbp_hdr.num_entries + 1); - goto mbp_failure; - } - - me2host_pending -= mbp_item_hdr.length; - - mbp_ident = MBP_MAKE_IDENT(mbp_item_hdr.app_id, - mbp_item_hdr.item_id); - - copy_size = mbp_item_hdr.length - 1; - -#define SET_UP_COPY(field) { copy_addr = (u32 *)&mbp_data->field; \ - buffer_room = sizeof(mbp_data->field) / sizeof(u32); \ - break; \ - } - - p = &mbp_item_hdr; - printk(BIOS_INFO, "ME: MBP item header %8.8x\n", *((u32*)p)); - - switch(mbp_ident) { - case MBP_IDENT(KERNEL, FW_VER): - SET_UP_COPY(fw_version_name); - - case MBP_IDENT(ICC, PROFILE): - SET_UP_COPY(icc_profile); - - case MBP_IDENT(INTEL_AT, STATE): - SET_UP_COPY(at_state); - - case MBP_IDENT(KERNEL, FW_CAP): - mbp_data->fw_caps_sku.available = 1; - SET_UP_COPY(fw_caps_sku.fw_capabilities); - - case MBP_IDENT(KERNEL, ROM_BIST): - SET_UP_COPY(rom_bist_data); - - case MBP_IDENT(KERNEL, PLAT_KEY): - SET_UP_COPY(platform_key); - - case MBP_IDENT(KERNEL, FW_TYPE): - mbp_data->fw_plat_type.available = 1; - SET_UP_COPY(fw_plat_type.rule_data); - - case MBP_IDENT(KERNEL, MFS_FAILURE): - SET_UP_COPY(mfsintegrity); - - default: - printk(BIOS_ERR, "ME: unknown mbp item id 0x%x!!!\n", - mbp_ident); - goto mbp_failure; - } - - if (buffer_room != copy_size) { - printk(BIOS_ERR, "ME: buffer room %d != %d copy size" - " for item 0x%x!!!\n", - buffer_room, copy_size, mbp_ident); - goto mbp_failure; - } - while(copy_size--) - *copy_addr++ = read_cb(); + i = 0; + while (i != me2host_pending) { + mei_read_dword_ptr(&mbp->data[i], MEI_ME_CB_RW); + i++; } + /* Signal to the ME that the host has finished reading the MBP. */ read_host_csr(&host); host.interrupt_generate = 1; write_host_csr(&host); + /* Wait for the mbp_cleared indicator. */ for (count = ME_RETRY; count > 0; --count) { pci_read_dword_ptr(dev, &hfs2, PCI_ME_HFS2); if (hfs2.mbp_cleared) @@ -938,6 +879,58 @@ static int intel_me_read_mbp(me_bios_payload *mbp_data, device_t dev) intel_me_mbp_give_up(dev); } + /* Dump out the MBP contents. */ +#if (CONFIG_DEFAULT_CONSOLE_LOGLEVEL >= BIOS_DEBUG) + printk(BIOS_INFO, "ME MBP: Header: items: %d, size dw: %d\n", + mbp->header.num_entries, mbp->header.mbp_size); + for (i = 0; i < mbp->header.mbp_size - 1; i++) { + printk(BIOS_INFO, "ME MBP: %04x: 0x%08x\n", i, mbp->data[i]); + } +#endif + + #define ASSIGN_FIELD_PTR(field_,val_) \ + { \ + mbp_data->field_ = (typeof(mbp_data->field_))(void *)val_; \ + break; \ + } + /* Setup the pointers in the me_bios_payload structure. */ + for (i = 0; i < mbp->header.mbp_size - 1;) { + mbp_item_header *item = (void *)&mbp->data[i]; + + switch(MBP_MAKE_IDENT(item->app_id, item->item_id)) { + case MBP_IDENT(KERNEL, FW_VER): + ASSIGN_FIELD_PTR(fw_version_name, &mbp->data[i+1]); + + case MBP_IDENT(ICC, PROFILE): + ASSIGN_FIELD_PTR(icc_profile, &mbp->data[i+1]); + + case MBP_IDENT(INTEL_AT, STATE): + ASSIGN_FIELD_PTR(at_state, &mbp->data[i+1]); + + case MBP_IDENT(KERNEL, FW_CAP): + ASSIGN_FIELD_PTR(fw_capabilities, &mbp->data[i+1]); + + case MBP_IDENT(KERNEL, ROM_BIST): + ASSIGN_FIELD_PTR(rom_bist_data, &mbp->data[i+1]); + + case MBP_IDENT(KERNEL, PLAT_KEY): + ASSIGN_FIELD_PTR(platform_key, &mbp->data[i+1]); + + case MBP_IDENT(KERNEL, FW_TYPE): + ASSIGN_FIELD_PTR(fw_plat_type, &mbp->data[i+1]); + + case MBP_IDENT(KERNEL, MFS_FAILURE): + ASSIGN_FIELD_PTR(mfsintegrity, &mbp->data[i+1]); + + default: + printk(BIOS_ERR, "ME MBP: unknown item 0x%x @ dw offset 0x%x\n", + mbp->data[i], i); + break; + } + i += item->length; + } + #undef ASSIGN_FIELD_PTR + return 0; mbp_failure: