mirror of https://github.com/wolfSSL/wolfBoot.git
Add function headers
parent
f791e98b16
commit
a29b78d680
|
@ -33,6 +33,9 @@
|
|||
#define PCI_AHCI_DEV 0x17
|
||||
#define PCI_AHCI_FUN 0
|
||||
|
||||
/*!
|
||||
* \brief Initializes the SATA controller.
|
||||
*/
|
||||
void x86_fsp_tgl_init_sata(void)
|
||||
{
|
||||
uint32_t sata_bar;
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit bbbafd68d09c6d453a5ef93214c9296dd7bc93b3
|
||||
Subproject commit 7c9391ebf3341ac10c8357adedd96ff42d59c845
|
|
@ -101,6 +101,16 @@ extern uint8_t _wolfboot_flash_end[];
|
|||
extern uint8_t wb_end_bss[], wb_start_bss[];
|
||||
extern int main(void);
|
||||
|
||||
/*!
|
||||
* \brief Get the top address from the EFI HOB (Hand-Off Block) list.
|
||||
*
|
||||
* This function retrieves the top address from the EFI Hand-Off Block (HOB) list
|
||||
* and stores it in the 'top' parameter.
|
||||
*
|
||||
* \param top Pointer to a variable where the top address will be stored.
|
||||
* \param hoblist Pointer to the EFI HOB list.
|
||||
* \return 0 if the top address is successfully retrieved, -1 otherwise.
|
||||
*/
|
||||
static int get_top_address(uint64_t *top, struct efi_hob *hoblist)
|
||||
{
|
||||
struct efi_hob_resource_descriptor *fsp_reserved;
|
||||
|
@ -115,6 +125,16 @@ static int get_top_address(uint64_t *top, struct efi_hob *hoblist)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Change the stack and invoke a function with the new stack.
|
||||
*
|
||||
* This function changes the stack to the specified 'new_stack' value and then
|
||||
* calls the function pointed to by 'other_func', passing the 'ptr' parameter as an argument.
|
||||
*
|
||||
* \param new_stack The new stack address.
|
||||
* \param other_func Pointer to the function to be invoked with the new stack.
|
||||
* \param ptr Pointer to the parameter to be passed to the invoked function.
|
||||
*/
|
||||
static void change_stack_and_invoke(uint32_t new_stack,
|
||||
void (*other_func)(void *), void *ptr)
|
||||
{
|
||||
|
@ -127,7 +147,12 @@ static void change_stack_and_invoke(uint32_t new_stack,
|
|||
: "r"(new_stack), "r"(ptr), "r"(other_func)
|
||||
: "%eax");
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Load the WolfBoot bootloader into memory.
|
||||
*
|
||||
* This static function loads the WolfBoot bootloader into memory at the specified
|
||||
* address (WOLFBOOT_LOAD_BASE) from the flash memory.
|
||||
*/
|
||||
static void load_wolfboot(void)
|
||||
{
|
||||
size_t wolfboot_size, bss_size;
|
||||
|
@ -153,12 +178,26 @@ static void load_fsp_s_to_ram(void)
|
|||
|
||||
extern uint8_t _stage2_params[];
|
||||
|
||||
/*!
|
||||
* \brief Set the stage 2 parameter for the WolfBoot bootloader.
|
||||
*
|
||||
* This static function sets the stage 2 parameter for the WolfBoot bootloader,
|
||||
* which will be used by the bootloader during its execution.
|
||||
*
|
||||
* \param p Pointer to the stage 2 parameter structure.
|
||||
*/
|
||||
static void set_stage2_parameter(struct stage2_parameter *p)
|
||||
{
|
||||
memcpy((uint8_t*)_stage2_params, (uint8_t*)p, sizeof(*p));
|
||||
}
|
||||
|
||||
#ifdef WOLFBOOT_64BIT
|
||||
/*!
|
||||
* \brief Jump into the WolfBoot bootloader.
|
||||
*
|
||||
* This static function transfers control to the WolfBoot bootloader by calling
|
||||
* the main() function or switch_to_long_mode() for 64-bit systems.
|
||||
*/
|
||||
static void jump_into_wolfboot(void)
|
||||
{
|
||||
struct stage2_parameter *params = (struct stage2_parameter*)_stage2_params;
|
||||
|
@ -183,7 +222,15 @@ static void jump_into_wolfboot()
|
|||
main();
|
||||
}
|
||||
#endif /* WOLFBOOT_64BIT */
|
||||
|
||||
/*!
|
||||
* \brief Check if the payload is valid.
|
||||
*
|
||||
* This static function checks if the given payload is valid by verifying
|
||||
* its signature.
|
||||
*
|
||||
* \param base_addr Pointer to the payload
|
||||
* \return 0 if the payload is successfully retrieved, -1 otherwise.
|
||||
*/
|
||||
static inline int verify_payload(uint8_t *base_addr)
|
||||
{
|
||||
int ret = -1;
|
||||
|
@ -208,7 +255,14 @@ static inline int verify_payload(uint8_t *base_addr)
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Entry point after memory initialization.
|
||||
*
|
||||
* This static function serves as the entry point for further execution after the
|
||||
* memory initialization is completed.
|
||||
*
|
||||
* \param ptr Pointer to a parameter structure.
|
||||
*/
|
||||
static void memory_ready_entry(void *ptr)
|
||||
{
|
||||
struct stage2_parameter *stage2_params = (struct stage2_parameter *)ptr;
|
||||
|
@ -308,6 +362,15 @@ static void memory_ready_entry(void *ptr)
|
|||
jump_into_wolfboot();
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Check if the FSP info header is valid.
|
||||
*
|
||||
* This static function checks if the given FSP info header is valid by verifying
|
||||
* its signature.
|
||||
*
|
||||
* \param hdr Pointer to the FSP info header structure.
|
||||
* \return 1 if the FSP info header is valid, 0 otherwise.
|
||||
*/
|
||||
static int fsp_info_header_is_ok(struct fsp_info_header *hdr)
|
||||
{
|
||||
uint8_t *raw_signature;
|
||||
|
@ -320,6 +383,18 @@ static int fsp_info_header_is_ok(struct fsp_info_header *hdr)
|
|||
return 1;
|
||||
}
|
||||
|
||||
/*!
|
||||
* \brief Entry point for the FSP-M (Firmware Support Package - Memory) module.
|
||||
*
|
||||
* This function serves as the entry point for the FSP-M module, which is executed
|
||||
* during the boot process. It takes the stack base, stack top, timestamp, and BIST
|
||||
* (Built-In Self Test) as input arguments.
|
||||
*
|
||||
* \param stack_base The base address of the stack.
|
||||
* \param stack_top The top address of the stack.
|
||||
* \param timestamp A timestamp value.
|
||||
* \param bist Built-In Self Test value.
|
||||
*/
|
||||
void start(uint32_t stack_base, uint32_t stack_top, uint64_t timestamp,
|
||||
uint32_t bist)
|
||||
{
|
||||
|
|
|
@ -18,6 +18,16 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
/**
|
||||
* @file boot_x86_fsp_payload.c
|
||||
*
|
||||
* @brief Boot functions for x86 FSP payload
|
||||
*
|
||||
* This file contains the boot functions for the x86 FSP payload of wolfBoot.
|
||||
* These functions include booting into Linux payload or ELF binaries.
|
||||
*/
|
||||
#ifndef BOOT_X86_FSP_PAYLOAD_H_
|
||||
#define BOOT_X86_FSP_PAYLOAD_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
@ -35,7 +45,13 @@
|
|||
#include <elf.h>
|
||||
#include <multiboot.h>
|
||||
|
||||
/**
|
||||
* @brief Maximum size of Multiboot2 boot info data structure.
|
||||
*/
|
||||
#define MAX_MB2_BOOT_INFO_SIZE 0x2000
|
||||
/**
|
||||
* @brief Multiboot2 boot info data structure.
|
||||
*/
|
||||
uint8_t mb2_boot_info[MAX_MB2_BOOT_INFO_SIZE];
|
||||
#endif
|
||||
#ifdef WOLFBOOT_64BIT
|
||||
|
@ -52,6 +68,13 @@ static char *cmdline = "console=ttyS0,115200 pci=earlydump debug";
|
|||
static char *cmdline = "auto";
|
||||
#endif /* TARGET_kontron_vx3060_s2 */
|
||||
|
||||
/**
|
||||
* @brief Jump to the specified entry point.
|
||||
*
|
||||
* This function performs an unconditional jump to the provided entry point.
|
||||
*
|
||||
* @param entry The entry point address to jump to.
|
||||
*/
|
||||
void jump(uintptr_t entry)
|
||||
{
|
||||
__asm__(
|
||||
|
@ -60,7 +83,15 @@ void jump(uintptr_t entry)
|
|||
: "g"(entry));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Perform the boot process for the given application.
|
||||
*
|
||||
* This function performs the boot process for the specified application.
|
||||
* It either loads and boots a Linux payload or an ELF binary, depending on the
|
||||
* configuration.
|
||||
*
|
||||
* @param app Pointer to the start of the application.
|
||||
*/
|
||||
void do_boot(const uint32_t *app)
|
||||
{
|
||||
|
||||
|
@ -112,3 +143,4 @@ void do_boot(const uint32_t *app)
|
|||
#error "No payload compiled in"
|
||||
#endif /* WOLFBOOT_LINUX_PAYLOAD */
|
||||
}
|
||||
#endif /* BOOT_X86_FSP_PAYLOAD_H_ */
|
||||
|
|
236
src/image.c
236
src/image.c
|
@ -18,6 +18,13 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
/**
|
||||
* @file image.c
|
||||
* @brief This file contains functions related to image handling and
|
||||
* verification.
|
||||
*/
|
||||
#ifndef IMAGE_H_
|
||||
#define IMAGE_H_
|
||||
#include "loader.h"
|
||||
#include "image.h"
|
||||
#include "hal.h"
|
||||
|
@ -50,6 +57,12 @@ static WOLFTPM2_KEY wolftpm_srk;
|
|||
static uint8_t digest[WOLFBOOT_SHA_DIGEST_SIZE];
|
||||
|
||||
/* Forward declarations */
|
||||
/**
|
||||
* @brief Find the key slot ID based on the SHA hash of the key.
|
||||
*
|
||||
* @param hint The SHA hash to find the key slot ID for.
|
||||
* @return The key slot ID corresponding to the provided SHA hash.
|
||||
*/
|
||||
static int keyslot_id_by_sha(const uint8_t *hint);
|
||||
|
||||
#ifdef WOLFBOOT_SIGN_ED25519
|
||||
|
@ -116,6 +129,14 @@ static void wolfBoot_verify_signature(uint8_t key_slot,
|
|||
#define ECC_KEY_TYPE ECC_SECP521R1
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Verify the ECC signature of the image using the provided key slot
|
||||
* and signature.
|
||||
*
|
||||
* @param key_slot The key slot ID to use for verification.
|
||||
* @param img The image to verify.
|
||||
* @param sig The ECC signature to use for verification.
|
||||
*/
|
||||
static void wolfBoot_verify_signature(uint8_t key_slot,
|
||||
struct wolfBoot_image *img, uint8_t *sig)
|
||||
{
|
||||
|
@ -372,10 +393,25 @@ static void wolfBoot_verify_signature(uint8_t key_slot,
|
|||
#endif /* WOLFBOOT_SIGN_RSA2048 || WOLFBOOT_SIGN_3072 || \
|
||||
* WOLFBOOT_SIGN_RSA4096 */
|
||||
|
||||
|
||||
/**
|
||||
* @brief Get the specified header type from the extended flash image.
|
||||
*
|
||||
* @param img The image to retrieve the header from.
|
||||
* @param type The type of header to retrieve.
|
||||
* @param ptr A pointer to the header data.
|
||||
* @return The size of the header if found, otherwise 0.
|
||||
*/
|
||||
static uint16_t get_header_ext(struct wolfBoot_image *img, uint16_t type,
|
||||
uint8_t **ptr);
|
||||
|
||||
/**
|
||||
* @brief Get the specified header type from the image.
|
||||
*
|
||||
* @param img The image to retrieve the header from.
|
||||
* @param type The type of header to retrieve.
|
||||
* @param ptr A pointer to the header data.
|
||||
* @return The size of the header if found, otherwise 0.
|
||||
*/
|
||||
static uint16_t get_header(struct wolfBoot_image *img, uint16_t type,
|
||||
uint8_t **ptr)
|
||||
{
|
||||
|
@ -388,6 +424,13 @@ static uint16_t get_header(struct wolfBoot_image *img, uint16_t type,
|
|||
#ifdef EXT_FLASH
|
||||
static uint8_t ext_hash_block[WOLFBOOT_SHA_BLOCK_SIZE];
|
||||
#endif
|
||||
/**
|
||||
* @brief Get a block of data from the SHA256 hash of the image.
|
||||
*
|
||||
* @param img The image to retrieve the data from.
|
||||
* @param offset The offset to start reading the data from.
|
||||
* @return A pointer to the data block.
|
||||
*/
|
||||
static uint8_t *get_sha_block(struct wolfBoot_image *img, uint32_t offset)
|
||||
{
|
||||
if (offset > img->fw_size)
|
||||
|
@ -406,6 +449,12 @@ static uint8_t *get_sha_block(struct wolfBoot_image *img, uint32_t offset)
|
|||
static uint8_t hdr_cpy[IMAGE_HEADER_SIZE];
|
||||
static int hdr_cpy_done = 0;
|
||||
|
||||
/**
|
||||
* @brief Get a copy of the image header.
|
||||
*
|
||||
* @param img The image to retrieve the header from.
|
||||
* @return A pointer to the copied header data.
|
||||
*/
|
||||
static uint8_t *fetch_hdr_cpy(struct wolfBoot_image *img)
|
||||
{
|
||||
if (!hdr_cpy_done) {
|
||||
|
@ -473,6 +522,13 @@ static int self_sha256(uint8_t *hash)
|
|||
}
|
||||
#endif /* WOLFBOOT_MEASURED_BOOT */
|
||||
|
||||
/**
|
||||
* @brief Calculate the SHA256 hash of the image.
|
||||
*
|
||||
* @param img The image to calculate the hash for.
|
||||
* @param hash A pointer to store the resulting SHA256 hash.
|
||||
* @return 0 on success, -1 on failure.
|
||||
*/
|
||||
static int image_sha256(struct wolfBoot_image *img, uint8_t *hash)
|
||||
{
|
||||
uint8_t *stored_sha, *end_sha;
|
||||
|
@ -514,6 +570,13 @@ static int image_sha256(struct wolfBoot_image *img, uint8_t *hash)
|
|||
}
|
||||
|
||||
#ifndef WOLFBOOT_NO_SIGN
|
||||
|
||||
/**
|
||||
* @brief Calculate the SHA256 hash of the RSA key.
|
||||
*
|
||||
* @param key_slot The key slot ID to calculate the hash for.
|
||||
* @param hash A pointer to store the resulting SHA256 hash.
|
||||
*/
|
||||
static void key_sha256(uint8_t key_slot, uint8_t *hash)
|
||||
{
|
||||
int blksz;
|
||||
|
@ -571,6 +634,15 @@ static int self_sha384(uint8_t *hash)
|
|||
}
|
||||
#endif /* WOLFBOOT_MEASURED_BOOT */
|
||||
|
||||
/**
|
||||
* @brief Calculate SHA-384 hash of the image.
|
||||
*
|
||||
* This function calculates the SHA-384 hash of the given image.
|
||||
*
|
||||
* @param img The pointer to the wolfBoot_image structure representing the image.
|
||||
* @param hash The buffer to store the SHA-384 hash (48 bytes).
|
||||
* @return 0 on success, -1 on error.
|
||||
*/
|
||||
static int image_sha384(struct wolfBoot_image *img, uint8_t *hash)
|
||||
{
|
||||
uint8_t *stored_sha, *end_sha;
|
||||
|
@ -612,6 +684,18 @@ static int image_sha384(struct wolfBoot_image *img, uint8_t *hash)
|
|||
}
|
||||
|
||||
#ifndef WOLFBOOT_NO_SIGN
|
||||
|
||||
/**
|
||||
* @brief Calculate SHA-384 hash of a public key in the keystore.
|
||||
*
|
||||
* This function calculates the SHA-384 hash of the public key stored in
|
||||
* the keystore at the specified key slot.
|
||||
*
|
||||
* @param key_slot The key slot ID where the public key is stored in the
|
||||
* keystore.
|
||||
* @param hash The buffer to store the SHA-384 hash (48 bytes).
|
||||
* @return None.
|
||||
*/
|
||||
static void key_sha384(uint8_t key_slot, uint8_t *hash)
|
||||
{
|
||||
int blksz;
|
||||
|
@ -640,6 +724,15 @@ static void key_sha384(uint8_t key_slot, uint8_t *hash)
|
|||
|
||||
#include <wolfssl/wolfcrypt/sha3.h>
|
||||
|
||||
/**
|
||||
* @brief Calculate SHA3-384 hash of the image.
|
||||
*
|
||||
* This function calculates the SHA3-384 hash of the given image.
|
||||
*
|
||||
* @param img The pointer to the wolfBoot_image structure representing the image.
|
||||
* @param hash The buffer to store the SHA3-384 hash (48 bytes).
|
||||
* @return 0 on success, -1 on error.
|
||||
*/
|
||||
static int image_sha3_384(struct wolfBoot_image *img, uint8_t *hash)
|
||||
{
|
||||
uint8_t *stored_sha, *end_sha;
|
||||
|
@ -680,6 +773,18 @@ static int image_sha3_384(struct wolfBoot_image *img, uint8_t *hash)
|
|||
return 0;
|
||||
}
|
||||
#ifndef WOLFBOOT_NO_SIGN
|
||||
|
||||
/**
|
||||
* @brief Calculate SHA3-384 hash of a public key in the keystore.
|
||||
*
|
||||
* This function calculates the SHA3-384 hash of the public key stored
|
||||
* in the keystore at the specified key slot.
|
||||
*
|
||||
* @param key_slot The key slot ID where the public key is stored in the
|
||||
* keystore.
|
||||
* @param hash The buffer to store the SHA3-384 hash (48 bytes).
|
||||
* @return None.
|
||||
*/
|
||||
static void key_sha3_384(uint8_t key_slot, uint8_t *hash)
|
||||
{
|
||||
int blksz;
|
||||
|
@ -748,6 +853,21 @@ static void wolfBoot_PrintBin(const byte* buffer, word32 length)
|
|||
static int TPM2_IoCb(TPM2_CTX* ctx, int isRead, word32 addr, byte* buf,
|
||||
word16 size, void* userCtx)
|
||||
#else
|
||||
|
||||
/**
|
||||
* @brief TPM2 I/O callback function for communication with TPM2 device.
|
||||
*
|
||||
* This function is used as the I/O callback function for communication
|
||||
* with the TPM2 device. It is called during TPM operations to send and
|
||||
* receive data from the TPM2 device.
|
||||
*
|
||||
* @param ctx The pointer to the TPM2 context.
|
||||
* @param txBuf The buffer containing data to be sent to the TPM2 device.
|
||||
* @param rxBuf The buffer to store the received data from the TPM2 device.
|
||||
* @param xferSz The size of the data to be transferred.
|
||||
* @param userCtx The user context (not used in this implementation).
|
||||
* @return The return code from the TPM2 device operation.
|
||||
*/
|
||||
static int TPM2_IoCb(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf,
|
||||
word16 xferSz, void* userCtx)
|
||||
#endif
|
||||
|
@ -846,6 +966,17 @@ static int TPM2_IoCb(TPM2_CTX* ctx, const byte* txBuf, byte* rxBuf,
|
|||
#ifdef WOLFBOOT_MEASURED_BOOT
|
||||
#define measure_boot(hash) wolfBoot_tpm2_extend((hash), __LINE__)
|
||||
static int wolfBoot_tpm2_extend(uint8_t* hash, int line)
|
||||
|
||||
/**
|
||||
* @brief Measure the boot state using TPM2 PCR extend operation.
|
||||
*
|
||||
* This function measures the boot state by extending the SHA-256 digest of
|
||||
* the image into the TPM2 Platform Configuration Registers (PCRs).
|
||||
*
|
||||
* @param img The pointer to the wolfBoot_image structure representing the image.
|
||||
* @return 0 on success, -1 on error.
|
||||
*/
|
||||
static int measure_boot(struct wolfBoot_image *img)
|
||||
{
|
||||
int rc;
|
||||
PCR_Extend_In pcrExtend;
|
||||
|
@ -896,6 +1027,13 @@ static int wolfRNG_GetSeedCB(OS_Seed* os, byte* seed, word32 sz)
|
|||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize the TPM2 device and retrieve its capabilities.
|
||||
*
|
||||
* This function initializes the TPM2 device and retrieves its capabilities.
|
||||
*
|
||||
* @return 0 on success, an error code on failure.
|
||||
*/
|
||||
int wolfBoot_tpm2_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
@ -974,6 +1112,13 @@ int wolfBoot_tpm2_init(void)
|
|||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deinitialize the TPM2 device.
|
||||
*
|
||||
* This function deinitializes the TPM2 device and cleans up any resources.
|
||||
*
|
||||
* @return None.
|
||||
*/
|
||||
void wolfBoot_tpm2_deinit(void)
|
||||
{
|
||||
#ifdef WOLFBOOT_TPM_KEYSTORE
|
||||
|
@ -996,6 +1141,15 @@ void wolfBoot_tpm2_deinit(void)
|
|||
|
||||
#endif /* WOLFBOOT_TPM */
|
||||
|
||||
/**
|
||||
* @brief Convert a 32-bit integer from little-endian to native byte order.
|
||||
*
|
||||
* This function converts a 32-bit integer from little-endian byte order to
|
||||
* the native byte order of the machine.
|
||||
*
|
||||
* @param val The 32-bit integer value in little-endian byte order.
|
||||
* @return The 32-bit integer value in native byte order.
|
||||
*/
|
||||
static inline uint32_t im2n(uint32_t val)
|
||||
{
|
||||
#ifdef BIG_ENDIAN_ORDER
|
||||
|
@ -1007,12 +1161,30 @@ static inline uint32_t im2n(uint32_t val)
|
|||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the size of the image from the image header.
|
||||
*
|
||||
* This function retrieves the size of the image from the image header.
|
||||
*
|
||||
* @param image The pointer to the image header.
|
||||
* @return The size of the image in bytes.
|
||||
*/
|
||||
uint32_t wolfBoot_image_size(uint8_t *image)
|
||||
{
|
||||
uint32_t *size = (uint32_t *)(image + sizeof (uint32_t));
|
||||
return im2n(*size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Open an image using the provided image address.
|
||||
*
|
||||
* This function opens an image using the provided image address and initializes
|
||||
* the wolfBoot_image structure.
|
||||
*
|
||||
* @param img The pointer to the wolfBoot_image structure to be initialized.
|
||||
* @param image The pointer to the image address.
|
||||
* @return 0 on success, -1 on error.
|
||||
*/
|
||||
int wolfBoot_open_image_address(struct wolfBoot_image *img, uint8_t *image)
|
||||
{
|
||||
uint32_t *magic = (uint32_t *)(image);
|
||||
|
@ -1054,6 +1226,15 @@ static uint32_t wb_reverse_word32(uint32_t x)
|
|||
return ByteReverseWord32(x);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the size of the Device Tree Blob (DTB).
|
||||
*
|
||||
* This function retrieves the size of the Device Tree Blob (DTB) from
|
||||
* the given DTB address.
|
||||
*
|
||||
* @param dts_addr The pointer to the Device Tree Blob (DTB) address.
|
||||
* @return The size of the DTB in bytes, or -1 if the magic number is invalid.
|
||||
*/
|
||||
int wolfBoot_get_dts_size(void *dts_addr)
|
||||
{
|
||||
uint32_t hdr[2];
|
||||
|
@ -1076,6 +1257,17 @@ int wolfBoot_get_dts_size(void *dts_addr)
|
|||
#endif
|
||||
|
||||
#ifdef WOLFBOOT_FIXED_PARTITIONS
|
||||
|
||||
/**
|
||||
* @brief Open an image in a specified partition.
|
||||
*
|
||||
* This function opens an image in the specified partition and initializes
|
||||
* the wolfBoot_image structure.
|
||||
*
|
||||
* @param img The pointer to the wolfBoot_image structure to be initialized.
|
||||
* @param part The partition ID (PART_BOOT, PART_UPDATE, PART_SWAP, etc.).
|
||||
* @return 0 on success, -1 on error.
|
||||
*/
|
||||
int wolfBoot_open_image(struct wolfBoot_image *img, uint8_t part)
|
||||
{
|
||||
#ifdef MMU
|
||||
|
@ -1141,6 +1333,15 @@ int wolfBoot_open_image(struct wolfBoot_image *img, uint8_t part)
|
|||
}
|
||||
#endif /* WOLFBOOT_FIXED_PARTITIONS */
|
||||
|
||||
/**
|
||||
* @brief Verify the integrity of the image using the stored SHA hash.
|
||||
*
|
||||
* This function verifies the integrity of the image by calculating its SHA hash
|
||||
* and comparing it with the stored hash.
|
||||
*
|
||||
* @param img The pointer to the wolfBoot_image structure representing the image.
|
||||
* @return 0 on success, -1 on error.
|
||||
*/
|
||||
int wolfBoot_verify_integrity(struct wolfBoot_image *img)
|
||||
{
|
||||
uint8_t *stored_sha;
|
||||
|
@ -1162,6 +1363,15 @@ int wolfBoot_verify_integrity(struct wolfBoot_image *img)
|
|||
}
|
||||
|
||||
#ifdef WOLFBOOT_NO_SIGN
|
||||
/**
|
||||
* @brief Verify the authenticity of the image using a digital signature.
|
||||
*
|
||||
* This function verifies the authenticity of the image by verifying its digital
|
||||
* signature.
|
||||
*
|
||||
* @param img The pointer to the wolfBoot_image structure representing the image.
|
||||
* @return 0 on success, -1 on error, -2 if the signature verification fails.
|
||||
*/
|
||||
int wolfBoot_verify_authenticity(struct wolfBoot_image *img)
|
||||
{
|
||||
wolfBoot_image_confirm_signature_ok(img);
|
||||
|
@ -1242,8 +1452,17 @@ int wolfBoot_verify_authenticity(struct wolfBoot_image *img)
|
|||
}
|
||||
#endif
|
||||
|
||||
/* Peek at image offset and return static pointer */
|
||||
/* sz: optional and returns length of peek */
|
||||
/**
|
||||
* @brief Peek at the content of the image at a specific offset.
|
||||
*
|
||||
* This function allows peeking at the content of the image at a specific offset
|
||||
* without modifying the image.
|
||||
*
|
||||
* @param img The pointer to the wolfBoot_image structure representing the image.
|
||||
* @param offset The offset within the image to peek at.
|
||||
* @param sz Optional pointer to store the size of the peeked data.
|
||||
* @return The pointer to the peeked data, or NULL if the offset is out of bounds.
|
||||
*/
|
||||
uint8_t* wolfBoot_peek_image(struct wolfBoot_image *img, uint32_t offset,
|
||||
uint32_t* sz)
|
||||
{
|
||||
|
@ -1254,6 +1473,16 @@ uint8_t* wolfBoot_peek_image(struct wolfBoot_image *img, uint32_t offset,
|
|||
}
|
||||
|
||||
#if !defined(WOLFBOOT_NO_SIGN) && !defined(WOLFBOOT_RENESAS_SCEPROTECT)
|
||||
|
||||
/**
|
||||
* @brief Get the key slot ID by SHA hash.
|
||||
*
|
||||
* This function retrieves the key slot ID from the keystore that matches the
|
||||
* provided SHA hash.
|
||||
*
|
||||
* @param hint The SHA hash of the public key to search for.
|
||||
* @return The key slot ID if found, -1 if the key was not found.
|
||||
*/
|
||||
static int keyslot_id_by_sha(const uint8_t *hint)
|
||||
{
|
||||
#ifdef STAGE1_AUTH
|
||||
|
@ -1301,3 +1530,4 @@ static int keyslot_id_by_sha(const uint8_t *hint)
|
|||
return -1;
|
||||
}
|
||||
#endif
|
||||
#endif /* IMAGE_H_ */
|
||||
|
|
|
@ -18,7 +18,13 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file libwolfboot.c
|
||||
*
|
||||
* @brief wolfBoot library implementation.
|
||||
*
|
||||
* This file contains the implementation of the wolfBoot library.
|
||||
*/
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
|
@ -28,12 +34,30 @@
|
|||
#include "printf.h"
|
||||
|
||||
#ifdef UNIT_TEST
|
||||
/**
|
||||
* @def unit_dbg
|
||||
* @brief Conditional debug macro for unit tests.
|
||||
*
|
||||
* Conditional debug macro for unit tests, redirects to wolfBoot_printf.
|
||||
*/
|
||||
# define unit_dbg wolfBoot_printf
|
||||
#else
|
||||
/**
|
||||
* @def unit_dbg
|
||||
* @brief Empty macro for unit_dbg in non-test builds.
|
||||
*
|
||||
* Empty macro for unit_dbg in non-test builds.
|
||||
*/
|
||||
# define unit_dbg(...) do{}while(0)
|
||||
#endif
|
||||
|
||||
#ifndef TRAILER_SKIP
|
||||
/**
|
||||
* @def TRAILER_SKIP
|
||||
* @brief Trailer skip value for partition encryption.
|
||||
*
|
||||
* Trailer skip value for partition encryption, defaults to 0 if not defined.
|
||||
*/
|
||||
# define TRAILER_SKIP 0
|
||||
#endif
|
||||
|
||||
|
@ -265,6 +289,16 @@ finish:
|
|||
return sel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write the trailer in a non-volatile memory.
|
||||
*
|
||||
* This function writes the trailer in a non-volatile memory.
|
||||
*
|
||||
* @param[in] part Partition number.
|
||||
* @param[in] addr Address of the trailer.
|
||||
* @param[in] val New value to write in the trailer.
|
||||
* @return 0 on success, -1 on failure.
|
||||
*/
|
||||
static int RAMFUNCTION trailer_write(uint8_t part, uintptr_t addr, uint8_t val)
|
||||
{
|
||||
uintptr_t addr_align = (size_t)(addr & (~(NVM_CACHE_SIZE - 1)));
|
||||
|
@ -303,6 +337,15 @@ static int RAMFUNCTION trailer_write(uint8_t part, uintptr_t addr, uint8_t val)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write the partition magic in a non-volatile memory.
|
||||
*
|
||||
* This function writes the partition magic in a non-volatile memory.
|
||||
*
|
||||
* @param[in] part Partition number.
|
||||
* @param[in] addr Address of the magic trailer.
|
||||
* @return 0 on success, -1 on failure.
|
||||
*/
|
||||
static int RAMFUNCTION partition_magic_write(uint8_t part, uintptr_t addr)
|
||||
{
|
||||
uintptr_t off = addr % NVM_CACHE_SIZE;
|
||||
|
@ -328,6 +371,15 @@ static int RAMFUNCTION partition_magic_write(uint8_t part, uintptr_t addr)
|
|||
|
||||
#ifdef EXT_FLASH
|
||||
|
||||
/**
|
||||
* @brief Get the trailer at a specific address in a fixed partition.
|
||||
*
|
||||
* This function retrieves the trailer at a specific address in a fixed partition.
|
||||
*
|
||||
* @param[in] part Partition number.
|
||||
* @param[in] at Address offset.
|
||||
* @return Pointer to the trailer at the specified address.
|
||||
*/
|
||||
static uint8_t* RAMFUNCTION get_trailer_at(uint8_t part, uint32_t at)
|
||||
{
|
||||
uint8_t *ret = NULL;
|
||||
|
@ -363,6 +415,15 @@ static uint8_t* RAMFUNCTION get_trailer_at(uint8_t part, uint32_t at)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the trailer at a specific address in an external flash.
|
||||
*
|
||||
* This function sets the trailer at a specific address in an external flash.
|
||||
*
|
||||
* @param[in] part Partition number.
|
||||
* @param[in] at Address offset.
|
||||
* @param[in] val New value to set in the trailer.
|
||||
*/
|
||||
static void RAMFUNCTION set_trailer_at(uint8_t part, uint32_t at, uint8_t val)
|
||||
{
|
||||
if (part == PART_BOOT) {
|
||||
|
@ -383,6 +444,13 @@ static void RAMFUNCTION set_trailer_at(uint8_t part, uint32_t at, uint8_t val)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the partition magic trailer in an external flash.
|
||||
*
|
||||
* This function sets the partition magic trailer in an external flash.
|
||||
*
|
||||
* @param[in] part Partition number.
|
||||
*/
|
||||
static void RAMFUNCTION set_partition_magic(uint8_t part)
|
||||
{
|
||||
if (part == PART_BOOT) {
|
||||
|
@ -465,6 +533,14 @@ static void RAMFUNCTION set_partition_magic(uint8_t part)
|
|||
|
||||
|
||||
#ifdef WOLFBOOT_FIXED_PARTITIONS
|
||||
/**
|
||||
* @brief Get the magic trailer of a partition.
|
||||
*
|
||||
* This function retrieves the magic trailer of a fixed partition.
|
||||
*
|
||||
* @param[in] part Partition number.
|
||||
* @return Pointer to the magic trailer of the partition.
|
||||
*/
|
||||
static uint32_t* RAMFUNCTION get_partition_magic(uint8_t part)
|
||||
{
|
||||
return (uint32_t *)get_trailer_at(part, 0);
|
||||
|
@ -481,16 +557,42 @@ static void RAMFUNCTION set_partition_state(uint8_t part, uint8_t val)
|
|||
set_trailer_at(part, 1, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the flags of an update sector.
|
||||
*
|
||||
* This function sets the flags of an update sector in a fixed partition.
|
||||
*
|
||||
* @param[in] pos Update sector position.
|
||||
* @param[in] val New flags value to set.
|
||||
* @return 0 on success, -1 on failure.
|
||||
*/
|
||||
static void RAMFUNCTION set_update_sector_flags(uint32_t pos, uint8_t val)
|
||||
{
|
||||
set_trailer_at(PART_UPDATE, 2 + pos, val);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the flags of an update sector.
|
||||
*
|
||||
* This function retrieves the flags of an update sector in a fixed partition.
|
||||
*
|
||||
* @param[in] pos Update sector position.
|
||||
* @return Pointer to the flags of the update sector.
|
||||
*/
|
||||
static uint8_t* RAMFUNCTION get_update_sector_flags(uint32_t pos)
|
||||
{
|
||||
return (uint8_t *)get_trailer_at(PART_UPDATE, 2 + pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the state of a partition.
|
||||
*
|
||||
* This function sets the state of a fixed partition.
|
||||
*
|
||||
* @param[in] part Partition number.
|
||||
* @param[in] newst New state value to set.
|
||||
* @return 0 on success, -1 on failure.
|
||||
*/
|
||||
int RAMFUNCTION wolfBoot_set_partition_state(uint8_t part, uint8_t newst)
|
||||
{
|
||||
uint32_t *magic;
|
||||
|
@ -525,6 +627,15 @@ int RAMFUNCTION wolfBoot_set_update_sector_flag(uint16_t sector, uint8_t newflag
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the state of a partition.
|
||||
*
|
||||
* This function retrieves the state of a fixed partition.
|
||||
*
|
||||
* @param[in] part Partition number.
|
||||
* @param[out] st Pointer to store the partition state.
|
||||
* @return 0 on success, -1 on failure.
|
||||
*/
|
||||
int RAMFUNCTION wolfBoot_get_partition_state(uint8_t part, uint8_t *st)
|
||||
{
|
||||
uint32_t *magic;
|
||||
|
@ -553,7 +664,13 @@ int wolfBoot_get_update_sector_flag(uint16_t sector, uint8_t *flag)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Erase a partition.
|
||||
*
|
||||
* This function erases a partition.
|
||||
*
|
||||
* @param[in] part Partition number.
|
||||
*/
|
||||
void RAMFUNCTION wolfBoot_erase_partition(uint8_t part)
|
||||
{
|
||||
uint32_t address = 0;
|
||||
|
@ -583,6 +700,15 @@ void RAMFUNCTION wolfBoot_erase_partition(uint8_t part)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update trigger function.
|
||||
*
|
||||
* This function updates the boot partition state to "IMG_STATE_UPDATING".
|
||||
* If the FLAGS_HOME macro is defined, it erases the last sector of the boot
|
||||
* partition before updating the partition state. It also checks FLAGS_UPDATE_EXT
|
||||
* and calls the appropriate flash unlock and lock functions before
|
||||
* updating the partition state.
|
||||
*/
|
||||
void RAMFUNCTION wolfBoot_update_trigger(void)
|
||||
{
|
||||
uint8_t st = IMG_STATE_UPDATING;
|
||||
|
@ -636,6 +762,14 @@ void RAMFUNCTION wolfBoot_update_trigger(void)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Success function.
|
||||
*
|
||||
* This function updates the boot partition state to "IMG_STATE_SUCCESS".
|
||||
* If the FLAGS_BOOT_EXT macro is defined, it calls the appropriate flash unlock
|
||||
* and lock functions before updating the partition state. If the EXT_ENCRYPTED
|
||||
* macro is defined, it calls wolfBoot_erase_encrypt_key function.
|
||||
*/
|
||||
void RAMFUNCTION wolfBoot_success(void)
|
||||
{
|
||||
uint8_t st = IMG_STATE_SUCCESS;
|
||||
|
@ -654,6 +788,19 @@ void RAMFUNCTION wolfBoot_success(void)
|
|||
}
|
||||
#endif /* WOLFBOOT_FIXED_PARTITIONS */
|
||||
|
||||
/**
|
||||
* @brief Find header function.
|
||||
*
|
||||
* This function searches for a specific header type in the given buffer.
|
||||
* It returns the length of the header and sets the 'ptr' parameter to the
|
||||
* position of the header if found.
|
||||
* @param haystack Pointer to the buffer to search for the header.
|
||||
* @param type The type of header to search for.
|
||||
* @param ptr Pointer to store the position of the header.
|
||||
*
|
||||
* @return uint16_t The length of the header found, or 0 if not found.
|
||||
*
|
||||
*/
|
||||
uint16_t wolfBoot_find_header(uint8_t *haystack, uint16_t type, uint8_t **ptr)
|
||||
{
|
||||
uint8_t *p = haystack;
|
||||
|
@ -706,6 +853,16 @@ static uint8_t hdr_cpy[IMAGE_HEADER_SIZE];
|
|||
static uint32_t hdr_cpy_done = 0;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Convert little-endian to native-endian (uint32_t).
|
||||
*
|
||||
* This function converts a little-endian 32-bit value to the native-endian format.
|
||||
* It is used to handle endianness differences when reading data from memory.
|
||||
*
|
||||
* @param val The value to convert.
|
||||
*
|
||||
* @return The converted value.
|
||||
*/
|
||||
static inline uint32_t im2n(uint32_t val)
|
||||
{
|
||||
#ifdef BIG_ENDIAN_ORDER
|
||||
|
@ -717,7 +874,16 @@ static inline uint32_t im2n(uint32_t val)
|
|||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert little-endian to native-endian (uint16_t).
|
||||
*
|
||||
* This function converts a little-endian 16-bit value to the native-endian format.
|
||||
* It is used to handle endianness differences when reading data from memory.
|
||||
*
|
||||
* @param val The value to convert.
|
||||
* @return uint16_t The converted value.
|
||||
|
||||
*/
|
||||
static inline uint16_t im2ns(uint16_t val)
|
||||
{
|
||||
#ifdef BIG_ENDIAN_ORDER
|
||||
|
@ -728,6 +894,22 @@ static inline uint16_t im2ns(uint16_t val)
|
|||
}
|
||||
|
||||
#ifdef DELTA_UPDATES
|
||||
/**
|
||||
* @brief Get delta update information.
|
||||
*
|
||||
* This function retrieves the delta update information for a given partition.
|
||||
* It checks if the partition is extended, reads the image header, and returns
|
||||
* the delta image offset and size. The 'inverse' flag indicates whether to get
|
||||
* the inverse delta information or regular delta information.
|
||||
*
|
||||
* @param part The partition to check for delta update information.
|
||||
* @param inverse Flag to indicate if the delta update is inverse.
|
||||
* @param img_offset Pointer to store the delta image offset.
|
||||
* @param img_size Pointer to store the delta image size.
|
||||
*
|
||||
* @return int 0 if successful, -1 if not found or an error occurred.
|
||||
*
|
||||
*/
|
||||
int wolfBoot_get_delta_info(uint8_t part, int inverse, uint32_t **img_offset,
|
||||
uint16_t **img_size)
|
||||
{
|
||||
|
@ -805,7 +987,18 @@ static int decrypt_header(uint8_t *src)
|
|||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Get blob version.
|
||||
*
|
||||
* This function retrieves the version number from the blob.
|
||||
* It checks the magic number in the blob to ensure it is valid before reading
|
||||
* the version field.
|
||||
*
|
||||
* @param blob Pointer to the buffer containing the blob.
|
||||
*
|
||||
* @return The version number of the blob, or 0 if the blob is invalid.
|
||||
*
|
||||
*/
|
||||
uint32_t wolfBoot_get_blob_version(uint8_t *blob)
|
||||
{
|
||||
uint32_t *volatile version_field = NULL;
|
||||
|
@ -829,6 +1022,17 @@ uint32_t wolfBoot_get_blob_version(uint8_t *blob)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get blob type.
|
||||
*
|
||||
* This function retrieves the type of the blob.
|
||||
* It checks the magic number in the blob to ensure it is valid before reading
|
||||
* the type field.
|
||||
*
|
||||
* @param blob Pointer to the buffer containing the blob.
|
||||
*
|
||||
* @return The type of the blob, or 0 if the blob is invalid.
|
||||
*/
|
||||
uint32_t wolfBoot_get_blob_type(uint8_t *blob)
|
||||
{
|
||||
uint32_t *volatile type_field = NULL;
|
||||
|
@ -853,6 +1057,20 @@ uint32_t wolfBoot_get_blob_type(uint8_t *blob)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get blob difference base version.
|
||||
*
|
||||
* This function retrieves the difference base version from the blob.
|
||||
* It checks the magic number in the blob to ensure it is valid before reading
|
||||
* the difference base field.
|
||||
*
|
||||
* @param blob Pointer to the buffer containing the blob.
|
||||
*
|
||||
* @return The difference base version of the blob, or 0 if not found
|
||||
* or the blob is invalid.
|
||||
*
|
||||
*/
|
||||
|
||||
uint32_t wolfBoot_get_blob_diffbase_version(uint8_t *blob)
|
||||
{
|
||||
uint32_t *volatile delta_base = NULL;
|
||||
|
@ -878,6 +1096,19 @@ uint32_t wolfBoot_get_blob_diffbase_version(uint8_t *blob)
|
|||
|
||||
|
||||
#ifdef WOLFBOOT_FIXED_PARTITIONS
|
||||
/**
|
||||
* @brief Get image pointer from a partition.
|
||||
*
|
||||
* This function retrieves the pointer to the image in the specified partition.
|
||||
* It handles both regular and extended partitions by reading from memory or
|
||||
* external flash if needed.
|
||||
*
|
||||
* @param part The partition to get the image pointer for.
|
||||
*
|
||||
* @return uint8_t* Pointer to the image in the specified partition, or
|
||||
* NULL if the partition is invalid or empty.
|
||||
*
|
||||
*/
|
||||
static uint8_t* wolfBoot_get_image_from_part(uint8_t part)
|
||||
{
|
||||
uint8_t *image = (uint8_t *)0x00000000;
|
||||
|
@ -899,6 +1130,19 @@ static uint8_t* wolfBoot_get_image_from_part(uint8_t part)
|
|||
return image;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get image version for a partition.
|
||||
*
|
||||
* This function retrieves the version number of the image in the specified
|
||||
* partition. It uses the 'wolfBoot_get_blob_version' function to extract the
|
||||
* version from the image blob.
|
||||
*
|
||||
* @param part The partition to get the image version for.
|
||||
*
|
||||
* @return The version number of the image in the partition,
|
||||
* or 0 if the partition is invalid or empty.
|
||||
*
|
||||
*/
|
||||
|
||||
uint32_t wolfBoot_get_image_version(uint8_t part)
|
||||
{
|
||||
|
@ -906,13 +1150,39 @@ uint32_t wolfBoot_get_image_version(uint8_t part)
|
|||
return wolfBoot_get_blob_version(wolfBoot_get_image_from_part(part));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get difference base version for a partition.
|
||||
*
|
||||
* This function retrieves the difference base version from the image in the
|
||||
* specified partition. It uses the 'wolfBoot_get_blob_diffbase_version'
|
||||
* function to extract the difference base version from the image blob.
|
||||
*
|
||||
* @param part The partition to get the difference base version for.
|
||||
*
|
||||
* @return The difference base version of the image in the partition, or
|
||||
* 0 if not found or the partition is invalid or empty.
|
||||
*
|
||||
*/
|
||||
|
||||
uint32_t wolfBoot_get_diffbase_version(uint8_t part)
|
||||
{
|
||||
/* Don't check image against NULL to allow using address 0x00000000 */
|
||||
return wolfBoot_get_blob_diffbase_version(
|
||||
wolfBoot_get_image_from_part(part));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get image type for a partition.
|
||||
*
|
||||
* This function retrieves the image type from the image in the specified
|
||||
* partition. It uses the 'wolfBoot_get_blob_type' function to extract the image
|
||||
* type from the image blob.
|
||||
*
|
||||
* @param part The partition to get the image type for.
|
||||
*
|
||||
* @return uint16_t The image type of the image in the partition, or
|
||||
* 0 if the partition is invalid or empty.
|
||||
*
|
||||
*/
|
||||
uint16_t wolfBoot_get_image_type(uint8_t part)
|
||||
{
|
||||
uint8_t *image = wolfBoot_get_image_from_part(part);
|
||||
|
@ -928,7 +1198,21 @@ uint16_t wolfBoot_get_image_type(uint8_t part)
|
|||
#if defined(WOLFBOOT_DUALBOOT)
|
||||
|
||||
#if defined(WOLFBOOT_FIXED_PARTITIONS)
|
||||
|
||||
/**
|
||||
* @brief Find the dual-boot candidate partition.
|
||||
*
|
||||
* This function determines the dual-boot candidate partition based on the
|
||||
* current firmware versions and states. If both primary and update images
|
||||
* are present, it chooses the one with a higher version.
|
||||
* If no primary image is present, it selects the update partition.
|
||||
* It also handles the case where the current partition is in "IMG_STATE_TESTING"
|
||||
* and switches to the other partition if available.
|
||||
*
|
||||
* @return The partition number (PART_BOOT or PART_UPDATE) to be used as
|
||||
* the dual-boot candidate.
|
||||
* Returns -1 if no valid candidate is found.
|
||||
*
|
||||
*/
|
||||
int wolfBoot_dualboot_candidate(void)
|
||||
{
|
||||
int candidate = PART_BOOT;
|
||||
|
@ -1005,7 +1289,15 @@ int wolfBoot_dualboot_candidate_addr(void** addr)
|
|||
return retval;
|
||||
}
|
||||
#endif /* WOLFBOOT_FIXED_PARTITIONS */
|
||||
|
||||
/**
|
||||
* @brief Check if fallback is possible.
|
||||
*
|
||||
* This function checks if fallback is possible, i.e., both primary and
|
||||
* update images are present.
|
||||
*
|
||||
* @return 1 if fallback is possible, 0 otherwise.
|
||||
*
|
||||
*/
|
||||
int wolfBoot_fallback_is_possible(void)
|
||||
{
|
||||
uint32_t boot_v, update_v;
|
||||
|
@ -1068,7 +1360,18 @@ static int RAMFUNCTION hal_set_key(const uint8_t *k, const uint8_t *nonce)
|
|||
return ret;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the encryption key.
|
||||
*
|
||||
* This function sets the encryption key and nonce used for encrypting the
|
||||
* firmware image. It stores the key and nonce in the designated memory location.
|
||||
*
|
||||
* @param key Pointer to the encryption key.
|
||||
* @param nonce Pointer to the encryption nonce.
|
||||
*
|
||||
* @return 0 if successful.
|
||||
*
|
||||
*/
|
||||
int RAMFUNCTION wolfBoot_set_encrypt_key(const uint8_t *key,
|
||||
const uint8_t *nonce)
|
||||
{
|
||||
|
@ -1077,6 +1380,18 @@ int RAMFUNCTION wolfBoot_set_encrypt_key(const uint8_t *key,
|
|||
}
|
||||
|
||||
#ifndef UNIT_TEST
|
||||
/**
|
||||
* @brief Set the encryption key.
|
||||
*
|
||||
* This function sets the encryption key and nonce used for encrypting the
|
||||
* firmware image. It stores the key and nonce in the designated memory location.
|
||||
*
|
||||
* @param key Pointer to the encryption key.
|
||||
* @param nonce Pointer to the encryption nonce.
|
||||
*
|
||||
* @return 0 if successful.
|
||||
*
|
||||
*/
|
||||
int RAMFUNCTION wolfBoot_get_encrypt_key(uint8_t *k, uint8_t *nonce)
|
||||
{
|
||||
#if defined(MMU)
|
||||
|
@ -1096,7 +1411,15 @@ int RAMFUNCTION wolfBoot_get_encrypt_key(uint8_t *k, uint8_t *nonce)
|
|||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Erase the encryption key.
|
||||
*
|
||||
* This function erases the encryption key and nonce, resetting them to all 0xFF
|
||||
* bytes.It ensures that the key and nonce cannot be accessed after erasure.
|
||||
*
|
||||
* @return 0 if successful.
|
||||
*
|
||||
*/
|
||||
int RAMFUNCTION wolfBoot_erase_encrypt_key(void)
|
||||
{
|
||||
#if defined(MMU)
|
||||
|
@ -1161,7 +1484,15 @@ int RAMFUNCTION chacha_init(void)
|
|||
#elif defined(ENCRYPT_WITH_AES128) || defined(ENCRYPT_WITH_AES256)
|
||||
|
||||
Aes aes_dec, aes_enc;
|
||||
|
||||
/**
|
||||
* @brief Initialize AES encryption.
|
||||
*
|
||||
* This function initializes the AES encryption by setting the encryption key
|
||||
* and encryption nonce, checking for valid keys, and copying the encryption
|
||||
* nonce from the key buffer.
|
||||
*
|
||||
* @return 0 if successful, -1 on failure.
|
||||
*/
|
||||
int aes_init(void)
|
||||
{
|
||||
#if defined(MMU) || defined(UNIT_TEST)
|
||||
|
@ -1202,6 +1533,17 @@ int aes_init(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the AES initialization vector (IV) for CTR mode.
|
||||
*
|
||||
* This function sets the AES initialization vector (IV) for the Counter (CTR)
|
||||
* mode encryption. It takes a 12-byte nonce and a 32-bit IV counter value to
|
||||
* construct the 16-byte IV used for encryption.
|
||||
*
|
||||
* @param nonce Pointer to the 12-byte nonce (IV) buffer.
|
||||
* @param iv_ctr The IV counter value.
|
||||
*
|
||||
*/
|
||||
void aes_set_iv(uint8_t *nonce, uint32_t iv_ctr)
|
||||
{
|
||||
uint32_t iv_buf[ENCRYPT_BLOCK_SIZE / sizeof(uint32_t)];
|
||||
|
@ -1232,7 +1574,19 @@ void aes_set_iv(uint8_t *nonce, uint32_t iv_ctr)
|
|||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Determine the partition address type.
|
||||
*
|
||||
* This function determines the partition type based on the provided address.
|
||||
* If the address belongs to the update partition or swap partition (if defined),
|
||||
* the corresponding partition type is returned.
|
||||
* Otherwise, PART_NONE is returned.
|
||||
*
|
||||
* @param a The address to check for its partition type.
|
||||
*
|
||||
* @return The partition type (PART_UPDATE, PART_SWAP, or PART_NONE).
|
||||
|
||||
*/
|
||||
static uint8_t RAMFUNCTION part_address(uintptr_t a)
|
||||
{
|
||||
#ifdef WOLFBOOT_FIXED_PARTITIONS
|
||||
|
@ -1257,6 +1611,18 @@ static uint8_t RAMFUNCTION part_address(uintptr_t a)
|
|||
}
|
||||
|
||||
#ifdef EXT_FLASH
|
||||
/**
|
||||
* @brief Write encrypted data to an external flash.
|
||||
*
|
||||
* This function encrypts the provided data using the AES encryption algorithm
|
||||
* and writes it to the external flash.
|
||||
*
|
||||
* @param address The address in the external flash to write the data to.
|
||||
* @param data Pointer to the data buffer to be written.
|
||||
* @param len The length of the data to be written.
|
||||
*
|
||||
* @return int 0 if successful, -1 on failure.
|
||||
*/
|
||||
int RAMFUNCTION ext_flash_encrypt_write(uintptr_t address, const uint8_t *data, int len)
|
||||
{
|
||||
uint8_t block[ENCRYPT_BLOCK_SIZE];
|
||||
|
@ -1322,7 +1688,20 @@ int RAMFUNCTION ext_flash_encrypt_write(uintptr_t address, const uint8_t *data,
|
|||
|
||||
return ext_flash_write(address, ENCRYPT_CACHE, step);
|
||||
}
|
||||
/**
|
||||
* @brief Read and decrypt data from an external flash.
|
||||
*
|
||||
* This function reads the encrypted data from the external flash,
|
||||
* decrypts it using the AES decryption algorithm, and stores the decrypted data
|
||||
* in the provided buffer.
|
||||
|
||||
* @param address The address in the external flash to read the encrypted data from.
|
||||
* @param data Pointer to the buffer to store the decrypted data.
|
||||
* @param len The length of the data to be read and decrypted.
|
||||
*
|
||||
* @return The number of decrypted bytes read, or -1 on failure.
|
||||
*
|
||||
*/
|
||||
int RAMFUNCTION ext_flash_decrypt_read(uintptr_t address, uint8_t *data, int len)
|
||||
{
|
||||
uint8_t block[ENCRYPT_BLOCK_SIZE];
|
||||
|
@ -1407,6 +1786,17 @@ int RAMFUNCTION ext_flash_decrypt_read(uintptr_t address, uint8_t *data, int len
|
|||
#endif /* __WOLFBOOT */
|
||||
|
||||
#if defined(MMU)
|
||||
/**
|
||||
* @brief Decrypt data from RAM.
|
||||
*
|
||||
* This function decrypts data from the RAM using the AES decryption algorithm.
|
||||
*
|
||||
* @param src Pointer to the source buffer containing the encrypted data.
|
||||
* @param dst Pointer to the destination buffer to store the decrypted data.
|
||||
*
|
||||
* @return int 0 if successful, -1 on failure.
|
||||
*
|
||||
*/
|
||||
int wolfBoot_ram_decrypt(uint8_t *src, uint8_t *dst)
|
||||
{
|
||||
uint8_t block[ENCRYPT_BLOCK_SIZE];
|
||||
|
|
45
src/loader.c
45
src/loader.c
|
@ -18,6 +18,16 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
/**
|
||||
* @file loader.c
|
||||
*
|
||||
* @brief Loader implementation for wolfBoot.
|
||||
*
|
||||
* This file contains the implementation of the loader for wolfBoot. It includes
|
||||
* functions to initialize the hardware, probe SPI flash,
|
||||
* initialize UART (if applicable), initialize TPM2 (if applicable), and
|
||||
* start the wolfBoot process.
|
||||
*/
|
||||
|
||||
#include "loader.h"
|
||||
#include "image.h"
|
||||
|
@ -27,16 +37,51 @@
|
|||
#include "wolfboot/wolfboot.h"
|
||||
|
||||
#ifdef RAM_CODE
|
||||
/**
|
||||
* @brief Start address of the text section in RAM code.
|
||||
*/
|
||||
extern unsigned int _start_text;
|
||||
/**
|
||||
* @brief wolfBoot version number (used in RAM code).
|
||||
*/
|
||||
static volatile const uint32_t __attribute__((used)) wolfboot_version = WOLFBOOT_VERSION;
|
||||
/**
|
||||
* @brief RAM Interrupt Vector table.
|
||||
*/
|
||||
extern void (** const IV_RAM)(void);
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_sim
|
||||
/**
|
||||
* @brief Command line arguments for the test-app in sim mode.
|
||||
*/
|
||||
extern char **main_argv;
|
||||
/**
|
||||
* @brief Number of command line arguments for the test-app in sim mode.
|
||||
*/
|
||||
extern int main_argc;
|
||||
|
||||
/**
|
||||
* @brief Main function in sim platform.
|
||||
*
|
||||
* This function is the entry point for the simulator platform. It forwards the
|
||||
* command line arguments to the test-app for testing purposes.
|
||||
*
|
||||
* @param argc Number of command line arguments.
|
||||
* @param argv Array of command line arguments.
|
||||
* @return The return code of the test-app.
|
||||
*/
|
||||
int main(int argc, char *argv[])
|
||||
#elif defined(WOLFBOOT_LOADER_MAIN)
|
||||
/**
|
||||
* @brief Main function for the wolfBoot loader.
|
||||
*
|
||||
* This function is the entry point for the wolfBoot loader. It initializes
|
||||
* the hardware, probes SPI flash, initializes UART (if applicable), initializes
|
||||
* TPM2 (if applicable), and starts the wolfBoot process.
|
||||
*
|
||||
* @return The return code of the wolfBoot process (should not return).
|
||||
*/
|
||||
int loader_main(void)
|
||||
#else
|
||||
int main(void)
|
||||
|
|
|
@ -22,7 +22,20 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
/**
|
||||
* @file update_disk.c
|
||||
*
|
||||
* @brief Implementation for RAM based updater, for systems that provide
|
||||
* drives and partition mapping.
|
||||
*
|
||||
* This file contains the implementation for the RAM-based updater for systems
|
||||
* that offer drives and partition mapping. It includes functions to read
|
||||
* and load OS images from disk partitions, validate their integrity and
|
||||
* authenticity, and perform the boot process.
|
||||
*/
|
||||
|
||||
#ifndef UPDATE_DISK_H_
|
||||
#define UPDATE_DISK_H_
|
||||
#include "image.h"
|
||||
#include "loader.h"
|
||||
#include "hal.h"
|
||||
|
@ -50,7 +63,13 @@
|
|||
#define MAX_FAILURES 4
|
||||
|
||||
#define IMAGE_PRELOAD_ADDRESS 0x5000100
|
||||
|
||||
/**
|
||||
* @brief RAM function for starting the boot process.
|
||||
*
|
||||
* This function starts the boot process by attempting to read and load
|
||||
* the OS image from disk partitions. It then verifies the integrity and
|
||||
* authenticity of the loaded image before initiating the boot.
|
||||
*/
|
||||
void RAMFUNCTION wolfBoot_start(void)
|
||||
{
|
||||
struct wolfBoot_image os_image;
|
||||
|
@ -170,3 +189,4 @@ void RAMFUNCTION wolfBoot_start(void)
|
|||
do_boot((uint32_t*)os_image.fw_base);
|
||||
|
||||
}
|
||||
#endif /* UPDATE_DISK_H_ */
|
||||
|
|
|
@ -19,7 +19,18 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* @file ahci.c
|
||||
*
|
||||
* @brief AHCI (Advanced Host Controller Interface) Implementation.
|
||||
*
|
||||
* This file contains the implementation of the AHCI (Advanced Host Controller
|
||||
* Interface) driver. It includes functions to enable and disable the AHCI
|
||||
* controller, detect SATA disks, and initialize ATA drives for detected disks.
|
||||
*/
|
||||
|
||||
#ifndef AHCI_H_
|
||||
#define AHCI_H_
|
||||
#include <stdint.h>
|
||||
|
||||
#include <x86/common.h>
|
||||
|
@ -60,13 +71,32 @@
|
|||
#define AHCI_DEBUG_PRINTF(...) do {} while(0)
|
||||
#endif /* DEBUG_AHCI */
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets the AHCI Base Address Register (ABAR) for the given device.
|
||||
*
|
||||
* @param bus The PCI bus number of the AHCI device.
|
||||
* @param dev The PCI device number of the AHCI device.
|
||||
* @param fun The PCI function number of the AHCI device.
|
||||
* @param addr The address to set as the ABAR.
|
||||
*/
|
||||
static inline void ahci_set_bar(uint32_t bus, uint32_t dev,
|
||||
uint32_t func, uint32_t addr)
|
||||
{
|
||||
pci_config_write32(bus, dev, func, AHCI_ABAR_OFFSET, addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the SATA controller for the given device.
|
||||
*
|
||||
* This function initializes the SATA controller for the specified AHCI device
|
||||
* and detects connected SATA disks. It sets up the necessary registers and
|
||||
* configurations for the controller to function properly.
|
||||
*
|
||||
* @param bus The PCI bus number of the AHCI device.
|
||||
* @param dev The PCI device number of the AHCI device.
|
||||
* @param fun The PCI function number of the AHCI device.
|
||||
* @return 0 on success, or a negative value on failure.
|
||||
*/
|
||||
int init_sata_controller(uint32_t bus, uint32_t dev, uint32_t fun)
|
||||
{
|
||||
uint16_t reg16;
|
||||
|
@ -89,6 +119,17 @@ int init_sata_controller(uint32_t bus, uint32_t dev, uint32_t fun)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables the AHCI controller for the given device.
|
||||
*
|
||||
* This function enables the AHCI controller for the specified AHCI device
|
||||
* and returns the AHCI Base Address Register (ABAR) for accessing AHCI registers.
|
||||
*
|
||||
* @param bus The PCI bus number of the AHCI device.
|
||||
* @param dev The PCI device number of the AHCI device.
|
||||
* @param fun The PCI function number of the AHCI device.
|
||||
* @return The ABAR address on success, or 0 on failure.
|
||||
*/
|
||||
uint32_t ahci_enable(uint32_t bus, uint32_t dev, uint32_t fun)
|
||||
{
|
||||
uint16_t reg16;
|
||||
|
@ -118,6 +159,15 @@ uint32_t ahci_enable(uint32_t bus, uint32_t dev, uint32_t fun)
|
|||
return bar;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Dumps the status of the specified AHCI port.
|
||||
*
|
||||
* This function dumps the status of the AHCI port with the given index.
|
||||
* It prints the status of various port registers for debugging purposes.
|
||||
*
|
||||
* @param base The AHCI Base Address Register (ABAR) for accessing AHCI registers.
|
||||
* @param i The index of the AHCI port to dump status for.
|
||||
*/
|
||||
void ahci_dump_port(uint32_t base, int i)
|
||||
{
|
||||
uint32_t cmd, ci, is, tfd, serr, ssst;
|
||||
|
@ -132,6 +182,14 @@ void ahci_dump_port(uint32_t base, int i)
|
|||
i, cmd, ci, is, tfd, serr, ssst);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables SATA ports and detects connected SATA disks.
|
||||
*
|
||||
* This function enables SATA ports in the AHCI controller and detects connected SATA disks.
|
||||
* It initializes the ATA drives for the detected disks.
|
||||
*
|
||||
* @param base The AHCI Base Address Register (ABAR) for accessing AHCI registers.
|
||||
*/
|
||||
void sata_enable(uint32_t base) {
|
||||
volatile uint32_t count;
|
||||
uint32_t cap, ports_impl;
|
||||
|
@ -337,6 +395,14 @@ void sata_enable(uint32_t base) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables SATA ports in the AHCI controller.
|
||||
*
|
||||
* This function disables SATA ports in the AHCI controller and stops any DMA operation.
|
||||
* It clears status registers and puts the AHCI ports into an inactive state.
|
||||
*
|
||||
* @param base The AHCI Base Address Register (ABAR) for accessing AHCI registers.
|
||||
*/
|
||||
void sata_disable(uint32_t base)
|
||||
{
|
||||
uint32_t i, reg;
|
||||
|
@ -398,3 +464,5 @@ void sata_disable(uint32_t base)
|
|||
/* mmio_or32(AHCI_HBA_GHC(base), HBA_GHC_HR | HBA_GHC_IE); */
|
||||
/* memset((void *)SATA_BASE, 0, 0x1000000); */
|
||||
}
|
||||
#endif /* AHCI_H_ */
|
||||
|
||||
|
|
127
src/x86/ata.c
127
src/x86/ata.c
|
@ -19,7 +19,16 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file ata.c
|
||||
* @brief This file contains the implementation of the ATA
|
||||
* (Advanced Technology Attachment) driver used for interacting with AHCI
|
||||
* (Advanced Host Controller Interface) based SATA drives.
|
||||
* It supports functions for drive initialization, read and write operations,
|
||||
* and device identification.
|
||||
*/
|
||||
#ifndef ATA_C
|
||||
#define ATA_C
|
||||
#include <stdint.h>
|
||||
#include <x86/common.h>
|
||||
#include <x86/ahci.h>
|
||||
|
@ -33,6 +42,14 @@
|
|||
#define CACHE_INVALID 0xBADF00DBADC0FFEEULL
|
||||
|
||||
#ifdef DEBUG_ATA
|
||||
/**
|
||||
* @brief This macro is used to conditionally print debug messages for the ATA
|
||||
* driver. If DEBUG_ATA is defined, it calls the wolfBoot_printf function with
|
||||
* the specified format and arguments. Otherwise, it is defined as an empty
|
||||
* do-while loop.
|
||||
*
|
||||
* @param[in] ... Format and arguments for the debug printf.
|
||||
*/
|
||||
#define ATA_DEBUG_PRINTF(...) wolfBoot_printf(__VA_ARGS__)
|
||||
#else
|
||||
#define ATA_DEBUG_PRINTF(...) do {} while(0)
|
||||
|
@ -41,6 +58,10 @@
|
|||
|
||||
static int ata_drive_count = -1;
|
||||
|
||||
/**
|
||||
* @brief This structure holds the necessary information for an ATA drive,
|
||||
* including AHCI base address, AHCI port number, and sector cache.
|
||||
*/
|
||||
struct ata_drive {
|
||||
uint32_t ahci_base;
|
||||
unsigned ahci_port;
|
||||
|
@ -52,9 +73,17 @@ struct ata_drive {
|
|||
uint64_t cached;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This array holds instances of the `struct ata_drive` representing
|
||||
* multiple ATA drives (up to `MAX_ATA_DRIVES`).
|
||||
*/
|
||||
struct ata_drive ATA_Drv[MAX_ATA_DRIVES];
|
||||
|
||||
|
||||
/**
|
||||
* @brief This packed structure defines a single entry in the HBA
|
||||
* (Host Bus Adapter) HBA PRDT (Physical Region Descriptor Table) used for
|
||||
* DMA data transfer.
|
||||
*/
|
||||
struct __attribute__((packed)) hba_prdt_entry {
|
||||
uint32_t dba;
|
||||
uint32_t dbau;
|
||||
|
@ -63,6 +92,10 @@ struct __attribute__((packed)) hba_prdt_entry {
|
|||
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This packed structure defines the layout of an HBA command table,
|
||||
* which contains command headers and PRDT entries for DMA data transfer.
|
||||
*/
|
||||
struct __attribute__((packed)) hba_cmd_table {
|
||||
uint8_t cfis[64];
|
||||
uint8_t acmd[16];
|
||||
|
@ -70,6 +103,10 @@ struct __attribute__((packed)) hba_cmd_table {
|
|||
struct hba_prdt_entry prdt_entry[8];
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This packed structure defines the format of an H2D Register FIS
|
||||
* used for ATA commands.
|
||||
*/
|
||||
struct __attribute__((packed)) fis_reg_h2d {
|
||||
uint8_t fis_type;
|
||||
|
||||
|
@ -95,6 +132,10 @@ struct __attribute__((packed)) fis_reg_h2d {
|
|||
uint32_t _res1;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This packed structure defines the format of a D2H Register FIS
|
||||
* used for ATA commands completion.
|
||||
*/
|
||||
struct __attribute__((packed)) fis_reg_d2h {
|
||||
uint8_t fis_type;
|
||||
|
||||
|
@ -119,6 +160,10 @@ struct __attribute__((packed)) fis_reg_d2h {
|
|||
uint32_t _res4;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This packed structure defines the format of a Data FIS used for
|
||||
* data transfer.
|
||||
*/
|
||||
struct __attribute__((packed)) fis_data {
|
||||
uint8_t fis_type;
|
||||
uint8_t pmport:4, _res0:4;
|
||||
|
@ -126,6 +171,19 @@ struct __attribute__((packed)) fis_data {
|
|||
uint32_t data[0];
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This function initializes a new ATA drive instance with the provided
|
||||
* parameters and stores it in the ATA_Drv array.
|
||||
*
|
||||
* @param[in] ahci_base The base address of the AHCI controller.
|
||||
* @param[in] ahci_port The port number of the AHCI controller.
|
||||
* @param[in] clb The command list base address for the drive.
|
||||
* @param[in] ctable The command table base address for the drive.
|
||||
* @param[in] fis The FIS base address for the drive.
|
||||
*
|
||||
* @return The index of the new ATA drive if successful, or -1 if the maximum
|
||||
* number of drives has been reached.
|
||||
*/
|
||||
int ata_drive_new(uint32_t ahci_base, unsigned ahci_port, uint32_t clb,
|
||||
uint32_t ctable, uint32_t fis)
|
||||
{
|
||||
|
@ -144,6 +202,15 @@ int ata_drive_new(uint32_t ahci_base, unsigned ahci_port, uint32_t clb,
|
|||
return ata_drive_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This static function finds an available command slot for the specified
|
||||
* ATA drive and returns the slot number.
|
||||
*
|
||||
* @param[in] drv The index of the ATA drive in the ATA_Drv array.
|
||||
*
|
||||
* @return The index of the available command slot if found, or -1 if no slot is
|
||||
* available.
|
||||
*/
|
||||
static int find_cmd_slot(int drv)
|
||||
{
|
||||
struct ata_drive *ata = &ATA_Drv[drv];
|
||||
|
@ -161,6 +228,17 @@ static int find_cmd_slot(int drv)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This static function prepares a command slot for DMA data transfer by
|
||||
* initializing the command header and command table entries.
|
||||
*
|
||||
* @param[in] drv The index of the ATA drive in the ATA_Drv array.
|
||||
* @param[in] buf The buffer containing the data to be transferred.
|
||||
* @param[in] sz The size of the data to be transferred in bytes.
|
||||
*
|
||||
* @return The index of the prepared command slot if successful, or -1 if an error
|
||||
* occurs.
|
||||
*/
|
||||
static int prepare_cmd_slot(int drv, const uint8_t *buf, int sz)
|
||||
{
|
||||
struct hba_cmd_header *cmd;
|
||||
|
@ -185,6 +263,16 @@ static int prepare_cmd_slot(int drv, const uint8_t *buf, int sz)
|
|||
return slot;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief This static function executes the command in the specified command
|
||||
* slot for the ATA drive and waits for the command to complete.
|
||||
*
|
||||
* @param[in] drv The index of the ATA drive in the ATA_Drv array.
|
||||
* @param[in] slot The index of the command slot to execute.
|
||||
*
|
||||
* @return 0 on success, or -1 if an error occurs during command execution.
|
||||
*/
|
||||
static int exec_cmd_slot(int drv, int slot)
|
||||
{
|
||||
struct ata_drive *ata = &ATA_Drv[drv];
|
||||
|
@ -229,6 +317,16 @@ static void invert_buf(uint8_t *src, uint8_t *dst, unsigned len)
|
|||
#define ATA_ID_MODEL_NO_POS 54
|
||||
#define ATA_ID_MODEL_NO_LEN 40
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function identifies the ATA device connected to the specified
|
||||
* ATA drive and retrieves its device information, such as serial number and
|
||||
* model name.
|
||||
*
|
||||
* @param[in] drv The index of the ATA drive in the ATA_Drv array.
|
||||
*
|
||||
* @return 0 on success, or -1 if an error occurs during device identification.
|
||||
*/
|
||||
int ata_identify_device(int drv)
|
||||
{
|
||||
struct ata_drive *ata = &ATA_Drv[drv];
|
||||
|
@ -352,6 +450,18 @@ static void ata_cache_commit(int drv)
|
|||
ata_drive_write_sector(drv, ata->cached, 1, ata->sector_cache);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function reads data from the specified ATA drive starting from
|
||||
* the given sector and copies it into the provided buffer. It handles partial
|
||||
* reads and multiple sector transfers.
|
||||
*
|
||||
* @param[in] drv The index of the ATA drive in the ATA_Drv array.
|
||||
* @param[in] start The starting sector number to read from.
|
||||
* @param[in] size The size of the data to read in bytes.
|
||||
* @param[out] buf The buffer to store the read data.
|
||||
*
|
||||
* @return The number of bytes read into the buffer, or -1 if an error occurs.
|
||||
*/
|
||||
int ata_drive_read(int drv, uint64_t start, uint32_t size, uint8_t *buf)
|
||||
{
|
||||
uint64_t sect_start, sect_off;
|
||||
|
@ -390,6 +500,18 @@ int ata_drive_read(int drv, uint64_t start, uint32_t size, uint8_t *buf)
|
|||
return buffer_off;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function writes data from the provided buffer to the specified ATA
|
||||
* drive starting from the given sector. It handles partial writes and multiple
|
||||
* sector transfers.
|
||||
*
|
||||
* @param[in] drv The index of the ATA drive in the ATA_Drv array.
|
||||
* @param[in] start The starting sector number to write to.
|
||||
* @param[in] size The size of the data to write in bytes.
|
||||
* @param[in] buf The buffer containing the data to write.
|
||||
*
|
||||
* @return The number of bytes written to the drive, or -1 if an error occurs.
|
||||
*/
|
||||
int ata_drive_write(int drv, uint64_t start, uint32_t size,
|
||||
const uint8_t *buf)
|
||||
{
|
||||
|
@ -430,3 +552,4 @@ int ata_drive_write(int drv, uint64_t start, uint32_t size,
|
|||
}
|
||||
return buffer_off;
|
||||
}
|
||||
#endif /* ATA_C */
|
||||
|
|
130
src/x86/common.c
130
src/x86/common.c
|
@ -19,6 +19,17 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* @file common.c
|
||||
*
|
||||
* @brief Common functions and macros for wolfBoot
|
||||
*
|
||||
* This file contains common functions and macros used in wolfBoot for
|
||||
* x86 architecture. These functions include memory-mapped I/O access,
|
||||
* I/O port access, CPUID instruction, and reset control functions.
|
||||
*/
|
||||
#ifndef COMMON_H_
|
||||
#define COMMON_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
@ -39,6 +50,12 @@
|
|||
#define NULL 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Memory-mapped write access to a 32-bit register.
|
||||
*
|
||||
* @param address The memory address of the register to write to.
|
||||
* @param value The 32-bit value to write.
|
||||
*/
|
||||
void mmio_write32(uintptr_t address, uint32_t value)
|
||||
{
|
||||
volatile uint32_t *_addr = (uint32_t*)address;
|
||||
|
@ -46,6 +63,13 @@ void mmio_write32(uintptr_t address, uint32_t value)
|
|||
barrier();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Memory-mapped read access to a 32-bit register.
|
||||
*
|
||||
* @param address The memory address of the register to read from.
|
||||
* @return The 32-bit value read from the register.
|
||||
*/
|
||||
uint32_t mmio_read32(uintptr_t address)
|
||||
{
|
||||
volatile uint32_t *_addr = (uint32_t*)address;
|
||||
|
@ -55,6 +79,13 @@ uint32_t mmio_read32(uintptr_t address)
|
|||
barrier();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Memory-mapped write access to a 16-bit register.
|
||||
*
|
||||
* @param address The memory address of the register to write to.
|
||||
* @param value The 16-bit value to write.
|
||||
*/
|
||||
void mmio_write16(uintptr_t address, uint16_t value)
|
||||
{
|
||||
volatile uint16_t *_addr = (uint16_t*)address;
|
||||
|
@ -63,6 +94,12 @@ void mmio_write16(uintptr_t address, uint16_t value)
|
|||
barrier();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Memory-mapped read access to a 16-bit register.
|
||||
*
|
||||
* @param address The memory address of the register to read from.
|
||||
* @return The 16-bit value read from the register.
|
||||
*/
|
||||
uint16_t mmio_read16(uintptr_t address)
|
||||
{
|
||||
volatile uint16_t *_addr = (uint16_t*)address;
|
||||
|
@ -73,6 +110,12 @@ uint16_t mmio_read16(uintptr_t address)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Memory-mapped write access to an 8-bit register.
|
||||
*
|
||||
* @param address The memory address of the register to write to.
|
||||
* @param value The 8-bit value to write.
|
||||
*/
|
||||
void mmio_write8(uintptr_t address, uint8_t value)
|
||||
{
|
||||
volatile uint8_t *_addr = (uint8_t*)address;
|
||||
|
@ -81,6 +124,12 @@ void mmio_write8(uintptr_t address, uint8_t value)
|
|||
barrier();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Memory-mapped read access to an 8-bit register.
|
||||
*
|
||||
* @param address The memory address of the register to read from.
|
||||
* @return The 8-bit value read from the register.
|
||||
*/
|
||||
uint8_t mmio_read8(uintptr_t address)
|
||||
{
|
||||
volatile uint8_t *_addr = (uint8_t*)address;
|
||||
|
@ -91,16 +140,34 @@ uint8_t mmio_read8(uintptr_t address)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I/O port write access to an 8-bit register.
|
||||
*
|
||||
* @param port The I/O port address of the register to write to.
|
||||
* @param value The 8-bit value to write.
|
||||
*/
|
||||
void io_write8(uint16_t port, uint8_t value)
|
||||
{
|
||||
asm volatile("outb %0, %1" : : "a"(value), "Nd"(port));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I/O port write access to a 32-bit register.
|
||||
*
|
||||
* @param port The I/O port address of the register to write to.
|
||||
* @param value The 32-bit value to write.
|
||||
*/
|
||||
void io_write32(uint16_t port, uint32_t value)
|
||||
{
|
||||
__asm__ __volatile__ ("outl %0,%w1": :"a" (value), "Nd" (port));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I/O port read access to a 32-bit register.
|
||||
*
|
||||
* @param port The I/O port address of the register to read from.
|
||||
* @return The 32-bit value read from the register.
|
||||
*/
|
||||
uint32_t io_read32(uint16_t port)
|
||||
{
|
||||
unsigned int _v;
|
||||
|
@ -109,11 +176,23 @@ uint32_t io_read32(uint16_t port)
|
|||
return _v;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I/O port write access to a 16-bit register.
|
||||
*
|
||||
* @param port The I/O port address of the register to write to.
|
||||
* @param value The 16-bit value to write.
|
||||
*/
|
||||
void io_write16(uint16_t port, uint16_t value)
|
||||
{
|
||||
__asm__ __volatile__ ("outw %0,%w1": :"a" (value), "Nd" (port));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I/O port read access to a 16-bit register.
|
||||
*
|
||||
* @param port The I/O port address of the register to read from.
|
||||
* @return The 16-bit value read from the register.
|
||||
*/
|
||||
uint16_t io_read16(uint16_t port)
|
||||
{
|
||||
uint16_t _v;
|
||||
|
@ -122,6 +201,16 @@ uint16_t io_read16(uint16_t port)
|
|||
return _v;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Memory-mapped OR operation with a 32-bit register.
|
||||
*
|
||||
* Reads the 32-bit register at the given address, performs a bitwise OR operation
|
||||
* with the provided value, and writes the result back to the register.
|
||||
*
|
||||
* @param address The memory address of the register.
|
||||
* @param value The 32-bit value to OR with the register contents.
|
||||
* @return The updated 32-bit value of the register after the OR operation.
|
||||
*/
|
||||
uint32_t mmio_or32(uintptr_t address, uint32_t value)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
@ -140,6 +229,11 @@ uint8_t io_read8(uint16_t port)
|
|||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the system.
|
||||
*
|
||||
* @param warm Set to 1 for a warm reset, 0 for a cold reset.
|
||||
*/
|
||||
void reset(uint8_t warm)
|
||||
{
|
||||
uint8_t value;
|
||||
|
@ -150,6 +244,11 @@ void reset(uint8_t warm)
|
|||
while(1){};
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Delay the execution for a specified number of milliseconds.
|
||||
*
|
||||
* @param msec The number of milliseconds to delay.
|
||||
*/
|
||||
void delay(int msec)
|
||||
{
|
||||
int i;
|
||||
|
@ -157,6 +256,12 @@ void delay(int msec)
|
|||
io_write8(0x80, 0x41);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enter an infinite loop, causing a panic state.
|
||||
*
|
||||
* This function is used for error handling when the system encounters an unrecoverable issue.
|
||||
* It enters an infinite loop, causing a panic state.
|
||||
*/
|
||||
void panic()
|
||||
{
|
||||
while (1) {
|
||||
|
@ -164,6 +269,15 @@ void panic()
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Execute the CPUID instruction and retrieve the result.
|
||||
*
|
||||
* @param eax_param The value to set in the EAX register before executing CPUID.
|
||||
* @param eax Pointer to store the output value of the EAX register.
|
||||
* @param ebx Pointer to store the output value of the EBX register.
|
||||
* @param ecx Pointer to store the output value of the ECX register.
|
||||
* @param edx Pointer to store the output value of the EDX register.
|
||||
*/
|
||||
void cpuid(uint32_t eax_param,
|
||||
uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx)
|
||||
{
|
||||
|
@ -189,6 +303,11 @@ void cpuid(uint32_t eax_param,
|
|||
*edx = _edx;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if 1GB page is supported by the CPU.
|
||||
*
|
||||
* @return 1 if 1GB page is supported, 0 otherwise.
|
||||
*/
|
||||
int cpuid_is_1gb_page_supported()
|
||||
{
|
||||
uint32_t edx;
|
||||
|
@ -200,7 +319,15 @@ int cpuid_is_1gb_page_supported()
|
|||
/* Needs to match the code_sel_long offset inside the GDT. The GDT is populated
|
||||
* in src/x86 */
|
||||
#define CODE_SEL_LONG 0x18
|
||||
|
||||
/**
|
||||
* @brief Switch the CPU to long mode.
|
||||
*
|
||||
* This function switches the CPU to long mode with the provided entry point
|
||||
* and page table.
|
||||
*
|
||||
* @param entry The entry point of the long mode code.
|
||||
* @param page_table The page table address to use in long mode.
|
||||
*/
|
||||
void switch_to_long_mode(uint64_t *entry, uint32_t page_table)
|
||||
{
|
||||
/* refer to Intel Software Developer's Manual Vol 3 sec 9.8.5*/
|
||||
|
@ -235,3 +362,4 @@ void switch_to_long_mode(uint64_t *entry, uint32_t page_table)
|
|||
_entry();
|
||||
}
|
||||
#endif /* BUILD_LOADER_STAGE1 */
|
||||
#endif /* COMMON_H_ */
|
||||
|
|
|
@ -19,6 +19,16 @@
|
|||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* @file gpt.c
|
||||
* @brief GPT (GUID Partition Table) driver implementation.
|
||||
*
|
||||
* This file contains the implementation of the GPT driver used for interacting
|
||||
* with GPT partitioned disks. It provides functions for disk initialization,
|
||||
* partition reading, and writing.
|
||||
*/
|
||||
#ifndef GPT_C
|
||||
#define GPT_C
|
||||
#include <x86/common.h>
|
||||
#include <x86/ahci.h>
|
||||
#include <x86/ata.h>
|
||||
|
@ -36,7 +46,10 @@
|
|||
#define P_ENTRY_START 0x01BE
|
||||
#define P_BOOTSIG_OFFSET 0x01FE
|
||||
|
||||
|
||||
/**
|
||||
* @brief This packed structure defines the layout of an MBR partition table entry
|
||||
* used to identify GPT partitions.
|
||||
*/
|
||||
struct __attribute__((packed)) mbr_ptable_entry {
|
||||
uint8_t stat;
|
||||
uint8_t chs_first[3];
|
||||
|
@ -46,6 +59,9 @@ struct __attribute__((packed)) mbr_ptable_entry {
|
|||
uint32_t lba_size;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Structure representing a GPT (GUID Partition Table) header.
|
||||
*/
|
||||
struct __attribute__((packed)) guid_ptable
|
||||
{
|
||||
uint64_t signature;
|
||||
|
@ -65,6 +81,10 @@ struct __attribute__((packed)) guid_ptable
|
|||
uint8_t res1[SECTOR_SIZE - 0x5C];
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This packed structure defines the layout of a GPT partition entry
|
||||
* used to describe individual partitions on the disk.
|
||||
*/
|
||||
struct __attribute__((packed)) guid_part_array
|
||||
{
|
||||
uint64_t type[2];
|
||||
|
@ -75,6 +95,10 @@ struct __attribute__((packed)) guid_part_array
|
|||
int16_t name[72];
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This structure holds information about a disk partition, including
|
||||
* the drive it belongs to, partition number, start, and end offsets.
|
||||
*/
|
||||
struct disk_partition
|
||||
{
|
||||
int drv;
|
||||
|
@ -83,6 +107,11 @@ struct disk_partition
|
|||
uint64_t end;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief This structure holds information about a disk drive, including its
|
||||
* drive number, open status, the number of partitions, and an array of disk
|
||||
* partitions.
|
||||
*/
|
||||
struct disk_drive {
|
||||
int drv;
|
||||
int is_open;
|
||||
|
@ -90,8 +119,24 @@ struct disk_drive {
|
|||
struct disk_partition part[MAX_PARTITIONS];
|
||||
};
|
||||
|
||||
static struct disk_drive Drives[MAX_DISKS] = { };
|
||||
/**
|
||||
* @brief This array holds instances of the `struct disk_drive` representing
|
||||
* multiple disk drives (up to `MAX_DISKS`).
|
||||
*/
|
||||
static struct disk_drive Drives[MAX_DISKS] = {0};
|
||||
|
||||
/**
|
||||
* @brief Opens a disk drive and initializes its partitions.
|
||||
*
|
||||
* This function opens a disk drive with the specified drive number, reads its
|
||||
* MBR (Master Boot Record) to identify GPT partitions, and initializes the
|
||||
* disk_drive structure for further operations.
|
||||
*
|
||||
* @param[in] drv The drive number to open (0 to `MAX_DISKS - 1`).
|
||||
*
|
||||
* @return The number of partitions found and initialized on success, or -1 if
|
||||
* the drive cannot be opened or no valid GPT partition table is found.
|
||||
*/
|
||||
int disk_open(int drv)
|
||||
{
|
||||
int r;
|
||||
|
@ -185,7 +230,19 @@ int disk_open(int drv)
|
|||
wolfBoot_printf("Total partitions on disk%u: %u\r\n", drv, Drives[drv].n_parts);
|
||||
return Drives[drv].n_parts;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Opens a disk partition and returns a pointer to its structure.
|
||||
*
|
||||
* This function opens a disk partition with the specified drive number and
|
||||
* partition number and returns a pointer to its disk_partition structure.
|
||||
* It is a static helper function used internally by the disk_read and disk_write
|
||||
* functions to validate the partition before performing read/write operations.
|
||||
*
|
||||
* @param[in] drv The drive number of the disk containing the partition (0 to `MAX_DISKS - 1`).
|
||||
* @param[in] part The partition number on the disk (0 to `MAX_PARTITIONS - 1`).
|
||||
*
|
||||
* @return A pointer to the disk_partition structure on success, or NULL if an error occurs.
|
||||
*/
|
||||
static struct disk_partition *open_part(int drv, int part)
|
||||
{
|
||||
if ((drv < 0) || (drv > MAX_DISKS)) {
|
||||
|
@ -207,6 +264,20 @@ static struct disk_partition *open_part(int drv, int part)
|
|||
return &Drives[drv].part[part];
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads data from a disk partition into the provided buffer.
|
||||
*
|
||||
* This function reads data from the specified disk partition starting from the
|
||||
* given offset and copies it into the provided buffer.
|
||||
*
|
||||
* @param[in] drv The drive number of the disk containing the partition (0 to `MAX_DISKS - 1`).
|
||||
* @param[in] part The partition number on the disk (0 to `MAX_PARTITIONS - 1`).
|
||||
* @param[in] off The offset in bytes from the start of the partition to read from.
|
||||
* @param[in] sz The size of the data to read in bytes.
|
||||
* @param[out] buf The buffer to store the read data.
|
||||
*
|
||||
* @return The number of bytes read into the buffer on success, or -1 if an error occurs.
|
||||
*/
|
||||
int disk_read(int drv, int part, uint64_t off, uint64_t sz, uint8_t *buf)
|
||||
{
|
||||
struct disk_partition *p = open_part(drv, part);
|
||||
|
@ -225,6 +296,20 @@ int disk_read(int drv, int part, uint64_t off, uint64_t sz, uint8_t *buf)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes data to a disk partition from the provided buffer.
|
||||
*
|
||||
* This function writes data from the provided buffer to the specified disk
|
||||
* partition starting from the given offset.
|
||||
*
|
||||
* @param[in] drv The drive number of the disk containing the partition (0 to `MAX_DISKS - 1`).
|
||||
* @param[in] part The partition number on the disk (0 to `MAX_PARTITIONS - 1`).
|
||||
* @param[in] off The offset in bytes from the start of the partition to write to.
|
||||
* @param[in] sz The size of the data to write in bytes.
|
||||
* @param[in] buf The buffer containing the data to write.
|
||||
*
|
||||
* @return The number of bytes written to the partition on success, or -1 if an error occurs.
|
||||
*/
|
||||
int disk_write(int drv, int part, uint64_t off, uint64_t sz, const uint8_t *buf)
|
||||
{
|
||||
struct disk_partition *p = open_part(drv, part);
|
||||
|
@ -242,3 +327,4 @@ int disk_write(int drv, int part, uint64_t off, uint64_t sz, const uint8_t *buf)
|
|||
ret = ata_drive_write(drv, p->start + off, len, buf);
|
||||
return ret;
|
||||
}
|
||||
#endif /* GPT_C */
|
||||
|
|
|
@ -20,7 +20,8 @@
|
|||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
||||
*/
|
||||
|
||||
#ifndef HOB_C
|
||||
#define HOB_C
|
||||
#include <stdint.h>
|
||||
#include <x86/hob.h>
|
||||
#include <string.h>
|
||||
|
@ -37,16 +38,44 @@ static struct efi_guid hob_fsp_reserved_guid = {
|
|||
{ 0xa6, 0xc4, 0xc7, 0xf5, 0x9e, 0xfd, 0x98, 0x6e }
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Retrieves the HOB type from the provided HOB structure.
|
||||
*
|
||||
* This function takes a pointer to an EFI_HOB structure and returns the HOB type
|
||||
* as a uint16_t.
|
||||
*
|
||||
* @param[in] hob Pointer to the EFI_HOB structure.
|
||||
* @return The HOB type as a uint16_t.
|
||||
*/
|
||||
uint16_t hob_get_type(struct efi_hob *hob)
|
||||
{
|
||||
return hob->u.header.hob_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves the length of the HOB structure from the provided HOB structure.
|
||||
*
|
||||
* This function takes a pointer to an EFI_HOB structure and returns the length
|
||||
* of the HOB structure as a uint16_t.
|
||||
*
|
||||
* @param[in] hob Pointer to the EFI_HOB structure.
|
||||
* @return The length of the HOB structure as a uint16_t.
|
||||
*/
|
||||
uint16_t hob_get_length(struct efi_hob *hob)
|
||||
{
|
||||
return hob->u.header.hob_length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Retrieves the next HOB structure in the HOB list.
|
||||
*
|
||||
* This function takes a pointer to an EFI_HOB structure and returns a pointer to
|
||||
* the next HOB structure in the HOB list.
|
||||
*
|
||||
* @param[in] hob Pointer to the EFI_HOB structure.
|
||||
* @return A pointer to the next HOB structure or NULL if the end of the list is
|
||||
* reached.
|
||||
*/
|
||||
struct efi_hob *hob_get_next(struct efi_hob *hob)
|
||||
{
|
||||
struct efi_hob *ret;
|
||||
|
@ -54,11 +83,32 @@ struct efi_hob *hob_get_next(struct efi_hob *hob)
|
|||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compares two EFI_GUID structures for equality.
|
||||
*
|
||||
* This function takes two pointers to EFI_GUID structures and compares them
|
||||
* for equality. It returns 1 if the GUIDs are equal and 0 otherwise.
|
||||
*
|
||||
* @param[in] a Pointer to the first EFI_GUID structure.
|
||||
* @param[in] b Pointer to the second EFI_GUID structure.
|
||||
* @return 1 if the GUIDs are equal, 0 otherwise.
|
||||
*/
|
||||
int hob_guid_equals(struct efi_guid *a, struct efi_guid *b)
|
||||
{
|
||||
return memcmp(a, b, sizeof(*a)) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Finds an EFI_HOB_RESOURCE_DESCRIPTOR with a specific owner GUID.
|
||||
*
|
||||
* This function searches the HOB list for an EFI_HOB_RESOURCE_DESCRIPTOR with
|
||||
* the specified owner GUID. If found, it returns a pointer to the descriptor,
|
||||
* otherwise, it returns NULL.
|
||||
*
|
||||
* @param[in] hoblist Pointer to the beginning of the HOB list.
|
||||
* @param[in] guid Pointer to the owner GUID to search for.
|
||||
* @return A pointer to the EFI_HOB_RESOURCE_DESCRIPTOR or NULL if not found.
|
||||
*/
|
||||
struct efi_hob_resource_descriptor *
|
||||
hob_find_resource_by_guid(struct efi_hob *hoblist, struct efi_guid *guid)
|
||||
{
|
||||
|
@ -78,12 +128,35 @@ hob_find_resource_by_guid(struct efi_hob *hoblist, struct efi_guid *guid)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Finds the EFI_HOB_RESOURCE_DESCRIPTOR with the FSP reserved GUID.
|
||||
*
|
||||
* This function searches the HOB list for the EFI_HOB_RESOURCE_DESCRIPTOR
|
||||
* with the FSP reserved GUID and returns a pointer to the descriptor if found.
|
||||
* If not found, it returns NULL.
|
||||
*
|
||||
* @param[in] hoblist Pointer to the beginning of the HOB list.
|
||||
* @return A pointer to the EFI_HOB_RESOURCE_DESCRIPTOR or NULL if not found.
|
||||
*/
|
||||
struct efi_hob_resource_descriptor *
|
||||
hob_find_fsp_reserved(struct efi_hob *hoblist)
|
||||
{
|
||||
return hob_find_resource_by_guid(hoblist, &hob_fsp_reserved_guid);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Iterates through the memory map in the HOB list and calls a callback
|
||||
* function for each resource descriptor.
|
||||
*
|
||||
* This function iterates through the memory map in the HOB list and calls the
|
||||
* specified callback function for each EFI_HOB_RESOURCE_DESCRIPTOR found
|
||||
* in the list.
|
||||
*
|
||||
* @param[in] hobList Pointer to the beginning of the HOB list.
|
||||
* @param[in] cb Callback function to be called for each resource descriptor.
|
||||
* @param[in] ctx User-defined context to be passed to the callback function.
|
||||
* @return 0 on success, or an error code if an error occurs during iteration.
|
||||
*/
|
||||
int hob_iterate_memory_map(struct efi_hob *hobList, hob_mem_map_cb cb,
|
||||
void *ctx)
|
||||
{
|
||||
|
@ -103,3 +176,4 @@ int hob_iterate_memory_map(struct efi_hob *hobList, hob_mem_map_cb cb,
|
|||
|
||||
return 0;
|
||||
}
|
||||
#endif /* HOB_C */
|
||||
|
|
|
@ -20,6 +20,18 @@
|
|||
*
|
||||
* Machine dependent code for TigerLake x86 with FSP
|
||||
*/
|
||||
/**
|
||||
* @file tgl_fsp.c
|
||||
*
|
||||
* @brief Machine dependent code for TigerLake x86 with FSP
|
||||
*
|
||||
* This file contains machine dependent code for TigerLake x86 platform
|
||||
* with Firmware Support Package (FSP).
|
||||
*/
|
||||
|
||||
#ifndef TGL_FSP_H
|
||||
#define TGL_FSP_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <x86/hob.h>
|
||||
|
@ -405,6 +417,15 @@ static int disable_watchdog_tco()
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update S parameters in FSPS_UPD structure.
|
||||
*
|
||||
* This function updates the S parameters in the FSPS_UPD structure for
|
||||
* TigerLake x86 platform with FSP.
|
||||
*
|
||||
* @param[in,out] default_s_params Pointer to the default S parameters data.
|
||||
* @return 0 on success, -1 on failure.
|
||||
*/
|
||||
int fsp_machine_update_s_parameters(uint8_t *default_s_params)
|
||||
{
|
||||
FSP_S_CONFIG *upd;
|
||||
|
@ -442,7 +463,16 @@ int fsp_machine_update_s_parameters(uint8_t *default_s_params)
|
|||
upd->EnableMultiPhaseSiliconInit = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure GPIO settings for a specific device.
|
||||
*
|
||||
* This function configures GPIO settings for a specific device on TigerLake x86
|
||||
* platform.
|
||||
*
|
||||
* @param[in,out] gpio Pointer to the tgl_gpio_info structure containing GPIO
|
||||
* information.
|
||||
* @return void
|
||||
*/
|
||||
static int tgl_setup_lpc_decode(uint32_t address, uint32_t length,
|
||||
uint32_t range)
|
||||
{
|
||||
|
@ -477,6 +507,15 @@ struct tgl_gpio_info {
|
|||
uint8_t pad_reset:2;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Configure GPIO settings for a specific device.
|
||||
* @details This function configures GPIO settings for a specific device on
|
||||
* TigerLake x86 platform.
|
||||
*
|
||||
* @param[in,out] gpio Pointer to the tgl_gpio_info structure containing
|
||||
* GPIO information.
|
||||
* @return void
|
||||
*/
|
||||
static void tgl_gpio_configure(struct tgl_gpio_info *gpio)
|
||||
{
|
||||
uint16_t off;
|
||||
|
@ -495,6 +534,13 @@ static void tgl_gpio_configure(struct tgl_gpio_info *gpio)
|
|||
}
|
||||
|
||||
#ifdef TARGET_kontron_vx3060_s2
|
||||
/**
|
||||
* @brief Set up ECE1200 device on Kontron VX3060-S2 board.
|
||||
*
|
||||
* This function sets up the ECE1200 device on the Kontron VX3060-S2 board.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
static void setup_ece1200()
|
||||
{
|
||||
uint8_t reg;
|
||||
|
@ -515,7 +561,14 @@ static void setup_ece1200()
|
|||
io_write8(ECE1200_DATA, reg);
|
||||
io_write8(ECE1200_INDEX, 0xaa); /* close conf mode */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure Kontron CPLD for special settings.
|
||||
*
|
||||
* This function configures the Kontron CPLD for special settings on the Kontron
|
||||
* VX3060-S2 board.
|
||||
*
|
||||
* @return 0 on success, -1 on failure.
|
||||
*/
|
||||
static int configure_kontron_cpld()
|
||||
{
|
||||
uint8_t reg;
|
||||
|
@ -543,6 +596,13 @@ static int configure_kontron_cpld()
|
|||
|
||||
#define CPLD_I2C_MISC 0x78
|
||||
#define CPLD_I2C_MISC_FORCE_RESCUE (1 << 7)
|
||||
/**
|
||||
* @brief Ask for recovery mode using CPLD.
|
||||
*
|
||||
* This function asks for recovery mode using CPLD on the Kontron VX3060-S2 board.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
static void kontron_ask_for_recovery() {
|
||||
uint32_t reg;
|
||||
uint8_t ch;
|
||||
|
@ -566,6 +626,13 @@ static void kontron_ask_for_recovery() {
|
|||
}
|
||||
#endif /* TARGET_kontron_vx3060_s2 */
|
||||
|
||||
/**
|
||||
* @brief Callback function after temporary RAM initialization.
|
||||
*
|
||||
* This function is a callback after temporary RAM initialization on TigerLake x86.
|
||||
*
|
||||
* @return 0 on success, -1 on failure.
|
||||
*/
|
||||
int post_temp_ram_init_cb(void)
|
||||
{
|
||||
disable_watchdog_tco();
|
||||
|
@ -598,6 +665,17 @@ int post_temp_ram_init_cb(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update M parameters in FSPM_UPD structure.
|
||||
*
|
||||
* This function updates the M parameters in the FSPM_UPD structure for
|
||||
* TigerLake x86 platform with FSP.
|
||||
*
|
||||
* @param[in,out] default_m_params Pointer to the default M parameters data.
|
||||
* @param[in] mem_base Base address of memory.
|
||||
* @param[in] mem_size Size of memory.
|
||||
* @return 0 on success, -1 on failure.
|
||||
*/
|
||||
int fsp_machine_update_m_parameters(uint8_t *default_m_params,
|
||||
uint32_t mem_base,
|
||||
uint32_t mem_size)
|
||||
|
@ -619,3 +697,5 @@ int fsp_machine_update_m_parameters(uint8_t *default_m_params,
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* TGL_FSP_H */
|
||||
|
|
Loading…
Reference in New Issue