| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| config CRB_TPM | ||
| bool | ||
| help | ||
| CRB TPM driver is enabled! | ||
|
|
||
| config CRB_TPM_BASE_ADDRESS | ||
| hex | ||
| default 0xfed40000 | ||
| help | ||
| Base Address of the CRB TPM Command Structure | ||
|
|
||
| config MAINBOARD_HAS_CRB_TPM | ||
| bool | ||
| default n | ||
| select CRB_TPM | ||
| help | ||
| Mainboard has Command Response Buffer support |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| bootblock-$(CONFIG_CRB_TPM) += tis.c tpm.c | ||
| verstage-$(CONFIG_CRB_TPM) += tis.c tpm.c | ||
| romstage-$(CONFIG_CRB_TPM) += tis.c tpm.c | ||
| ramstage-$(CONFIG_CRB_TPM) += tis.c tpm.c | ||
| postcar-$(CONFIG_CRB_TPM) += tis.c tpm.c |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,159 @@ | ||
| /* | ||
| * This file is part of the coreboot project. | ||
| * | ||
| * This program is free software; you can redistribute it and/or modify | ||
| * it under the terms of the GNU General Public License as published by | ||
| * the Free Software Foundation; version 2 of the License. | ||
| * | ||
| * This program is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| * GNU General Public License for more details. | ||
| */ | ||
|
|
||
| #include <arch/early_variables.h> | ||
| #include <console/console.h> | ||
| #include <security/tpm/tis.h> | ||
| #include <arch/acpigen.h> | ||
| #include <device/device.h> | ||
| #include <drivers/intel/ptt/ptt.h> | ||
|
|
||
| #include "tpm.h" | ||
| #include "chip.h" | ||
|
|
||
| static unsigned tpm_is_open CAR_GLOBAL; | ||
|
|
||
| static const struct { | ||
| uint16_t vid; | ||
| uint16_t did; | ||
| const char *device_name; | ||
| } dev_map[] = { | ||
| {0x1ae0, 0x0028, "CR50"}, | ||
| {0xa13a, 0x8086, "Intel iTPM"} | ||
| }; | ||
|
|
||
| static const char *tis_get_dev_name(struct tpm2_info *info) | ||
| { | ||
| int i; | ||
|
|
||
| for (i = 0; i < ARRAY_SIZE(dev_map); i++) | ||
| if ((dev_map[i].vid == info->vendor_id) && (dev_map[i].did == info->device_id)) | ||
| return dev_map[i].device_name; | ||
| return "Unknown"; | ||
| } | ||
|
|
||
|
|
||
| int tis_open(void) | ||
| { | ||
| if (car_get_var(tpm_is_open)) { | ||
| printk(BIOS_ERR, "%s called twice.\n", __func__); | ||
| return -1; | ||
| } | ||
|
|
||
| if (CONFIG(HAVE_INTEL_PTT)) { | ||
| if (!ptt_active()) { | ||
| printk(BIOS_ERR, "%s: Intel PTT is not active.\n", __func__); | ||
| return -1; | ||
| } | ||
| printk(BIOS_DEBUG, "%s: Intel PTT is active.\n", __func__); | ||
| } | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| int tis_close(void) | ||
| { | ||
| if (car_get_var(tpm_is_open)) { | ||
|
|
||
| /* | ||
| * Do we need to do something here, like waiting for a | ||
| * transaction to stop? | ||
| */ | ||
| car_set_var(tpm_is_open, 0); | ||
| } | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| int tis_init(void) | ||
| { | ||
| struct tpm2_info info; | ||
|
|
||
| // Wake TPM up (if necessary) | ||
| if (tpm2_init() != 0) | ||
| return -1; | ||
|
|
||
| tpm2_get_info(&info); | ||
|
|
||
| printk(BIOS_INFO, "Initialized TPM device %s revision %d\n", tis_get_dev_name(&info), | ||
| info.revision); | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
|
|
||
| int tis_sendrecv(const uint8_t *sendbuf, size_t sbuf_size, uint8_t *recvbuf, size_t *rbuf_len) | ||
| { | ||
| int len = tpm2_process_command(sendbuf, sbuf_size, recvbuf, *rbuf_len); | ||
|
|
||
| if (len == 0) | ||
| return -1; | ||
|
|
||
| *rbuf_len = len; | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| #ifdef __RAMSTAGE__ | ||
|
|
||
| static void crb_tpm_fill_ssdt(struct device *dev) | ||
| { | ||
| const char *path = acpi_device_path(dev); | ||
| if (!path) { | ||
| path = "\\_SB_.TPM"; | ||
| printk(BIOS_DEBUG, "Using default TPM2 ACPI path: '%s'\n", path); | ||
| } | ||
|
|
||
| /* Device */ | ||
| acpigen_write_device(path); | ||
|
|
||
| acpigen_write_name_string("_HID", "MSFT0101"); | ||
| acpigen_write_name_string("_CID", "MSFT0101"); | ||
|
|
||
| acpigen_write_name_integer("_UID", 1); | ||
|
|
||
| acpigen_write_STA(ACPI_STATUS_DEVICE_ALL_ON); | ||
|
|
||
| /* Resources */ | ||
| acpigen_write_name("_CRS"); | ||
| acpigen_write_resourcetemplate_header(); | ||
| acpigen_write_mem32fixed(1, TPM_CRB_BASE_ADDRESS, 0x5000); | ||
|
|
||
| acpigen_write_resourcetemplate_footer(); | ||
|
|
||
| acpigen_pop_len(); /* Device */ | ||
| } | ||
|
|
||
| static const char *crb_tpm_acpi_name(const struct device *dev) | ||
| { | ||
| return "TPM"; | ||
| } | ||
|
|
||
| static struct device_operations crb_ops = { | ||
| .read_resources = DEVICE_NOOP, | ||
| .set_resources = DEVICE_NOOP, | ||
| #if CONFIG(HAVE_ACPI_TABLES) | ||
| .acpi_name = crb_tpm_acpi_name, | ||
| .acpi_fill_ssdt_generator = crb_tpm_fill_ssdt, | ||
| #endif | ||
|
|
||
| }; | ||
|
|
||
| static void enable_dev(struct device *dev) | ||
| { | ||
| dev->ops = &crb_ops; | ||
| } | ||
|
|
||
| struct chip_operations drivers_crb_ops = {CHIP_NAME("CRB TPM").enable_dev = enable_dev}; | ||
|
|
||
| #endif /* __RAMSTAGE__ */ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,280 @@ | ||
| /*. | ||
| * Use of this source code is governed by a BSD-style license that can be | ||
| * found in the LICENSE file. | ||
| * | ||
| * This is a driver for a CRB Interface. | ||
| * | ||
| * The general flow looks like this: | ||
| * | ||
| * TPM starts in IDLE Mode | ||
| * | ||
| * IDLE --> READY --> Command Receiption | ||
| * ^ | | ||
| * | v | ||
| -- Cmd Complete <-- Command Execution | ||
| */ | ||
|
|
||
| #include <timer.h> | ||
| #include <arch/early_variables.h> | ||
| #include <console/console.h> | ||
| #include <arch/mmio.h> | ||
| #include <delay.h> | ||
| #include <string.h> | ||
| #include <endian.h> | ||
| #include <soc/pci_devs.h> | ||
| #include <device/pci_ops.h> | ||
|
|
||
| #include "tpm.h" | ||
|
|
||
| static struct control_area { | ||
| uint32_t request; | ||
| uint32_t status; | ||
| uint32_t cancel; | ||
| uint32_t start; | ||
| uint64_t interrupt_control; | ||
| uint32_t command_size; | ||
| void *command_bfr; | ||
| uint32_t response_size; | ||
| void *response_bfr; | ||
| } control_area; | ||
|
|
||
| static uint8_t cur_loc = 0; | ||
|
|
||
| /* Read Control Area Structure back */ | ||
| static void crb_readControlArea(void) | ||
| { | ||
| control_area.request = read32(CRB_REG(cur_loc, CRB_REG_REQUEST)); | ||
| control_area.status = read32(CRB_REG(cur_loc, CRB_REG_STATUS)); | ||
| control_area.cancel = read32(CRB_REG(cur_loc, CRB_REG_CANCEL)); | ||
| control_area.interrupt_control = read64(CRB_REG(cur_loc, CRB_REG_INT_CTRL)); | ||
| control_area.command_size = read32(CRB_REG(cur_loc, CRB_REG_CMD_SIZE)); | ||
| control_area.command_bfr = (void *)(uint32_t)read64(CRB_REG(cur_loc, CRB_REG_CMD_ADDR)); | ||
| control_area.response_size = read32(CRB_REG(cur_loc, CRB_REG_RESP_SIZE)); | ||
| control_area.response_bfr = | ||
| (void *)(uint32_t)read64(CRB_REG(cur_loc, CRB_REG_RESP_ADDR)); | ||
| } | ||
|
|
||
| /* Wait for Reg to be expected Value */ | ||
| static int crb_wait_for_reg32(const void *addr, uint32_t timeoutMs, uint32_t mask, | ||
| uint32_t expectedValue) | ||
| { | ||
| uint32_t regValue; | ||
| struct stopwatch sw; | ||
|
|
||
| // Set up a timer which breaks the loop after timeout | ||
| stopwatch_init_msecs_expire(&sw, timeoutMs); | ||
|
|
||
| while (1) { | ||
| // Now check if the TPM is in IDLE mode | ||
| regValue = read32(addr); | ||
|
|
||
| if ((regValue & mask) == expectedValue) | ||
| return 0; | ||
|
|
||
| if (stopwatch_expired(&sw)) { | ||
| printk(BIOS_ERR, | ||
| "CRB_WAIT: Error - Returning Zero with RegValue: %08x, Mask: %08x, Expected: %08x\n", | ||
| regValue, mask, expectedValue); | ||
| return -1; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /* CRB PROBE | ||
| * | ||
| * Checks if the CRB Interface is ready | ||
| */ | ||
| static int crb_probe(void) | ||
| { | ||
| uint64_t tpmStatus = read64(CRB_REG(cur_loc, CRB_REG_INTF_ID)); | ||
| printk(BIOS_SPEW, "Interface ID Reg. %llx\n", tpmStatus); | ||
|
|
||
| if ((tpmStatus & CRB_INTF_REG_CAP_CRB) == 0) { | ||
| printk(BIOS_DEBUG, "TPM: CRB Interface is not supported.\n"); | ||
| return -1; | ||
| } | ||
|
|
||
| if ((tpmStatus & (0xf)) != 1) { | ||
| printk(BIOS_DEBUG, | ||
| "TPM: CRB Interface is not active. System needs reboot in order to active TPM.\n"); | ||
| write32(CRB_REG(cur_loc, CRB_REG_INTF_ID), CRB_INTF_REG_INTF_SEL); | ||
| return -1; | ||
| } | ||
|
|
||
| write32(CRB_REG(cur_loc, CRB_REG_INTF_ID), CRB_INTF_REG_INTF_SEL); | ||
| write32(CRB_REG(cur_loc, CRB_REG_INTF_ID), CRB_INTF_REG_INTF_LOCK); | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| /* | ||
| * Get active Locality | ||
| * | ||
| * Get the active locality | ||
| */ | ||
| static uint8_t crb_activate_locality(void) | ||
| { | ||
|
|
||
| uint8_t locality = (read8(CRB_REG(0, CRB_REG_LOC_STATE)) >> 2) & 0x07; | ||
| printk(BIOS_SPEW, "Active locality: %i\n", locality); | ||
|
|
||
| int rc = crb_wait_for_reg32(CRB_REG(locality, CRB_REG_LOC_STATE), 750, | ||
| LOC_STATE_LOC_ASSIGN, LOC_STATE_LOC_ASSIGN); | ||
| if (!rc && (locality == 0)) | ||
| return locality; | ||
|
|
||
| if (rc) | ||
| write8(CRB_REG(locality, CRB_REG_LOC_CTRL), LOC_CTRL_REQ_ACCESS); | ||
|
|
||
|
|
||
| rc = crb_wait_for_reg32(CRB_REG(locality, CRB_REG_LOC_STATE), 750, LOC_STATE_LOC_ASSIGN, | ||
| LOC_STATE_LOC_ASSIGN); | ||
| if (rc) { | ||
| printk(BIOS_ERR, "TPM: Error - No Locality has been assigned TPM-wise.\n"); | ||
| return 0; | ||
| } | ||
|
|
||
| rc = crb_wait_for_reg32(CRB_REG(locality, CRB_REG_LOC_STATE), 1500, | ||
| LOC_STATE_REG_VALID_STS, LOC_STATE_REG_VALID_STS); | ||
| if (rc) { | ||
| printk(BIOS_ERR, "TPM: Error - LOC_STATE Register %u contains errors.\n", | ||
| locality); | ||
| return 0; | ||
| } | ||
|
|
||
|
|
||
| return locality; | ||
| } | ||
|
|
||
| /* Switch Device into a Ready State */ | ||
| static int crb_switch_to_ready(void) | ||
| { | ||
| /* Transition into ready state */ | ||
| write8(CRB_REG(cur_loc, CRB_REG_REQUEST), 0x1); | ||
| int rc = crb_wait_for_reg32(CRB_REG(cur_loc, CRB_REG_REQUEST), 200, | ||
| CRB_REG_REQUEST_CMD_RDY, 0x0); | ||
| if (rc) { | ||
| printk(BIOS_ERR, | ||
| "TPM: Error - TPM did not transition into ready state in time.\n"); | ||
| return -1; | ||
| } | ||
|
|
||
| /* Check TPM_CRB_CTRL_STS[0] to be "0" - no unrecoverable error */ | ||
| rc = crb_wait_for_reg32(CRB_REG(cur_loc, CRB_REG_STATUS), 500, CRB_REG_STATUS_ERROR, | ||
| 0x0); | ||
| if (rc) { | ||
| printk(BIOS_ERR, "TPM: Fatal Error - Could not recover.\n"); | ||
| return -1; | ||
| } | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| /* | ||
| * tpm2_init | ||
| * | ||
| * Even though the TPM does not need an initialization we check | ||
| * if the TPM responds and is in IDLE mode, which should be the | ||
| * normal bring up mode. | ||
| * | ||
| */ | ||
| int tpm2_init(void) | ||
| { | ||
|
|
||
|
|
||
| if (crb_probe()) { | ||
| printk(BIOS_ERR, "TPM: Probe failed.\n"); | ||
| return -1; | ||
| } | ||
|
|
||
| /* Read back control area structure */ | ||
| crb_readControlArea(); | ||
|
|
||
| /* Good to go. */ | ||
| printk(BIOS_SPEW, "TPM: CRB TPM initialized successfully\n"); | ||
|
|
||
| return 0; | ||
| } | ||
|
|
||
| /* | ||
| * tpm2_process_command | ||
| */ | ||
| size_t tpm2_process_command(const void *tpm2_command, size_t command_size, void *tpm2_response, | ||
| size_t max_response) | ||
| { | ||
| int rc; | ||
|
|
||
| if (command_size > control_area.command_size) { | ||
| printk(BIOS_ERR, "TPM: Command size is too big.\n"); | ||
| return -1; | ||
| } | ||
|
|
||
| if (control_area.response_size < max_response) { | ||
| printk(BIOS_ERR, "TPM: Response size could be too big.\n"); | ||
| return -1; | ||
| } | ||
|
|
||
| cur_loc = crb_activate_locality(); | ||
|
|
||
| // Check if CMD bit is cleared. | ||
| rc = crb_wait_for_reg32(CRB_REG(0, CRB_REG_START), 250, CRB_REG_START_START, 0x0); | ||
| if (rc) { | ||
| printk(BIOS_ERR, "TPM: Error - Cmd Bit not cleared.\n"); | ||
| return -1; | ||
| } | ||
|
|
||
| if (crb_switch_to_ready()) | ||
| return -1; | ||
|
|
||
| // Write to Command Buffer | ||
| memcpy(control_area.command_bfr, tpm2_command, command_size); | ||
|
|
||
| // Write Start Bit | ||
| write8(CRB_REG(cur_loc, CRB_REG_START), 0x1); | ||
|
|
||
| // Poll for Response | ||
| rc = crb_wait_for_reg32(CRB_REG(cur_loc, CRB_REG_START), 3500, CRB_REG_START_START, 0); | ||
| if (rc) { | ||
| printk(BIOS_DEBUG, "TPM: Command Timed out.\n"); | ||
| return -1; | ||
| } | ||
|
|
||
| // Check for errors | ||
| rc = crb_wait_for_reg32(CRB_REG(cur_loc, CRB_REG_STATUS), 200, CRB_REG_STATUS_ERROR, 0); | ||
| if (rc) { | ||
| printk(BIOS_DEBUG, "TPM: Command errored.\n"); | ||
| return -1; | ||
| } | ||
|
|
||
| // Get Response Length | ||
| uint32_t length = be32_to_cpu(read32(control_area.response_bfr + 2)); | ||
|
|
||
| /* Response has to have at least 6 bytes */ | ||
| if (length < 6) | ||
| return 1; | ||
|
|
||
| // Copy Response | ||
| memcpy(tpm2_response, control_area.response_bfr, length); | ||
|
|
||
| if (crb_switch_to_ready()) { | ||
| printk(BIOS_DEBUG, "TPM: Can not transition into ready state again.\n"); | ||
| return -1; | ||
| } | ||
|
|
||
| return length; | ||
| } | ||
|
|
||
| /* | ||
| * tp2_get_info | ||
| * | ||
| * Returns information about the TPM | ||
| * | ||
| */ | ||
| void tpm2_get_info(struct tpm2_info *tpm2_info) | ||
| { | ||
| uint64_t interfaceReg = read64(CRB_REG(cur_loc, CRB_REG_INTF_ID)); | ||
|
|
||
| tpm2_info->vendor_id = (interfaceReg >> 48) & 0xFFFF; | ||
| tpm2_info->device_id = (interfaceReg >> 32) & 0xFFFF; | ||
| tpm2_info->revision = (interfaceReg >> 24) & 0xFF; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,70 @@ | ||
| /* | ||
| * Copyright 2016 The Chromium OS Authors. All rights reserved. | ||
| * Use of this source code is governed by a BSD-style license that can be | ||
| * found in the LICENSE file. | ||
| * | ||
| * This is a driver for a Command Response Buffer Interface | ||
| */ | ||
|
|
||
| /* CRB driver */ | ||
| /* address of locality 0 (CRB) */ | ||
| #define TPM_CRB_BASE_ADDRESS CONFIG_CRB_TPM_BASE_ADDRESS | ||
|
|
||
| #define CRB_REG(LOCTY, REG) \ | ||
| (void *)(CONFIG_CRB_TPM_BASE_ADDRESS + (LOCTY << 12) + REG) | ||
|
|
||
| /* hardware registers */ | ||
| #define CRB_REG_LOC_STATE 0x00 | ||
| #define CRB_REG_LOC_CTRL 0x08 | ||
| #define CRB_REG_LOC_STS 0x0C | ||
|
|
||
| /* LOC_CTRL BIT MASKS */ | ||
| #define LOC_CTRL_REQ_ACCESS 0x01 | ||
|
|
||
| /* LOC STATE BIT MASKS */ | ||
| #define LOC_STATE_LOC_ASSIGN 0x02 | ||
| #define LOC_STATE_REG_VALID_STS 0x80 | ||
|
|
||
| /* LOC STS BIT MASKS */ | ||
| #define LOC_STS_GRANTED 0x01 | ||
|
|
||
| #define CRB_REG_INTF_ID 0x30 | ||
| #define CRB_REG_REQUEST 0x40 | ||
| #define CRB_REG_STATUS 0x44 | ||
| #define CRB_REG_CANCEL 0x48 | ||
| #define CRB_REG_START 0x4C | ||
| #define CRB_REG_INT_CTRL 0x50 | ||
| #define CRB_REG_CMD_SIZE 0x58 | ||
| #define CRB_REG_CMD_ADDR 0x5C | ||
| #define CRB_REG_RESP_SIZE 0x64 | ||
| #define CRB_REG_RESP_ADDR 0x68 | ||
|
|
||
| /* CRB INTF BIT MASK */ | ||
| #define CRB_INTF_REG_CAP_CRB (1<<14) | ||
| #define CRB_INTF_REG_INTF_SEL (1<<17) | ||
| #define CRB_INTF_REG_INTF_LOCK (1<<19) | ||
|
|
||
|
|
||
| /*REQUEST Register related */ | ||
| #define CRB_REG_REQUEST_CMD_RDY 0x01 | ||
| #define CRB_REG_REQUEST_GO_IDLE 0x02 | ||
|
|
||
| /* STATUS Register related */ | ||
| #define CRB_REG_STATUS_ERROR 0x01 | ||
| #define CRB_REG_STATUS_IDLE 0x02 | ||
|
|
||
| /* START Register related */ | ||
| #define CRB_REG_START_START 0x01 | ||
|
|
||
| /* TPM Info Struct */ | ||
| struct tpm2_info { | ||
| uint16_t vendor_id; | ||
| uint16_t device_id; | ||
| uint16_t revision; | ||
| }; | ||
|
|
||
|
|
||
| int tpm2_init(void); | ||
| void tpm2_get_info(struct tpm2_info *tpm2_info); | ||
| size_t tpm2_process_command(const void *tpm2_command, size_t command_size, | ||
| void *tpm2_response, size_t max_response); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| with HW.GFX.GMA; | ||
| with HW.GFX.GMA.Display_Probing; | ||
|
|
||
| use HW.GFX.GMA; | ||
|
|
||
| package body GMA is | ||
|
|
||
| function read_edid | ||
| (raw_edid : out HW.GFX.EDID.Raw_EDID_Data; | ||
| port : in Interfaces.C.int) | ||
| return Interfaces.C.int | ||
| is | ||
| use type Interfaces.C.int; | ||
| success : Boolean := true; | ||
| begin | ||
| if port not in Active_Port_Type'Pos (Active_Port_Type'First) | ||
| .. Active_Port_Type'Pos (Active_Port_Type'Last) | ||
| then | ||
| raw_edid := (others => 0); | ||
| return -2; | ||
| else | ||
| if not HW.GFX.GMA.Is_Initialized then | ||
| HW.GFX.GMA.Initialize (Success => success); | ||
| end if; | ||
| if success then | ||
| HW.GFX.GMA.Display_Probing.Read_EDID | ||
| (raw_edid, Active_Port_Type'Val (port), success); | ||
| end if; | ||
| if success then | ||
| return 0; | ||
| else | ||
| return -1; | ||
| end if; | ||
| end if; | ||
| end read_edid; | ||
|
|
||
| end GMA; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,14 @@ | ||
| with Interfaces.C; | ||
|
|
||
| with HW.GFX.EDID; | ||
|
|
||
| package GMA is | ||
|
|
||
| function read_edid | ||
| (raw_edid : out HW.GFX.EDID.Raw_EDID_Data; | ||
| Port : in Interfaces.C.int) | ||
| return Interfaces.C.int | ||
| with | ||
| Export, Convention => C, External_Name => "gma_read_edid"; | ||
|
|
||
| end GMA; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,6 @@ | ||
| config HAVE_INTEL_PTT | ||
| bool | ||
| default n | ||
| select VBOOT_MOCK_SECDATA if VBOOT | ||
| help | ||
| Activate if your platform has Intel Platform Trust Technology like Intel iTPM and you want to use it. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,4 @@ | ||
| romstage-$(CONFIG_HAVE_INTEL_PTT) += ptt.c | ||
| ramstage-$(CONFIG_HAVE_INTEL_PTT) += ptt.c | ||
| postcar-$(CONFIG_HAVE_INTEL_PTT) += ptt.c | ||
| verstage-$(CONFIG_HAVE_INTEL_PTT) += ptt.c |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,53 @@ | ||
| /* | ||
| * This file is part of the coreboot project. | ||
| * | ||
| * This program is free software; you can redistribute it and/or modify | ||
| * it under the terms of the GNU General Public License as published by | ||
| * the Free Software Foundation; version 2 of the License. | ||
| * | ||
| * This program is distributed in the hope that it will be useful, | ||
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| * GNU General Public License for more details. | ||
| */ | ||
|
|
||
| #include <soc/pci_devs.h> | ||
| #include <device/pci_ops.h> | ||
| #include <console/console.h> | ||
| #include <timer.h> | ||
|
|
||
| #include "ptt.h" | ||
|
|
||
| #define PCI_ME_HFSTS4 0x64 | ||
| #define PTT_ENABLE (1 << 19) | ||
|
|
||
| /* Dump Intel ME register */ | ||
| static uint32_t read_register(int reg_addr) | ||
| { | ||
| if (!PCH_DEV_CSE) | ||
| return 0xFFFFFFFF; | ||
|
|
||
| return pci_read_config32(PCH_DEV_CSE, reg_addr); | ||
| } | ||
|
|
||
| /* | ||
| * ptt_active() | ||
| * | ||
| * Check if PTT Flag is set - so that PTT is active. | ||
| * | ||
| * Return true if active, false otherwise. | ||
| */ | ||
| bool ptt_active(void) | ||
| { | ||
| uint32_t fwsts4 = read_register(PCI_ME_HFSTS4); | ||
|
|
||
| if (fwsts4 == 0xFFFFFFFF) | ||
| return false; | ||
|
|
||
| if ((fwsts4 & PTT_ENABLE) == 0) { | ||
| printk(BIOS_DEBUG, "Intel ME Establishment bit not valid.\n"); | ||
| return false; | ||
| } | ||
|
|
||
| return true; | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,53 +1,8 @@ | ||
| config DRIVERS_INTEL_WIFI | ||
| bool "Support Intel PCI-e WiFi adapters" | ||
| depends on PCI | ||
| default y if PCIEXP_PLUGIN_SUPPORT | ||
| select DRIVERS_GENERIC_WIFI if HAVE_ACPI_TABLES | ||
| help | ||
| When enabled, add identifiers in ACPI and SMBIOS tables to | ||
| make OS drivers work with certain Intel PCI-e WiFi chipsets. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,57 @@ | ||
| config DRIVERS_GENERIC_WIFI | ||
| bool | ||
| default n | ||
| depends on HAVE_ACPI_TABLES | ||
| help | ||
| When enabled, add identifiers in ACPI tables that are common | ||
| to WiFi chipsets from multiple vendors. | ||
|
|
||
| if DRIVERS_GENERIC_WIFI | ||
|
|
||
| config USE_SAR | ||
| bool | ||
| default n | ||
| help | ||
| Enable it when wifi driver uses SAR configuration feature. | ||
| VPD entry "wifi_sar" is read to get SAR settings, if its | ||
| not found driver may look into CBFS for default settigs. | ||
| WIFI_SAR_CBFS is option to enable CBFS lookup. | ||
|
|
||
| config SAR_ENABLE | ||
| bool | ||
| default n | ||
| depends on USE_SAR | ||
|
|
||
| config DSAR_ENABLE | ||
| bool | ||
| default n | ||
| depends on USE_SAR | ||
|
|
||
| config GEO_SAR_ENABLE | ||
| bool | ||
| default n | ||
| depends on USE_SAR | ||
|
|
||
| config WIFI_SAR_CBFS | ||
| bool "Enable SAR table addition to CBFS" | ||
| default n | ||
| depends on USE_SAR | ||
| help | ||
| wifi driver would look for "wifi_sar" vpd key and load SAR settings from | ||
| it, if the vpd key is not found then the driver tries to look for sar | ||
| settings from CBFS with file name wifi_sar_defaults.hex. | ||
| So OEM/ODM can override wifi sar with VPD. | ||
|
|
||
| config WIFI_SAR_CBFS_FILEPATH | ||
| string "The cbfs file which has WIFI SAR defaults" | ||
| depends on WIFI_SAR_CBFS | ||
| default "src/mainboard/$(MAINBOARDDIR)/wifi_sar_defaults.hex" | ||
|
|
||
| config DSAR_SET_NUM | ||
| hex "Number of SAR sets when D-SAR is enabled" | ||
| default 0x3 | ||
| depends on USE_SAR | ||
| help | ||
| There can be up to 3 optional SAR table sets. | ||
|
|
||
| endif # DRIVERS_GENERIC_WIFI |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1 @@ | ||
| ramstage-$(CONFIG_DRIVERS_GENERIC_WIFI) += generic.c |