diff options
author | Derek Huang <derekhuang@google.com> | 2022-12-14 10:01:02 +0000 |
---|---|---|
committer | Chromeos LUCI <chromeos-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2023-03-08 03:52:46 +0000 |
commit | 42a911f7d9ca7db0933315c0eed6367ba7469681 (patch) | |
tree | 8e33ceba1068d2e14253d26918930ea046280792 /driver | |
parent | 1fbdcd9f057bc34d9b15b6a0d5eafee19df33152 (diff) | |
download | chrome-ec-42a911f7d9ca7db0933315c0eed6367ba7469681.tar.gz |
driver/wpc/cps8100.c: Add support of CPS8200 firmware update
This patch adds cps8200_update_open, cps8200_update_write and
cps8200_update_close functions which allow the host updater
(e.g. ectool) to update firmware of cps8200 via I2C.
Example:
localhost ~ # ectool pchg 0 update 0x3 0x0 /path/to/image.bin
Opened update session (port=0 ver=0x3 bsize=128):
0x0 /path/to/image.bin
Writing /path/to/image.bin (33980 bytes)
**************************************************************
Firmware was updated successfully (CRC32=0xfe43d401).
BUG=b:195708351
BRANCH=none
TEST=ectool pchg 0 update 0x3 0x0 ./CPS8200_A0_40_V3_CRCBEA6.bin
Change-Id: I4e17a308714c94dc2b9335943536a732297b86fc
Signed-off-by: Derek Huang <derekhuang@google.com>
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/4105947
Reviewed-by: Daisuke Nojiri <dnojiri@chromium.org>
Diffstat (limited to 'driver')
-rw-r--r-- | driver/wpc/cps8100.c | 487 | ||||
-rw-r--r-- | driver/wpc/cps8100.h | 1 | ||||
-rw-r--r-- | driver/wpc/cps8200_bootloader.h | 85 |
3 files changed, 535 insertions, 38 deletions
diff --git a/driver/wpc/cps8100.c b/driver/wpc/cps8100.c index bac911d167..006a42f131 100644 --- a/driver/wpc/cps8100.c +++ b/driver/wpc/cps8100.c @@ -6,6 +6,8 @@ #include "chipset.h" #include "common.h" #include "console.h" +#include "cps8200_bootloader.h" +#include "crc.h" #include "gpio.h" #include "i2c.h" #include "peripheral_charger.h" @@ -56,11 +58,36 @@ #define CPS8200_REG_I2C_ENABLE 0xFFFFFF00 #define CPS8200_REG_PASSWORD 0x400140FC +/* Firmware update */ +#define CPS8200_ADDR_SRAM 0x20000000 +#define CPS8200_ADDR_BUFFER0 0x20002800 +#define CPS8200_ADDR_BUFFER1 0x20003000 +#define CPS8200_ADDR_CMD 0x200038F8 +#define CPS8200_ADDR_CMD_STATUS 0x200038FC +#define CPS8200_ADDR_BUF_SIZE 0x200038F4 +#define CFG_BUFF_SIZE 128 +#define CPS8200_CMD_TIMEOUT (3 * SECOND) +/* CMD and CMD status. Lower 4 bits are for command ID */ +#define CMD_PGM_BUFFER0 (0x1 << 4) +#define CMD_PGM_BUFFER1 (0x2 << 4) +#define CMD_PGM_WR_FLAG (0x8 << 4) +#define CMD_CACL_CRC_APP (0x9 << 4) +#define CMD_CACL_CRC_BOOT (0xB << 4) +#define CMD_STATUS_RUNNING (0x1 << 4) +#define CMD_STATUS_PASS (0x2 << 4) +#define CMD_STATUS_FAIL (0x3 << 4) +#define CMD_STATUS_ILLEGAL (0x4 << 4) + #define CPS8100_STATUS_PROFILE(r) (((r)&GENMASK(5, 4)) >> 4) #define CPS8100_STATUS_CHARGE(r) ((r)&BIT(6)) #define CPS8100_STATUS_DEVICE(r) ((r)&BIT(7)) #define CPS8100_STATUS_BATTERY(r) (((r)&GENMASK(15, 8)) >> 8) #define CPS8100_IRQ_TYPE(r) (((r)&GENMASK(23, 20)) >> 20) +#define CPS8200_CMD_STATUS(flag) ((flag)&GENMASK(7, 4)) +#define CPS8X00_GET_FW_VER(value) ((value)&GENMASK(7, 0)) +#define CPS8X00_BAD_FW_VERSION 0xff +#define CPS8200_CMD_MASK GENMASK(7, 4) +#define CPS8200_CMD_ID_MASK GENMASK(3, 0) /* Status flags in ALERT_INFO register */ #define CPS8100_STATUS_FOD BIT(0) @@ -72,7 +99,15 @@ /* Buffer size for i2c read & write */ #define CPS8100_MESSAGE_BUFFER_SIZE 0x20 +/* + * CPS8100 needs 100~120ms delay and CPS8200 needs 40~50ms delay between + * reset and the first access to I2C register. + */ +#define CPS8200_POWER_ON_DELAY_MS 50 +#define CPS8100_POWER_ON_DELAY_MS 120 + static uint32_t chip_id; +static const int short_sleep_ms = 2; /* TODO: Check datasheet how to wake up and how long it takes to wake up. */ static const int cps8100_wake_up_delay_ms = 10; @@ -305,6 +340,23 @@ static int cps8100_read32(int port, uint32_t reg, uint32_t *val) sizeof(*val)); } +static int cps8200_write32(int port, uint32_t reg, uint32_t val) +{ + uint8_t buf[8]; + + buf[0] = (reg >> 24) & 0xff; + buf[1] = (reg >> 16) & 0xff; + buf[2] = (reg >> 8) & 0xff; + buf[3] = (reg >> 0) & 0xff; + + buf[4] = (val >> 0) & 0xff; + buf[5] = (val >> 8) & 0xff; + buf[6] = (val >> 16) & 0xff; + buf[7] = (val >> 24) & 0xff; + + return cps8100_i2c_write(port, CPS8200_I2C_ADDR, buf, sizeof(buf)); +} + static int cps8200_read32(int port, uint32_t reg, uint32_t *val) { uint8_t buf[4]; @@ -314,10 +366,36 @@ static int cps8200_read32(int port, uint32_t reg, uint32_t *val) buf[2] = (reg >> 8) & 0xff; buf[3] = (reg >> 0) & 0xff; - return i2c_xfer(port, CPS8200_I2C_ADDR, buf, 4, (void *)val, + return i2c_xfer(port, CPS8200_I2C_ADDR, buf, sizeof(buf), (void *)val, sizeof(*val)); } +static int cps8200_write_mem(int port, uint32_t addr, uint8_t *data, size_t len) +{ + int rv; + uint8_t buf[4]; + + buf[0] = (addr >> 24) & 0xff; + buf[1] = (addr >> 16) & 0xff; + buf[2] = (addr >> 8) & 0xff; + buf[3] = (addr >> 0) & 0xff; + + i2c_lock(port, 1); + /* Addr */ + rv = i2c_xfer_unlocked(port, CPS8200_I2C_ADDR, buf, sizeof(buf), NULL, + 0, I2C_XFER_START); + if (rv) { + i2c_lock(port, 0); + return rv; + } + /* Data */ + rv = i2c_xfer_unlocked(port, CPS8200_I2C_ADDR, data, len, NULL, 0, + I2C_XFER_STOP); + i2c_lock(port, 0); + + return rv; +} + static int cps8100_unlock(int port) { int rv; @@ -334,7 +412,80 @@ static int cps8200_unlock(int port) return rv ? rv : cps8200_set_unlock(port); } -static int cps8100_reset(struct pchg *ctx) +/* + * Send command to CPS8200 by writing command to CPS8200_ADDR_CMD register. + * command = cmd (higher 4 bits) + id (lower 4 bits), id needs to be increased + * every time. + */ +static uint8_t cps8200_send_cmd(struct pchg *ctx, uint8_t cmd, uint8_t *id) +{ + uint8_t port = ctx->cfg->i2c_port; + struct cps8x00_update *upd = &(ctx->update.driver_data.cps8200_update); + + *id = upd->cmd_id; + cmd &= CPS8200_CMD_MASK; + cmd |= *id; + upd->cmd_id++; + upd->cmd_id &= CPS8200_CMD_ID_MASK; + + return cps8200_write32(port, CPS8200_ADDR_CMD, (uint32_t)cmd); +} + +/* + * Read the response of command by reading CPS8200_ADDR_CMD_STATUS register. + * Return EC_SUCCESS if the status is CMD_STATUS_PASS and the id matches to + * the id which is expected. + */ +static int cps8200_wait_cmd_done(int port, uint8_t id) +{ + int rv; + uint32_t u32; + timestamp_t deadline; + + deadline.val = get_time().val + CPS8200_CMD_TIMEOUT; + while (1) { + msleep(10); + rv = cps8200_read32(port, CPS8200_ADDR_CMD_STATUS, &u32); + if (rv) + return EC_ERROR_UNKNOWN; + + if ((CMD_STATUS_PASS | id) == (u32 & 0x00ff)) + break; + if (CPS8200_CMD_STATUS(u32) == CMD_STATUS_FAIL || + CPS8200_CMD_STATUS(u32) == CMD_STATUS_ILLEGAL) { + CPRINTS("Command failed or illegal: %02x", + CPS8200_CMD_STATUS(u32)); + return EC_ERROR_UNKNOWN; + } + + rv = timestamp_expired(deadline, NULL); + if (rv) { + CPRINTS("Command timeout!"); + return EC_ERROR_TIMEOUT; + } + } + return EC_SUCCESS; +} + +static int cps8x00_read_firmware_ver(struct pchg *ctx) +{ + uint32_t u32; + int port = ctx->cfg->i2c_port; + int rv; + + rv = cps8x00_read32(port, CPS8100_REG_FW_INFO, &u32); + if (!rv) { + ctx->fw_version = CPS8X00_GET_FW_VER(u32); + } else { + ctx->fw_version = CPS8X00_BAD_FW_VERSION; + CPRINTS("Failed to read FW info: %d", rv); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; +} + +static int cps8x00_reset(struct pchg *ctx) { gpio_set_level(GPIO_QI_RESET_L, 0); cps8100_status_update(ctx, 0); @@ -344,7 +495,7 @@ static int cps8100_reset(struct pchg *ctx) return EC_SUCCESS; } -static int cps8100_init(struct pchg *ctx) +static int cps8x00_init(struct pchg *ctx) { int port = ctx->cfg->i2c_port; @@ -357,7 +508,7 @@ static int cps8100_init(struct pchg *ctx) return EC_ERROR_UNKNOWN; } -static int cps8100_enable(struct pchg *ctx, bool enable) +static int cps8x00_enable(struct pchg *ctx, bool enable) { return EC_SUCCESS; } @@ -375,30 +526,26 @@ static int cps8100_get_alert_info(struct pchg *ctx, uint32_t *reg) return EC_SUCCESS; } -static int cps8100_get_chip_info(struct pchg *ctx) +static int cps8x00_get_chip_info(struct pchg *ctx) { uint32_t u32; int port = ctx->cfg->i2c_port; int rv = EC_ERROR_UNKNOWN; - /* - * CPS8100 needs 100~120ms delay, CPS8200 needs 40~50ms delay - * between reset and the first access to I2C register. - */ if (chip_id == CPS8100_CHIPID) { /* * already probed but unlock again in case it's turned * off. */ - msleep(120); + msleep(CPS8100_POWER_ON_DELAY_MS); return cps8100_unlock(port); } else if (chip_id == CPS8200_CHIPID) { - msleep(50); + msleep(CPS8200_POWER_ON_DELAY_MS); return cps8200_unlock(port); } /* not probed yet, need to unlock blindly first. */ - msleep(120); + msleep(MAX(CPS8100_POWER_ON_DELAY_MS, CPS8200_POWER_ON_DELAY_MS)); if (!cps8100_unlock(port)) rv = cps8100_read32(port, CPS8100_REG_IC_INFO, &u32); else if (!cps8200_unlock(port)) @@ -409,7 +556,7 @@ static int cps8100_get_chip_info(struct pchg *ctx) return rv; } - /* Probe */; + /* Probe */ CPRINTS("IC=0x%08x", u32); if ((u32 & 0xffff) == CPS8100_CHIPID) { cps8x00_read32 = cps8100_read32; @@ -422,12 +569,9 @@ static int cps8100_get_chip_info(struct pchg *ctx) return EC_ERROR_UNKNOWN; } - if (!cps8x00_read32(port, CPS8100_REG_FW_INFO, &u32)) { - CPRINTS("FW=0x%08x", u32); - } else { - CPRINTS("Failed to read FW info!"); - return EC_ERROR_UNKNOWN; - } + rv = cps8x00_read_firmware_ver(ctx); + if (!rv) + CPRINTS("FW=0x%02x", ctx->fw_version); return EC_SUCCESS; } @@ -445,7 +589,7 @@ static void cps8100_print_alert_info(uint32_t reg) CPRINTFP("Battery: %d%%\n", CPS8100_STATUS_BATTERY(reg)); } -static int cps8100_get_event(struct pchg *ctx) +static int cps8x00_get_event(struct pchg *ctx) { uint32_t r1, r2; int rv; @@ -486,38 +630,305 @@ static int cps8100_get_event(struct pchg *ctx) return EC_SUCCESS; } -static int cps8100_get_soc(struct pchg *ctx) +static int cps8x00_get_soc(struct pchg *ctx) { ctx->battery_percent = CPS8100_STATUS_BATTERY(cps8100_state.reg); return EC_SUCCESS; } -static int cps8100_update_open(struct pchg *ctx) +/* + * This function does the preparation for firmware update, the steps are: + * 1. Enable i2c and unlock. + * 2. Reset MCU, reset watchdog, disable DCDC and reset MCU clock. + * 3. Program bootloader to SRAM. + * 4. Run bootloader. + * 5. Check CRC of bootloader. + * 6. Ready for firmware download. Configure buffer size for firmware download. + */ +static int cps8200_update_open(struct pchg *ctx) { - return EC_ERROR_UNIMPLEMENTED; + uint32_t u32; + uint8_t id; + int port = ctx->cfg->i2c_port; + int rv; + struct cps8x00_update *upd = &(ctx->update.driver_data.cps8200_update); + + upd->cmd_id = 0; + upd->crc = 0; + upd->firmware_len = 0; + + /* enable i2c and unlock */ + rv = cps8200_unlock(port); + if (rv) + return rv; + + /* + * The value and address of the registers are from the sample code + * and programming guide provided by the vendor in + * https://issuetracker.google.com/issues/195708351#comment32 + */ + + /* Reset MCU and halt */ + rv = cps8200_write32(port, 0x40014028, 0x00010000); + if (rv) + return rv; + msleep(50); + + /* Reset watchdog */ + rv = cps8200_write32(port, 0x40008400, 0x1ACCE551); + if (rv) + return rv; + msleep(short_sleep_ms); + rv = cps8200_write32(port, 0x40008008, 0x0); + if (rv) + return rv; + msleep(short_sleep_ms); + + /* Disable DCDC module */ + rv = cps8200_write32(port, 0x4000F0A4, 0x0); + if (rv) + return rv; + msleep(50); + + /* Reset MCU clock */ + rv = cps8200_write32(port, 0x40014020, 0x0); + if (rv) + return rv; + msleep(short_sleep_ms); + rv = cps8200_write32(port, 0x40014024, 0x0); + if (rv) + return rv; + msleep(short_sleep_ms); + rv = cps8200_write32(port, 0x400140A8, 0x0); + if (rv) + return rv; + msleep(short_sleep_ms); + + /* Program bootloader to SRAM */ + CPRINTS("Loading bootloader hex!"); + if (cps8200_write_mem(port, CPS8200_ADDR_SRAM, (uint8_t *)&boot_hex, + boot_hex_len * 4)) { + CPRINTS("Failed to write bootloader!"); + return EC_ERROR_UNKNOWN; + } + msleep(short_sleep_ms); + + /* disable trim */ + rv = cps8200_write32(port, 0x4001F01C, 0x0); + if (rv) + return rv; + msleep(short_sleep_ms); + + /* enable address remap */ + rv = cps8200_write32(port, 0x4001F030, 0xFFFFFF00); + if (rv) + return rv; + msleep(short_sleep_ms); + rv = cps8200_write32(port, 0x4001F034, 0xFFFFFFFF); + if (rv) + return rv; + msleep(short_sleep_ms); + rv = cps8200_write32(port, 0x4001F038, 0xFFFFFFFF); + if (rv) + return rv; + msleep(short_sleep_ms); + rv = cps8200_write32(port, 0x4001F03C, 0xFFFFFFFF); + if (rv) + return rv; + msleep(short_sleep_ms); + + /* disable mcu halt, run bootloader */ + rv = cps8200_write32(port, 0x40014028, 0x101); + if (rv) + return rv; + msleep(short_sleep_ms); + + /* enable i2c and unlock */ + rv = cps8200_i2c_enable(port); + if (rv) + return rv; + msleep(short_sleep_ms); + + /* write bootloader length */ + rv = cps8200_write32(port, CPS8200_ADDR_BUFFER0, boot_hex_len * 4); + if (rv) + return rv; + msleep(short_sleep_ms); + + /* calculate CRC of bootloader */ + rv = cps8200_send_cmd(ctx, CMD_CACL_CRC_BOOT, &id); + if (rv) + return rv; + + /* check command status */ + rv = cps8200_wait_cmd_done(port, id); + if (rv) + return rv; + msleep(100); + + /* check CRC */ + rv = cps8200_read32(port, CPS8200_ADDR_BUFFER0, &u32); + if (rv) + return rv; + upd->crc = cros_crc16((uint8_t *)boot_hex, boot_hex_len * 4, 0); + if (upd->crc != (u32 & 0x0000ffff)) { + CPRINTS("crc = %04x, expect %04x", u32, upd->crc); + CPRINTS("CRC of bootloader is wroing!"); + return EC_ERROR_UNKNOWN; + } + CPRINTS("Successfully load bootloader!"); + + upd->crc = 0x0000; + /* Prepare to download firmware and program flash, change buffer size */ + rv = cps8200_write32(port, CPS8200_ADDR_BUF_SIZE, + ctx->cfg->block_size / 4); + if (rv) { + CPRINTS("Failed to change buffer size (%d)", rv); + return EC_ERROR_UNKNOWN; + } + + return EC_SUCCESS; } -static int cps8100_update_write(struct pchg *ctx) +/* + * This function writes the firmware block to the chip and returns only after + * the write is complete. The steps are: + * 1. Write firmware block to the chip buffer. + * 2. Send command to the chip. + * 3. The chip program the flash. + * 4. Calculate and update CRC. + */ +static int cps8200_update_write(struct pchg *ctx) { - return EC_ERROR_UNIMPLEMENTED; + int port = ctx->cfg->i2c_port; + int rv; + uint8_t id; + uint8_t *buf = ctx->update.data; + struct cps8x00_update *upd = &(ctx->update.driver_data.cps8200_update); + + /* Write data to buffer */ + if (cps8200_write_mem(port, CPS8200_ADDR_BUFFER0, buf, + ctx->update.size)) + return EC_ERROR_UNKNOWN; + msleep(short_sleep_ms); + + /* Write buffer to flash */ + rv = cps8200_send_cmd(ctx, CMD_PGM_BUFFER0, &id); + if (rv) + return rv; + + /* Check the program result */ + rv = cps8200_wait_cmd_done(port, id); + if (rv) { + CPRINTS("Failed to write flash : %d", rv); + return EC_ERROR_UNKNOWN; + } + + /* Calculate and update CRC */ + upd->firmware_len += ctx->update.size; + upd->crc = cros_crc16(ctx->update.data, ctx->update.size, upd->crc); + + return EC_SUCCESS; } -static int cps8100_update_close(struct pchg *ctx) +/* + * This function checks firmware update result, power on and power off the chip + * if firmware update is successful. The steps are: + * 1. Send command to the chip to calculate the firmware CRC. + * 2. Read the CRC value from the chip and compare. + * 3. If CRC is correct, power off and power on the chip. + */ +static int cps8200_update_close(struct pchg *ctx) { - return EC_ERROR_UNIMPLEMENTED; + int port = ctx->cfg->i2c_port; + int rv; + uint32_t u32; + uint8_t id; + struct cps8x00_update *upd = &(ctx->update.driver_data.cps8200_update); + uint32_t len = upd->firmware_len; + + /* Write firmware length */ + rv = cps8200_write32(port, CPS8200_ADDR_BUFFER0, len); + if (rv) + return rv; + msleep(short_sleep_ms); + + /* Check firmware CRC */ + CPRINTS("Checking Firmware CRC..."); + rv = cps8200_send_cmd(ctx, CMD_CACL_CRC_APP, &id); + if (rv) + return rv; + + rv = cps8200_wait_cmd_done(port, id); + if (rv) { + CPRINTS("Command to calculate CRC timeout or failed: %d", rv); + return EC_ERROR_UNKNOWN; + } + msleep(100); + + cps8200_read32(port, CPS8200_ADDR_BUFFER0, &u32); + if (upd->crc != (u32 & 0x0000ffff)) { + CPRINTS("crc = %04x, expect %04x", u32, upd->crc); + CPRINTS("CRC of firmware is wroing!"); + return EC_ERROR_UNKNOWN; + } + CPRINTS("Firmware CRC is correct!"); + CPRINTS("Successfully update the firmware"); + + rv = cps8200_send_cmd(ctx, CMD_PGM_WR_FLAG, &id); + if (rv) + return rv; + + rv = cps8200_wait_cmd_done(port, id); + if (rv) { + CPRINTS("Command to program flash failed: %d", rv); + return EC_ERROR_UNKNOWN; + } + + /* + * Due to the CPS8200 issue + * (https://issuetracker.google.com/issues/258093708), we can't simply + * reset CPS8200. CPS8200 needs to be powered off to completely reset + * its internal modules after completing the firmware update, and then + * power on after some delay. We need 50ms delay after power on to + * ensure there is enough delay before first I2C command + */ + + /* power off MCU */ + board_pchg_power_on(PCHG_CTX_TO_PORT(ctx), 0); + msleep(short_sleep_ms); + /* power on MCU */ + board_pchg_power_on(PCHG_CTX_TO_PORT(ctx), 1); + msleep(CPS8200_POWER_ON_DELAY_MS); + /* Update the information of firmware version */ + cps8200_unlock(port); + rv = cps8x00_read_firmware_ver(ctx); + if (!rv) + CPRINTS("FW=0x%02x", ctx->fw_version); + + return EC_SUCCESS; } const struct pchg_drv cps8100_drv = { - .reset = cps8100_reset, - .init = cps8100_init, - .enable = cps8100_enable, - .get_chip_info = cps8100_get_chip_info, - .get_event = cps8100_get_event, - .get_soc = cps8100_get_soc, - .update_open = cps8100_update_open, - .update_write = cps8100_update_write, - .update_close = cps8100_update_close, + .reset = cps8x00_reset, + .init = cps8x00_init, + .enable = cps8x00_enable, + .get_chip_info = cps8x00_get_chip_info, + .get_event = cps8x00_get_event, + .get_soc = cps8x00_get_soc, +}; + +const struct pchg_drv cps8200_drv = { + .reset = cps8x00_reset, + .init = cps8x00_init, + .enable = cps8x00_enable, + .get_chip_info = cps8x00_get_chip_info, + .get_event = cps8x00_get_event, + .get_soc = cps8x00_get_soc, + .update_open = cps8200_update_open, + .update_write = cps8200_update_write, + .update_close = cps8200_update_close, }; static void cps8100_dump(struct pchg *ctx) @@ -555,8 +966,8 @@ static int cc_cps8100(int argc, const char **argv) } if (!strcasecmp(argv[2], "reset")) { - cps8100_reset(ctx); - cps8100_init(ctx); + cps8x00_reset(ctx); + cps8x00_init(ctx); } else { return EC_ERROR_PARAM3; } diff --git a/driver/wpc/cps8100.h b/driver/wpc/cps8100.h index 0fb6fe0c4e..644ee37089 100644 --- a/driver/wpc/cps8100.h +++ b/driver/wpc/cps8100.h @@ -11,5 +11,6 @@ #include "peripheral_charger.h" extern struct pchg_drv cps8100_drv; +extern struct pchg_drv cps8200_drv; #endif /* __CROS_EC_WPC_CPS8100_H */ diff --git a/driver/wpc/cps8200_bootloader.h b/driver/wpc/cps8200_bootloader.h new file mode 100644 index 0000000000..32b0af4a23 --- /dev/null +++ b/driver/wpc/cps8200_bootloader.h @@ -0,0 +1,85 @@ +/* Copyright 2023 The ChromiumOS Authors + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ +const uint32_t boot_hex[] = { + 0x20003D00, 0x20000149, 0x20000157, 0x20000159, 0x00000000, 0x00000000, + 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x2000015B, + 0x00000000, 0x00000000, 0x2000015D, 0x2000015F, 0x20000161, 0x20000161, + 0x20000161, 0x20000161, 0x20000161, 0x20000161, 0x20000161, 0x20000161, + 0x20000161, 0x20000161, 0x20000161, 0x20000161, 0x20000161, 0x20000161, + 0x20000161, 0x20000161, 0x20000161, 0x20000161, 0x20000161, 0x20000161, + 0x20000161, 0x20000161, 0x20000161, 0x20000161, 0x20000161, 0x20000161, + 0x20000161, 0x20000161, 0x20000161, 0x20000161, 0x20000161, 0x20000161, + 0xF802F000, 0xF830F000, 0xC830A00C, 0x18243808, 0x46A2182D, 0x46AB1E67, + 0x465D4654, 0xD10142AC, 0xF822F000, 0x3E0F467E, 0x46B6CC0F, 0x42332601, + 0x1AFBD000, 0x46AB46A2, 0x47184333, 0x0000061C, 0x0000062C, 0x24002300, + 0x26002500, 0xD3013A10, 0xD8FBC178, 0xD3000752, 0xD500C130, 0x4770600B, + 0xBD1FB51F, 0xBD10B510, 0xFAC3F000, 0xF7FF4611, 0xF000FFF7, 0xF000FA8C, + 0xB403FADB, 0xFFF2F7FF, 0xF000BC03, 0x0000FAE1, 0x490A4809, 0x480A6001, + 0x480A4780, 0xE7FE4700, 0xE7FEE7FE, 0xE7FEE7FE, 0x0000E7FE, 0x49074806, + 0x4B084A07, 0x00004770, 0x4001F030, 0xFFFFFFFF, 0x200006AB, 0x200000C1, + 0x20002060, 0x20003D00, 0x20002460, 0x20003900, 0x48FD49FE, 0x49FE63C8, + 0x60082000, 0x202049FC, 0x60083914, 0x210B48FB, 0x60416001, 0x60812100, + 0x48F760C1, 0x698130E8, 0x04522201, 0x61814391, 0x09096981, 0x1C490109, + 0x49F16181, 0x680A3168, 0x439A0583, 0x6981600A, 0x0112223F, 0x31C04391, + 0x69826181, 0x430A1399, 0x69826182, 0x431A1403, 0x4AE96182, 0x1C402000, + 0xD3FC4290, 0x38C048E3, 0x438A6B02, 0x6B026302, 0x01D209D2, 0x6302325F, + 0x430A6B02, 0x68026302, 0x6002438A, 0x09526802, 0x60020152, 0x430A6802, + 0x6A026002, 0x431A2301, 0x68426202, 0x6042438A, 0x09126842, 0x60420112, + 0x430A6842, 0x47706042, 0x210348D2, 0x4AD162C1, 0x32C02100, 0x61816391, + 0x61C22201, 0x48CB6102, 0x460863C1, 0x4ACB4770, 0x62516210, 0x20082163, + 0x43036AD3, 0x1E4962D3, 0x6AD1D2FA, 0x62D14301, 0x43016AD1, 0x6AD162D1, + 0x62D14381, 0x06806BD0, 0x2062D4FC, 0xD2FD1E40, 0x47702000, 0x48BA49BB, + 0x49BC63C8, 0x62C82003, 0x210148BA, 0x638130C0, 0x63C149BA, 0x47702000, + 0x4604B570, 0x4DB82000, 0xE00E4602, 0x021B5CA3, 0x23004058, 0xD5020406, + 0x40680040, 0x0040E000, 0xB2801C5B, 0xDBF52B08, 0x428A1C52, 0xBD70D3EE, + 0x260048A8, 0x463449A6, 0x4AA863C1, 0x63C661D6, 0xFFD0F7FF, 0x48AA49A9, + 0xFFB1F7FF, 0xFFA0F7FF, 0x680849A8, 0xD0FB2800, 0x600A2200, 0x600849A6, + 0x400121F0, 0x0F000700, 0x42A04615, 0x48A3D105, 0x22016800, 0x42900252, + 0x2040DD05, 0x48A04304, 0x24006004, 0x2010E7E4, 0x43204A9D, 0x4A916010, + 0x63D0488F, 0xD01C2990, 0x2910DC06, 0x2920D036, 0x2980D051, 0xE029D163, + 0xD02329A0, 0xD15E29B0, 0x68284D94, 0x03092101, 0xDD034288, 0x43C02000, + 0xE03C6028, 0x20016829, 0xF7FF0740, 0x6028FF99, 0x4982E052, 0x61C82001, + 0x62784F8B, 0x68294D89, 0x07002003, 0xFF8CF7FF, 0x62792100, 0x487B6028, + 0xE04161C1, 0x20004983, 0xE03D6008, 0xFF72F7FF, 0x487B4982, 0xFF53F7FF, + 0xE0124605, 0xFF6AF7FF, 0xE0082700, 0x00B9487B, 0x46305841, 0xFF47F7FF, + 0x1D364305, 0x48751C7F, 0x42876800, 0x4875DBF2, 0xF7FFE01B, 0x1C68FF2D, + 0x2D00D019, 0x4620D01C, 0x43082130, 0xF7FFE01A, 0x2700FF4D, 0x4870E008, + 0x584100B9, 0xF7FF4630, 0x4305FF2A, 0x1C7F1D36, 0x68004866, 0xDBF24287, + 0x60064869, 0x4964E7E1, 0x60082040, 0xE0062400, 0x43202020, 0x60084960, + 0x07241C64, 0x49530F24, 0x63C82000, 0x2100E760, 0x43C9485D, 0x63416301, + 0x63C16381, 0x62422201, 0x20004A4E, 0x62506210, 0x62D32303, 0x6313230E, + 0x4A4A6350, 0x635032C0, 0x63D06390, 0x38404845, 0x08926802, 0x1C520092, + 0x68026002, 0x439A230C, 0x60021D12, 0x23306802, 0x3210439A, 0x68026002, + 0x439A23C0, 0x60023240, 0x009B6802, 0x6002439A, 0x009B6802, 0x6002439A, + 0x009B6802, 0x6002439A, 0x009B6802, 0x6002439A, 0x009B6802, 0x6002439A, + 0x009B6802, 0x6002439A, 0x009B6802, 0x6002439A, 0x009B6802, 0x6002439A, + 0x009B6802, 0x6002439A, 0x009B6802, 0x6002439A, 0x009B6802, 0x0543439A, + 0x600218D2, 0x05C36802, 0x08920092, 0x600218D2, 0x08D26842, 0x1C5200D2, + 0x68426042, 0x439A2318, 0x60423208, 0x6101482B, 0x61416041, 0x47702000, + 0x4B18B570, 0x63D84816, 0x48274928, 0x4A286008, 0x60902000, 0x49136008, + 0x62883940, 0x39C04911, 0x62086248, 0x2201680C, 0x43940412, 0x680C600C, + 0x01640964, 0x600C3409, 0x4314680C, 0x684C600C, 0x604C4394, 0x0924684C, + 0x1D240124, 0x684C604C, 0x604C4314, 0x60084905, 0x22016048, 0xE029608A, + 0x00001250, 0x400140C0, 0x4000F018, 0x40012000, 0x000061A8, 0x00008888, + 0x00001021, 0x12345678, 0x000100F8, 0x200038F8, 0x200038F0, 0x200038F4, + 0x200038FC, 0x20002800, 0x4001F000, 0x5724E185, 0x20003000, 0x40010000, + 0x1ACCE551, 0x40008400, 0x40008000, 0x610A60CA, 0x62CA2203, 0x630A220E, + 0x63484923, 0x63C86388, 0x4C234922, 0x49236BCA, 0xD10A42A2, 0x22004C1F, + 0x19153C40, 0x682D1856, 0x60351D12, 0xDDF82A28, 0x2200E007, 0x1D121854, + 0x2A286020, 0x4A1ADDFA, 0x4A1861CA, 0x32802100, 0x1D09188C, 0x29D46020, + 0x63D8DDFA, 0x4B152100, 0x25014C15, 0x008A026D, 0x50A05098, 0x42A91C49, + 0x2000DBF9, 0x4911BD70, 0x60082040, 0x20004910, 0x49106008, 0x60082020, + 0x480F4910, 0xF7FF6008, 0xF7FFFF5F, 0xF7FFFD91, 0xF7FFFEEA, 0x0000FE39, + 0x400120C0, 0x000100C0, 0x7455874E, 0x4000F000, 0x00005030, 0x20002800, + 0x20003000, 0x200038F4, 0x200038F8, 0x200038FC, 0x12345678, 0x200038F0, + 0x47704770, 0x47704770, 0x46754770, 0xF824F000, 0x000546AE, 0x46534669, + 0x00C008C0, 0xB0184685, 0xF7FFB520, 0xBC60FD4B, 0x08492700, 0x260046B6, + 0xC5C0C5C0, 0xC5C0C5C0, 0xC5C0C5C0, 0xC5C0C5C0, 0x00493D40, 0x4770468D, + 0x4604B510, 0x46C046C0, 0xF7FF4620, 0xBD10FD1E, 0x47704800, 0x20002000, + 0x20184901, 0xE7FEBEAB, 0x00020026, 0x00004770, 0x20000728, 0x20002000, + 0x00001D00, 0x20000104 +}; +const size_t boot_hex_len = ARRAY_SIZE(boot_hex); +BUILD_ASSERT(ARRAY_SIZE(boot_hex) == 458); |