Merge remote-tracking branch 'upstream/master' into galp5
Change-Id: Ia43c6f4cdd97cd8c20a15a71499291ad4a92dedf
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -59,6 +59,7 @@ site-local
|
||||
*.debug
|
||||
!Kconfig.debug
|
||||
*.elf
|
||||
*.fd
|
||||
*.o
|
||||
*.o.d
|
||||
*.out
|
||||
|
2
3rdparty/amd_blobs
vendored
2
3rdparty/amd_blobs
vendored
Submodule 3rdparty/amd_blobs updated: e393a885c8...8c668ab552
2
3rdparty/blobs
vendored
2
3rdparty/blobs
vendored
Submodule 3rdparty/blobs updated: 1aff9c32eb...a59fb6e389
@@ -19,7 +19,7 @@ In order to add support for x86_64 the following assumptions were made:
|
||||
* x86 payloads are loaded below 4GiB in physical memory and are jumped
|
||||
to in *protected mode*
|
||||
|
||||
## Assuptions for all stages using the reference implementation
|
||||
## Assumptions for all stages using the reference implementation
|
||||
* 0-4GiB are identity mapped using 2MiB-pages as WB
|
||||
* Memory above 4GiB isn't accessible
|
||||
* page tables reside in memory mapped ROM
|
||||
|
@@ -7,3 +7,4 @@ they allow to easily reuse existing code accross platforms.
|
||||
* [IPMI KCS](ipmi_kcs.md)
|
||||
* [SMMSTORE](smmstore.md)
|
||||
* [SoundWire](soundwire.md)
|
||||
* [SMMSTOREv2](smmstorev2.md)
|
||||
|
40
Documentation/drivers/retimer.md
Normal file
40
Documentation/drivers/retimer.md
Normal file
@@ -0,0 +1,40 @@
|
||||
# USB4 Retimers
|
||||
|
||||
# Introduction
|
||||
As USB speeds continue to increase (up to 5G, 10G, and even 20G or higher in
|
||||
newer revisions of the spec), it becomes more difficult to maintain signal
|
||||
integrity for longer traces. Devices such as retimers and redrivers can be used
|
||||
to help signals maintain their integrity over long distances.
|
||||
|
||||
A redriver is a device that boosts the high-frequency content of a signal in
|
||||
order to compensate for the attenuation typically caused by travelling through
|
||||
various circuit components (PCB, connectors, CPU, etc.). Redrivers are not
|
||||
protocol-aware, which makes them relatively simple. However, their effectiveness
|
||||
is limited, and may not work at all in some scenarios.
|
||||
|
||||
A retimer is a device that retransmits a fresh copy of the signal it receives,
|
||||
by doing CDR and retransmitting the data (i.e., it is protocol-aware). Since
|
||||
this is a digital component, it may have firmware.
|
||||
|
||||
|
||||
# Driver Usage
|
||||
|
||||
Some operating systems may have the ability to update firmware on USB4 retimers,
|
||||
and ultimately will need some way to power the device on and off so that its new
|
||||
firmware can be loaded. This is achieved by providing a GPIO signal that can be
|
||||
used for this purpose; its active state must be the one in which power is
|
||||
applied to the retimer. This driver will generate the required ACPI AML code
|
||||
which will toggle the GPIO in response to the kernel's request (through the
|
||||
`_DSM` ACPI method). Simply put something like the following in your devicetree:
|
||||
|
||||
```
|
||||
device pci 0.0 on
|
||||
chip drivers/intel/usb4/retimer
|
||||
register "power_gpio" = "ACPI_GPIO_OUTPUT_ACTIVE_HIGH(GPP_A0)"
|
||||
device generic 0 on end
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
replacing the GPIO with the appropriate pin and polarity.
|
||||
|
221
Documentation/drivers/smmstorev2.md
Normal file
221
Documentation/drivers/smmstorev2.md
Normal file
@@ -0,0 +1,221 @@
|
||||
# SMM based flash storage driver Version 2
|
||||
|
||||
This documents the API exposed by the x86 system management based
|
||||
storage driver.
|
||||
|
||||
## SMMSTOREv2
|
||||
|
||||
SMMSTOREv2 is a [SMM] mediated driver to read from, write to and erase
|
||||
a predefined region in flash. It can be enabled by setting
|
||||
`CONFIG_SMMSTORE=y` and `CONFIG_SMMSTORE_V2=y` in menuconfig.
|
||||
|
||||
This can be used by the OS or the payload to implement persistent
|
||||
storage to hold for instance configuration data, without needing to
|
||||
implement a (platform specific) storage driver in the payload itself.
|
||||
|
||||
### Storage size and alignment
|
||||
|
||||
SMMSTORE version 2 requires a minimum alignment of 64 KiB, which should
|
||||
be supported by all flash chips. Not having to perform read-modify-write
|
||||
operations is desired, as it reduces complexity and potential for bugs.
|
||||
|
||||
This can be used by a FTW (FaultTolerantWrite) implementation that uses
|
||||
at least two regions in an A/B update scheme. The FTW implementation in
|
||||
EDK2 uses three different regions in the store:
|
||||
|
||||
- The variable store
|
||||
- The FTW spare block
|
||||
- The FTW working block
|
||||
|
||||
All regions must be block-aligned, and the FTW spare size must be larger
|
||||
than that of the variable store. FTW working block can be much smaller.
|
||||
With 64 KiB as block size, the minimum size of the FTW-enabled store is:
|
||||
|
||||
- The variable store: 1 block = 64 KiB
|
||||
- The FTW spare block: 2 blocks = 2 * 64 KiB
|
||||
- The FTW working block: 1 block = 64 KiB
|
||||
|
||||
Therefore, the minimum size for EDK2 FTW is 4 blocks, or 256 KiB.
|
||||
|
||||
## API
|
||||
|
||||
The API provides read and write access to an unformatted block storage.
|
||||
|
||||
### Storage region
|
||||
|
||||
By default SMMSTOREv2 will operate on a separate FMAP region called
|
||||
`SMMSTORE`. The default generated FMAP will include such a region. On
|
||||
systems with a locked FMAP, e.g. in an existing vboot setup with a
|
||||
locked RO region, the option exists to add a cbfsfile called `smm_store`
|
||||
in the `RW_LEGACY` (if CHROMEOS) or in the `COREBOOT` FMAP regions. It
|
||||
is recommended for new builds using a handcrafted FMD that intend to
|
||||
make use of SMMSTORE to include a sufficiently large `SMMSTORE` FMAP
|
||||
region. It is mandatory to align the `SMMSTORE` region to 64KiB for
|
||||
compatibility with the largest flash erase operation.
|
||||
|
||||
When a default generated FMAP is used, the size of the FMAP region is
|
||||
equal to `CONFIG_SMMSTORE_SIZE`. UEFI payloads expect at least 64 KiB.
|
||||
To support a fault tolerant write mechanism, at least a multiple of
|
||||
this size is recommended.
|
||||
|
||||
### Communication buffer
|
||||
|
||||
To prevent malicious ring0 code to access arbitrary memory locations,
|
||||
SMMSTOREv2 uses a communication buffer in CBMEM/HOB for all transfers.
|
||||
This buffer has to be at least 64 KiB in size and must be installed
|
||||
before calling any of the SMMSTORE read or write operations. Usually,
|
||||
coreboot will install this buffer to transfer data between ring0 and
|
||||
the [SMM] handler.
|
||||
|
||||
In order to get the communication buffer address, the payload or OS
|
||||
has to read the coreboot table with tag `0x0039`, containing:
|
||||
|
||||
```C
|
||||
struct lb_smmstorev2 {
|
||||
uint32_t tag;
|
||||
uint32_t size;
|
||||
uint32_t num_blocks; /* Number of writeable blocks in SMM */
|
||||
uint32_t block_size; /* Size of a block in byte. Default: 64 KiB */
|
||||
uint32_t mmap_addr; /* MMIO address of the store for read only access */
|
||||
uint32_t com_buffer; /* Physical address of the communication buffer */
|
||||
uint32_t com_buffer_size; /* Size of the communication buffer in byte */
|
||||
uint8_t apm_cmd; /* The command byte to write to the APM I/O port */
|
||||
uint8_t unused[3]; /* Set to zero */
|
||||
};
|
||||
```
|
||||
|
||||
The absence of this coreboot table entry indicates that there's no
|
||||
SMMSTOREv2 support.
|
||||
|
||||
### Blocks
|
||||
|
||||
The SMMSTOREv2 splits the SMMSTORE FMAP partition into smaller chunks
|
||||
called *blocks*. Every block is at least the size of 64KiB to support
|
||||
arbitrary NOR flash erase ops. A payload or OS must make no further
|
||||
assumptions about the block or communication buffer size.
|
||||
|
||||
### Generating the SMI
|
||||
|
||||
SMMSTOREv2 is called via an SMI, which is generated via a write to the
|
||||
IO port defined in the smi_cmd entry of the FADT ACPI table. `%al`
|
||||
contains `APM_CNT_SMMSTORE=0xed` and is written to the smi_cmd IO
|
||||
port. `%ah` contains the SMMSTOREv2 command. `%ebx` contains the
|
||||
parameter buffer to the SMMSTOREv2 command.
|
||||
|
||||
### Return values
|
||||
|
||||
If a command succeeds, SMMSTOREv2 will return with
|
||||
`SMMSTORE_RET_SUCCESS=0` in `%eax`. On failure SMMSTORE will return
|
||||
`SMMSTORE_RET_FAILURE=1`. For unsupported SMMSTORE commands
|
||||
`SMMSTORE_REG_UNSUPPORTED=2` is returned.
|
||||
|
||||
**NOTE 1**: The caller **must** check the return value and should make
|
||||
no assumption on the returned data if `%eax` does not contain
|
||||
`SMMSTORE_RET_SUCCESS`.
|
||||
|
||||
**NOTE 2**: If the SMI returns without changing `%ax`, it can be assumed
|
||||
that the SMMSTOREv2 feature is not installed.
|
||||
|
||||
### Calling arguments
|
||||
|
||||
SMMSTOREv2 supports 3 subcommands that are passed via `%ah`, the
|
||||
additional calling arguments are passed via `%ebx`.
|
||||
|
||||
**NOTE**: The size of the struct entries are in the native word size of
|
||||
smihandler. This means 32 bits in almost all cases.
|
||||
|
||||
#### - SMMSTORE_CMD_INIT = 4
|
||||
|
||||
This installs the communication buffer to use and thus enables the
|
||||
SMMSTORE handler. This command can only be executed once and is done
|
||||
by the firmware. Calling this function at runtime has no effect.
|
||||
|
||||
The additional parameter buffer `%ebx` contains a pointer to the
|
||||
following struct:
|
||||
|
||||
```C
|
||||
struct smmstore_params_init {
|
||||
uint32_t com_buffer;
|
||||
uint32_t com_buffer_size;
|
||||
} __packed;
|
||||
```
|
||||
|
||||
INPUT:
|
||||
- `com_buffer`: Physical address of the communication buffer (CBMEM)
|
||||
- `com_buffer_size`: Size in bytes of the communication buffer
|
||||
|
||||
#### - SMMSTORE_CMD_RAW_READ = 5
|
||||
|
||||
SMMSTOREv2 allows reading arbitrary data. It is up to the caller to
|
||||
initialize the store with meaningful data before using it.
|
||||
|
||||
The additional parameter buffer `%ebx` contains a pointer to the
|
||||
following struct:
|
||||
|
||||
```C
|
||||
struct smmstore_params_raw_read {
|
||||
uint32_t bufsize;
|
||||
uint32_t bufoffset;
|
||||
uint32_t block_id;
|
||||
} __packed;
|
||||
```
|
||||
|
||||
INPUT:
|
||||
- `bufsize`: Size of data to read within the communication buffer
|
||||
- `bufoffset`: Offset within the communication buffer
|
||||
- `block_id`: Block to read from
|
||||
|
||||
#### - SMMSTORE_CMD_RAW_WRITE = 6
|
||||
|
||||
SMMSTOREv2 allows writing arbitrary data. It is up to the caller to
|
||||
erase a block before writing it.
|
||||
|
||||
The additional parameter buffer `%ebx` contains a pointer to
|
||||
the following struct:
|
||||
|
||||
```C
|
||||
struct smmstore_params_raw_write {
|
||||
uint32_t bufsize;
|
||||
uint32_t bufoffset;
|
||||
uint32_t block_id;
|
||||
} __packed;
|
||||
```
|
||||
|
||||
INPUT:
|
||||
- `bufsize`: Size of data to write within the communication buffer
|
||||
- `bufoffset`: Offset within the communication buffer
|
||||
- `block_id`: Block to write to
|
||||
|
||||
#### - SMMSTORE_CMD_RAW_CLEAR = 7
|
||||
|
||||
SMMSTOREv2 allows clearing blocks. A cleared block will read as `0xff`.
|
||||
By providing multiple blocks the caller can implement a fault tolerant
|
||||
write mechanism. It is up to the caller to clear blocks before writing
|
||||
to them.
|
||||
|
||||
|
||||
```C
|
||||
struct smmstore_params_raw_clear {
|
||||
uint32_t block_id;
|
||||
} __packed;
|
||||
```
|
||||
|
||||
INPUT:
|
||||
- `block_id`: Block to erase
|
||||
|
||||
#### Security
|
||||
|
||||
Pointers provided by the payload or OS are checked to not overlap with
|
||||
SMM. This protects the SMM handler from being compromised.
|
||||
|
||||
As all information is exchanged using the communication buffer and
|
||||
coreboot tables, there's no risk that a malicious application capable
|
||||
of issuing SMIs could extract arbitrary data or modify the currently
|
||||
running kernel.
|
||||
|
||||
## External links
|
||||
|
||||
* [A Tour Beyond BIOS Implementing UEFI Authenticated Variables in SMM with EDKI](https://software.intel.com/sites/default/files/managed/cf/ea/a_tour_beyond_bios_implementing_uefi_authenticated_variables_in_smm_with_edkii.pdf)
|
||||
Note that this differs significantly from coreboot's implementation.
|
||||
|
||||
[SMM]: ../security/smm.md
|
@@ -0,0 +1,103 @@
|
||||
# Supermicro X11SSH-F
|
||||
|
||||
This section details how to run coreboot on the [Supermicro X11SSH-F].
|
||||
|
||||
## Flashing coreboot
|
||||
|
||||
The board can be flashed externally. [STM32-based programmers] worked.
|
||||
|
||||
The flash IC "W25Q128.V" (detected by flashrom) can be found near PCH PCIe Slot 4. It is sometime
|
||||
socketed, and covered by a sticker, hindering the observation of its precise model.
|
||||
|
||||
It can be programmed in-system with a clip like pomona 5250.
|
||||
|
||||
## BMC (IPMI)
|
||||
|
||||
This board has an ASPEED [AST2400], which has BMC/[IPMI] functionality. The BMC firmware resides in a
|
||||
32 MiB SOIC-16 chip in the corner of the mainboard near the PCH PCIe Slot 4. This chip is a
|
||||
[MX25L25635F].
|
||||
|
||||
## IGD
|
||||
|
||||
If an IGD is integrated with CPU, it will be enabled on this board. Though there is no video output
|
||||
for it (The onboard VGA port is connected to BMC), it is said to be capable of being used for compute
|
||||
tasks, or for offloading graphics rendering via "muxless" [vga_witcheroo].
|
||||
|
||||
## Tested and working
|
||||
|
||||
- SeaBIOS payload to boot Kali Linux live USB
|
||||
- ECC ram (Linux' ie31200 driver works)
|
||||
- Integrated graphics device available without output
|
||||
- USB ports
|
||||
- Ethernet
|
||||
- SATA ports
|
||||
- RS232 external
|
||||
- PCIe slots
|
||||
- BMC (IPMI)
|
||||
- VGA on Aspeed
|
||||
- TPM on TPM expansion header
|
||||
|
||||
## Known issues
|
||||
|
||||
- See general issue section
|
||||
- S3 resume not working (vendor and coreboot)
|
||||
- SeaBIOS cannot make use of VGA on Aspeed (even if IGD is disabled)
|
||||
|
||||
## ToDo
|
||||
|
||||
- Fix known issues
|
||||
- Testing other payloads
|
||||
|
||||
## Technology
|
||||
|
||||
```eval_rst
|
||||
+------------------+--------------------------------------------------+
|
||||
| CPU | Intel Kaby Lake |
|
||||
+------------------+--------------------------------------------------+
|
||||
| PCH | Intel C236 |
|
||||
+------------------+--------------------------------------------------+
|
||||
| Coprocessor | Intel SPS (server version of the ME) |
|
||||
+------------------+--------------------------------------------------+
|
||||
| Super I/O | ASPEED AST2400 |
|
||||
+------------------+--------------------------------------------------+
|
||||
| Ethernet | 2x Intel I210-AT 1 GbE |
|
||||
| | 1x dedicated BMC |
|
||||
+------------------+--------------------------------------------------+
|
||||
| PCIe slots | 1x 3.0 x8 |
|
||||
| | 1x 3.0 x8 (in x16) |
|
||||
| | 1x 3.0 x4 (in x8) |
|
||||
| | 1x 3.0 x2 (in M.2 slot with key M) |
|
||||
+------------------+--------------------------------------------------+
|
||||
| USB slots | 2x USB 2.0 (ext) |
|
||||
| | 2x USB 3.0 (ext) |
|
||||
| | 1x USB 3.0 (int) |
|
||||
| | 1x dual USB 3.0 header |
|
||||
| | 2x dual USB 2.0 header |
|
||||
+------------------+--------------------------------------------------+
|
||||
| SATA slots | 8x S-ATA III |
|
||||
+------------------+--------------------------------------------------+
|
||||
| Other slots | 1x RS232 (ext) |
|
||||
| | 1x RS232 header |
|
||||
| | 1x TPM header |
|
||||
| | 1x Power SMB header |
|
||||
| | 5x PWM Fan connector |
|
||||
| | 2x I-SGPIO |
|
||||
| | 2x S-ATA DOM Power connector |
|
||||
| | 1x XDP Port (connector may absent) |
|
||||
| | 1x External BMC I2C Header (for IPMI card) |
|
||||
| | 1x Chassis Intrusion Header |
|
||||
+------------------+--------------------------------------------------+
|
||||
```
|
||||
|
||||
## Extra links
|
||||
|
||||
- [Supermicro X11SSH-F]
|
||||
- [Board manual]
|
||||
|
||||
[Supermicro X11SSH-F]: https://www.supermicro.com/en/products/motherboard/X11SSH-F
|
||||
[Board manual]: https://www.supermicro.com/manuals/motherboard/C236/MNL-1778.pdf
|
||||
[AST2400]: https://www.aspeedtech.com/products.php?fPath=20&rId=376
|
||||
[IPMI]: ../../../../drivers/ipmi_kcs.md
|
||||
[MX25L25635F]: https://media.digikey.com/pdf/Data%20Sheets/Macronix/MX25L25635F.pdf
|
||||
[STM32-based programmers]: https://github.com/dword1511/stm32-vserprog
|
||||
[vga_switcheroo]: https://01.org/linuxgraphics/gfx-docs/drm/gpu/vga-switcheroo.html
|
@@ -208,6 +208,14 @@ F: src/mainboard/asus/p8z77-v_lx2/
|
||||
|
||||
|
||||
|
||||
CLEVO MAINBOARDS
|
||||
M: Felix Singer <felixsinger@posteo.net>
|
||||
M: Michael Niewöhner <foss@mniewoehner.de>
|
||||
S: Supported
|
||||
F: src/mainboard/clevo
|
||||
|
||||
|
||||
|
||||
FACEBOOK FBG1701 MAINBOARD
|
||||
M: Frans Hendriks <fhendriks@eltan.com>
|
||||
M: Wim Vervoorn <wvervoorn@eltan.com>
|
||||
|
@@ -80,7 +80,7 @@ subdirs-y := src/lib src/commonlib/ src/console src/device src/acpi
|
||||
subdirs-y += src/ec/acpi $(wildcard src/ec/*/*) $(wildcard src/southbridge/*/*)
|
||||
subdirs-y += $(wildcard src/soc/*/*) $(wildcard src/northbridge/*/*)
|
||||
subdirs-y += src/superio
|
||||
subdirs-y += $(wildcard src/drivers/*) $(wildcard src/drivers/*/*)
|
||||
subdirs-y += $(wildcard src/drivers/*) $(wildcard src/drivers/*/*) $(wildcard src/drivers/*/*/*)
|
||||
subdirs-y += src/cpu src/vendorcode
|
||||
subdirs-y += util/cbfstool util/sconfig util/nvramtool util/pgtblgen util/amdfwtool
|
||||
subdirs-y += util/futility util/marvell util/bincfg util/supermicro
|
||||
@@ -611,6 +611,12 @@ SCONFIG_OPTIONS += --output_c=$(DEVICETREE_STATIC_C)
|
||||
DEVICETREE_STATIC_H := $(obj)/static.h
|
||||
SCONFIG_OPTIONS += --output_h=$(DEVICETREE_STATIC_H)
|
||||
|
||||
DEVICETREE_DEVICENAMES_H := $(obj)/static_devices.h
|
||||
SCONFIG_OPTIONS += --output_d=$(DEVICETREE_DEVICENAMES_H)
|
||||
|
||||
DEVICETREE_FWCONFIG_H := $(obj)/static_fw_config.h
|
||||
SCONFIG_OPTIONS += --output_f=$(DEVICETREE_FWCONFIG_H)
|
||||
|
||||
$(DEVICETREE_STATIC_C): $(DEVICETREE_FILE) $(OVERRIDE_DEVICETREE_FILE) $(CHIPSET_DEVICETREE_FILE) $(objutil)/sconfig/sconfig
|
||||
@printf " SCONFIG $(subst $(src)/,,$(<))\n"
|
||||
mkdir -p $(dir $(DEVICETREE_STATIC_C))
|
||||
|
10
configs/config.asrock_b85m_pro4.tpm2_txt_placeholder_acms
Normal file
10
configs/config.asrock_b85m_pro4.tpm2_txt_placeholder_acms
Normal file
@@ -0,0 +1,10 @@
|
||||
# Known-working configuration to boot with TXT enabled. Since BIOS
|
||||
# and SINIT ACM blobs are missing, use something else as placeholder.
|
||||
# Used ACMs were extracted from a Supermicro X10SLH firmware update.
|
||||
CONFIG_VENDOR_ASROCK=y
|
||||
CONFIG_BOARD_ASROCK_B85M_PRO4=y
|
||||
CONFIG_USER_TPM2=y
|
||||
CONFIG_INTEL_TXT=y
|
||||
CONFIG_INTEL_TXT_BIOSACM_FILE="3rdparty/blobs/cpu/intel/stm/stm.bin"
|
||||
CONFIG_INTEL_TXT_SINITACM_FILE="3rdparty/blobs/cpu/intel/stm/stm.bin"
|
||||
CONFIG_INTEL_TXT_LOGGING=y
|
@@ -151,7 +151,7 @@ static int pci_module_redraw(WINDOW *win)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void pci_scan_bus(int bus)
|
||||
static void ci_pci_scan_bus(int bus)
|
||||
{
|
||||
int slot, func;
|
||||
unsigned int val;
|
||||
@@ -196,7 +196,7 @@ static void pci_scan_bus(int bus)
|
||||
|
||||
busses = pci_read_config32(dev, REG_PRIMARY_BUS);
|
||||
|
||||
pci_scan_bus((busses >> 8) & 0xff);
|
||||
ci_pci_scan_bus((busses >> 8) & 0xff);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -240,7 +240,7 @@ static int pci_module_handle(int key)
|
||||
|
||||
static int pci_module_init(void)
|
||||
{
|
||||
pci_scan_bus(0);
|
||||
ci_pci_scan_bus(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@@ -78,5 +78,10 @@ int lib_get_sysinfo(void)
|
||||
lib_sysinfo.memrange[1].type = CB_MEM_RAM;
|
||||
}
|
||||
|
||||
#if CONFIG(LP_PCI)
|
||||
pci_init(&lib_sysinfo.pacc);
|
||||
pci_scan_bus(&lib_sysinfo.pacc);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@@ -41,6 +41,7 @@ PDCurses portable platform definitions list:
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h> /* Required by X/Open usage below */
|
||||
|
||||
@@ -48,12 +49,6 @@ PDCurses portable platform definitions list:
|
||||
# include <wchar.h>
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus) || defined(__cplusplus__) || defined(__CPLUSPLUS)
|
||||
extern "C"
|
||||
{
|
||||
# define bool _bool
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------
|
||||
*
|
||||
* PDCurses Manifest Constants
|
||||
@@ -82,8 +77,6 @@ extern "C"
|
||||
*
|
||||
*/
|
||||
|
||||
typedef unsigned char bool; /* PDCurses Boolean type */
|
||||
|
||||
#ifdef CHTYPE_LONG
|
||||
# if _LP64
|
||||
typedef unsigned int chtype;
|
||||
|
@@ -87,7 +87,7 @@
|
||||
* User-definable tweak to disable the include of <stdbool.h>.
|
||||
*/
|
||||
#ifndef NCURSES_ENABLE_STDBOOL_H
|
||||
#define NCURSES_ENABLE_STDBOOL_H 0 //// XXX
|
||||
#define NCURSES_ENABLE_STDBOOL_H 1
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@@ -27,6 +27,8 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include <keycodes.h>
|
||||
#include <libpayload-config.h>
|
||||
#include <libpayload.h>
|
||||
@@ -169,14 +171,14 @@ static struct layout_maps keyboard_layouts[] = {
|
||||
#endif
|
||||
};
|
||||
|
||||
static unsigned char keyboard_cmd(unsigned char cmd)
|
||||
static bool keyboard_cmd(unsigned char cmd)
|
||||
{
|
||||
i8042_write_data(cmd);
|
||||
|
||||
return i8042_wait_read_ps2() == 0xfa;
|
||||
}
|
||||
|
||||
int keyboard_havechar(void)
|
||||
bool keyboard_havechar(void)
|
||||
{
|
||||
return i8042_data_ready_ps2();
|
||||
}
|
||||
@@ -306,13 +308,13 @@ int keyboard_set_layout(char *country)
|
||||
}
|
||||
|
||||
static struct console_input_driver cons = {
|
||||
.havekey = keyboard_havechar,
|
||||
.havekey = (int (*)(void))keyboard_havechar,
|
||||
.getchar = keyboard_getchar,
|
||||
.input_type = CONSOLE_INPUT_TYPE_EC,
|
||||
};
|
||||
|
||||
/* Enable keyboard translated */
|
||||
static int enable_translated(void)
|
||||
static bool enable_translated(void)
|
||||
{
|
||||
if (!i8042_cmd(I8042_CMD_RD_CMD_BYTE)) {
|
||||
int cmd = i8042_read_data_ps2();
|
||||
@@ -321,19 +323,19 @@ static int enable_translated(void)
|
||||
i8042_write_data(cmd);
|
||||
} else {
|
||||
printf("ERROR: i8042_cmd WR_CMD failed!\n");
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
printf("ERROR: i8042_cmd RD_CMD failed!\n");
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
return 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Set scancode set 1 */
|
||||
static int set_scancode_set(void)
|
||||
static bool set_scancode_set(void)
|
||||
{
|
||||
unsigned int ret;
|
||||
bool ret;
|
||||
ret = keyboard_cmd(I8042_KBCMD_SET_SCANCODE);
|
||||
if (!ret) {
|
||||
printf("ERROR: Keyboard set scancode failed!\n");
|
||||
|
@@ -12,7 +12,7 @@ config STORAGE
|
||||
config STORAGE_64BIT_LBA
|
||||
bool "Use 64-bit integers to address sectors"
|
||||
depends on STORAGE
|
||||
default n
|
||||
default y
|
||||
help
|
||||
If this is selected, sectors will be addressed by an 64-bit integer.
|
||||
Select this to support LBA-48 for ATA drives.
|
||||
@@ -45,7 +45,7 @@ config STORAGE_AHCI
|
||||
config STORAGE_AHCI_ONLY_TESTED
|
||||
bool "Only enable tested controllers"
|
||||
depends on STORAGE_AHCI
|
||||
default y
|
||||
default n
|
||||
help
|
||||
If this option is selected only AHCI controllers which are known
|
||||
If this option is selected, only AHCI controllers which are known
|
||||
to work will be used.
|
||||
|
@@ -227,34 +227,28 @@ static u32 working_controllers[] = {
|
||||
0x8086 | 0x5ae3 << 16, /* Apollo Lake */
|
||||
};
|
||||
#endif
|
||||
static void ahci_init_pci(pcidev_t dev)
|
||||
|
||||
void ahci_initialize(struct pci_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
const u16 class = pci_read_config16(dev, 0xa);
|
||||
if (class != 0x0106)
|
||||
return;
|
||||
const u16 vendor = pci_read_config16(dev, 0x00);
|
||||
const u16 device = pci_read_config16(dev, 0x02);
|
||||
|
||||
#if CONFIG(LP_STORAGE_AHCI_ONLY_TESTED)
|
||||
const u32 vendor_device = pci_read_config32(dev, 0x0);
|
||||
const u32 vendor_device = dev->vendor_id | dev->device_id << 16;
|
||||
for (i = 0; i < ARRAY_SIZE(working_controllers); ++i)
|
||||
if (vendor_device == working_controllers[i])
|
||||
break;
|
||||
if (i == ARRAY_SIZE(working_controllers)) {
|
||||
printf("ahci: Not using untested SATA controller "
|
||||
"%02x:%02x.%02x (%04x:%04x).\n", PCI_BUS(dev),
|
||||
PCI_SLOT(dev), PCI_FUNC(dev), vendor, device);
|
||||
"%02x:%02x.%02x (%04x:%04x).\n", dev->bus,
|
||||
dev->dev, dev->func, dev->vendor_id, dev->device_id);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
printf("ahci: Found SATA controller %02x:%02x.%02x (%04x:%04x).\n",
|
||||
PCI_BUS(dev), PCI_SLOT(dev), PCI_FUNC(dev), vendor, device);
|
||||
dev->bus, dev->dev, dev->func, dev->vendor_id, dev->device_id);
|
||||
|
||||
hba_ctrl_t *const ctrl = phys_to_virt(
|
||||
pci_read_config32(dev, 0x24) & ~0x3ff);
|
||||
hba_ctrl_t *const ctrl = phys_to_virt(pci_read_long(dev, 0x24) & ~0x3ff);
|
||||
hba_port_t *const ports = ctrl->ports;
|
||||
|
||||
/* Reset host controller. */
|
||||
@@ -273,8 +267,8 @@ static void ahci_init_pci(pcidev_t dev)
|
||||
ctrl->global_ctrl |= HBA_CTRL_AHCI_EN;
|
||||
|
||||
/* Enable bus mastering. */
|
||||
const u16 command = pci_read_config16(dev, PCI_COMMAND);
|
||||
pci_write_config16(dev, PCI_COMMAND, command | PCI_COMMAND_MASTER);
|
||||
const u16 command = pci_read_word(dev, PCI_COMMAND);
|
||||
pci_write_word(dev, PCI_COMMAND, command | PCI_COMMAND_MASTER);
|
||||
|
||||
/* Probe for devices. */
|
||||
for (i = 0; i < 32; ++i) {
|
||||
@@ -282,19 +276,3 @@ static void ahci_init_pci(pcidev_t dev)
|
||||
ahci_port_probe(ctrl, &ports[i], i + 1);
|
||||
}
|
||||
}
|
||||
|
||||
void ahci_initialize(void)
|
||||
{
|
||||
int bus, dev, func;
|
||||
|
||||
for (bus = 0; bus < 256; ++bus) {
|
||||
for (dev = 0; dev < 32; ++dev) {
|
||||
const u16 class =
|
||||
pci_read_config16(PCI_DEV(bus, dev, 0), 0xa);
|
||||
if (class != 0xffff) {
|
||||
for (func = 0; func < 8; ++func)
|
||||
ahci_init_pci(PCI_DEV(bus, dev, func));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -27,6 +27,7 @@
|
||||
*/
|
||||
|
||||
#include <libpayload.h>
|
||||
#include <pci/pci.h>
|
||||
#if CONFIG(LP_STORAGE_AHCI)
|
||||
# include <storage/ahci.h>
|
||||
#endif
|
||||
@@ -108,7 +109,18 @@ ssize_t storage_read_blocks512(const size_t dev_num,
|
||||
*/
|
||||
void storage_initialize(void)
|
||||
{
|
||||
#if CONFIG(LP_PCI)
|
||||
struct pci_dev *dev;
|
||||
for (dev = lib_sysinfo.pacc.devices; dev; dev = dev->next) {
|
||||
switch (dev->device_class) {
|
||||
#if CONFIG(LP_STORAGE_AHCI)
|
||||
ahci_initialize();
|
||||
case PCI_CLASS_STORAGE_AHCI:
|
||||
ahci_initialize(dev);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
@@ -79,6 +79,7 @@ enum {
|
||||
CB_TAG_MMC_INFO = 0x0035,
|
||||
CB_TAG_TCPA_LOG = 0x0036,
|
||||
CB_TAG_FMAP = 0x0037,
|
||||
CB_TAG_SMMSTOREV2 = 0x0039,
|
||||
CB_TAG_CMOS_OPTION_TABLE = 0x00c8,
|
||||
CB_TAG_OPTION = 0x00c9,
|
||||
CB_TAG_OPTION_ENUM = 0x00ca,
|
||||
|
@@ -42,6 +42,7 @@
|
||||
#ifndef _LIBPAYLOAD_H
|
||||
#define _LIBPAYLOAD_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <libpayload-config.h>
|
||||
#include <compiler.h>
|
||||
#include <cbgfx.h>
|
||||
@@ -186,7 +187,7 @@ int add_reset_handler(void (*new_handler)(void));
|
||||
*/
|
||||
void keyboard_init(void);
|
||||
void keyboard_disconnect(void);
|
||||
int keyboard_havechar(void);
|
||||
bool keyboard_havechar(void);
|
||||
unsigned char keyboard_get_scancode(void);
|
||||
int keyboard_getchar(void);
|
||||
int keyboard_set_layout(char *country);
|
||||
@@ -445,6 +446,8 @@ u8 hex2bin(u8 h);
|
||||
void hexdump(const void *memory, size_t length);
|
||||
void fatal(const char *msg) __attribute__((noreturn));
|
||||
|
||||
/* Population Count: number of bits that are one */
|
||||
static inline int popcnt(u32 x) { return __builtin_popcount(x); }
|
||||
/* Count Leading Zeroes: clz(0) == 32, clz(0xf) == 28, clz(1 << 31) == 0 */
|
||||
static inline int clz(u32 x)
|
||||
{
|
||||
@@ -454,6 +457,15 @@ static inline int clz(u32 x)
|
||||
static inline int log2(u32 x) { return (int)sizeof(x) * 8 - clz(x) - 1; }
|
||||
/* Find First Set: __ffs(0xf) == 0, __ffs(0) == -1, __ffs(1 << 31) == 31 */
|
||||
static inline int __ffs(u32 x) { return log2(x & (u32)(-(s32)x)); }
|
||||
|
||||
static inline int popcnt64(u64 x) { return __builtin_popcountll(x); }
|
||||
static inline int clz64(u64 x)
|
||||
{
|
||||
return x ? __builtin_clzll(x) : sizeof(x) * 8;
|
||||
}
|
||||
|
||||
static inline int log2_64(u64 x) { return sizeof(x) * 8 - clz64(x) - 1; }
|
||||
static inline int __ffs64(u64 x) { return log2_64(x & (u64)(-(s64)x)); }
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
|
@@ -66,6 +66,7 @@
|
||||
#define PCI_ROM_ADDRESS1 0x38 // on bridges
|
||||
#define PCI_ROM_ADDRESS_MASK ~0x7ff
|
||||
|
||||
#define PCI_CLASS_STORAGE_AHCI 0x0106
|
||||
#define PCI_CLASS_MEMORY_OTHER 0x0580
|
||||
|
||||
#define PCI_VENDOR_ID_INTEL 0x8086
|
||||
@@ -74,6 +75,7 @@ struct pci_dev {
|
||||
u16 domain;
|
||||
u8 bus, dev, func;
|
||||
u16 vendor_id, device_id;
|
||||
u16 device_class;
|
||||
struct pci_dev *next;
|
||||
};
|
||||
|
||||
|
10
payloads/libpayload/include/stdbool.h
Normal file
10
payloads/libpayload/include/stdbool.h
Normal file
@@ -0,0 +1,10 @@
|
||||
/* SPDX-License-Identifier: BSD-3-Clause */
|
||||
|
||||
#ifndef __STDBOOL_H
|
||||
#define __STDBOOL_H
|
||||
|
||||
#define bool _Bool
|
||||
#define false 0
|
||||
#define true (!false)
|
||||
|
||||
#endif
|
@@ -26,9 +26,11 @@
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <pci/pci.h>
|
||||
|
||||
#ifndef _STORAGE_AHCI_H
|
||||
#define _STORAGE_AHCI_H
|
||||
|
||||
void ahci_initialize(void);
|
||||
void ahci_initialize(struct pci_dev *dev);
|
||||
|
||||
#endif
|
||||
|
@@ -29,6 +29,7 @@
|
||||
#ifndef _SYSINFO_H
|
||||
#define _SYSINFO_H
|
||||
|
||||
#include <pci/pci.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/* Maximum number of memory range definitions. */
|
||||
@@ -130,6 +131,10 @@ struct sysinfo_t {
|
||||
|
||||
/* Pointer to FMAP cache in CBMEM */
|
||||
uintptr_t fmap_cache;
|
||||
|
||||
#if CONFIG(LP_PCI)
|
||||
struct pci_access pacc;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern struct sysinfo_t lib_sysinfo;
|
||||
|
@@ -32,4 +32,36 @@
|
||||
#define cpuid(fn, eax, ebx, ecx, edx) \
|
||||
asm("cpuid" : "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx) : "0"(fn))
|
||||
|
||||
#define _declare_cpuid(reg) \
|
||||
static inline unsigned int cpuid_##reg(unsigned int fn) \
|
||||
{ \
|
||||
unsigned int eax, ebx, ecx, edx; \
|
||||
cpuid(fn, eax, ebx, ecx, edx); \
|
||||
return reg; \
|
||||
}
|
||||
|
||||
_declare_cpuid(eax)
|
||||
_declare_cpuid(ebx)
|
||||
_declare_cpuid(ecx)
|
||||
_declare_cpuid(edx)
|
||||
|
||||
#undef _declare_cpuid
|
||||
|
||||
static inline unsigned int cpuid_max(void)
|
||||
{
|
||||
return cpuid_eax(0);
|
||||
}
|
||||
|
||||
static inline unsigned int cpuid_family(void)
|
||||
{
|
||||
const unsigned int eax = cpuid_eax(1);
|
||||
return (eax & 0xff00000) >> (20 - 4) | (eax & 0xf00) >> 8;
|
||||
}
|
||||
|
||||
static inline unsigned int cpuid_model(void)
|
||||
{
|
||||
const unsigned int eax = cpuid_eax(1);
|
||||
return (eax & 0xf0000) >> (16 - 4) | (eax & 0xf0) >> 4;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -72,8 +72,7 @@ int pci_write_long(struct pci_dev *dev, int pos, u32 data)
|
||||
|
||||
struct pci_access *pci_alloc(void)
|
||||
{
|
||||
struct pci_access *pacc = malloc(sizeof(*pacc));
|
||||
return pacc;
|
||||
return malloc(sizeof(struct pci_access));
|
||||
}
|
||||
|
||||
void pci_init(struct pci_access *pacc)
|
||||
@@ -179,6 +178,7 @@ static struct pci_dev *pci_scan_single_bus(struct pci_dev *dev, uint8_t bus)
|
||||
dev->func = func;
|
||||
dev->vendor_id = val & 0xffff;
|
||||
dev->device_id = (uint16_t)(val >> 16);
|
||||
dev->device_class = pci_read_config16(PCI_DEV(bus, slot, func), PCI_CLASS_DEVICE);
|
||||
dev->next = 0;
|
||||
|
||||
hdr = pci_read_config8(PCI_DEV(bus, slot, func),
|
||||
|
@@ -554,6 +554,7 @@ source "src/device/Kconfig"
|
||||
menu "Generic Drivers"
|
||||
source "src/drivers/*/Kconfig"
|
||||
source "src/drivers/*/*/Kconfig"
|
||||
source "src/drivers/*/*/*/Kconfig"
|
||||
source "src/commonlib/storage/Kconfig"
|
||||
endmenu
|
||||
|
||||
|
@@ -408,7 +408,7 @@ void acpigen_write_processor_cnot(const unsigned int number_of_cores)
|
||||
* len is region length.
|
||||
* OperationRegion(regionname, regionspace, regionoffset, regionlength)
|
||||
*/
|
||||
void acpigen_write_opregion(struct opregion *opreg)
|
||||
void acpigen_write_opregion(const struct opregion *opreg)
|
||||
{
|
||||
/* OpregionOp */
|
||||
acpigen_emit_ext_op(OPREGION_OP);
|
||||
@@ -505,6 +505,12 @@ static void acpigen_write_field_name(const char *name, uint32_t size)
|
||||
acpigen_write_field_length(size);
|
||||
}
|
||||
|
||||
static void acpigen_write_field_reserved(uint32_t size)
|
||||
{
|
||||
acpigen_emit_byte(0);
|
||||
acpigen_write_field_length(size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate ACPI AML code for Field
|
||||
* Arg0: region name
|
||||
@@ -515,6 +521,7 @@ static void acpigen_write_field_name(const char *name, uint32_t size)
|
||||
* struct fieldlist l[] = {
|
||||
* FIELDLIST_OFFSET(0x84),
|
||||
* FIELDLIST_NAMESTR("PMCS", 2),
|
||||
* FIELDLIST_RESERVED(6),
|
||||
* };
|
||||
* acpigen_write_field("UART", l, ARRAY_SIZE(l), FIELD_ANYACC | FIELD_NOLOCK |
|
||||
* FIELD_PRESERVE);
|
||||
@@ -522,7 +529,8 @@ static void acpigen_write_field_name(const char *name, uint32_t size)
|
||||
* Field (UART, AnyAcc, NoLock, Preserve)
|
||||
* {
|
||||
* Offset (0x84),
|
||||
* PMCS, 2
|
||||
* PMCS, 2,
|
||||
* , 6,
|
||||
* }
|
||||
*/
|
||||
void acpigen_write_field(const char *name, const struct fieldlist *l, size_t count,
|
||||
@@ -546,6 +554,10 @@ void acpigen_write_field(const char *name, const struct fieldlist *l, size_t cou
|
||||
acpigen_write_field_name(l[i].name, l[i].bits);
|
||||
current_bit_pos += l[i].bits;
|
||||
break;
|
||||
case RESERVED:
|
||||
acpigen_write_field_reserved(l[i].bits);
|
||||
current_bit_pos += l[i].bits;
|
||||
break;
|
||||
case OFFSET:
|
||||
acpigen_write_field_offset(l[i].bits, current_bit_pos);
|
||||
current_bit_pos = l[i].bits;
|
||||
@@ -1231,6 +1243,22 @@ void acpigen_write_store_op_to_namestr(uint8_t src, const char *dst)
|
||||
acpigen_emit_namestring(dst);
|
||||
}
|
||||
|
||||
/* Store (src, "namestr") */
|
||||
void acpigen_write_store_int_to_namestr(uint64_t src, const char *dst)
|
||||
{
|
||||
acpigen_write_store();
|
||||
acpigen_write_integer(src);
|
||||
acpigen_emit_namestring(dst);
|
||||
}
|
||||
|
||||
/* Store (src, dst) */
|
||||
void acpigen_write_store_int_to_op(uint64_t src, uint8_t dst)
|
||||
{
|
||||
acpigen_write_store();
|
||||
acpigen_write_integer(src);
|
||||
acpigen_emit_byte(dst);
|
||||
}
|
||||
|
||||
/* Or (arg1, arg2, res) */
|
||||
void acpigen_write_or(uint8_t arg1, uint8_t arg2, uint8_t res)
|
||||
{
|
||||
@@ -1353,6 +1381,14 @@ void acpigen_write_else(void)
|
||||
acpigen_write_len_f();
|
||||
}
|
||||
|
||||
void acpigen_write_shiftleft_op_int(uint8_t src_result, uint64_t count)
|
||||
{
|
||||
acpigen_emit_byte(SHIFT_LEFT_OP);
|
||||
acpigen_emit_byte(src_result);
|
||||
acpigen_write_integer(count);
|
||||
acpigen_emit_byte(ZERO_OP);
|
||||
}
|
||||
|
||||
void acpigen_write_to_buffer(uint8_t src, uint8_t dst)
|
||||
{
|
||||
acpigen_emit_byte(TO_BUFFER_OP);
|
||||
@@ -1829,7 +1865,7 @@ int __weak acpigen_soc_clear_tx_gpio(unsigned int gpio_num)
|
||||
*
|
||||
* Returns 0 on success and -1 on error.
|
||||
*/
|
||||
int acpigen_enable_tx_gpio(struct acpi_gpio *gpio)
|
||||
int acpigen_enable_tx_gpio(const struct acpi_gpio *gpio)
|
||||
{
|
||||
if (gpio->active_low)
|
||||
return acpigen_soc_clear_tx_gpio(gpio->pins[0]);
|
||||
@@ -1837,7 +1873,7 @@ int acpigen_enable_tx_gpio(struct acpi_gpio *gpio)
|
||||
return acpigen_soc_set_tx_gpio(gpio->pins[0]);
|
||||
}
|
||||
|
||||
int acpigen_disable_tx_gpio(struct acpi_gpio *gpio)
|
||||
int acpigen_disable_tx_gpio(const struct acpi_gpio *gpio)
|
||||
{
|
||||
if (gpio->active_low)
|
||||
return acpigen_soc_set_tx_gpio(gpio->pins[0]);
|
||||
@@ -1845,7 +1881,7 @@ int acpigen_disable_tx_gpio(struct acpi_gpio *gpio)
|
||||
return acpigen_soc_clear_tx_gpio(gpio->pins[0]);
|
||||
}
|
||||
|
||||
void acpigen_get_rx_gpio(struct acpi_gpio *gpio)
|
||||
void acpigen_get_rx_gpio(const struct acpi_gpio *gpio)
|
||||
{
|
||||
acpigen_soc_read_rx_gpio(gpio->pins[0]);
|
||||
|
||||
@@ -1853,7 +1889,7 @@ void acpigen_get_rx_gpio(struct acpi_gpio *gpio)
|
||||
acpigen_write_xor(LOCAL0_OP, 1, LOCAL0_OP);
|
||||
}
|
||||
|
||||
void acpigen_get_tx_gpio(struct acpi_gpio *gpio)
|
||||
void acpigen_get_tx_gpio(const struct acpi_gpio *gpio)
|
||||
{
|
||||
acpigen_soc_get_tx_gpio(gpio->pins[0]);
|
||||
|
||||
|
@@ -7,28 +7,27 @@
|
||||
|
||||
#define ACPI_DSM_I2C_HID_UUID "3CDFF6F7-4267-4555-AD05-B30A3D8938DE"
|
||||
|
||||
/* I2C HID currently supports revision 1 only, for which, only 1 additional
|
||||
* function is supported. Thus, the query function should return 0x3:
|
||||
* bit 0 = additional function supported
|
||||
* bit 1 = function with index 1 supported
|
||||
* All other revisions do not support additional functions and hence return 0
|
||||
*/
|
||||
|
||||
static void i2c_hid_func0_cb(void *arg)
|
||||
{
|
||||
/* ToInteger (Arg1, Local2) */
|
||||
acpigen_write_to_integer(ARG1_OP, LOCAL2_OP);
|
||||
/* If (LEqual (Local2, 0x0)) */
|
||||
acpigen_write_if_lequal_op_int(LOCAL2_OP, 0x0);
|
||||
/* Return (Buffer (One) { 0x1f }) */
|
||||
acpigen_write_return_singleton_buffer(0x1f);
|
||||
/* If (LEqual (Local2, 0x1)) */
|
||||
acpigen_write_if_lequal_op_int(LOCAL2_OP, 0x1);
|
||||
/* Return (Buffer (One) { 0x3 }) */
|
||||
acpigen_write_return_singleton_buffer(0x3);
|
||||
acpigen_pop_len(); /* Pop : If */
|
||||
/* Else */
|
||||
acpigen_write_else();
|
||||
/* If (LEqual (Local2, 0x1)) */
|
||||
acpigen_write_if_lequal_op_int(LOCAL2_OP, 0x1);
|
||||
/* Return (Buffer (One) { 0x3f }) */
|
||||
acpigen_write_return_singleton_buffer(0x3f);
|
||||
acpigen_pop_len(); /* Pop : If */
|
||||
/* Else */
|
||||
acpigen_write_else();
|
||||
/* Return (Buffer (One) { 0x0 }) */
|
||||
acpigen_write_return_singleton_buffer(0x0);
|
||||
acpigen_pop_len(); /* Pop : Else */
|
||||
acpigen_pop_len(); /* Pop : Else */
|
||||
}
|
||||
|
||||
static void i2c_hid_func1_cb(void *arg)
|
||||
|
@@ -71,7 +71,7 @@ static void add_device_ref(struct acpi_dp *dsd,
|
||||
const char *path;
|
||||
char *fresh;
|
||||
|
||||
if (!dev)
|
||||
if (!dev || !dev->enabled)
|
||||
return;
|
||||
|
||||
/*
|
||||
|
@@ -1019,33 +1019,72 @@ struct acpi_dp *acpi_dp_add_integer_array(struct acpi_dp *dp, const char *name,
|
||||
return dp_array;
|
||||
}
|
||||
|
||||
struct acpi_dp *acpi_dp_add_gpio_array(struct acpi_dp *dp, const char *name,
|
||||
const struct acpi_gpio_res_params *params,
|
||||
size_t param_count)
|
||||
{
|
||||
struct acpi_dp *gpio;
|
||||
uint32_t i;
|
||||
|
||||
if (!dp || !param_count)
|
||||
return NULL;
|
||||
|
||||
gpio = acpi_dp_new_table(name);
|
||||
if (!gpio)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* Generate ACPI identifiers as follows:
|
||||
* Package () {
|
||||
* name, // e.g. cs-gpios
|
||||
* Package() {
|
||||
* ref, index, pin, active_low, // GPIO-0 (params[0])
|
||||
* ref, index, pin, active_low, // GPIO-1 (params[1])
|
||||
* ...
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
for (i = 0; i < param_count; i++, params++) {
|
||||
/*
|
||||
* If refs is NULL, leave a hole in the gpio array. This can be used in
|
||||
* conditions where some controllers use both GPIOs and native signals.
|
||||
*/
|
||||
if (!params->ref) {
|
||||
acpi_dp_add_integer(gpio, NULL, 0);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* The device that has _CRS containing GpioIO()/GpioInt() */
|
||||
acpi_dp_add_reference(gpio, NULL, params->ref);
|
||||
|
||||
/* Index of the GPIO resource in _CRS starting from zero */
|
||||
acpi_dp_add_integer(gpio, NULL, params->index);
|
||||
|
||||
/* Pin in the GPIO resource, typically zero */
|
||||
acpi_dp_add_integer(gpio, NULL, params->pin);
|
||||
|
||||
/* Set if pin is active low */
|
||||
acpi_dp_add_integer(gpio, NULL, params->active_low);
|
||||
}
|
||||
acpi_dp_add_array(dp, gpio);
|
||||
|
||||
return gpio;
|
||||
|
||||
}
|
||||
|
||||
|
||||
struct acpi_dp *acpi_dp_add_gpio(struct acpi_dp *dp, const char *name,
|
||||
const char *ref, int index, int pin,
|
||||
int active_low)
|
||||
{
|
||||
if (!dp)
|
||||
return NULL;
|
||||
struct acpi_gpio_res_params param = {
|
||||
.ref = ref,
|
||||
.index = index,
|
||||
.pin = pin,
|
||||
.active_low = active_low,
|
||||
};
|
||||
|
||||
struct acpi_dp *gpio = acpi_dp_new_table(name);
|
||||
|
||||
if (!gpio)
|
||||
return NULL;
|
||||
|
||||
/* The device that has _CRS containing GpioIO()/GpioInt() */
|
||||
acpi_dp_add_reference(gpio, NULL, ref);
|
||||
|
||||
/* Index of the GPIO resource in _CRS starting from zero */
|
||||
acpi_dp_add_integer(gpio, NULL, index);
|
||||
|
||||
/* Pin in the GPIO resource, typically zero */
|
||||
acpi_dp_add_integer(gpio, NULL, pin);
|
||||
|
||||
/* Set if pin is active low */
|
||||
acpi_dp_add_integer(gpio, NULL, active_low);
|
||||
|
||||
acpi_dp_add_array(dp, gpio);
|
||||
|
||||
return gpio;
|
||||
return acpi_dp_add_gpio_array(dp, name, ¶m, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@@ -31,6 +31,7 @@ bootblock-y += id.S
|
||||
$(call src-to-obj,decompressor,$(dir)/id.S): $(obj)/build.h
|
||||
$(call src-to-obj,bootblock,$(dir)/id.S): $(obj)/build.h
|
||||
|
||||
decompressor-$(CONFIG_ARM64_USE_ARCH_TIMER) += arch_timer.c
|
||||
bootblock-$(CONFIG_ARM64_USE_ARCH_TIMER) += arch_timer.c
|
||||
bootblock-y += transition.c transition_asm.S
|
||||
|
||||
|
@@ -478,6 +478,51 @@ unsigned int __weak smbios_processor_family(struct cpuid_result res)
|
||||
return (res.eax > 0) ? 0x0c : 0x6;
|
||||
}
|
||||
|
||||
unsigned int __weak smbios_cache_error_correction_type(u8 level)
|
||||
{
|
||||
return SMBIOS_CACHE_ERROR_CORRECTION_UNKNOWN;
|
||||
}
|
||||
|
||||
unsigned int __weak smbios_cache_sram_type(void)
|
||||
{
|
||||
return SMBIOS_CACHE_SRAM_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
unsigned int __weak smbios_cache_conf_operation_mode(u8 level)
|
||||
{
|
||||
return SMBIOS_CACHE_OP_MODE_UNKNOWN; /* Unknown */
|
||||
}
|
||||
|
||||
static size_t get_number_of_caches(struct cpuid_result res_deterministic_cache)
|
||||
{
|
||||
size_t max_logical_cpus_sharing_cache = 0;
|
||||
size_t number_of_cpus_per_package = 0;
|
||||
size_t max_logical_cpus_per_package = 0;
|
||||
struct cpuid_result res;
|
||||
|
||||
if (!cpu_have_cpuid())
|
||||
return 1;
|
||||
|
||||
res = cpuid(1);
|
||||
|
||||
max_logical_cpus_per_package = (res.ebx >> 16) & 0xff;
|
||||
|
||||
max_logical_cpus_sharing_cache = ((res_deterministic_cache.eax >> 14) & 0xfff) + 1;
|
||||
|
||||
/* Check if it's last level cache */
|
||||
if (max_logical_cpus_sharing_cache == max_logical_cpus_per_package)
|
||||
return 1;
|
||||
|
||||
if (cpuid_get_max_func() >= 0xb) {
|
||||
res = cpuid_ext(0xb, 1);
|
||||
number_of_cpus_per_package = res.ebx & 0xff;
|
||||
} else {
|
||||
number_of_cpus_per_package = max_logical_cpus_per_package;
|
||||
}
|
||||
|
||||
return number_of_cpus_per_package / max_logical_cpus_sharing_cache;
|
||||
}
|
||||
|
||||
static int smbios_write_type1(unsigned long *current, int handle)
|
||||
{
|
||||
struct smbios_type1 *t = (struct smbios_type1 *)*current;
|
||||
@@ -662,7 +707,6 @@ static int smbios_write_type7(unsigned long *current,
|
||||
{
|
||||
struct smbios_type7 *t = (struct smbios_type7 *)*current;
|
||||
int len = sizeof(struct smbios_type7);
|
||||
static unsigned int cnt = 0;
|
||||
char buf[8];
|
||||
|
||||
memset(t, 0, sizeof(struct smbios_type7));
|
||||
@@ -670,13 +714,13 @@ static int smbios_write_type7(unsigned long *current,
|
||||
t->handle = handle;
|
||||
t->length = len - 2;
|
||||
|
||||
snprintf(buf, sizeof(buf), "CACHE%x", cnt++);
|
||||
snprintf(buf, sizeof(buf), "CACHE%x", level);
|
||||
t->socket_designation = smbios_add_string(t->eos, buf);
|
||||
|
||||
t->cache_configuration = SMBIOS_CACHE_CONF_LEVEL(level) |
|
||||
SMBIOS_CACHE_CONF_LOCATION(0) | /* Internal */
|
||||
SMBIOS_CACHE_CONF_ENABLED(1) | /* Enabled */
|
||||
SMBIOS_CACHE_CONF_OPERATION_MODE(3); /* Unknown */
|
||||
SMBIOS_CACHE_CONF_OPERATION_MODE(smbios_cache_conf_operation_mode(level));
|
||||
|
||||
if (max_cache_size < (SMBIOS_CACHE_SIZE_MASK * KiB)) {
|
||||
t->max_cache_size = max_cache_size / KiB;
|
||||
@@ -716,7 +760,7 @@ static int smbios_write_type7(unsigned long *current,
|
||||
t->supported_sram_type = sram_type;
|
||||
t->current_sram_type = sram_type;
|
||||
t->cache_speed = 0; /* Unknown */
|
||||
t->error_correction_type = SMBIOS_CACHE_ERROR_CORRECTION_UNKNOWN;
|
||||
t->error_correction_type = smbios_cache_error_correction_type(level);
|
||||
t->system_cache_type = type;
|
||||
|
||||
len = t->length + smbios_string_table_len(t->eos);
|
||||
@@ -811,7 +855,8 @@ static int smbios_write_type7_cache_parameters(unsigned long *current,
|
||||
const size_t partitions = CPUID_CACHE_PHYS_LINE(res) + 1;
|
||||
const size_t cache_line_size = CPUID_CACHE_COHER_LINE(res) + 1;
|
||||
const size_t number_of_sets = CPUID_CACHE_NO_OF_SETS(res) + 1;
|
||||
const size_t cache_size = assoc * partitions * cache_line_size * number_of_sets;
|
||||
const size_t cache_size = assoc * partitions * cache_line_size * number_of_sets
|
||||
* get_number_of_caches(res);
|
||||
|
||||
if (!cache_type)
|
||||
/* No more caches in the system */
|
||||
@@ -840,7 +885,7 @@ static int smbios_write_type7_cache_parameters(unsigned long *current,
|
||||
const int h = (*handle)++;
|
||||
|
||||
update_max(len, *max_struct_size, smbios_write_type7(current, h,
|
||||
level, SMBIOS_CACHE_SRAM_TYPE_UNKNOWN, associativity,
|
||||
level, smbios_cache_sram_type(), associativity,
|
||||
type, cache_size, cache_size));
|
||||
|
||||
if (type4) {
|
||||
|
@@ -68,6 +68,7 @@
|
||||
#define CBMEM_ID_ROM3 0x524f4d33
|
||||
#define CBMEM_ID_FMAP 0x464d4150
|
||||
#define CBMEM_ID_FSP_LOGO 0x4c4f474f
|
||||
#define CBMEM_ID_SMM_COMBUFFER 0x53534d32
|
||||
|
||||
#define CBMEM_ID_TO_NAME_TABLE \
|
||||
{ CBMEM_ID_ACPI, "ACPI " }, \
|
||||
|
@@ -80,6 +80,7 @@ enum {
|
||||
LB_TAG_TCPA_LOG = 0x0036,
|
||||
LB_TAG_FMAP = 0x0037,
|
||||
LB_TAG_PLATFORM_BLOB_VERSION = 0x0038,
|
||||
LB_TAG_SMMSTOREV2 = 0x0039,
|
||||
LB_TAG_CMOS_OPTION_TABLE = 0x00c8,
|
||||
LB_TAG_OPTION = 0x00c9,
|
||||
LB_TAG_OPTION_ENUM = 0x00ca,
|
||||
@@ -484,4 +485,20 @@ struct cmos_checksum {
|
||||
#define CHECKSUM_PCBIOS 1
|
||||
};
|
||||
|
||||
/* SMMSTOREv2 record
|
||||
* This record contains information to use SMMSTOREv2.
|
||||
*/
|
||||
|
||||
struct lb_smmstorev2 {
|
||||
uint32_t tag;
|
||||
uint32_t size;
|
||||
uint32_t num_blocks; /* Number of writeable blocks in SMM */
|
||||
uint32_t block_size; /* Size of a block in byte. Default: 64 KiB */
|
||||
uint32_t mmap_addr; /* MMIO address of the store for read only access */
|
||||
uint32_t com_buffer; /* Physical address of the communication buffer */
|
||||
uint32_t com_buffer_size; /* Size of the communication buffer in bytes */
|
||||
uint8_t apm_cmd; /* The command byte to write to the APM I/O port */
|
||||
uint8_t unused[3]; /* Set to zero */
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -8,40 +8,25 @@
|
||||
#include <option.h>
|
||||
#include <version.h>
|
||||
|
||||
/* Mutable console log level only allowed when RAM comes online. */
|
||||
#define CONSOLE_LEVEL_CONST !ENV_STAGE_HAS_DATA_SECTION
|
||||
#define FIRST_CONSOLE (ENV_BOOTBLOCK || (CONFIG(NO_BOOTBLOCK_CONSOLE) && ENV_ROMSTAGE))
|
||||
|
||||
static int console_inited;
|
||||
static int console_loglevel = CONFIG_DEFAULT_CONSOLE_LOGLEVEL;
|
||||
static int console_loglevel;
|
||||
|
||||
static inline int get_log_level(void)
|
||||
{
|
||||
if (console_inited == 0)
|
||||
return -1;
|
||||
if (CONSOLE_LEVEL_CONST)
|
||||
return get_console_loglevel();
|
||||
|
||||
return console_loglevel;
|
||||
}
|
||||
|
||||
static inline void set_log_level(int new_level)
|
||||
{
|
||||
if (CONSOLE_LEVEL_CONST)
|
||||
return;
|
||||
|
||||
console_loglevel = new_level;
|
||||
}
|
||||
|
||||
static void init_log_level(void)
|
||||
{
|
||||
int debug_level = get_console_loglevel();
|
||||
console_loglevel = get_console_loglevel();
|
||||
|
||||
if (CONSOLE_LEVEL_CONST)
|
||||
return;
|
||||
|
||||
get_option(&debug_level, "debug_level");
|
||||
|
||||
set_log_level(debug_level);
|
||||
if (!FIRST_CONSOLE)
|
||||
get_option(&console_loglevel, "debug_level");
|
||||
}
|
||||
|
||||
int console_log_level(int msg_level)
|
||||
|
@@ -19,10 +19,15 @@ config SET_IA32_FC_LOCK_BIT
|
||||
However, leaving the lock bit unset will break Windows' detection of
|
||||
VMX support and built-in virtualization features like Hyper-V.
|
||||
|
||||
config CPU_INTEL_COMMON_TIMEBASE
|
||||
bool
|
||||
config SET_MSR_AESNI_LOCK_BIT
|
||||
bool "Lock the AES-NI enablement state"
|
||||
default y
|
||||
help
|
||||
This config sets the AES-NI lock bit, if available, to prevent any
|
||||
further change of AES-NI enablement. This may be disabled for e.g.
|
||||
testing or debugging.
|
||||
|
||||
config CPU_INTEL_COMMON_HYPERTHREADING
|
||||
config CPU_INTEL_COMMON_TIMEBASE
|
||||
bool
|
||||
|
||||
endif
|
||||
|
@@ -1,5 +1,5 @@
|
||||
ramstage-$(CONFIG_CPU_INTEL_COMMON) += common_init.c
|
||||
ramstage-$(CONFIG_CPU_INTEL_COMMON_HYPERTHREADING) += hyperthreading.c
|
||||
ramstage-$(CONFIG_CPU_INTEL_COMMON) += hyperthreading.c
|
||||
|
||||
ifeq ($(CONFIG_CPU_INTEL_COMMON_TIMEBASE),y)
|
||||
bootblock-y += fsb.c
|
||||
|
@@ -27,4 +27,22 @@ bool intel_ht_supported(void);
|
||||
*/
|
||||
bool intel_ht_sibling(void);
|
||||
|
||||
/*
|
||||
* Lock AES-NI feature (MSR_FEATURE_CONFIG) to prevent unintended changes
|
||||
* to the enablement state as suggested in Intel document 325384-070US.
|
||||
*/
|
||||
void set_aesni_lock(void);
|
||||
|
||||
/* Enable local CPU APIC TPR (Task Priority Register) updates */
|
||||
void enable_lapic_tpr(void);
|
||||
|
||||
/* Enable DCA (Direct Cache Access) */
|
||||
void configure_dca_cap(void);
|
||||
|
||||
/*
|
||||
* Set EPB (Energy Performance Bias)
|
||||
* Possible values are 0 (performance) to 15 (powersave).
|
||||
*/
|
||||
void set_energy_perf_bias(u8 policy);
|
||||
|
||||
#endif
|
||||
|
@@ -3,9 +3,13 @@
|
||||
#include <acpi/acpigen.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <console/console.h>
|
||||
#include <cpu/intel/msr.h>
|
||||
#include <cpu/x86/lapic.h>
|
||||
#include <cpu/x86/msr.h>
|
||||
#include "common.h"
|
||||
|
||||
#define CPUID_6_ECX_EPB (1 << 3)
|
||||
|
||||
void set_vmx_and_lock(void)
|
||||
{
|
||||
set_feature_ctrl_vmx();
|
||||
@@ -235,11 +239,23 @@ void cpu_init_cppc_config(struct cppc_config *config, u32 version)
|
||||
if (version >= 2) {
|
||||
/* Autonomous Selection Enable is populated below */
|
||||
|
||||
/* Autonomous Activity Window Register */
|
||||
config->regs[CPPC_AUTO_ACTIVITY_WINDOW] = unsupported;
|
||||
msr.addrl = IA32_HWP_REQUEST;
|
||||
|
||||
/* Energy Performance Preference Register */
|
||||
config->regs[CPPC_PERF_PREF] = unsupported;
|
||||
/*
|
||||
* Autonomous Activity Window Register
|
||||
* ResourceTemplate(){Register(FFixedHW, 0x0a, 0x20, 0x774, 0x04,)},
|
||||
*/
|
||||
msr.bit_width = 10;
|
||||
msr.bit_offset = 32;
|
||||
config->regs[CPPC_AUTO_ACTIVITY_WINDOW] = msr;
|
||||
|
||||
/*
|
||||
* Autonomous Energy Performance Preference Register
|
||||
* ResourceTemplate(){Register(FFixedHW, 0x08, 0x18, 0x774, 0x04,)},
|
||||
*/
|
||||
msr.bit_width = 8;
|
||||
msr.bit_offset = 24;
|
||||
config->regs[CPPC_PERF_PREF] = msr;
|
||||
|
||||
/* Reference Performance */
|
||||
config->regs[CPPC_REF_PERF] = unsupported;
|
||||
@@ -264,3 +280,46 @@ void cpu_init_cppc_config(struct cppc_config *config, u32 version)
|
||||
config->regs[CPPC_AUTO_SELECT] = msr;
|
||||
}
|
||||
}
|
||||
|
||||
void set_aesni_lock(void)
|
||||
{
|
||||
msr_t msr;
|
||||
|
||||
if (!CONFIG(SET_MSR_AESNI_LOCK_BIT))
|
||||
return;
|
||||
|
||||
if (!(cpu_get_feature_flags_ecx() & CPUID_AES))
|
||||
return;
|
||||
|
||||
/* Only run once per core as specified in the MSR datasheet */
|
||||
if (intel_ht_sibling())
|
||||
return;
|
||||
|
||||
msr = rdmsr(MSR_FEATURE_CONFIG);
|
||||
if (msr.lo & AESNI_LOCK)
|
||||
return;
|
||||
|
||||
msr_set(MSR_FEATURE_CONFIG, AESNI_LOCK);
|
||||
}
|
||||
|
||||
void enable_lapic_tpr(void)
|
||||
{
|
||||
msr_unset(MSR_PIC_MSG_CONTROL, TPR_UPDATES_DISABLE);
|
||||
}
|
||||
|
||||
void configure_dca_cap(void)
|
||||
{
|
||||
if (cpu_get_feature_flags_ecx() & CPUID_DCA)
|
||||
msr_set(IA32_PLATFORM_DCA_CAP, DCA_TYPE0_EN);
|
||||
}
|
||||
|
||||
void set_energy_perf_bias(u8 policy)
|
||||
{
|
||||
u8 epb = policy & ENERGY_POLICY_MASK;
|
||||
|
||||
if (!(cpuid_ecx(6) & CPUID_6_ECX_EPB))
|
||||
return;
|
||||
|
||||
msr_unset_and_set(IA32_ENERGY_PERF_BIAS, ENERGY_POLICY_MASK, epb);
|
||||
printk(BIOS_DEBUG, "cpu: energy policy set to %u\n", epb);
|
||||
}
|
||||
|
@@ -65,50 +65,6 @@ static void generate_cstate_entries(acpi_cstate_t *cstates,
|
||||
acpigen_pop_len();
|
||||
}
|
||||
|
||||
static void generate_C_state_entries(void)
|
||||
{
|
||||
struct cpu_info *info;
|
||||
struct cpu_driver *cpu;
|
||||
struct device *lapic;
|
||||
struct cpu_intel_haswell_config *conf = NULL;
|
||||
|
||||
/* Find the SpeedStep CPU in the device tree using magic APIC ID */
|
||||
lapic = dev_find_lapic(SPEEDSTEP_APIC_MAGIC);
|
||||
if (!lapic)
|
||||
return;
|
||||
conf = lapic->chip_info;
|
||||
if (!conf)
|
||||
return;
|
||||
|
||||
/* Find CPU map of supported C-states */
|
||||
info = cpu_info();
|
||||
if (!info)
|
||||
return;
|
||||
cpu = find_cpu_driver(info->cpu);
|
||||
if (!cpu || !cpu->cstates)
|
||||
return;
|
||||
|
||||
acpigen_emit_byte(0x14); /* MethodOp */
|
||||
acpigen_write_len_f(); /* PkgLength */
|
||||
acpigen_emit_namestring("_CST");
|
||||
acpigen_emit_byte(0x00); /* No Arguments */
|
||||
|
||||
/* If running on AC power */
|
||||
acpigen_emit_byte(0xa0); /* IfOp */
|
||||
acpigen_write_len_f(); /* PkgLength */
|
||||
acpigen_emit_namestring("PWRS");
|
||||
acpigen_emit_byte(0xa4); /* ReturnOp */
|
||||
generate_cstate_entries(cpu->cstates, conf->c1_acpower,
|
||||
conf->c2_acpower, conf->c3_acpower);
|
||||
acpigen_pop_len();
|
||||
|
||||
/* Else on battery power */
|
||||
acpigen_emit_byte(0xa4); /* ReturnOp */
|
||||
generate_cstate_entries(cpu->cstates, conf->c1_battery,
|
||||
conf->c2_battery, conf->c3_battery);
|
||||
acpigen_pop_len();
|
||||
}
|
||||
|
||||
static acpi_tstate_t tss_table_fine[] = {
|
||||
{ 100, 1000, 0, 0x00, 0 },
|
||||
{ 94, 940, 0, 0x1f, 0 },
|
||||
@@ -161,6 +117,50 @@ static void generate_T_state_entries(int core, int cores_per_package)
|
||||
ARRAY_SIZE(tss_table_coarse), tss_table_coarse);
|
||||
}
|
||||
|
||||
static void generate_C_state_entries(void)
|
||||
{
|
||||
struct cpu_info *info;
|
||||
struct cpu_driver *cpu;
|
||||
struct device *lapic;
|
||||
struct cpu_intel_haswell_config *conf = NULL;
|
||||
|
||||
/* Find the SpeedStep CPU in the device tree using magic APIC ID */
|
||||
lapic = dev_find_lapic(SPEEDSTEP_APIC_MAGIC);
|
||||
if (!lapic)
|
||||
return;
|
||||
conf = lapic->chip_info;
|
||||
if (!conf)
|
||||
return;
|
||||
|
||||
/* Find CPU map of supported C-states */
|
||||
info = cpu_info();
|
||||
if (!info)
|
||||
return;
|
||||
cpu = find_cpu_driver(info->cpu);
|
||||
if (!cpu || !cpu->cstates)
|
||||
return;
|
||||
|
||||
acpigen_emit_byte(0x14); /* MethodOp */
|
||||
acpigen_write_len_f(); /* PkgLength */
|
||||
acpigen_emit_namestring("_CST");
|
||||
acpigen_emit_byte(0x00); /* No Arguments */
|
||||
|
||||
/* If running on AC power */
|
||||
acpigen_emit_byte(0xa0); /* IfOp */
|
||||
acpigen_write_len_f(); /* PkgLength */
|
||||
acpigen_emit_namestring("PWRS");
|
||||
acpigen_emit_byte(0xa4); /* ReturnOp */
|
||||
generate_cstate_entries(cpu->cstates, conf->c1_acpower,
|
||||
conf->c2_acpower, conf->c3_acpower);
|
||||
acpigen_pop_len();
|
||||
|
||||
/* Else on battery power */
|
||||
acpigen_emit_byte(0xa4); /* ReturnOp */
|
||||
generate_cstate_entries(cpu->cstates, conf->c1_battery,
|
||||
conf->c2_battery, conf->c3_battery);
|
||||
acpigen_pop_len();
|
||||
}
|
||||
|
||||
static int calculate_power(int tdp, int p1_ratio, int ratio)
|
||||
{
|
||||
u32 m;
|
||||
@@ -307,19 +307,19 @@ void generate_cpu_entries(const struct device *device)
|
||||
|
||||
/* Generate processor \_SB.CPUx */
|
||||
acpigen_write_processor(
|
||||
(cpuID-1)*cores_per_package+coreID-1,
|
||||
(cpuID - 1) * cores_per_package+coreID - 1,
|
||||
pcontrol_blk, plen);
|
||||
|
||||
/* Generate P-state tables */
|
||||
generate_P_state_entries(
|
||||
coreID-1, cores_per_package);
|
||||
coreID - 1, cores_per_package);
|
||||
|
||||
/* Generate C-state tables */
|
||||
generate_C_state_entries();
|
||||
|
||||
/* Generate T-state tables */
|
||||
generate_T_state_entries(
|
||||
cpuID-1, cores_per_package);
|
||||
cpuID - 1, cores_per_package);
|
||||
|
||||
acpigen_pop_len();
|
||||
}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <types.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <cpu/x86/msr.h>
|
||||
#include "haswell.h"
|
||||
@@ -7,5 +8,5 @@
|
||||
void intel_cpu_haswell_finalize_smm(void)
|
||||
{
|
||||
/* Lock memory configuration to protect SMM */
|
||||
msr_set_bit(MSR_LT_LOCK_MEMORY, 0);
|
||||
msr_set(MSR_LT_LOCK_MEMORY, BIT(0));
|
||||
}
|
||||
|
@@ -28,7 +28,6 @@
|
||||
#define MSR_TEMPERATURE_TARGET 0x1a2
|
||||
#define MSR_LT_LOCK_MEMORY 0x2e7
|
||||
|
||||
#define MSR_PIC_MSG_CONTROL 0x2e
|
||||
#define MSR_PLATFORM_INFO 0xce
|
||||
#define PLATFORM_INFO_SET_TDP (1 << 29)
|
||||
#define MSR_PKG_CST_CONFIG_CONTROL 0xe2
|
||||
|
@@ -207,8 +207,8 @@ int haswell_is_ult(void)
|
||||
return ult;
|
||||
}
|
||||
|
||||
/* The core 100MHz BLCK is disabled in deeper c-states. One needs to calibrate
|
||||
* the 100MHz BCLCK against the 24MHz BLCK to restore the clocks properly
|
||||
/* The core 100MHz BCLK is disabled in deeper c-states. One needs to calibrate
|
||||
* the 100MHz BCLK against the 24MHz BCLK to restore the clocks properly
|
||||
* when a core is woken up. */
|
||||
static int pcode_ready(void)
|
||||
{
|
||||
@@ -247,7 +247,7 @@ static void calibrate_24mhz_bclk(void)
|
||||
|
||||
err_code = MCHBAR32(BIOS_MAILBOX_INTERFACE) & 0xff;
|
||||
|
||||
printk(BIOS_DEBUG, "PCODE: 24MHz BLCK calibration response: %d\n",
|
||||
printk(BIOS_DEBUG, "PCODE: 24MHz BCLK calibration response: %d\n",
|
||||
err_code);
|
||||
|
||||
/* Read the calibrated value. */
|
||||
@@ -259,7 +259,7 @@ static void calibrate_24mhz_bclk(void)
|
||||
return;
|
||||
}
|
||||
|
||||
printk(BIOS_DEBUG, "PCODE: 24MHz BLCK calibration value: 0x%08x\n",
|
||||
printk(BIOS_DEBUG, "PCODE: 24MHz BCLK calibration value: 0x%08x\n",
|
||||
MCHBAR32(BIOS_MAILBOX_DATA));
|
||||
}
|
||||
|
||||
@@ -577,29 +577,6 @@ static void configure_misc(void)
|
||||
wrmsr(IA32_PACKAGE_THERM_INTERRUPT, msr);
|
||||
}
|
||||
|
||||
static void enable_lapic_tpr(void)
|
||||
{
|
||||
msr_t msr;
|
||||
|
||||
msr = rdmsr(MSR_PIC_MSG_CONTROL);
|
||||
msr.lo &= ~(1 << 10); /* Enable APIC TPR updates */
|
||||
wrmsr(MSR_PIC_MSG_CONTROL, msr);
|
||||
}
|
||||
|
||||
static void configure_dca_cap(void)
|
||||
{
|
||||
uint32_t feature_flag;
|
||||
msr_t msr;
|
||||
|
||||
/* Check feature flag in CPUID.(EAX=1):ECX[18]==1 */
|
||||
feature_flag = cpu_get_feature_flags_ecx();
|
||||
if (feature_flag & CPUID_DCA) {
|
||||
msr = rdmsr(IA32_PLATFORM_DCA_CAP);
|
||||
msr.lo |= 1;
|
||||
wrmsr(IA32_PLATFORM_DCA_CAP, msr);
|
||||
}
|
||||
}
|
||||
|
||||
static void set_max_ratio(void)
|
||||
{
|
||||
msr_t msr, perf_ctl;
|
||||
@@ -622,25 +599,6 @@ static void set_max_ratio(void)
|
||||
((perf_ctl.lo >> 8) & 0xff) * HASWELL_BCLK);
|
||||
}
|
||||
|
||||
static void set_energy_perf_bias(u8 policy)
|
||||
{
|
||||
msr_t msr;
|
||||
int ecx;
|
||||
|
||||
/* Determine if energy efficient policy is supported. */
|
||||
ecx = cpuid_ecx(0x6);
|
||||
if (!(ecx & (1 << 3)))
|
||||
return;
|
||||
|
||||
/* Energy Policy is bits 3:0 */
|
||||
msr = rdmsr(IA32_ENERGY_PERF_BIAS);
|
||||
msr.lo &= ~0xf;
|
||||
msr.lo |= policy & 0xf;
|
||||
wrmsr(IA32_ENERGY_PERF_BIAS, msr);
|
||||
|
||||
printk(BIOS_DEBUG, "CPU: energy policy set to %u\n", policy);
|
||||
}
|
||||
|
||||
static void configure_mca(void)
|
||||
{
|
||||
msr_t msr;
|
||||
|
@@ -156,7 +156,6 @@ static void fill_in_relocation_params(struct smm_relocation_params *params)
|
||||
{
|
||||
uintptr_t tseg_base;
|
||||
size_t tseg_size;
|
||||
|
||||
u32 prmrr_base;
|
||||
u32 prmrr_size;
|
||||
int phys_bits;
|
||||
@@ -197,7 +196,7 @@ static void fill_in_relocation_params(struct smm_relocation_params *params)
|
||||
params->uncore_prmrr_base.lo = prmrr_base;
|
||||
params->uncore_prmrr_base.hi = 0;
|
||||
params->uncore_prmrr_mask.lo = (~(prmrr_size - 1) & rmask) |
|
||||
MTRR_PHYS_MASK_VALID;
|
||||
MTRR_PHYS_MASK_VALID;
|
||||
params->uncore_prmrr_mask.hi = (1 << (39 - 32)) - 1;
|
||||
}
|
||||
|
||||
@@ -282,6 +281,5 @@ void smm_lock(void)
|
||||
* make the SMM registers writable again.
|
||||
*/
|
||||
printk(BIOS_DEBUG, "Locking SMM.\n");
|
||||
pci_write_config8(pcidev_on_root(0, 0), SMRAM,
|
||||
D_LCK | G_SMRAME | C_BASE_SEG);
|
||||
pci_write_config8(pcidev_on_root(0, 0), SMRAM, D_LCK | G_SMRAME | C_BASE_SEG);
|
||||
}
|
||||
|
@@ -1,5 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <types.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <cpu/x86/msr.h>
|
||||
#include <cpu/intel/speedstep.h>
|
||||
@@ -13,12 +14,8 @@
|
||||
void intel_model_2065x_finalize_smm(void)
|
||||
{
|
||||
/* Lock C-State MSR */
|
||||
msr_set_bit(MSR_PKG_CST_CONFIG_CONTROL, 15);
|
||||
|
||||
/* Lock AES-NI only if supported */
|
||||
if (cpuid_ecx(1) & (1 << 25))
|
||||
msr_set_bit(MSR_FEATURE_CONFIG, 0);
|
||||
msr_set(MSR_PKG_CST_CONFIG_CONTROL, BIT(15));
|
||||
|
||||
/* Lock TM interrupts - route thermal events to all processors */
|
||||
msr_set_bit(MSR_MISC_PWR_MGMT, 22);
|
||||
msr_set(MSR_MISC_PWR_MGMT, BIT(22));
|
||||
}
|
||||
|
@@ -15,7 +15,6 @@
|
||||
#define IA32_FERR_CAPABILITY 0x1f1
|
||||
#define FERR_ENABLE (1 << 0)
|
||||
|
||||
#define MSR_PIC_MSG_CONTROL 0x2e
|
||||
#define MSR_PLATFORM_INFO 0xce
|
||||
#define PLATFORM_INFO_SET_TDP (1 << 29)
|
||||
|
||||
|
@@ -148,15 +148,6 @@ static void configure_misc(void)
|
||||
wrmsr(IA32_THERM_INTERRUPT, msr);
|
||||
}
|
||||
|
||||
static void enable_lapic_tpr(void)
|
||||
{
|
||||
msr_t msr;
|
||||
|
||||
msr = rdmsr(MSR_PIC_MSG_CONTROL);
|
||||
msr.lo &= ~(1 << 10); /* Enable APIC TPR updates */
|
||||
wrmsr(MSR_PIC_MSG_CONTROL, msr);
|
||||
}
|
||||
|
||||
static void set_max_ratio(void)
|
||||
{
|
||||
msr_t msr, perf_ctl;
|
||||
@@ -216,6 +207,8 @@ static void model_2065x_init(struct device *cpu)
|
||||
/* Set virtualization based on Kconfig option */
|
||||
set_vmx_and_lock();
|
||||
|
||||
set_aesni_lock();
|
||||
|
||||
/* Configure Enhanced SpeedStep and Thermal Sensors */
|
||||
configure_misc();
|
||||
|
||||
|
@@ -1,5 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <types.h>
|
||||
#include <arch/cpu.h>
|
||||
#include <cpu/x86/msr.h>
|
||||
#include "model_206ax.h"
|
||||
@@ -11,13 +12,9 @@
|
||||
|
||||
void intel_model_206ax_finalize_smm(void)
|
||||
{
|
||||
/* Lock AES-NI only if supported */
|
||||
if (cpuid_ecx(1) & (1 << 25))
|
||||
msr_set_bit(MSR_FEATURE_CONFIG, 0);
|
||||
|
||||
/* Lock TM interrupts - route thermal events to all processors */
|
||||
msr_set_bit(MSR_MISC_PWR_MGMT, 22);
|
||||
msr_set(MSR_MISC_PWR_MGMT, BIT(22));
|
||||
|
||||
/* Lock memory configuration to protect SMM */
|
||||
msr_set_bit(MSR_LT_LOCK_MEMORY, 0);
|
||||
msr_set(MSR_LT_LOCK_MEMORY, BIT(0));
|
||||
}
|
||||
|
@@ -15,7 +15,6 @@
|
||||
#define FLEX_RATIO_EN (1 << 16)
|
||||
#define MSR_TEMPERATURE_TARGET 0x1a2
|
||||
#define MSR_LT_LOCK_MEMORY 0x2e7
|
||||
#define MSR_PIC_MSG_CONTROL 0x2e
|
||||
#define MSR_PLATFORM_INFO 0xce
|
||||
#define PLATFORM_INFO_SET_TDP (1 << 29)
|
||||
|
||||
|
@@ -338,29 +338,6 @@ static void configure_misc(void)
|
||||
wrmsr(IA32_PACKAGE_THERM_INTERRUPT, msr);
|
||||
}
|
||||
|
||||
static void enable_lapic_tpr(void)
|
||||
{
|
||||
msr_t msr;
|
||||
|
||||
msr = rdmsr(MSR_PIC_MSG_CONTROL);
|
||||
msr.lo &= ~(1 << 10); /* Enable APIC TPR updates */
|
||||
wrmsr(MSR_PIC_MSG_CONTROL, msr);
|
||||
}
|
||||
|
||||
static void configure_dca_cap(void)
|
||||
{
|
||||
uint32_t feature_flag;
|
||||
msr_t msr;
|
||||
|
||||
/* Check feature flag in CPUID.(EAX=1):ECX[18]==1 */
|
||||
feature_flag = cpu_get_feature_flags_ecx();
|
||||
if (feature_flag & CPUID_DCA) {
|
||||
msr = rdmsr(IA32_PLATFORM_DCA_CAP);
|
||||
msr.lo |= 1;
|
||||
wrmsr(IA32_PLATFORM_DCA_CAP, msr);
|
||||
}
|
||||
}
|
||||
|
||||
static void set_max_ratio(void)
|
||||
{
|
||||
msr_t msr, perf_ctl;
|
||||
@@ -383,20 +360,6 @@ static void set_max_ratio(void)
|
||||
((perf_ctl.lo >> 8) & 0xff) * SANDYBRIDGE_BCLK);
|
||||
}
|
||||
|
||||
static void set_energy_perf_bias(u8 policy)
|
||||
{
|
||||
msr_t msr;
|
||||
|
||||
/* Energy Policy is bits 3:0 */
|
||||
msr = rdmsr(IA32_ENERGY_PERF_BIAS);
|
||||
msr.lo &= ~0xf;
|
||||
msr.lo |= policy & 0xf;
|
||||
wrmsr(IA32_ENERGY_PERF_BIAS, msr);
|
||||
|
||||
printk(BIOS_DEBUG, "model_x06ax: energy policy set to %u\n",
|
||||
policy);
|
||||
}
|
||||
|
||||
static void configure_mca(void)
|
||||
{
|
||||
msr_t msr;
|
||||
@@ -470,6 +433,8 @@ static void model_206ax_init(struct device *cpu)
|
||||
/* Thermal throttle activation offset */
|
||||
configure_thermal_target();
|
||||
|
||||
set_aesni_lock();
|
||||
|
||||
/* Enable Direct Cache Access */
|
||||
configure_dca_cap();
|
||||
|
||||
|
@@ -4,4 +4,3 @@ config CPU_INTEL_MODEL_F2X
|
||||
select SUPPORT_CPU_UCODE_IN_CBFS
|
||||
select SMM_ASEG
|
||||
select CPU_INTEL_COMMON
|
||||
select CPU_INTEL_COMMON_HYPERTHREADING
|
||||
|
@@ -3,4 +3,3 @@ config CPU_INTEL_MODEL_F3X
|
||||
select ARCH_ALL_STAGES_X86_32
|
||||
select SUPPORT_CPU_UCODE_IN_CBFS
|
||||
select CPU_INTEL_COMMON
|
||||
select CPU_INTEL_COMMON_HYPERTHREADING
|
||||
|
@@ -104,9 +104,7 @@ static void enable_var_mtrr(unsigned char deftype)
|
||||
|
||||
#define MTRR_VERBOSE_LEVEL BIOS_NEVER
|
||||
|
||||
/* MTRRs are at a 4KiB granularity. Therefore all address calculations can
|
||||
* be done with 32-bit numbers. This allows for the MTRR code to handle
|
||||
* up to 2^44 bytes (16 TiB) of address space. */
|
||||
/* MTRRs are at a 4KiB granularity. */
|
||||
#define RANGE_SHIFT 12
|
||||
#define ADDR_SHIFT_TO_RANGE_SHIFT(x) \
|
||||
(((x) > RANGE_SHIFT) ? ((x) - RANGE_SHIFT) : RANGE_SHIFT)
|
||||
@@ -115,18 +113,18 @@ static void enable_var_mtrr(unsigned char deftype)
|
||||
#define NUM_FIXED_MTRRS (NUM_FIXED_RANGES / RANGES_PER_FIXED_MTRR)
|
||||
|
||||
/* Helpful constants. */
|
||||
#define RANGE_1MB PHYS_TO_RANGE_ADDR(1 << 20)
|
||||
#define RANGE_4GB (1 << (ADDR_SHIFT_TO_RANGE_SHIFT(32)))
|
||||
#define RANGE_1MB PHYS_TO_RANGE_ADDR(1ULL << 20)
|
||||
#define RANGE_4GB (1ULL << (ADDR_SHIFT_TO_RANGE_SHIFT(32)))
|
||||
|
||||
#define MTRR_ALGO_SHIFT (8)
|
||||
#define MTRR_TAG_MASK ((1 << MTRR_ALGO_SHIFT) - 1)
|
||||
|
||||
static inline uint32_t range_entry_base_mtrr_addr(struct range_entry *r)
|
||||
static inline uint64_t range_entry_base_mtrr_addr(struct range_entry *r)
|
||||
{
|
||||
return PHYS_TO_RANGE_ADDR(range_entry_base(r));
|
||||
}
|
||||
|
||||
static inline uint32_t range_entry_end_mtrr_addr(struct range_entry *r)
|
||||
static inline uint64_t range_entry_end_mtrr_addr(struct range_entry *r)
|
||||
{
|
||||
return PHYS_TO_RANGE_ADDR(range_entry_end(r));
|
||||
}
|
||||
@@ -402,7 +400,7 @@ static void clear_var_mtrr(int index)
|
||||
}
|
||||
|
||||
static void prep_var_mtrr(struct var_mtrr_state *var_state,
|
||||
uint32_t base, uint32_t size, int mtrr_type)
|
||||
uint64_t base, uint64_t size, int mtrr_type)
|
||||
{
|
||||
struct var_mtrr_regs *regs;
|
||||
resource_t rbase;
|
||||
@@ -444,24 +442,51 @@ static void prep_var_mtrr(struct var_mtrr_state *var_state,
|
||||
regs->mask.hi = rsize >> 32;
|
||||
}
|
||||
|
||||
/*
|
||||
* fls64: find least significant bit set in a 64-bit word
|
||||
* As samples, fls64(0x0) = 64; fls64(0x4400) = 10;
|
||||
* fls64(0x40400000000) = 34.
|
||||
*/
|
||||
static uint32_t fls64(uint64_t x)
|
||||
{
|
||||
uint32_t lo = (uint32_t)x;
|
||||
if (lo)
|
||||
return fls(lo);
|
||||
uint32_t hi = x >> 32;
|
||||
return fls(hi) + 32;
|
||||
}
|
||||
|
||||
/*
|
||||
* fms64: find most significant bit set in a 64-bit word
|
||||
* As samples, fms64(0x0) = 0; fms64(0x4400) = 14;
|
||||
* fms64(0x40400000000) = 42.
|
||||
*/
|
||||
static uint32_t fms64(uint64_t x)
|
||||
{
|
||||
uint32_t hi = (uint32_t)(x >> 32);
|
||||
if (!hi)
|
||||
return fms((uint32_t)x);
|
||||
return fms(hi) + 32;
|
||||
}
|
||||
|
||||
static void calc_var_mtrr_range(struct var_mtrr_state *var_state,
|
||||
uint32_t base, uint32_t size, int mtrr_type)
|
||||
uint64_t base, uint64_t size, int mtrr_type)
|
||||
{
|
||||
while (size != 0) {
|
||||
uint32_t addr_lsb;
|
||||
uint32_t size_msb;
|
||||
uint32_t mtrr_size;
|
||||
uint64_t mtrr_size;
|
||||
|
||||
addr_lsb = fls(base);
|
||||
size_msb = fms(size);
|
||||
addr_lsb = fls64(base);
|
||||
size_msb = fms64(size);
|
||||
|
||||
/* All MTRR entries need to have their base aligned to the mask
|
||||
* size. The maximum size is calculated by a function of the
|
||||
* min base bit set and maximum size bit set. */
|
||||
if (addr_lsb > size_msb)
|
||||
mtrr_size = 1 << size_msb;
|
||||
mtrr_size = 1ULL << size_msb;
|
||||
else
|
||||
mtrr_size = 1 << addr_lsb;
|
||||
mtrr_size = 1ULL << addr_lsb;
|
||||
|
||||
if (var_state->prepare_msrs)
|
||||
prep_var_mtrr(var_state, base, mtrr_size, mtrr_type);
|
||||
@@ -472,8 +497,8 @@ static void calc_var_mtrr_range(struct var_mtrr_state *var_state,
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t optimize_var_mtrr_hole(const uint32_t base,
|
||||
const uint32_t hole,
|
||||
static uint64_t optimize_var_mtrr_hole(const uint64_t base,
|
||||
const uint64_t hole,
|
||||
const uint64_t limit,
|
||||
const int carve_hole)
|
||||
{
|
||||
@@ -531,7 +556,7 @@ static uint32_t optimize_var_mtrr_hole(const uint32_t base,
|
||||
static void calc_var_mtrrs_with_hole(struct var_mtrr_state *var_state,
|
||||
struct range_entry *r)
|
||||
{
|
||||
uint32_t a1, a2, b1, b2;
|
||||
uint64_t a1, a2, b1, b2;
|
||||
int mtrr_type, carve_hole;
|
||||
|
||||
/*
|
||||
@@ -671,6 +696,7 @@ static void __calc_var_mtrrs(struct memranges *addr_space,
|
||||
wb_deftype_count += var_state.mtrr_index;
|
||||
}
|
||||
}
|
||||
|
||||
*num_def_wb_mtrrs = wb_deftype_count;
|
||||
*num_def_uc_mtrrs = uc_deftype_count;
|
||||
}
|
||||
|
@@ -520,7 +520,7 @@ config PCIEXP_PLUGIN_SUPPORT
|
||||
default y
|
||||
|
||||
config PCI_ALLOW_BUS_MASTER
|
||||
bool "Allow PCI bus master bit to be enabled by coreboot"
|
||||
bool "Allow coreboot to set optional PCI bus master bits"
|
||||
default y
|
||||
help
|
||||
For security reasons, bus mastering should be enabled as late as
|
||||
|
@@ -1006,16 +1006,11 @@ static struct device *pci_scan_get_dev(struct bus *bus, unsigned int devfn)
|
||||
|
||||
prev = &bus->children;
|
||||
for (dev = bus->children; dev; dev = dev->sibling) {
|
||||
if (dev->path.type == DEVICE_PATH_PCI) {
|
||||
if (dev->path.pci.devfn == devfn) {
|
||||
/* Unlink from the list. */
|
||||
*prev = dev->sibling;
|
||||
dev->sibling = NULL;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
printk(BIOS_ERR, "child %s not a PCI device\n",
|
||||
dev_path(dev));
|
||||
if (dev->path.type == DEVICE_PATH_PCI && dev->path.pci.devfn == devfn) {
|
||||
/* Unlink from the list. */
|
||||
*prev = dev->sibling;
|
||||
dev->sibling = NULL;
|
||||
break;
|
||||
}
|
||||
prev = &dev->sibling;
|
||||
}
|
||||
@@ -1283,6 +1278,16 @@ void pci_scan_bus(struct bus *bus, unsigned int min_devfn,
|
||||
|
||||
prev = &bus->children;
|
||||
for (dev = bus->children; dev; dev = dev->sibling) {
|
||||
|
||||
/*
|
||||
* If static device is not PCI then enable it here and don't
|
||||
* treat it as a leftover device.
|
||||
*/
|
||||
if (dev->path.type != DEVICE_PATH_PCI) {
|
||||
enable_static_device(dev);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* The device is only considered leftover if it is not hidden
|
||||
* and it has a Vendor ID of 0 (the default for a device that
|
||||
|
@@ -180,6 +180,8 @@ static void pciexp_enable_ltr(struct device *dev)
|
||||
|
||||
for (bus = dev->link_list ; bus ; bus = bus->next) {
|
||||
for (child = bus->children; child; child = child->sibling) {
|
||||
if (child->path.type != DEVICE_PATH_PCI)
|
||||
continue;
|
||||
pciexp_configure_ltr(child);
|
||||
if (child->ops && child->ops->scan_bus)
|
||||
pciexp_enable_ltr(child);
|
||||
@@ -478,6 +480,8 @@ void pciexp_scan_bus(struct bus *bus, unsigned int min_devfn,
|
||||
pci_scan_bus(bus, min_devfn, max_devfn);
|
||||
|
||||
for (child = bus->children; child; child = child->sibling) {
|
||||
if (child->path.type != DEVICE_PATH_PCI)
|
||||
continue;
|
||||
if ((child->path.pci.devfn < min_devfn) ||
|
||||
(child->path.pci.devfn > max_devfn)) {
|
||||
continue;
|
||||
|
@@ -7,6 +7,18 @@
|
||||
|
||||
const char mainboard_name[] = CONFIG_MAINBOARD_VENDOR " " CONFIG_MAINBOARD_PART_NUMBER;
|
||||
|
||||
void enable_static_device(struct device *dev)
|
||||
{
|
||||
if (dev->chip_ops && dev->chip_ops->enable_dev)
|
||||
dev->chip_ops->enable_dev(dev);
|
||||
|
||||
if (dev->ops && dev->ops->enable)
|
||||
dev->ops->enable(dev);
|
||||
|
||||
printk(BIOS_DEBUG, "%s %s\n", dev_path(dev),
|
||||
dev->enabled ? "enabled" : "disabled");
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable devices on static buses.
|
||||
*
|
||||
@@ -32,15 +44,7 @@ void enable_static_devices(struct device *bus)
|
||||
|
||||
for (link = bus->link_list; link; link = link->next) {
|
||||
for (child = link->children; child; child = child->sibling) {
|
||||
|
||||
if (child->chip_ops && child->chip_ops->enable_dev)
|
||||
child->chip_ops->enable_dev(child);
|
||||
|
||||
if (child->ops && child->ops->enable)
|
||||
child->ops->enable(child);
|
||||
|
||||
printk(BIOS_DEBUG, "%s %s\n", dev_path(child),
|
||||
child->enabled ? "enabled" : "disabled");
|
||||
enable_static_device(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -58,18 +62,9 @@ void scan_generic_bus(struct device *bus)
|
||||
link->secondary = ++bus_max;
|
||||
|
||||
for (child = link->children; child; child = child->sibling) {
|
||||
|
||||
if (child->chip_ops && child->chip_ops->enable_dev)
|
||||
child->chip_ops->enable_dev(child);
|
||||
|
||||
if (child->ops && child->ops->enable)
|
||||
child->ops->enable(child);
|
||||
|
||||
enable_static_device(child);
|
||||
printk(BIOS_DEBUG, "bus: %s[%d]->", dev_path(child->bus->dev),
|
||||
child->bus->link_num);
|
||||
|
||||
printk(BIOS_DEBUG, "%s %s\n", dev_path(child),
|
||||
child->enabled ? "enabled" : "disabled");
|
||||
}
|
||||
}
|
||||
|
||||
|
7
src/drivers/camera/Kconfig
Normal file
7
src/drivers/camera/Kconfig
Normal file
@@ -0,0 +1,7 @@
|
||||
config CHROMEOS_CAMERA
|
||||
bool
|
||||
default n
|
||||
help
|
||||
Camera with identifiers following Chrome OS Camera Info. The info is
|
||||
usually available on MIPI camera EEPROM for identifying correct
|
||||
drivers and config.
|
1
src/drivers/camera/Makefile.inc
Normal file
1
src/drivers/camera/Makefile.inc
Normal file
@@ -0,0 +1 @@
|
||||
ramstage-$(CONFIG_CHROMEOS_CAMERA) += cros_camera.c
|
39
src/drivers/camera/cros_camera.c
Normal file
39
src/drivers/camera/cros_camera.c
Normal file
@@ -0,0 +1,39 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <console/console.h>
|
||||
#include <crc_byte.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cros_camera.h"
|
||||
|
||||
int check_cros_camera_info(const struct cros_camera_info *info)
|
||||
{
|
||||
if (memcmp(info->magic, CROS_CAMERA_INFO_MAGIC, sizeof(info->magic))) {
|
||||
printk(BIOS_ERR, "Invalid magic in camera info\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
const uint8_t *ptr = (void *)(&info->crc16 + 1);
|
||||
uint16_t crc16 = 0;
|
||||
while (ptr < (uint8_t *)info + sizeof(struct cros_camera_info))
|
||||
crc16 = crc16_byte(crc16, *ptr++);
|
||||
|
||||
if (info->crc16 != crc16) {
|
||||
printk(BIOS_ERR, "Incorrect CRC16: expected %#06x, got %#06x\n",
|
||||
crc16, info->crc16);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (info->version != CROS_CAMERA_INFO_VERSION) {
|
||||
printk(BIOS_ERR, "Unknown camera info version: %u\n",
|
||||
info->version);
|
||||
return -1;
|
||||
}
|
||||
if (info->size < CROS_CAMERA_INFO_SIZE_MIN) {
|
||||
printk(BIOS_ERR, "Size of camera info is too small: %u\n",
|
||||
info->size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
27
src/drivers/camera/cros_camera.h
Normal file
27
src/drivers/camera/cros_camera.h
Normal file
@@ -0,0 +1,27 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef __VENDORCODE_GOOGLE_CHROMEOS_CAMERA_H
|
||||
#define __VENDORCODE_GOOGLE_CHROMEOS_CAMERA_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define CROS_CAMERA_INFO_MAGIC "CrOS"
|
||||
#define CROS_CAMERA_INFO_VERSION 1
|
||||
#define CROS_CAMERA_INFO_SIZE_MIN 0x0a
|
||||
|
||||
struct cros_camera_info {
|
||||
uint8_t magic[4]; /* CROS_CAMERA_INFO_MAGIC */
|
||||
uint16_t crc16;
|
||||
uint8_t version;
|
||||
uint8_t size;
|
||||
uint16_t data_format;
|
||||
uint16_t module_pid;
|
||||
uint8_t module_vid[2];
|
||||
uint8_t sensor_vid[2];
|
||||
uint16_t sensor_pid;
|
||||
};
|
||||
|
||||
/* Returns 0 on success, non-zero on errors. */
|
||||
int check_cros_camera_info(const struct cros_camera_info *info);
|
||||
|
||||
#endif
|
6
src/drivers/i2c/gpiomux/Kconfig
Normal file
6
src/drivers/i2c/gpiomux/Kconfig
Normal file
@@ -0,0 +1,6 @@
|
||||
config DRIVERS_I2C_GPIO_MUX
|
||||
bool
|
||||
default n
|
||||
depends on HAVE_ACPI_TABLES
|
||||
help
|
||||
When enabled, add identifiers in ACPI tables for GPIO based I2C multiplexer.
|
2
src/drivers/i2c/gpiomux/Makefile.inc
Normal file
2
src/drivers/i2c/gpiomux/Makefile.inc
Normal file
@@ -0,0 +1,2 @@
|
||||
subdirs-$(CONFIG_DRIVERS_I2C_GPIO_MUX) += mux
|
||||
subdirs-$(CONFIG_DRIVERS_I2C_GPIO_MUX) += bus
|
1
src/drivers/i2c/gpiomux/bus/Makefile.inc
Normal file
1
src/drivers/i2c/gpiomux/bus/Makefile.inc
Normal file
@@ -0,0 +1 @@
|
||||
ramstage-$(CONFIG_DRIVERS_I2C_GPIO_MUX) += bus.c
|
60
src/drivers/i2c/gpiomux/bus/bus.c
Normal file
60
src/drivers/i2c/gpiomux/bus/bus.c
Normal file
@@ -0,0 +1,60 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <acpi/acpi_device.h>
|
||||
#include <acpi/acpigen.h>
|
||||
#include <console/console.h>
|
||||
#include <device/device.h>
|
||||
#include <device/path.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "chip.h"
|
||||
|
||||
static const char *i2c_gpiomux_bus_acpi_name(const struct device *dev)
|
||||
{
|
||||
static char name[ACPI_NAME_BUFFER_SIZE];
|
||||
|
||||
snprintf(name, ACPI_NAME_BUFFER_SIZE, "MXA%01.1X", dev->path.generic.id);
|
||||
return name;
|
||||
}
|
||||
|
||||
static void i2c_gpiomux_bus_fill_ssdt(const struct device *dev)
|
||||
{
|
||||
const char *scope = acpi_device_scope(dev);
|
||||
const char *path = acpi_device_path(dev);
|
||||
|
||||
if (!dev || !dev->enabled || !scope || !path)
|
||||
return;
|
||||
|
||||
/* Device */
|
||||
acpigen_write_scope(scope);
|
||||
acpigen_write_device(acpi_device_name(dev));
|
||||
|
||||
acpigen_write_STA(acpi_device_status(dev));
|
||||
acpigen_write_ADR(dev->path.generic.id);
|
||||
|
||||
acpigen_pop_len(); /* Device */
|
||||
acpigen_pop_len(); /* Scope */
|
||||
|
||||
printk(BIOS_INFO, "%s: %s at %s\n", path, dev->chip_ops->name, dev_path(dev));
|
||||
}
|
||||
|
||||
static struct device_operations i2c_gpiomux_bus_ops = {
|
||||
.read_resources = noop_read_resources,
|
||||
.set_resources = noop_set_resources,
|
||||
.scan_bus = scan_static_bus,
|
||||
.acpi_name = i2c_gpiomux_bus_acpi_name,
|
||||
.acpi_fill_ssdt = i2c_gpiomux_bus_fill_ssdt,
|
||||
};
|
||||
|
||||
static void i2c_gpiomux_bus_enable(struct device *dev)
|
||||
{
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
dev->ops = &i2c_gpiomux_bus_ops;
|
||||
}
|
||||
|
||||
struct chip_operations drivers_i2c_gpiomux_bus_ops = {
|
||||
CHIP_NAME("I2C GPIO MUX Bus Device")
|
||||
.enable_dev = i2c_gpiomux_bus_enable
|
||||
};
|
9
src/drivers/i2c/gpiomux/bus/chip.h
Normal file
9
src/drivers/i2c/gpiomux/bus/chip.h
Normal file
@@ -0,0 +1,9 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef __I2C_GPIOMUX_BUS_CHIP_H__
|
||||
#define __I2C_GPIOMUX_BUS_CHIP_H__
|
||||
|
||||
struct drivers_i2c_gpiomux_bus_config {
|
||||
};
|
||||
|
||||
#endif /* __I2C_GPIOMUX_BUS_CHIP_H__ */
|
1
src/drivers/i2c/gpiomux/mux/Makefile.inc
Normal file
1
src/drivers/i2c/gpiomux/mux/Makefile.inc
Normal file
@@ -0,0 +1 @@
|
||||
ramstage-$(CONFIG_DRIVERS_I2C_GPIO_MUX) += mux.c
|
17
src/drivers/i2c/gpiomux/mux/chip.h
Normal file
17
src/drivers/i2c/gpiomux/mux/chip.h
Normal file
@@ -0,0 +1,17 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef __I2C_GPIOMUX_MUX_CHIP_H__
|
||||
#define __I2C_GPIOMUX_MUX_CHIP_H__
|
||||
|
||||
#include <acpi/acpi_device.h>
|
||||
#include <types.h>
|
||||
|
||||
#define MAX_NUM_MUX_GPIOS 4
|
||||
|
||||
struct drivers_i2c_gpiomux_mux_config {
|
||||
/* GPIOs used to select the mux lines */
|
||||
uint32_t mux_gpio_count;
|
||||
struct acpi_gpio mux_gpio[MAX_NUM_MUX_GPIOS];
|
||||
};
|
||||
|
||||
#endif /* __I2C_GPIOMUX_MUX_CHIP_H__ */
|
82
src/drivers/i2c/gpiomux/mux/mux.c
Normal file
82
src/drivers/i2c/gpiomux/mux/mux.c
Normal file
@@ -0,0 +1,82 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <acpi/acpi_device.h>
|
||||
#include <acpi/acpigen.h>
|
||||
#include <console/console.h>
|
||||
#include <device/device.h>
|
||||
#include <device/path.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "chip.h"
|
||||
|
||||
static const char *i2c_gpiomux_mux_acpi_name(const struct device *dev)
|
||||
{
|
||||
static char name[ACPI_NAME_BUFFER_SIZE];
|
||||
|
||||
snprintf(name, ACPI_NAME_BUFFER_SIZE, "MUX%01.1X", dev->path.generic.id);
|
||||
return name;
|
||||
}
|
||||
|
||||
static void i2c_gpiomux_mux_fill_ssdt(const struct device *dev)
|
||||
{
|
||||
const char *scope = acpi_device_scope(dev);
|
||||
const char *path = acpi_device_path(dev);
|
||||
struct drivers_i2c_gpiomux_mux_config *config = config_of(dev);
|
||||
struct acpi_dp *dsd = NULL;
|
||||
const char *compat_string = "i2c-mux-gpio";
|
||||
struct acpi_gpio_res_params param[MAX_NUM_MUX_GPIOS];
|
||||
int i;
|
||||
|
||||
if (!dev->enabled || !scope || !path)
|
||||
return;
|
||||
|
||||
/* Device */
|
||||
acpigen_write_scope(scope);
|
||||
acpigen_write_device(acpi_device_name(dev));
|
||||
acpigen_write_name_string("_HID", ACPI_DT_NAMESPACE_HID);
|
||||
acpigen_write_STA(acpi_device_status(dev));
|
||||
|
||||
/* Resources */
|
||||
acpigen_write_name("_CRS");
|
||||
acpigen_write_resourcetemplate_header();
|
||||
for (i = 0; i < config->mux_gpio_count; i++) {
|
||||
acpi_device_write_gpio(&config->mux_gpio[i]);
|
||||
param[i].ref = path;
|
||||
param[i].index = i;
|
||||
param[i].pin = 0;
|
||||
param[i].active_low = config->mux_gpio[i].active_low;
|
||||
}
|
||||
acpigen_write_resourcetemplate_footer();
|
||||
|
||||
/* DSD */
|
||||
dsd = acpi_dp_new_table("_DSD");
|
||||
acpi_dp_add_string(dsd, "compatible", compat_string);
|
||||
acpi_dp_add_gpio_array(dsd, "mux-gpios", param, config->mux_gpio_count);
|
||||
acpi_dp_write(dsd);
|
||||
|
||||
acpigen_pop_len(); /* Device */
|
||||
acpigen_pop_len(); /* Scope */
|
||||
|
||||
printk(BIOS_INFO, "%s: %s at %s\n", path, dev->chip_ops->name, dev_path(dev));
|
||||
}
|
||||
|
||||
static struct device_operations i2c_gpiomux_mux_ops = {
|
||||
.read_resources = noop_read_resources,
|
||||
.set_resources = noop_set_resources,
|
||||
.scan_bus = scan_static_bus,
|
||||
.acpi_name = i2c_gpiomux_mux_acpi_name,
|
||||
.acpi_fill_ssdt = i2c_gpiomux_mux_fill_ssdt,
|
||||
};
|
||||
|
||||
static void i2c_gpiomux_mux_enable(struct device *dev)
|
||||
{
|
||||
if (!dev)
|
||||
return;
|
||||
|
||||
dev->ops = &i2c_gpiomux_mux_ops;
|
||||
}
|
||||
|
||||
struct chip_operations drivers_i2c_gpiomux_mux_ops = {
|
||||
CHIP_NAME("I2C GPIO MUX Device")
|
||||
.enable_dev = i2c_gpiomux_mux_enable
|
||||
};
|
@@ -141,23 +141,6 @@ config FSP_TEMP_RAM_SIZE
|
||||
own stack that will be placed in DRAM and not in CAR, this is the
|
||||
amount of memory the FSP needs for its stack and heap.
|
||||
|
||||
config FSP2_0_USES_TPM_MRC_HASH
|
||||
bool
|
||||
depends on TPM1 || TPM2
|
||||
depends on VBOOT && VBOOT_STARTS_IN_BOOTBLOCK
|
||||
default y if HAS_RECOVERY_MRC_CACHE
|
||||
default n
|
||||
select VBOOT_HAS_REC_HASH_SPACE
|
||||
help
|
||||
Store hash of trained recovery MRC cache in NVRAM space in TPM.
|
||||
Use the hash to validate recovery MRC cache before using it.
|
||||
This hash needs to be updated every time recovery mode training
|
||||
is recomputed, or if the hash does not match recovery MRC cache.
|
||||
Selecting this option requires that TPM already be setup by this
|
||||
point in time. Thus it is only compatible when the option
|
||||
VBOOT_STARTS_IN_BOOTBLOCK is selected, which causes verstage and
|
||||
TPM setup to occur prior to memory initialization.
|
||||
|
||||
config FSP_PLATFORM_MEMORY_SETTINGS_VERSIONS
|
||||
bool
|
||||
help
|
||||
|
@@ -1,19 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef _FSP2_0_MEMORY_INIT_H_
|
||||
#define _FSP2_0_MEMORY_INIT_H_
|
||||
|
||||
#include <types.h>
|
||||
|
||||
/*
|
||||
* Updates mrc cache hash if it differs.
|
||||
*/
|
||||
void mrc_cache_update_hash(const uint8_t *data, size_t size);
|
||||
|
||||
/*
|
||||
* Verifies mrc cache hash which is stored somewhere.
|
||||
* return 1 verification was successful and 0 for error.
|
||||
*/
|
||||
int mrc_cache_verify_hash(const uint8_t *data, size_t size);
|
||||
|
||||
#endif /* _FSP2_0_MEMORY_INIT_H_ */
|
@@ -21,16 +21,10 @@
|
||||
#include <security/vboot/vboot_common.h>
|
||||
#include <security/tpm/tspi.h>
|
||||
#include <vb2_api.h>
|
||||
#include <fsp/memory_init.h>
|
||||
#include <types.h>
|
||||
|
||||
static uint8_t temp_ram[CONFIG_FSP_TEMP_RAM_SIZE] __aligned(sizeof(uint64_t));
|
||||
|
||||
/* TPM MRC hash functionality depends on vboot starting before memory init. */
|
||||
_Static_assert(!CONFIG(FSP2_0_USES_TPM_MRC_HASH) ||
|
||||
CONFIG(VBOOT_STARTS_IN_BOOTBLOCK),
|
||||
"for TPM MRC hash functionality, vboot must start in bootblock");
|
||||
|
||||
static void save_memory_training_data(bool s3wake, uint32_t fsp_version)
|
||||
{
|
||||
size_t mrc_data_size;
|
||||
@@ -54,9 +48,6 @@ static void save_memory_training_data(bool s3wake, uint32_t fsp_version)
|
||||
if (mrc_cache_stash_data(MRC_TRAINING_DATA, fsp_version, mrc_data,
|
||||
mrc_data_size) < 0)
|
||||
printk(BIOS_ERR, "Failed to stash MRC data\n");
|
||||
|
||||
if (CONFIG(FSP2_0_USES_TPM_MRC_HASH))
|
||||
mrc_cache_update_hash(mrc_data, mrc_data_size);
|
||||
}
|
||||
|
||||
static void do_fsp_post_memory_init(bool s3wake, uint32_t fsp_version)
|
||||
@@ -121,10 +112,6 @@ static void fsp_fill_mrc_cache(FSPM_ARCH_UPD *arch_upd, uint32_t fsp_version)
|
||||
if (data == NULL)
|
||||
return;
|
||||
|
||||
if (CONFIG(FSP2_0_USES_TPM_MRC_HASH) &&
|
||||
!mrc_cache_verify_hash(data, mrc_size))
|
||||
return;
|
||||
|
||||
/* MRC cache found */
|
||||
arch_upd->NvsBufferPtr = data;
|
||||
|
||||
|
@@ -19,7 +19,7 @@ const char *mainboard_vbt_filename(void)
|
||||
return "vbt.bin";
|
||||
}
|
||||
|
||||
static char vbt_data[8 * KiB];
|
||||
static char vbt_data[9 * KiB];
|
||||
static size_t vbt_data_sz;
|
||||
|
||||
void *locate_vbt(size_t *vbt_size)
|
||||
|
8
src/drivers/intel/usb4/retimer/Kconfig
Normal file
8
src/drivers/intel/usb4/retimer/Kconfig
Normal file
@@ -0,0 +1,8 @@
|
||||
config DRIVERS_INTEL_USB4_RETIMER
|
||||
bool
|
||||
depends on HAVE_ACPI_TABLES
|
||||
help
|
||||
A retimer is a device that retransmits a fresh copy of the signal it
|
||||
receives, by doing CDR and retransmitting the data (i.e., it is
|
||||
protocol-aware). If your mainboard has a USB4 retimer (usually
|
||||
located close to the USB4 ports), then select this driver.
|
1
src/drivers/intel/usb4/retimer/Makefile.inc
Normal file
1
src/drivers/intel/usb4/retimer/Makefile.inc
Normal file
@@ -0,0 +1 @@
|
||||
ramstage-$(CONFIG_DRIVERS_INTEL_USB4_RETIMER) += retimer.c
|
13
src/drivers/intel/usb4/retimer/chip.h
Normal file
13
src/drivers/intel/usb4/retimer/chip.h
Normal file
@@ -0,0 +1,13 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#ifndef __DRIVERS_INTEL_USB4_RETIMER_H__
|
||||
#define __DRIVERS_INTEL_USB4_RETIMER_H__
|
||||
|
||||
#include <acpi/acpi_device.h>
|
||||
|
||||
struct drivers_intel_usb4_retimer_config {
|
||||
/* GPIO used to control power of retimer device. */
|
||||
struct acpi_gpio power_gpio;
|
||||
};
|
||||
|
||||
#endif /* __DRIVERS_INTEL_USB4_RETIMER_H__ */
|
136
src/drivers/intel/usb4/retimer/retimer.c
Normal file
136
src/drivers/intel/usb4/retimer/retimer.c
Normal file
@@ -0,0 +1,136 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include <acpi/acpigen.h>
|
||||
#include <acpi/acpi_device.h>
|
||||
#include <console/console.h>
|
||||
#include <device/device.h>
|
||||
#include <device/path.h>
|
||||
#include <gpio.h>
|
||||
#include <string.h>
|
||||
#include "chip.h"
|
||||
|
||||
/* Unique ID for the retimer _DSM. */
|
||||
#define INTEL_USB4_RETIMER_DSM_UUID "61788900-C470-42BB-80F0-23A313864593"
|
||||
|
||||
/*
|
||||
* Arg0: UUID
|
||||
* Arg1: Revision ID (set to 1)
|
||||
* Arg2: Function Index
|
||||
* 0: Query command implemented
|
||||
* 1: Query force power enable state
|
||||
* 2: Set force power state
|
||||
* Arg3: A package containing parameters for the function specified
|
||||
* by the UUID, revision ID and function index.
|
||||
*/
|
||||
|
||||
static void usb4_retimer_cb_standard_query(void *arg)
|
||||
{
|
||||
/*
|
||||
* ToInteger (Arg1, Local2)
|
||||
* If (Local2 == 1) {
|
||||
* Return(Buffer() {0x07})
|
||||
* }
|
||||
* Return (Buffer() {0x01})
|
||||
*/
|
||||
acpigen_write_to_integer(ARG1_OP, LOCAL2_OP);
|
||||
|
||||
/* Revision 1 supports 2 Functions beyond the standard query */
|
||||
acpigen_write_if_lequal_op_int(LOCAL2_OP, 1);
|
||||
acpigen_write_return_singleton_buffer(0x07);
|
||||
acpigen_pop_len(); /* If */
|
||||
|
||||
/* Other revisions support no additional functions */
|
||||
acpigen_write_return_singleton_buffer(0);
|
||||
}
|
||||
|
||||
static void usb4_retimer_cb_get_power_state(void *arg)
|
||||
{
|
||||
struct acpi_gpio *power_gpio = arg;
|
||||
|
||||
/*
|
||||
* // Read power gpio into Local0
|
||||
* Store (\_SB.PCI0.GTXS (power_gpio), Local0)
|
||||
* Return (Local0)
|
||||
*/
|
||||
acpigen_get_tx_gpio(power_gpio);
|
||||
acpigen_write_return_op(LOCAL0_OP);
|
||||
}
|
||||
|
||||
static void usb4_retimer_cb_set_power_state(void *arg)
|
||||
{
|
||||
struct acpi_gpio *power_gpio = arg;
|
||||
|
||||
/*
|
||||
* // Get argument for on/off from Arg3[0]
|
||||
* Local0 = DeRefOf (Arg3[0])
|
||||
*/
|
||||
acpigen_get_package_op_element(ARG3_OP, 0, LOCAL0_OP);
|
||||
|
||||
/*
|
||||
* If (Local0 == 0) {
|
||||
* // Turn power off
|
||||
* \_SB.PCI0.CTXS (power_gpio)
|
||||
* }
|
||||
*/
|
||||
acpigen_write_if_lequal_op_int(LOCAL0_OP, 0);
|
||||
acpigen_disable_tx_gpio(power_gpio);
|
||||
acpigen_pop_len(); /* If */
|
||||
|
||||
/*
|
||||
* Else {
|
||||
* // Turn power on
|
||||
* \_SB.PCI0.STXS (power_gpio)
|
||||
* }
|
||||
*/
|
||||
acpigen_write_else();
|
||||
acpigen_enable_tx_gpio(power_gpio);
|
||||
acpigen_pop_len();
|
||||
|
||||
/* Return (Zero) */
|
||||
acpigen_write_return_integer(0);
|
||||
}
|
||||
|
||||
static void (*usb4_retimer_callbacks[3])(void *) = {
|
||||
usb4_retimer_cb_standard_query, /* Function 0 */
|
||||
usb4_retimer_cb_get_power_state, /* Function 1 */
|
||||
usb4_retimer_cb_set_power_state, /* Function 2 */
|
||||
};
|
||||
|
||||
static void usb4_retimer_fill_ssdt(const struct device *dev)
|
||||
{
|
||||
const struct drivers_intel_usb4_retimer_config *config = dev->chip_info;
|
||||
const char *scope = acpi_device_scope(dev);
|
||||
|
||||
if (!dev->enabled || !scope || !config)
|
||||
return;
|
||||
|
||||
if (!config->power_gpio.pin_count) {
|
||||
printk(BIOS_ERR, "%s: Power GPIO required for %s\n", __func__, dev_path(dev));
|
||||
return;
|
||||
}
|
||||
|
||||
/* Write the _DSM that toggles power with provided GPIO. */
|
||||
acpigen_write_scope(scope);
|
||||
acpigen_write_dsm(INTEL_USB4_RETIMER_DSM_UUID, usb4_retimer_callbacks,
|
||||
ARRAY_SIZE(usb4_retimer_callbacks), (void *)&config->power_gpio);
|
||||
acpigen_pop_len(); /* Scope */
|
||||
|
||||
printk(BIOS_INFO, "%s: %s at %s\n", acpi_device_path(dev), dev->chip_ops->name,
|
||||
dev_path(dev));
|
||||
}
|
||||
|
||||
static struct device_operations usb4_retimer_dev_ops = {
|
||||
.read_resources = noop_read_resources,
|
||||
.set_resources = noop_set_resources,
|
||||
.acpi_fill_ssdt = usb4_retimer_fill_ssdt,
|
||||
};
|
||||
|
||||
static void usb4_retimer_enable(struct device *dev)
|
||||
{
|
||||
dev->ops = &usb4_retimer_dev_ops;
|
||||
}
|
||||
|
||||
struct chip_operations drivers_intel_usb4_retimer_ops = {
|
||||
CHIP_NAME("Intel USB4 Retimer")
|
||||
.enable_dev = usb4_retimer_enable
|
||||
};
|
@@ -1,8 +0,0 @@
|
||||
config DRIVERS_INTEL_WIFI
|
||||
bool "Support Intel PCI-e WiFi adapters"
|
||||
depends on PCI
|
||||
default y if PCIEXP_PLUGIN_SUPPORT
|
||||
select DRIVERS_WIFI_GENERIC 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.
|
@@ -1,7 +0,0 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
ramstage-$(CONFIG_DRIVERS_INTEL_WIFI) += wifi.c
|
||||
|
||||
cbfs-files-$(CONFIG_WIFI_SAR_CBFS) += wifi_sar_defaults.hex
|
||||
wifi_sar_defaults.hex-file := $(call strip_quotes,$(CONFIG_WIFI_SAR_CBFS_FILEPATH))
|
||||
wifi_sar_defaults.hex-type := raw
|
@@ -1,10 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#ifndef _INTEL_WIFI_CHIP_H_
|
||||
#define _INTEL_WIFI_CHIP_H_
|
||||
|
||||
struct drivers_intel_wifi_config {
|
||||
unsigned int wake; /* Wake pin for ACPI _PRW */
|
||||
};
|
||||
|
||||
#endif /* _INTEL_WIFI_CHIP_H_ */
|
@@ -1,146 +0,0 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <device/device.h>
|
||||
#include <device/pci.h>
|
||||
#include <device/pci_ops.h>
|
||||
#include <device/pci_ids.h>
|
||||
#include <elog.h>
|
||||
#include <smbios.h>
|
||||
#include <string.h>
|
||||
#include "chip.h"
|
||||
#include "drivers/wifi/generic/chip.h"
|
||||
|
||||
#if CONFIG(GENERATE_SMBIOS_TABLES)
|
||||
static int smbios_write_wifi(struct device *dev, int *handle,
|
||||
unsigned long *current)
|
||||
{
|
||||
struct smbios_type_intel_wifi {
|
||||
u8 type;
|
||||
u8 length;
|
||||
u16 handle;
|
||||
u8 str;
|
||||
u8 eos[2];
|
||||
} __packed;
|
||||
|
||||
struct smbios_type_intel_wifi *t =
|
||||
(struct smbios_type_intel_wifi *)*current;
|
||||
int len = sizeof(struct smbios_type_intel_wifi);
|
||||
|
||||
memset(t, 0, sizeof(struct smbios_type_intel_wifi));
|
||||
t->type = 0x85;
|
||||
t->length = len - 2;
|
||||
t->handle = *handle;
|
||||
/*
|
||||
* Intel wifi driver expects this string to be in the table 0x85
|
||||
* with PCI IDs enumerated below.
|
||||
*/
|
||||
t->str = smbios_add_string(t->eos, "KHOIHGIUCCHHII");
|
||||
|
||||
len = t->length + smbios_string_table_len(t->eos);
|
||||
*current += len;
|
||||
*handle += 1;
|
||||
return len;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CONFIG(HAVE_ACPI_TABLES)
|
||||
static void intel_wifi_fill_ssdt(const struct device *dev)
|
||||
{
|
||||
struct drivers_intel_wifi_config *config = dev->chip_info;
|
||||
struct drivers_wifi_generic_config generic_config;
|
||||
|
||||
if (config)
|
||||
generic_config.wake = config->wake;
|
||||
|
||||
wifi_generic_fill_ssdt(dev, config ? &generic_config : NULL);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void wifi_pci_dev_init(struct device *dev)
|
||||
{
|
||||
if (pci_dev_is_wake_source(dev))
|
||||
elog_add_event_wake(ELOG_WAKE_SOURCE_PME_WIFI, 0);
|
||||
}
|
||||
|
||||
struct device_operations device_ops = {
|
||||
.read_resources = pci_dev_read_resources,
|
||||
.set_resources = pci_dev_set_resources,
|
||||
.enable_resources = pci_dev_enable_resources,
|
||||
.init = wifi_pci_dev_init,
|
||||
#if CONFIG(GENERATE_SMBIOS_TABLES)
|
||||
.get_smbios_data = smbios_write_wifi,
|
||||
#endif
|
||||
.ops_pci = &pci_dev_ops_pci,
|
||||
#if CONFIG(HAVE_ACPI_TABLES)
|
||||
.acpi_name = wifi_generic_acpi_name,
|
||||
.acpi_fill_ssdt = intel_wifi_fill_ssdt,
|
||||
#endif
|
||||
};
|
||||
|
||||
static const unsigned short pci_device_ids[] = {
|
||||
PCI_DEVICE_ID_1000_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_6005_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_6005_I_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_1030_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_6030_I_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_6030_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_6150_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_2030_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_2000_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_0135_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_0105_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_6035_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_5300_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_5100_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_6000_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_6000_I_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_5350_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_5150_SERIES_WIFI,
|
||||
/* Wilkins Peak 2 */
|
||||
PCI_DEVICE_ID_WP_7260_SERIES_1_WIFI,
|
||||
PCI_DEVICE_ID_WP_7260_SERIES_2_WIFI,
|
||||
/* Stone Peak 2 */
|
||||
PCI_DEVICE_ID_SP_7265_SERIES_1_WIFI,
|
||||
PCI_DEVICE_ID_SP_7265_SERIES_2_WIFI,
|
||||
/* Stone Field Peak */
|
||||
PCI_DEVICE_ID_SFP_8260_SERIES_1_WIFI,
|
||||
PCI_DEVICE_ID_SFP_8260_SERIES_2_WIFI,
|
||||
/* Windstorm Peak */
|
||||
PCI_DEVICE_ID_WSP_8275_SERIES_1_WIFI,
|
||||
/* Jefferson Peak */
|
||||
PCI_DEVICE_ID_JP_9000_SERIES_1_WIFI,
|
||||
PCI_DEVICE_ID_JP_9000_SERIES_2_WIFI,
|
||||
PCI_DEVICE_ID_JP_9000_SERIES_3_WIFI,
|
||||
/* Thunder Peak 2 */
|
||||
PCI_DEVICE_ID_TP_9260_SERIES_WIFI,
|
||||
/* Harrison Peak */
|
||||
PCI_DEVICE_ID_HrP_9560_SERIES_1_WIFI,
|
||||
PCI_DEVICE_ID_HrP_9560_SERIES_2_WIFI,
|
||||
PCI_DEVICE_ID_HrP_9560_SERIES_3_WIFI,
|
||||
PCI_DEVICE_ID_HrP_9560_SERIES_4_WIFI,
|
||||
PCI_DEVICE_ID_HrP_6SERIES_WIFI,
|
||||
/* Cyclone Peak */
|
||||
PCI_DEVICE_ID_CyP_6SERIES_WIFI,
|
||||
/* Typhoon Peak */
|
||||
PCI_DEVICE_ID_TyP_6SERIES_WIFI,
|
||||
/* Garfiled Peak */
|
||||
PCI_DEVICE_ID_GrP_6SERIES_1_WIFI,
|
||||
PCI_DEVICE_ID_GrP_6SERIES_2_WIFI,
|
||||
0
|
||||
};
|
||||
|
||||
static const struct pci_driver pch_intel_wifi __pci_driver = {
|
||||
.ops = &device_ops,
|
||||
.vendor = PCI_VENDOR_ID_INTEL,
|
||||
.devices = pci_device_ids,
|
||||
};
|
||||
|
||||
static void intel_wifi_enable(struct device *dev)
|
||||
{
|
||||
dev->ops = &device_ops;
|
||||
}
|
||||
|
||||
struct chip_operations drivers_intel_wifi_ops = {
|
||||
CHIP_NAME("Intel WiFi")
|
||||
.enable_dev = intel_wifi_enable
|
||||
};
|
@@ -33,6 +33,8 @@ extern int ipmi_kcs_message(int port, int netfn, int lun, int cmd,
|
||||
* returns CB_SUCCESS on success and CB_ERR if an error occurred. */
|
||||
enum cb_err ipmi_kcs_premem_init(const u16 port, const u16 device);
|
||||
|
||||
void ipmi_bmc_version(uint8_t *ipmi_bmc_major_revision, uint8_t *ipmi_bmc_minor_revision);
|
||||
|
||||
struct ipmi_rsp {
|
||||
uint8_t lun;
|
||||
uint8_t cmd;
|
||||
|
@@ -8,6 +8,7 @@
|
||||
* end
|
||||
*/
|
||||
|
||||
#include <arch/io.h>
|
||||
#include <console/console.h>
|
||||
#include <device/device.h>
|
||||
#include <device/pnp.h>
|
||||
@@ -28,6 +29,9 @@
|
||||
static u8 ipmi_revision_major = 0x1;
|
||||
static u8 ipmi_revision_minor = 0x0;
|
||||
|
||||
static u8 bmc_revision_major = 0x0;
|
||||
static u8 bmc_revision_minor = 0x0;
|
||||
|
||||
static int ipmi_get_device_id(struct device *dev, struct ipmi_devid_rsp *rsp)
|
||||
{
|
||||
int ret;
|
||||
@@ -144,6 +148,9 @@ static void ipmi_kcs_init(struct device *dev)
|
||||
ipmi_revision_minor = IPMI_IPMI_VERSION_MINOR(rsp.ipmi_version);
|
||||
ipmi_revision_major = IPMI_IPMI_VERSION_MAJOR(rsp.ipmi_version);
|
||||
|
||||
bmc_revision_major = rsp.fw_rev1;
|
||||
bmc_revision_minor = rsp.fw_rev2;
|
||||
|
||||
memcpy(&man_id, rsp.manufacturer_id,
|
||||
sizeof(rsp.manufacturer_id));
|
||||
|
||||
@@ -272,6 +279,18 @@ static void ipmi_ssdt(const struct device *dev)
|
||||
}
|
||||
#endif
|
||||
|
||||
void ipmi_bmc_version(uint8_t *ipmi_bmc_major_revision, uint8_t *ipmi_bmc_minor_revision)
|
||||
{
|
||||
if (!bmc_revision_major || !bmc_revision_minor) {
|
||||
printk(BIOS_ERR, "IPMI: BMC revision missing\n");
|
||||
*ipmi_bmc_major_revision = 0;
|
||||
*ipmi_bmc_minor_revision = 0;
|
||||
} else {
|
||||
*ipmi_bmc_major_revision = bmc_revision_major;
|
||||
*ipmi_bmc_minor_revision = bmc_revision_minor;
|
||||
}
|
||||
}
|
||||
|
||||
#if CONFIG(GENERATE_SMBIOS_TABLES)
|
||||
static int ipmi_smbios_data(struct device *dev, int *handle,
|
||||
unsigned long *current)
|
||||
|
@@ -1,5 +1,6 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <arch/io.h>
|
||||
#include <console/console.h>
|
||||
#include <device/pnp.h>
|
||||
#include <delay.h>
|
||||
|
@@ -49,4 +49,12 @@ config MRC_STASH_TO_CBMEM
|
||||
that need to write back the MRC data in late ramstage boot
|
||||
states (MRC_WRITE_NV_LATE).
|
||||
|
||||
config MRC_SAVE_HASH_IN_TPM
|
||||
bool "Save a hash of the MRC_CACHE data in TPM NVRAM"
|
||||
depends on VBOOT_STARTS_IN_BOOTBLOCK && TPM2 && !TPM1
|
||||
default y
|
||||
help
|
||||
Store a hash of the MRC_CACHE training data in a TPM NVRAM
|
||||
space to ensure that it cannot be tampered with.
|
||||
|
||||
endif # CACHE_MRC_SETTINGS
|
||||
|
@@ -10,6 +10,8 @@
|
||||
#include <fmap.h>
|
||||
#include <ip_checksum.h>
|
||||
#include <region_file.h>
|
||||
#include <security/vboot/antirollback.h>
|
||||
#include <security/vboot/mrc_cache_hash_tpm.h>
|
||||
#include <security/vboot/vboot_common.h>
|
||||
#include <spi_flash.h>
|
||||
|
||||
@@ -44,6 +46,7 @@ struct cache_region {
|
||||
uint32_t cbmem_id;
|
||||
int type;
|
||||
int elog_slot;
|
||||
uint32_t tpm_hash_index;
|
||||
int flags;
|
||||
};
|
||||
|
||||
@@ -52,6 +55,7 @@ static const struct cache_region recovery_training = {
|
||||
.cbmem_id = CBMEM_ID_MRCDATA,
|
||||
.type = MRC_TRAINING_DATA,
|
||||
.elog_slot = ELOG_MEM_CACHE_UPDATE_SLOT_RECOVERY,
|
||||
.tpm_hash_index = MRC_REC_HASH_NV_INDEX,
|
||||
#if CONFIG(HAS_RECOVERY_MRC_CACHE)
|
||||
.flags = RECOVERY_FLAG,
|
||||
#else
|
||||
@@ -64,6 +68,7 @@ static const struct cache_region normal_training = {
|
||||
.cbmem_id = CBMEM_ID_MRCDATA,
|
||||
.type = MRC_TRAINING_DATA,
|
||||
.elog_slot = ELOG_MEM_CACHE_UPDATE_SLOT_NORMAL,
|
||||
.tpm_hash_index = MRC_RW_HASH_NV_INDEX,
|
||||
.flags = NORMAL_FLAG | RECOVERY_FLAG,
|
||||
};
|
||||
|
||||
@@ -72,6 +77,7 @@ static const struct cache_region variable_data = {
|
||||
.cbmem_id = CBMEM_ID_VAR_MRCDATA,
|
||||
.type = MRC_VARIABLE_DATA,
|
||||
.elog_slot = ELOG_MEM_CACHE_UPDATE_SLOT_VARIABLE,
|
||||
.tpm_hash_index = 0,
|
||||
.flags = NORMAL_FLAG | RECOVERY_FLAG,
|
||||
};
|
||||
|
||||
@@ -82,6 +88,11 @@ static const struct cache_region *cache_regions[] = {
|
||||
&variable_data,
|
||||
};
|
||||
|
||||
/* TPM MRC hash functionality depends on vboot starting before memory init. */
|
||||
_Static_assert(!CONFIG(MRC_SAVE_HASH_IN_TPM) ||
|
||||
CONFIG(VBOOT_STARTS_IN_BOOTBLOCK),
|
||||
"for TPM MRC hash functionality, vboot must start in bootblock");
|
||||
|
||||
static int lookup_region_by_name(const char *name, struct region *r)
|
||||
{
|
||||
if (fmap_locate_area(name, r) == 0)
|
||||
@@ -169,20 +180,31 @@ static int mrc_header_valid(struct region_device *rdev, struct mrc_metadata *md)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mrc_data_valid(const struct mrc_metadata *md,
|
||||
static int mrc_data_valid(int type, const struct mrc_metadata *md,
|
||||
void *data, size_t data_size)
|
||||
{
|
||||
uint16_t checksum;
|
||||
const struct cache_region *cr = lookup_region_type(type);
|
||||
uint32_t hash_idx;
|
||||
|
||||
if (cr == NULL)
|
||||
return -1;
|
||||
|
||||
if (md->data_size != data_size)
|
||||
return -1;
|
||||
|
||||
checksum = compute_ip_checksum(data, data_size);
|
||||
hash_idx = cr->tpm_hash_index;
|
||||
if (hash_idx && CONFIG(MRC_SAVE_HASH_IN_TPM)) {
|
||||
if (!mrc_cache_verify_hash(hash_idx, data, data_size))
|
||||
return -1;
|
||||
} else {
|
||||
checksum = compute_ip_checksum(data, data_size);
|
||||
|
||||
if (md->data_checksum != checksum) {
|
||||
printk(BIOS_ERR, "MRC: data checksum mismatch: %x vs %x\n",
|
||||
md->data_checksum, checksum);
|
||||
return -1;
|
||||
if (md->data_checksum != checksum) {
|
||||
printk(BIOS_ERR, "MRC: data checksum mismatch: %x vs %x\n",
|
||||
md->data_checksum, checksum);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -277,7 +299,7 @@ ssize_t mrc_cache_load_current(int type, uint32_t version, void *buffer,
|
||||
if (rdev_readat(&rdev, buffer, 0, data_size) != data_size)
|
||||
return -1;
|
||||
|
||||
if (mrc_data_valid(&md, buffer, data_size) < 0)
|
||||
if (mrc_data_valid(type, &md, buffer, data_size) < 0)
|
||||
return -1;
|
||||
|
||||
return data_size;
|
||||
@@ -304,7 +326,7 @@ void *mrc_cache_current_mmap_leak(int type, uint32_t version,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (mrc_data_valid(&md, data, region_device_size) < 0)
|
||||
if (mrc_data_valid(type, &md, data, region_device_size) < 0)
|
||||
return NULL;
|
||||
|
||||
return data;
|
||||
@@ -315,10 +337,10 @@ static bool mrc_cache_needs_update(const struct region_device *rdev,
|
||||
const void *new_data, size_t new_data_size)
|
||||
{
|
||||
void *mapping, *data_mapping;
|
||||
size_t size = region_device_sz(rdev);
|
||||
size_t old_data_size = region_device_sz(rdev) - sizeof(struct mrc_metadata);
|
||||
bool need_update = false;
|
||||
|
||||
if (new_data_size != size)
|
||||
if (new_data_size != old_data_size)
|
||||
return true;
|
||||
|
||||
mapping = rdev_mmap_full(rdev);
|
||||
@@ -384,6 +406,7 @@ static void update_mrc_cache_by_type(int type,
|
||||
const struct region_device *backing_rdev;
|
||||
struct region_device latest_rdev;
|
||||
const bool fail_bad_data = false;
|
||||
uint32_t hash_idx;
|
||||
|
||||
cr = lookup_region(®ion, type);
|
||||
|
||||
@@ -443,6 +466,9 @@ static void update_mrc_cache_by_type(int type,
|
||||
} else {
|
||||
printk(BIOS_DEBUG, "MRC: updated '%s'.\n", cr->name);
|
||||
log_event_cache_update(cr->elog_slot, UPDATE_SUCCESS);
|
||||
hash_idx = cr->tpm_hash_index;
|
||||
if (hash_idx && CONFIG(MRC_SAVE_HASH_IN_TPM))
|
||||
mrc_cache_update_hash(hash_idx, new_data, new_data_size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -6,6 +6,18 @@ config SMMSTORE
|
||||
default y if PAYLOAD_TIANOCORE
|
||||
select SPI_FLASH_SMM if BOOT_DEVICE_SPI_FLASH_RW_NOMMAP
|
||||
|
||||
config SMMSTORE_V2
|
||||
bool "Use version 2 of SMMSTORE API"
|
||||
depends on SMMSTORE
|
||||
default n
|
||||
help
|
||||
Version 2 of SMMSTORE allows secure communication with SMM and
|
||||
makes no assumptions on the structure of the data stored within.
|
||||
It splits the store into chunks to allows fault tolerant writes.
|
||||
|
||||
By using version 2 you cannot make use of software that expects
|
||||
a version 1 SMMSTORE.
|
||||
|
||||
config SMMSTORE_IN_CBFS
|
||||
bool
|
||||
default n
|
||||
|
@@ -1,3 +1,4 @@
|
||||
ramstage-$(CONFIG_SMMSTORE) += store.c
|
||||
ramstage-$(CONFIG_SMMSTORE_V2) += ramstage.c
|
||||
|
||||
smm-$(CONFIG_SMMSTORE) += store.c smi.c
|
||||
|
76
src/drivers/smmstore/ramstage.c
Normal file
76
src/drivers/smmstore/ramstage.c
Normal file
@@ -0,0 +1,76 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
|
||||
#include <bootstate.h>
|
||||
#include <cpu/x86/smm.h>
|
||||
#include <commonlib/helpers.h>
|
||||
#include <commonlib/region.h>
|
||||
#include <console/console.h>
|
||||
#include <smmstore.h>
|
||||
#include <types.h>
|
||||
#include <cbmem.h>
|
||||
|
||||
static struct smmstore_params_info info;
|
||||
|
||||
void lb_smmstorev2(struct lb_header *header)
|
||||
{
|
||||
struct lb_record *rec;
|
||||
struct lb_smmstorev2 *store;
|
||||
const struct cbmem_entry *e;
|
||||
|
||||
e = cbmem_entry_find(CBMEM_ID_SMM_COMBUFFER);
|
||||
if (!e)
|
||||
return;
|
||||
|
||||
rec = lb_new_record(header);
|
||||
store = (struct lb_smmstorev2 *)rec;
|
||||
|
||||
store->tag = LB_TAG_SMMSTOREV2;
|
||||
store->size = sizeof(*store);
|
||||
store->com_buffer = (uintptr_t)cbmem_entry_start(e);
|
||||
store->com_buffer_size = cbmem_entry_size(e);
|
||||
store->mmap_addr = info.mmap_addr;
|
||||
store->num_blocks = info.num_blocks;
|
||||
store->block_size = info.block_size;
|
||||
store->apm_cmd = APM_CNT_SMMSTORE;
|
||||
}
|
||||
|
||||
static void init_store(void *unused)
|
||||
{
|
||||
struct smmstore_params_init args;
|
||||
uint32_t eax = ~0;
|
||||
uint32_t ebx;
|
||||
|
||||
if (smmstore_get_info(&info) < 0) {
|
||||
printk(BIOS_INFO, "SMMSTORE: Failed to get meta data\n");
|
||||
return;
|
||||
}
|
||||
|
||||
void *ptr = cbmem_add(CBMEM_ID_SMM_COMBUFFER, info.block_size);
|
||||
if (!ptr) {
|
||||
printk(BIOS_ERR, "SMMSTORE: Failed to add com buffer\n");
|
||||
return;
|
||||
}
|
||||
|
||||
args.com_buffer = (uintptr_t)ptr;
|
||||
args.com_buffer_size = info.block_size;
|
||||
ebx = (uintptr_t)&args;
|
||||
|
||||
printk(BIOS_INFO, "SMMSTORE: Setting up SMI handler\n");
|
||||
|
||||
/* Issue SMI using APM to update the com buffer and to lock the SMMSTORE */
|
||||
__asm__ __volatile__ (
|
||||
"outb %%al, %%dx"
|
||||
: "=a" (eax)
|
||||
: "a" ((SMMSTORE_CMD_INIT << 8) | APM_CNT_SMMSTORE),
|
||||
"b" (ebx),
|
||||
"d" (APM_CNT)
|
||||
: "memory");
|
||||
|
||||
if (eax != SMMSTORE_RET_SUCCESS) {
|
||||
printk(BIOS_ERR, "SMMSTORE: Failed to install com buffer\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* The SMI APM handler is installed at DEV_INIT phase */
|
||||
BOOT_STATE_INIT_ENTRY(BS_DEV_INIT, BS_ON_EXIT, init_store, NULL);
|
@@ -23,8 +23,7 @@ static int range_check(void *start, size_t size)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Param is usually EBX, ret in EAX */
|
||||
uint32_t smmstore_exec(uint8_t command, void *param)
|
||||
static uint32_t smmstorev1_exec(uint8_t command, void *param)
|
||||
{
|
||||
uint32_t ret = SMMSTORE_RET_FAILURE;
|
||||
|
||||
@@ -66,13 +65,89 @@ uint32_t smmstore_exec(uint8_t command, void *param)
|
||||
ret = SMMSTORE_RET_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
printk(BIOS_DEBUG,
|
||||
"Unknown SMM store command: 0x%02x\n", command);
|
||||
"Unknown SMM store v1 command: 0x%02x\n", command);
|
||||
ret = SMMSTORE_RET_UNSUPPORTED;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static uint32_t smmstorev2_exec(uint8_t command, void *param)
|
||||
{
|
||||
uint32_t ret = SMMSTORE_RET_FAILURE;
|
||||
|
||||
switch (command) {
|
||||
case SMMSTORE_CMD_INIT: {
|
||||
printk(BIOS_DEBUG, "Init SMM store\n");
|
||||
struct smmstore_params_init *params = param;
|
||||
|
||||
if (range_check(params, sizeof(*params)) != 0)
|
||||
break;
|
||||
|
||||
void *buf = (void *)(uintptr_t)params->com_buffer;
|
||||
|
||||
if (range_check(buf, params->com_buffer_size) != 0)
|
||||
break;
|
||||
|
||||
if (smmstore_init(buf, params->com_buffer_size) == 0)
|
||||
ret = SMMSTORE_RET_SUCCESS;
|
||||
break;
|
||||
}
|
||||
case SMMSTORE_CMD_RAW_READ: {
|
||||
printk(BIOS_DEBUG, "Raw read from SMM store, param = %p\n", param);
|
||||
struct smmstore_params_raw_read *params = param;
|
||||
|
||||
if (range_check(params, sizeof(*params)) != 0)
|
||||
break;
|
||||
|
||||
if (smmstore_rawread_region(params->block_id, params->bufoffset,
|
||||
params->bufsize) == 0)
|
||||
ret = SMMSTORE_RET_SUCCESS;
|
||||
break;
|
||||
}
|
||||
case SMMSTORE_CMD_RAW_WRITE: {
|
||||
printk(BIOS_DEBUG, "Raw write to SMM store, param = %p\n", param);
|
||||
struct smmstore_params_raw_write *params = param;
|
||||
|
||||
if (range_check(params, sizeof(*params)) != 0)
|
||||
break;
|
||||
|
||||
if (smmstore_rawwrite_region(params->block_id, params->bufoffset,
|
||||
params->bufsize) == 0)
|
||||
ret = SMMSTORE_RET_SUCCESS;
|
||||
break;
|
||||
}
|
||||
case SMMSTORE_CMD_RAW_CLEAR: {
|
||||
printk(BIOS_DEBUG, "Raw clear SMM store, param = %p\n", param);
|
||||
struct smmstore_params_raw_clear *params = param;
|
||||
|
||||
if (range_check(params, sizeof(*params)) != 0)
|
||||
break;
|
||||
|
||||
if (smmstore_rawclear_region(params->block_id) == 0)
|
||||
ret = SMMSTORE_RET_SUCCESS;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
printk(BIOS_DEBUG,
|
||||
"Unknown SMM store v2 command: 0x%02x\n", command);
|
||||
ret = SMMSTORE_RET_UNSUPPORTED;
|
||||
break;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint32_t smmstore_exec(uint8_t command, void *param)
|
||||
{
|
||||
if (!param)
|
||||
return SMMSTORE_RET_FAILURE;
|
||||
|
||||
if (CONFIG(SMMSTORE_V2))
|
||||
return smmstorev2_exec(command, param);
|
||||
else
|
||||
return smmstorev1_exec(command, param);
|
||||
}
|
||||
|
@@ -262,3 +262,200 @@ int smmstore_clear_region(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Implementation of Version 2 */
|
||||
|
||||
static bool store_initialized;
|
||||
static struct mem_region_device mdev_com_buf;
|
||||
|
||||
static int smmstore_rdev_chain(struct region_device *rdev)
|
||||
{
|
||||
if (!store_initialized)
|
||||
return -1;
|
||||
|
||||
return rdev_chain_full(rdev, &mdev_com_buf.rdev);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call once before using the store. In SMM this must be called through an
|
||||
* APM SMI handler providing the communication buffer address and length.
|
||||
*/
|
||||
int smmstore_init(void *buf, size_t len)
|
||||
{
|
||||
if (!buf || len < SMM_BLOCK_SIZE)
|
||||
return -1;
|
||||
|
||||
if (store_initialized)
|
||||
return -1;
|
||||
|
||||
mem_region_device_rw_init(&mdev_com_buf, buf, len);
|
||||
|
||||
store_initialized = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if ENV_RAMSTAGE
|
||||
/**
|
||||
* Provide metadata for the coreboot tables.
|
||||
* Must only be called in ramstage, but not in SMM.
|
||||
*/
|
||||
int smmstore_get_info(struct smmstore_params_info *out)
|
||||
{
|
||||
struct region_device store;
|
||||
|
||||
if (lookup_store(&store) < 0) {
|
||||
printk(BIOS_ERR, "smm store: lookup of store failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!IS_ALIGNED(region_device_offset(&store), SMM_BLOCK_SIZE)) {
|
||||
printk(BIOS_ERR, "smm store: store not aligned to block size\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
out->block_size = SMM_BLOCK_SIZE;
|
||||
out->num_blocks = region_device_sz(&store) / SMM_BLOCK_SIZE;
|
||||
|
||||
/* FIXME: Broken EDK2 always assumes memory mapped Firmware Block Volumes */
|
||||
out->mmap_addr = (uintptr_t)rdev_mmap_full(&store);
|
||||
|
||||
printk(BIOS_DEBUG, "smm store: %d # blocks with size 0x%x\n",
|
||||
out->num_blocks, out->block_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Returns -1 on error, 0 on success */
|
||||
static int lookup_block_in_store(struct region_device *store, uint32_t block_id)
|
||||
{
|
||||
if (lookup_store(store) < 0) {
|
||||
printk(BIOS_ERR, "smm store: lookup of store failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((block_id * SMM_BLOCK_SIZE) >= region_device_sz(store)) {
|
||||
printk(BIOS_ERR, "smm store: block ID out of range\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns NULL on error, pointer from rdev_mmap on success */
|
||||
static void *mmap_com_buf(struct region_device *com_buf, uint32_t offset, uint32_t bufsize)
|
||||
{
|
||||
if (smmstore_rdev_chain(com_buf) < 0) {
|
||||
printk(BIOS_ERR, "smm store: lookup of com buffer failed\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (offset >= region_device_sz(com_buf)) {
|
||||
printk(BIOS_ERR, "smm store: offset out of range\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void *ptr = rdev_mmap(com_buf, offset, bufsize);
|
||||
if (!ptr)
|
||||
printk(BIOS_ERR, "smm store: not enough space for new data\n");
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the specified block of the SMMSTORE and places it in the communication
|
||||
* buffer.
|
||||
* @param block_id The id of the block to operate on
|
||||
* @param offset Offset within the block.
|
||||
* Must be smaller than the block size.
|
||||
* @param bufsize Size of chunk to read within the block.
|
||||
* Must be smaller than the block size.
|
||||
|
||||
* @return Returns -1 on error, 0 on success.
|
||||
*/
|
||||
int smmstore_rawread_region(uint32_t block_id, uint32_t offset, uint32_t bufsize)
|
||||
{
|
||||
struct region_device store;
|
||||
struct region_device com_buf;
|
||||
|
||||
if (lookup_block_in_store(&store, block_id) < 0)
|
||||
return -1;
|
||||
|
||||
void *ptr = mmap_com_buf(&com_buf, offset, bufsize);
|
||||
if (!ptr)
|
||||
return -1;
|
||||
|
||||
printk(BIOS_DEBUG, "smm store: reading %p block %d, offset=0x%x, size=%x\n",
|
||||
ptr, block_id, offset, bufsize);
|
||||
|
||||
ssize_t ret = rdev_readat(&store, ptr, block_id * SMM_BLOCK_SIZE + offset, bufsize);
|
||||
rdev_munmap(&com_buf, ptr);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the specified block of the SMMSTORE by reading it from the communication
|
||||
* buffer.
|
||||
* @param block_id The id of the block to operate on
|
||||
* @param offset Offset within the block.
|
||||
* Must be smaller than the block size.
|
||||
* @param bufsize Size of chunk to read within the block.
|
||||
* Must be smaller than the block size.
|
||||
|
||||
* @return Returns -1 on error, 0 on success.
|
||||
*/
|
||||
int smmstore_rawwrite_region(uint32_t block_id, uint32_t offset, uint32_t bufsize)
|
||||
{
|
||||
struct region_device store;
|
||||
struct region_device com_buf;
|
||||
|
||||
if (lookup_block_in_store(&store, block_id) < 0)
|
||||
return -1;
|
||||
|
||||
if (rdev_chain(&store, &store, block_id * SMM_BLOCK_SIZE + offset, bufsize)) {
|
||||
printk(BIOS_ERR, "smm store: not enough space for new data\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
void *ptr = mmap_com_buf(&com_buf, offset, bufsize);
|
||||
if (!ptr)
|
||||
return -1;
|
||||
|
||||
printk(BIOS_DEBUG, "smm store: writing %p block %d, offset=0x%x, size=%x\n",
|
||||
ptr, block_id, offset, bufsize);
|
||||
|
||||
ssize_t ret = rdev_writeat(&store, ptr, 0, bufsize);
|
||||
rdev_munmap(&com_buf, ptr);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Erases the specified block of the SMMSTORE. The communication buffer remains untouched.
|
||||
*
|
||||
* @param block_id The id of the block to operate on
|
||||
*
|
||||
* @return Returns -1 on error, 0 on success.
|
||||
*/
|
||||
int smmstore_rawclear_region(uint32_t block_id)
|
||||
{
|
||||
struct region_device store;
|
||||
|
||||
if (lookup_block_in_store(&store, block_id) < 0)
|
||||
return -1;
|
||||
|
||||
ssize_t ret = rdev_eraseat(&store, block_id * SMM_BLOCK_SIZE, SMM_BLOCK_SIZE);
|
||||
if (ret != SMM_BLOCK_SIZE) {
|
||||
printk(BIOS_ERR, "smm store: erasing block failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@@ -259,11 +259,11 @@ static void sn65dsi86_bridge_valid_dp_rates(uint8_t bus, uint8_t chip, bool rate
|
||||
DP_BRIDGE_DPCD_REV, 1, DPCD_READ, &dpcd_val);
|
||||
if (dpcd_val >= DP_BRIDGE_14) {
|
||||
/* eDP 1.4 devices must provide a custom table */
|
||||
uint8_t sink_rates[DP_MAX_SUPPORTED_RATES * 2];
|
||||
uint16_t sink_rates[DP_MAX_SUPPORTED_RATES] = {0};
|
||||
|
||||
sn65dsi86_bridge_dpcd_request(bus, chip, DP_SUPPORTED_LINK_RATES,
|
||||
sizeof(sink_rates),
|
||||
DPCD_READ, sink_rates);
|
||||
DPCD_READ, (void *)sink_rates);
|
||||
for (i = 0; i < ARRAY_SIZE(sink_rates); i++) {
|
||||
rate_per_200khz = le16_to_cpu(sink_rates[i]);
|
||||
|
||||
@@ -288,14 +288,12 @@ static void sn65dsi86_bridge_valid_dp_rates(uint8_t bus, uint8_t chip, bool rate
|
||||
}
|
||||
|
||||
/* On older versions best we can do is use DP_MAX_LINK_RATE */
|
||||
sn65dsi86_bridge_dpcd_request(bus, chip,
|
||||
DP_MAX_LINK_RATE, 1, DPCD_READ, &dpcd_val);
|
||||
sn65dsi86_bridge_dpcd_request(bus, chip, DP_MAX_LINK_RATE, 1, DPCD_READ, &dpcd_val);
|
||||
|
||||
switch (dpcd_val) {
|
||||
default:
|
||||
printk(BIOS_ERR,
|
||||
"Unexpected max rate (%#x); assuming 5.4 GHz\n",
|
||||
(int)dpcd_val);
|
||||
printk(BIOS_ERR, "Unexpected max rate (%#x); assuming 5.4 GHz\n",
|
||||
(int)dpcd_val);
|
||||
/* fall through */
|
||||
case DP_LINK_BW_5_4:
|
||||
rate_valid[7] = 1;
|
||||
|
@@ -1,11 +1,19 @@
|
||||
config DRIVERS_WIFI_GENERIC
|
||||
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.
|
||||
|
||||
config DRIVERS_INTEL_WIFI
|
||||
bool "Support Intel PCI-e WiFi adapters"
|
||||
depends on PCI
|
||||
default y if PCIEXP_PLUGIN_SUPPORT
|
||||
select DRIVERS_WIFI_GENERIC
|
||||
help
|
||||
When enabled, add identifiers in ACPI and SMBIOS tables to
|
||||
make OS drivers work with certain Intel PCI-e WiFi chipsets.
|
||||
|
||||
if DRIVERS_WIFI_GENERIC
|
||||
|
||||
config USE_SAR
|
||||
|
@@ -1 +1,5 @@
|
||||
ramstage-$(CONFIG_DRIVERS_WIFI_GENERIC) += generic.c
|
||||
|
||||
cbfs-files-$(CONFIG_WIFI_SAR_CBFS) += wifi_sar_defaults.hex
|
||||
wifi_sar_defaults.hex-file := $(call strip_quotes,$(CONFIG_WIFI_SAR_CBFS_FILEPATH))
|
||||
wifi_sar_defaults.hex-type := raw
|
||||
|
@@ -11,26 +11,4 @@ struct drivers_wifi_generic_config {
|
||||
unsigned int wake;
|
||||
};
|
||||
|
||||
/**
|
||||
* wifi_generic_fill_ssdt() - Fill ACPI SSDT table for WiFi controller
|
||||
* @dev: Device structure corresponding to WiFi controller.
|
||||
* @config: Generic wifi config required to fill ACPI SSDT table.
|
||||
*
|
||||
* This function implements common device operation to help fill ACPI SSDT
|
||||
* table for WiFi controller.
|
||||
*/
|
||||
void wifi_generic_fill_ssdt(const struct device *dev,
|
||||
const struct drivers_wifi_generic_config *config);
|
||||
|
||||
/**
|
||||
* wifi_generic_acpi_name() - Get ACPI name for WiFi controller
|
||||
* @dev: Device structure corresponding to WiFi controller.
|
||||
*
|
||||
* This function implements common device operation to get the ACPI name for
|
||||
* WiFi controller.
|
||||
*
|
||||
* Return: string representing the ACPI name for WiFi controller.
|
||||
*/
|
||||
const char *wifi_generic_acpi_name(const struct device *dev);
|
||||
|
||||
#endif /* _GENERIC_WIFI_H_ */
|
||||
|
@@ -6,8 +6,10 @@
|
||||
#include <device/device.h>
|
||||
#include <device/pci.h>
|
||||
#include <device/pci_def.h>
|
||||
#include <device/pci_ids.h>
|
||||
#include <elog.h>
|
||||
#include <sar.h>
|
||||
#include <smbios.h>
|
||||
#include <string.h>
|
||||
#include <wrdd.h>
|
||||
#include "chip.h"
|
||||
@@ -35,18 +37,23 @@
|
||||
*/
|
||||
#define WIFI_ACPI_NAME_MAX_LEN 5
|
||||
|
||||
#if CONFIG(HAVE_ACPI_TABLES)
|
||||
__weak
|
||||
int get_wifi_sar_limits(struct wifi_sar_limits *sar_limits)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void emit_sar_acpi_structures(void)
|
||||
static void emit_sar_acpi_structures(const struct device *dev)
|
||||
{
|
||||
int i, j, package_size;
|
||||
struct wifi_sar_limits sar_limits;
|
||||
struct wifi_sar_delta_table *wgds;
|
||||
|
||||
/* CBFS SAR and SAR ACPI tables are currently used only by Intel WiFi devices. */
|
||||
if (dev->vendor != PCI_VENDOR_ID_INTEL)
|
||||
return;
|
||||
|
||||
/* Retrieve the sar limits data */
|
||||
if (get_wifi_sar_limits(&sar_limits) < 0) {
|
||||
printk(BIOS_ERR, "Error: failed from getting SAR limits!\n");
|
||||
@@ -160,11 +167,11 @@ static void emit_sar_acpi_structures(void)
|
||||
acpigen_pop_len();
|
||||
}
|
||||
|
||||
void wifi_generic_fill_ssdt(const struct device *dev,
|
||||
const struct drivers_wifi_generic_config *config)
|
||||
static void wifi_generic_fill_ssdt(const struct device *dev)
|
||||
{
|
||||
const char *path;
|
||||
u32 address;
|
||||
const struct drivers_wifi_generic_config *config = dev->chip_info;
|
||||
|
||||
if (!dev->enabled)
|
||||
return;
|
||||
@@ -214,7 +221,7 @@ void wifi_generic_fill_ssdt(const struct device *dev,
|
||||
|
||||
/* Fill Wifi sar related ACPI structures */
|
||||
if (CONFIG(USE_SAR))
|
||||
emit_sar_acpi_structures();
|
||||
emit_sar_acpi_structures(dev);
|
||||
|
||||
acpigen_pop_len(); /* Device */
|
||||
acpigen_pop_len(); /* Scope */
|
||||
@@ -223,7 +230,7 @@ void wifi_generic_fill_ssdt(const struct device *dev,
|
||||
dev->chip_ops ? dev->chip_ops->name : "", dev_path(dev));
|
||||
}
|
||||
|
||||
const char *wifi_generic_acpi_name(const struct device *dev)
|
||||
static const char *wifi_generic_acpi_name(const struct device *dev)
|
||||
{
|
||||
static char wifi_acpi_name[WIFI_ACPI_NAME_MAX_LEN];
|
||||
|
||||
@@ -232,11 +239,7 @@ const char *wifi_generic_acpi_name(const struct device *dev)
|
||||
(dev_path_encode(dev) & 0xff));
|
||||
return wifi_acpi_name;
|
||||
}
|
||||
|
||||
static void wifi_generic_fill_ssdt_generator(const struct device *dev)
|
||||
{
|
||||
wifi_generic_fill_ssdt(dev, dev->chip_info);
|
||||
}
|
||||
#endif
|
||||
|
||||
static void wifi_pci_dev_init(struct device *dev)
|
||||
{
|
||||
@@ -244,14 +247,55 @@ static void wifi_pci_dev_init(struct device *dev)
|
||||
elog_add_event_wake(ELOG_WAKE_SOURCE_PME_WIFI, 0);
|
||||
}
|
||||
|
||||
#if CONFIG(GENERATE_SMBIOS_TABLES)
|
||||
static int smbios_write_intel_wifi(struct device *dev, int *handle, unsigned long *current)
|
||||
{
|
||||
struct smbios_type_intel_wifi {
|
||||
u8 type;
|
||||
u8 length;
|
||||
u16 handle;
|
||||
u8 str;
|
||||
u8 eos[2];
|
||||
} __packed;
|
||||
|
||||
struct smbios_type_intel_wifi *t = (struct smbios_type_intel_wifi *)*current;
|
||||
int len = sizeof(struct smbios_type_intel_wifi);
|
||||
|
||||
memset(t, 0, sizeof(struct smbios_type_intel_wifi));
|
||||
t->type = 0x85;
|
||||
t->length = len - 2;
|
||||
t->handle = *handle;
|
||||
/* Intel wifi driver expects this string to be in the table 0x85. */
|
||||
t->str = smbios_add_string(t->eos, "KHOIHGIUCCHHII");
|
||||
|
||||
len = t->length + smbios_string_table_len(t->eos);
|
||||
*current += len;
|
||||
*handle += 1;
|
||||
return len;
|
||||
}
|
||||
|
||||
static int smbios_write_wifi(struct device *dev, int *handle, unsigned long *current)
|
||||
{
|
||||
if (dev->vendor == PCI_VENDOR_ID_INTEL)
|
||||
return smbios_write_intel_wifi(dev, handle, current);
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct device_operations wifi_generic_ops = {
|
||||
.read_resources = pci_dev_read_resources,
|
||||
.set_resources = pci_dev_set_resources,
|
||||
.enable_resources = pci_dev_enable_resources,
|
||||
.init = wifi_pci_dev_init,
|
||||
.ops_pci = &pci_dev_ops_pci,
|
||||
#if CONFIG(HAVE_ACPI_TABLES)
|
||||
.acpi_name = wifi_generic_acpi_name,
|
||||
.acpi_fill_ssdt = wifi_generic_fill_ssdt_generator,
|
||||
.acpi_fill_ssdt = wifi_generic_fill_ssdt,
|
||||
#endif
|
||||
#if CONFIG(GENERATE_SMBIOS_TABLES)
|
||||
.get_smbios_data = smbios_write_wifi,
|
||||
#endif
|
||||
};
|
||||
|
||||
static void wifi_generic_enable(struct device *dev)
|
||||
@@ -268,3 +312,67 @@ struct chip_operations drivers_wifi_generic_ops = {
|
||||
CHIP_NAME("WIFI Device")
|
||||
.enable_dev = wifi_generic_enable
|
||||
};
|
||||
|
||||
static const unsigned short intel_pci_device_ids[] = {
|
||||
PCI_DEVICE_ID_1000_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_6005_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_6005_I_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_1030_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_6030_I_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_6030_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_6150_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_2030_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_2000_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_0135_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_0105_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_6035_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_5300_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_5100_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_6000_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_6000_I_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_5350_SERIES_WIFI,
|
||||
PCI_DEVICE_ID_5150_SERIES_WIFI,
|
||||
/* Wilkins Peak 2 */
|
||||
PCI_DEVICE_ID_WP_7260_SERIES_1_WIFI,
|
||||
PCI_DEVICE_ID_WP_7260_SERIES_2_WIFI,
|
||||
/* Stone Peak 2 */
|
||||
PCI_DEVICE_ID_SP_7265_SERIES_1_WIFI,
|
||||
PCI_DEVICE_ID_SP_7265_SERIES_2_WIFI,
|
||||
/* Stone Field Peak */
|
||||
PCI_DEVICE_ID_SFP_8260_SERIES_1_WIFI,
|
||||
PCI_DEVICE_ID_SFP_8260_SERIES_2_WIFI,
|
||||
/* Windstorm Peak */
|
||||
PCI_DEVICE_ID_WSP_8275_SERIES_1_WIFI,
|
||||
/* Jefferson Peak */
|
||||
PCI_DEVICE_ID_JP_9000_SERIES_1_WIFI,
|
||||
PCI_DEVICE_ID_JP_9000_SERIES_2_WIFI,
|
||||
PCI_DEVICE_ID_JP_9000_SERIES_3_WIFI,
|
||||
/* Thunder Peak 2 */
|
||||
PCI_DEVICE_ID_TP_9260_SERIES_WIFI,
|
||||
/* Harrison Peak */
|
||||
PCI_DEVICE_ID_HrP_9560_SERIES_1_WIFI,
|
||||
PCI_DEVICE_ID_HrP_9560_SERIES_2_WIFI,
|
||||
PCI_DEVICE_ID_HrP_9560_SERIES_3_WIFI,
|
||||
PCI_DEVICE_ID_HrP_9560_SERIES_4_WIFI,
|
||||
PCI_DEVICE_ID_HrP_6SERIES_WIFI,
|
||||
/* Cyclone Peak */
|
||||
PCI_DEVICE_ID_CyP_6SERIES_WIFI,
|
||||
/* Typhoon Peak */
|
||||
PCI_DEVICE_ID_TyP_6SERIES_WIFI,
|
||||
/* Garfield Peak */
|
||||
PCI_DEVICE_ID_GrP_6SERIES_1_WIFI,
|
||||
PCI_DEVICE_ID_GrP_6SERIES_2_WIFI,
|
||||
0
|
||||
};
|
||||
|
||||
/*
|
||||
* The PCI driver is retained for backward compatibility with boards that never utilized the
|
||||
* chip driver to support Intel WiFi device. For these devices, the PCI driver helps perform the
|
||||
* same operations as above (except exposing the wake property) by utilizing the same
|
||||
* `wifi_generic_ops`.
|
||||
*/
|
||||
static const struct pci_driver intel_wifi_pci_driver __pci_driver = {
|
||||
.ops = &wifi_generic_ops,
|
||||
.vendor = PCI_VENDOR_ID_INTEL,
|
||||
.devices = intel_pci_device_ids,
|
||||
};
|
||||
|
@@ -1380,11 +1380,11 @@ enum ec_image google_chromeec_get_current_image(void)
|
||||
return ec_image_type;
|
||||
}
|
||||
|
||||
int google_chromeec_get_num_pd_ports(int *num_ports)
|
||||
int google_chromeec_get_num_pd_ports(unsigned int *num_ports)
|
||||
{
|
||||
struct ec_response_charge_port_count resp = {};
|
||||
struct chromeec_command cmd = {
|
||||
.cmd_code = EC_CMD_CHARGE_PORT_COUNT,
|
||||
.cmd_code = EC_CMD_USB_PD_PORTS,
|
||||
.cmd_version = 0,
|
||||
.cmd_data_out = &resp,
|
||||
.cmd_size_in = 0,
|
||||
@@ -1441,6 +1441,65 @@ int google_ec_running_ro(void)
|
||||
return (google_chromeec_get_current_image() == EC_IMAGE_RO);
|
||||
}
|
||||
|
||||
int google_chromeec_usb_pd_control(int port, bool *ufp, bool *dbg_acc, uint8_t *dp_mode)
|
||||
{
|
||||
struct ec_params_usb_pd_control pd_control = {
|
||||
.port = port,
|
||||
.role = USB_PD_CTRL_ROLE_NO_CHANGE,
|
||||
.mux = USB_PD_CTRL_ROLE_NO_CHANGE,
|
||||
.swap = USB_PD_CTRL_SWAP_NONE,
|
||||
};
|
||||
struct ec_response_usb_pd_control_v2 resp = {};
|
||||
struct chromeec_command cmd = {
|
||||
.cmd_code = EC_CMD_USB_PD_CONTROL,
|
||||
.cmd_version = 2,
|
||||
.cmd_data_in = &pd_control,
|
||||
.cmd_size_in = sizeof(pd_control),
|
||||
.cmd_data_out = &resp,
|
||||
.cmd_size_out = sizeof(resp),
|
||||
.cmd_dev_index = 0,
|
||||
};
|
||||
|
||||
if (google_chromeec_command(&cmd) < 0)
|
||||
return -1;
|
||||
|
||||
*ufp = (resp.cc_state == PD_CC_DFP_ATTACHED);
|
||||
*dbg_acc = (resp.cc_state == PD_CC_DFP_DEBUG_ACC);
|
||||
*dp_mode = resp.dp_mode;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for the current mux state in EC. Flags representing the mux state found
|
||||
* in ec_commands.h
|
||||
*/
|
||||
int google_chromeec_usb_get_pd_mux_info(int port, uint8_t *flags)
|
||||
{
|
||||
struct ec_params_usb_pd_mux_info req_mux = {
|
||||
.port = port,
|
||||
};
|
||||
struct ec_response_usb_pd_mux_info resp_mux = {};
|
||||
struct chromeec_command cmd = {
|
||||
.cmd_code = EC_CMD_USB_PD_MUX_INFO,
|
||||
.cmd_version = 0,
|
||||
.cmd_data_in = &req_mux,
|
||||
.cmd_size_in = sizeof(req_mux),
|
||||
.cmd_data_out = &resp_mux,
|
||||
.cmd_size_out = sizeof(resp_mux),
|
||||
.cmd_dev_index = 0,
|
||||
};
|
||||
|
||||
if (port < 0)
|
||||
return -1;
|
||||
|
||||
if (google_chromeec_command(&cmd) < 0)
|
||||
return -1;
|
||||
|
||||
*flags = resp_mux.flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if EC/TCPM is in an alternate mode or not.
|
||||
*
|
||||
@@ -1557,3 +1616,50 @@ int google_chromeec_ap_reset(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int google_chromeec_regulator_set_voltage(uint32_t index, uint32_t min_mv,
|
||||
uint32_t max_mv)
|
||||
{
|
||||
struct ec_params_regulator_set_voltage params = {
|
||||
.index = index,
|
||||
.min_mv = min_mv,
|
||||
.max_mv = max_mv,
|
||||
};
|
||||
struct chromeec_command cmd = {
|
||||
.cmd_code = EC_CMD_REGULATOR_SET_VOLTAGE,
|
||||
.cmd_version = 0,
|
||||
.cmd_data_in = ¶ms,
|
||||
.cmd_size_in = sizeof(params),
|
||||
.cmd_data_out = NULL,
|
||||
.cmd_size_out = 0,
|
||||
.cmd_dev_index = 0,
|
||||
};
|
||||
|
||||
if (google_chromeec_command(&cmd))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int google_chromeec_regulator_get_voltage(uint32_t index, uint32_t *voltage_mv)
|
||||
{
|
||||
struct ec_params_regulator_get_voltage params = {
|
||||
.index = index,
|
||||
};
|
||||
struct ec_response_regulator_get_voltage resp = {};
|
||||
struct chromeec_command cmd = {
|
||||
.cmd_code = EC_CMD_REGULATOR_GET_VOLTAGE,
|
||||
.cmd_version = 0,
|
||||
.cmd_data_in = ¶ms,
|
||||
.cmd_size_in = sizeof(params),
|
||||
.cmd_data_out = &resp,
|
||||
.cmd_size_out = sizeof(resp),
|
||||
.cmd_dev_index = 0,
|
||||
};
|
||||
|
||||
if (google_chromeec_command(&cmd))
|
||||
return -1;
|
||||
|
||||
*voltage_mv = resp.voltage_mv;
|
||||
return 0;
|
||||
}
|
||||
|
@@ -27,6 +27,15 @@ int google_ec_running_ro(void);
|
||||
enum ec_image google_chromeec_get_current_image(void);
|
||||
void google_chromeec_init(void);
|
||||
int google_chromeec_pd_get_amode(uint16_t svid);
|
||||
/* Check for the current mux state in EC
|
||||
* in: int port physical port number of the type-c port
|
||||
* out: uint8_t flags flags representing the status of the mux such as
|
||||
* usb capability, dp capability, cable type, etc
|
||||
*/
|
||||
int google_chromeec_usb_get_pd_mux_info(int port, uint8_t *flags);
|
||||
/* Returns data role and type of device connected */
|
||||
int google_chromeec_usb_pd_control(int port, bool *ufp, bool *dbg_acc,
|
||||
uint8_t *dp_mode);
|
||||
int google_chromeec_wait_for_displayport(long timeout);
|
||||
|
||||
/* Device events */
|
||||
@@ -306,7 +315,7 @@ int google_chromeec_get_cmd_versions(int command, uint32_t *pmask);
|
||||
* of PD-capable USB ports according to the EC.
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
int google_chromeec_get_num_pd_ports(int *num_ports);
|
||||
int google_chromeec_get_num_pd_ports(unsigned int *num_ports);
|
||||
|
||||
/* Structure representing the capabilities of a USB-PD port */
|
||||
struct usb_pd_port_caps {
|
||||
@@ -344,6 +353,24 @@ int google_chromeec_get_keybd_config(struct ec_response_keybd_config *keybd);
|
||||
*/
|
||||
int google_chromeec_ap_reset(void);
|
||||
|
||||
/**
|
||||
* Set voltage for the voltage regulator within the range specified.
|
||||
* @param index Regulator ID
|
||||
* @param min_mv Minimum voltage
|
||||
* @param max_mv Maximum voltage
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
int google_chromeec_regulator_set_voltage(uint32_t index, uint32_t min_mv,
|
||||
uint32_t max_mv);
|
||||
|
||||
/**
|
||||
* Get the currently configured voltage for the voltage regulator.
|
||||
* @param index Regulator ID
|
||||
* @param *voltage_mv If successful, voltage_mv is filled with current voltage
|
||||
* @return 0 on success, -1 on error
|
||||
*/
|
||||
int google_chromeec_regulator_get_voltage(uint32_t index, uint32_t *voltage_mv);
|
||||
|
||||
#if CONFIG(HAVE_ACPI_TABLES)
|
||||
/**
|
||||
* Writes USB Type-C PD related information to the SSDT
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user