diff --git a/arch/arm/include/asm/arch-npcm7xx/gcr.h b/arch/arm/include/asm/arch-npcm7xx/gcr.h index 37a63fc32fe1..577bef366e1e 100644 --- a/arch/arm/include/asm/arch-npcm7xx/gcr.h +++ b/arch/arm/include/asm/arch-npcm7xx/gcr.h @@ -127,6 +127,12 @@ #define INTCR_MFTFEN 1 #define INTCR_KCSRST_MODE 0 +/* Integration Control Register 2 (INTCR2) */ +#define INTCR2_WDC 21 +#define INTCR2_CHOSEN_IMAGE 20 +#define INTCR2_SELFTEST_PASSED 11 +#define INTCR2_SELFTEST_REQUEST 10 + /* Integration Control Register 3 (INTCR3) */ #define INTCR3_PCIRREL 30 #define INTCR3_GFXRSTDLY 26 @@ -144,6 +150,10 @@ #define INTCR3_BIOSEN 1 #define INTCR3_HHRDIS 0 +/* Function Lock Register 1 (FLOCKR1) */ +#define FLOCKR1_UPDATE_APPROVE_LOCK 29 +#define FLOCKR1_UPDATE_APPROVE 28 + /* Serial Ports (SPSWC) */ #define SPSWC_RTSS 7 #define SPSWC_DTRS 6 diff --git a/arch/arm/include/asm/arch-npcm7xx/mailbox.h b/arch/arm/include/asm/arch-npcm7xx/mailbox.h new file mode 100644 index 000000000000..b0c0bc730ae0 --- /dev/null +++ b/arch/arm/include/asm/arch-npcm7xx/mailbox.h @@ -0,0 +1,98 @@ +/*----------------------------------------------------------------------------*/ +/* SPDX-License-Identifier: GPL-2.0 */ +/* */ +/* Copyright (c) 2010-2019 by Nuvoton Technology Corporation */ +/* All rights reserved */ +/* */ +/*----------------------------------------------------------------------------*/ +/* File Contents: */ +/* mailbox.h */ +/* This file contains API of routines for handling the PCI MailBox */ +/* Project: */ +/* Poleg Bootblock and ROM Code (shared header) */ +/*----------------------------------------------------------------------------*/ + +#ifndef _MAILBOX_H +#define _MAILBOX_H + +#include "shared_defs.h" + +#define ROM_STATUS_MSG_ADDR 0xF084BFE8 +#define BOOTBLK_STATUS_MSG_ADDR 0xF084BFD0 + +/*---------------------------------------------------------------------------------------------------------*/ +/* Image states */ +/*---------------------------------------------------------------------------------------------------------*/ +#define IMAGE_NOT_TESTED 0x00 +#define IMAGE_WRONG_START_TAG 0x01 +#define IMAGE_DEST_ADDRESS_UNALIGNED 0x02 +#define IMAGE_BAD_SIGNATURE 0x04 +#define IMAGE_MEMORY_OVERLAP 0x08 +#define IMAGE_HEADER_OK_COPY_IMAGE 0x10 +#define IMAGE_OK_RUN_FROM_FLASH 0x40 +#define IMAGE_OK 0x80 +#define IMAGE_REJECTED_BY_BB 0x11 +#define IMAGE_NEW_COPY 0x12 +#define IMAGE_NOT_IN_USE 0xFF /* image is not selected - depends on FUSE_FUSTRAP_oAltImgLoc */ + +/*---------------------------------------------------------------------------------------------------------*/ +/* Rom status */ +/*---------------------------------------------------------------------------------------------------------*/ +#define ST_ROM_BASIC_USE_IMAGE_SPI0_CS0_OFFSET0 0x21 // Select image at SPI0 CS0 offset 0 ( address 0x80000000) +#define ST_ROM_BASIC_USE_IMAGE_SPI0_CS0_OFFSET80000 0x22 // Select image at SPI0 CS0 offset 8000 ( address 0x80080000) +#define ST_ROM_BASIC_USE_IMAGE_SPI0_CS1_OFFSET0 0x23 // Select image at SPI0 CS1 offset 0 ( address 0x88000000) + +#define ST_ROM_USE_KEY0_IMAGE0 0x27 // checking image 0, select Pk0 according to fuses for signature varification. +#define ST_ROM_USE_KEY1_IMAGE0 0x28 // checking image 0, select Pk1 according to fuses for signature varification. +#define ST_ROM_USE_KEY2_IMAGE0 0x29 // checking image 0, select Pk2 according to fuses for signature varification. + +#define ST_ROM_USE_KEY0_IMAGE1 0x2A // checking image 1, select Pk0 according to fuses for signature varification. +#define ST_ROM_USE_KEY1_IMAGE1 0x2B // checking image 1, select Pk1 according to fuses for signature varification. +#define ST_ROM_USE_KEY2_IMAGE1 0x2C // checking image 1, select Pk2 according to fuses for signature varification. + +#define ST_ROM_USE_KEY0_IMAGE2 0x2D // checking image 2, select Pk0 according to fuses for signature varification. +#define ST_ROM_USE_KEY1_IMAGE2 0x2E // checking image 2, select Pk1 according to fuses for signature varification. +#define ST_ROM_USE_KEY2_IMAGE2 0x2F // checking image 2, select Pk2 according to fuses for signature varification. + +/*---------------------------------------------------------------------------------------------------------*/ +/* MailBox module internal structure definitions */ +/*---------------------------------------------------------------------------------------------------------*/ +#pragma pack(1) +typedef struct _ROM_STATUS_MSG +{ + union + { + struct + { + u8 image0State; + u8 image1State; + u8 image2state; + + union + { + struct + { + u8 image0_pk0; + u8 image0_pk1; + u8 image0_pk2; + u8 image1_pk0; + u8 image1_pk1; + u8 image1_pk2; + u8 image2_pk0; + u8 image2_pk1; + u8 image2_pk2; + } pk_states; + u8 pk_bytes[9]; + } pk; + } state ; + u8 bytes[12]; + } imageState ; + + u8 startTag[START_TAG_SIZE]; + u32 status; + +} ROM_STATUS_MSG; +#pragma pack() + +#endif + diff --git a/arch/arm/include/asm/arch-npcm7xx/otp.h b/arch/arm/include/asm/arch-npcm7xx/otp.h index 153037d3d0c2..4d5b72fb110c 100644 --- a/arch/arm/include/asm/arch-npcm7xx/otp.h +++ b/arch/arm/include/asm/arch-npcm7xx/otp.h @@ -55,6 +55,7 @@ struct npcm_otp_regs { #define FDATA_MASK (0xff) +#define FUSTRAP_O_ALTIMGLOC BIT(18) #define FUSTRAP_O_SECBOOT BIT(23) #define FCFG_FDIS BIT(31) diff --git a/arch/arm/include/asm/arch-npcm7xx/shared_defs.h b/arch/arm/include/asm/arch-npcm7xx/shared_defs.h new file mode 100644 index 000000000000..a9d3284eab45 --- /dev/null +++ b/arch/arm/include/asm/arch-npcm7xx/shared_defs.h @@ -0,0 +1,26 @@ +#ifndef SHARED_DEFS_H +#define SHARED_DEFS_H + +#include + +#define FLASH_BOOT_ALTERNATIVES 2 + +/*------------------------------------------------------*/ +/* Boot module exported definitions */ +/*------------------------------------------------------*/ +#define START_TAG_SIZE 8 // bytes +// 0xAA550750 T O O B +#define START_TAG_ARR_BOOTBLOCK {0x50, 0x07, 0x55, 0xAA, 0x54, 0x4F, 0x4F, 0x42} +// U B O O T B L K +#define START_TAG_ARR_UBOOT {0x55, 0x42, 0x4F, 0x4F, 0x54, 0x42, 0x4C, 0x4B} + +#define FLASH_EXAM_ADDR_1 (SPI0_BASE_ADDR) +#define FLASH_EXAM_ADDR_2 (SPI0_BASE_ADDR + 0x80000) +#define FLASH_EXAM_ADDR_3 (SPI0_BASE_ADDR + SPI_FLASH_REGION_SIZE) + +#define KBOLD_ON "\x1b[1m" +#define KBOLD_OFF "\x1b[22m" +#define KNRM "\x1B[0m" KBOLD_OFF +#define KRED "\x1B[31m" KBOLD_ON + +#endif diff --git a/arch/arm/mach-npcm/secure_boot.c b/arch/arm/mach-npcm/secure_boot.c index f90c65e91b34..6d2d85de03e9 100644 --- a/arch/arm/mach-npcm/secure_boot.c +++ b/arch/arm/mach-npcm/secure_boot.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #define NPCM_GCR_INTCR2_SELFTEST_PASSED BIT(11) @@ -82,7 +83,7 @@ static int secure_boot_configuration(void) * fuse images should be a part of the flash image, right after the uboot * TODO: set addr */ - //addr = POLEG_UBOOT_END; + addr = POLEG_UBOOT_END; /* * if found, program the image to the fuse arrays, set the secure boot diff --git a/board/nuvoton/poleg/Kconfig b/board/nuvoton/poleg/Kconfig index e821fdb8d697..d92324304664 100644 --- a/board/nuvoton/poleg/Kconfig +++ b/board/nuvoton/poleg/Kconfig @@ -27,5 +27,8 @@ config TARGET_POLEG_RUNBMC endchoice +config NPCM_NIST_BOOT + bool "NPCM NIST Boot" + source "board/nuvoton/common/Kconfig" endif diff --git a/board/nuvoton/poleg/Makefile b/board/nuvoton/poleg/Makefile index 3a3de5885371..8f0f9e071059 100644 --- a/board/nuvoton/poleg/Makefile +++ b/board/nuvoton/poleg/Makefile @@ -22,3 +22,4 @@ # obj-y := poleg.o +obj-$(CONFIG_NPCM_NIST_BOOT) += nist_boot.o diff --git a/board/nuvoton/poleg/nist_boot.c b/board/nuvoton/poleg/nist_boot.c new file mode 100644 index 000000000000..dd7db0ddcda4 --- /dev/null +++ b/board/nuvoton/poleg/nist_boot.c @@ -0,0 +1,510 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void BOOTBLOCK_GetLoadedBootBlockHeader (u32** bootBlockHeader, u32** secondbootBlockHeader,u32* image) +{ + struct npcm_gcr *gcr = (struct npcm_gcr *)npcm_get_base_gcr(); + bool bChosenImage; + bool bUseSecondLocationForSecondImage; + u32 swapAddress = 0; + u32 flashExamAddrArr[FLASH_BOOT_ALTERNATIVES]; + + /* init the location array */ + flashExamAddrArr[0] = FLASH_EXAM_ADDR_1; + flashExamAddrArr[1] = FLASH_EXAM_ADDR_2; + + /* check if location array needs update according to WDC and oAltImgLoc */ + bUseSecondLocationForSecondImage = readl(FUSTRAP) & FUSTRAP_O_ALTIMGLOC; + bChosenImage = readl(&gcr->intcr2) & (1 << INTCR2_CHOSEN_IMAGE); + + /* take second image from CS1 */ + if (bUseSecondLocationForSecondImage) + flashExamAddrArr[1] = FLASH_EXAM_ADDR_3; + + /* WDC (whatchdog counter) > 1 ? start from second image */ + if (bChosenImage) { + swapAddress = flashExamAddrArr[0]; + flashExamAddrArr[0] = flashExamAddrArr[1]; + flashExamAddrArr[1] = swapAddress; + } + + /*-------------------------------------------------------------------------------------------------*/ + /* Update the cureently tested image location. This is done for debug and visibility of ROM code */ + /*-------------------------------------------------------------------------------------------------*/ + if ( flashExamAddrArr[0] == FLASH_EXAM_ADDR_1) + *image = 0; + + if ( flashExamAddrArr[0] == FLASH_EXAM_ADDR_2) + *image = 1; + + if ( flashExamAddrArr[0] == FLASH_EXAM_ADDR_3) + *image = 2; + + *bootBlockHeader = (u32 *)flashExamAddrArr[0]; + *secondbootBlockHeader = (u32 *)flashExamAddrArr[1]; +} + +bool is_ROMCode_Status_Basic_mode (void) +{ + ROM_STATUS_MSG *msgPtrROM = (ROM_STATUS_MSG *)ROM_STATUS_MSG_ADDR; + + // According to ROM_status_ram->status we can decide is secure mode or basic mode + if ((msgPtrROM->status >= ST_ROM_USE_KEY0_IMAGE0) && + (msgPtrROM->status <= ST_ROM_USE_KEY2_IMAGE2)) + return false; + // basic mode + else if ((msgPtrROM->status >= ST_ROM_BASIC_USE_IMAGE_SPI0_CS0_OFFSET0) && + (msgPtrROM->status <= ST_ROM_BASIC_USE_IMAGE_SPI0_CS1_OFFSET0)) + return true; + + return false; +} + +int spi_erase_tag(int cs) +{ + struct spi_flash *flash; + struct udevice *udev; + int bus = 0; + int rc; + + rc = spi_flash_probe_bus_cs(bus, cs, + CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE, &udev); + if (rc) { + printf("SF: failed to probe spi\n"); + return rc; + } + + flash = dev_get_uclass_priv(udev); + if (!flash) { + printf("SF: probe for flash failed\n"); + return -1; + } + + rc = spi_flash_erase(flash, 0x0, flash->erase_size); + printf("SF: %zu bytes @ %#x Erased: %s\n", (size_t)flash->erase_size, + 0x0, rc ? "ERROR" : "OK"); + return rc; +} + +int spi_copy_image(int from, int to) +{ + struct spi_flash *flash; + struct udevice *udev; + int bus = 0; + unsigned long addr = 0x10000000; + void *src, *buf; + u32 len, sector_addr, sector_offset; + u32 dest_addr, end_addr; + int chunk_sz; + int newline; + int rc; + + rc = spi_flash_probe_bus_cs(bus, from, + CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE, &udev); + if (rc) { + printf("SF: failed to probe spi\n"); + return -1; + } + + flash = dev_get_uclass_priv(udev); + if (!flash) { + printf("SF: probe for flash failed\n"); + return -1; + } + + dest_addr = flash->erase_size; + end_addr = flash->size; + len = flash->size - flash->erase_size; + src = map_physmem(addr, len, MAP_WRBACK); + if (!src && addr) { + printf("Failed to map physical memory\n"); + return -1; + } + + rc = spi_flash_read(flash, dest_addr, len, src); + printf("SF: %zu bytes @ %#x Read: %s\n", (size_t)len, + dest_addr, rc ? "ERROR" : "OK"); + if(rc) + goto done; + + rc = spi_flash_probe_bus_cs(bus, to, + CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE, &udev); + if (rc) { + printf("SF: failed to probe spi\n"); + goto done; + } + + flash = dev_get_uclass_priv(udev); + if (!flash) { + printf("SF: probe for flash failed\n"); + goto done; + } + + /* + * sector_addr sector_end + * v v + * | <-- secotr_offset--> | <## chunk_sz ##> | + * ^ + * dest_addr + */ + + buf = memalign(ARCH_DMA_MINALIGN, flash->erase_size); + newline = 64; + + while (dest_addr < end_addr) { + sector_offset = dest_addr % flash->erase_size; + sector_addr = dest_addr - sector_offset; + chunk_sz = min(len, (flash->erase_size - sector_offset)); + + /* read sector to buf */ + rc = spi_flash_read(flash, sector_addr, flash->erase_size, buf); + if (rc) { + printf("Read ERROR @ %#x\n", sector_addr); + break; + } + + if (memcmp(src, buf + sector_offset, chunk_sz) == 0) { + printf("."); + if (--newline == 0) { + printf("\n"); + newline = 64; + } + /* source and target are the same, skip programming */ + dest_addr += chunk_sz; + src += chunk_sz; + len -= chunk_sz; + continue; + } + + if (chunk_sz < flash->erase_size) { + /* erase sector */ + rc= spi_flash_erase(flash, sector_addr, flash->erase_size); + debug("SF: %zu bytes @ %#x Erased: %s\n", (size_t)flash->erase_size, + sector_addr, rc ? "ERROR" : "OK"); + + /* update buf */ + memcpy(buf + sector_offset, src, chunk_sz); + + /* program sector */ + rc = spi_flash_write(flash, sector_addr, flash->erase_size, buf); + debug("SF: %zu bytes @ %#x Written: %s\n", (size_t)flash->erase_size, + sector_addr, rc ? "ERROR" : "OK"); + } else { + printf("#"); + if (--newline == 0) { + printf("\n"); + newline = 64; + } + /* erase sector */ + rc = spi_flash_erase(flash, sector_addr, flash->erase_size); + debug("SF: %zu bytes @ %#x Erased: %s\n", (size_t)flash->erase_size, + sector_addr, rc ? "ERROR" : "OK"); + + /* program sector */ + rc = spi_flash_write(flash, sector_addr, chunk_sz, src); + debug("SF: %zu bytes @ %#x Written: %s\n", (size_t)chunk_sz, + sector_addr, rc ? "ERROR" : "OK"); + } + dest_addr += chunk_sz; + src += chunk_sz; + len -= chunk_sz; + } + printf("\nSF: %zu bytes @ %#x Written: %s\n", (size_t)(flash->size - flash->erase_size), + flash->erase_size, rc ? "ERROR" : "OK"); + +done: + if (src) + unmap_physmem(src, len); + if (buf) + free(buf); + return rc == 0 ? 0 : 1; +} + +int spi_copy_header(int from, int to) +{ + struct spi_flash *flash; + struct udevice *udev; + int bus = 0; + char *buf; + int rc; + + rc = spi_flash_probe_bus_cs(bus, from, + CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE, &udev); + if (rc) { + printf("SF: failed to probe spi\n"); + return rc; + } + + flash = dev_get_uclass_priv(udev); + if (!flash) { + printf("SF: probe for flash failed\n"); + return -1; + } + + buf = memalign(ARCH_DMA_MINALIGN, flash->erase_size); + + rc = spi_flash_read(flash, 0x0, flash->erase_size, buf); + printf("SF: %zu bytes @ %#x Read: %s\n", (size_t)flash->erase_size, + 0x0, rc ? "ERROR" : "OK"); + if(rc) + goto done; + + rc = spi_flash_probe_bus_cs(bus, to, + CONFIG_SF_DEFAULT_SPEED, CONFIG_SF_DEFAULT_MODE, &udev); + if (rc) { + printf("SF: failed to probe spi\n"); + goto done; + } + + flash = dev_get_uclass_priv(udev); + if (!flash) { + printf("SF: probe for flash failed\n"); + goto done; + } + + rc = spi_flash_write(flash, 0x0, flash->erase_size, buf); + printf("SF: %zu bytes @ %#x Written: %s\n", (size_t)flash->erase_size, + 0x0, rc ? "ERROR" : "OK"); + +done: + free(buf); + return rc; +} + + +int recovery_flash(void) +{ + struct npcm_gcr *gcr = (struct npcm_gcr *)npcm_get_base_gcr(); + ROM_STATUS_MSG *msgPtrROM = (ROM_STATUS_MSG *)ROM_STATUS_MSG_ADDR; + ROM_STATUS_MSG *msgPtrBB = (ROM_STATUS_MSG *)BOOTBLK_STATUS_MSG_ADDR; + u32 val; + int status = 0; + + printf("> 9\n"); + printf("> NIST recovery\n"); + printf("> copy from 0x88000000 to 0x80000000 size 0x4000000\n"); + printf("> Prepare to copy...\n"); + + printf("> erase tag 0\n"); + status = spi_erase_tag(0); + if (status) + return status; + + printf("> erase image and program, one sector at a time\n"); + status = spi_copy_image(1, 0); + if (status) + return status; + + printf("> copy header\n"); + status = spi_copy_header(1, 0); + if (status) + return status; + + printf("> done copy\n"); + + val = readl(&gcr->intcr2); + val &= ~(1 << INTCR2_SELFTEST_PASSED); + writel(val, &gcr->intcr2); + printf("> set rSelfTestPassed flag 0, INTCR2= 0x%08x\n", readl(&gcr->intcr2)); + + val = readl(&gcr->intcr2); + val &= ~(1 << INTCR2_SELFTEST_REQUEST); + writel(val, &gcr->intcr2); + printf("> set rSelfTestRequest flag 0, INTCR2= 0x%08x\n", readl(&gcr->intcr2)); + + val = readl(&gcr->flockr1); + val &= ~(1 << FLOCKR1_UPDATE_APPROVE); + writel(val, &gcr->flockr1); + printf("> set rUpdateApprove flag 0, FLOCKR1= 0x%08x\n", readl(&gcr->flockr1)); + + reset_misc(); + printf("> set WDC 0, INTCR2= 0x%08x\n", readl(&gcr->intcr2)); + msgPtrBB->imageState.bytes[0] = IMAGE_NEW_COPY; + msgPtrROM->imageState.bytes[0] = IMAGE_NEW_COPY; + reset_cpu(0); + + return 0; +} + +int update_flash(void) +{ + struct npcm_gcr *gcr = (struct npcm_gcr *)npcm_get_base_gcr(); + ROM_STATUS_MSG *msgPtrROM = (ROM_STATUS_MSG *)ROM_STATUS_MSG_ADDR; + ROM_STATUS_MSG *msgPtrBB = (ROM_STATUS_MSG *)BOOTBLK_STATUS_MSG_ADDR; + u32 val; + int status; + + printf("> 6\n"); + printf("> NIST update\n"); + printf("> copy from 0x80000000 to 0x88000000 size 0x4000000\n"); + printf("> Prepare to copy...\n"); + + printf("> erase tag 1\n"); + status = spi_erase_tag(1); + if (status) + return status; + + printf("> erase image and program, one sector at a time\n"); + status = spi_copy_image(0, 1); + if (status) + return status; + + printf("> copy header\n"); + status = spi_copy_header(0, 1); + if (status) + return status; + + printf("> done copy\n"); + + val = readl(&gcr->intcr2); + val &= ~(1 << INTCR2_SELFTEST_PASSED); + writel(val, &gcr->intcr2); + printf("> set rSelfTestPassed flag 0, INTCR2= 0x%08x\n", readl(&gcr->intcr2)); + + val = readl(&gcr->intcr2); + val &= ~(1 << INTCR2_SELFTEST_REQUEST); + writel(val, &gcr->intcr2); + printf("> set rSelfTestRequest flag 0, INTCR2= 0x%08x\n", readl(&gcr->intcr2)); + + val = readl(&gcr->flockr1); + val &= ~(1 << FLOCKR1_UPDATE_APPROVE); + writel(val, &gcr->flockr1); + printf("> set rUpdateApprove flag 0, FLOCKR1= 0x%08x\n", readl(&gcr->flockr1)); + + reset_misc(); + printf("> set WDC 0, INTCR2= 0x%08x\n", readl(&gcr->intcr2)); + msgPtrBB->imageState.bytes[2] = IMAGE_NEW_COPY; + msgPtrROM->imageState.bytes[2] = IMAGE_NEW_COPY; + reset_cpu(0); + + return 0; +} + +void lock_flash1(void) +{ + printf("> 13\n"); + printf("Lock Flash #1\n"); +} + +void check_rSelfTestPass_status(struct npcm_gcr *gcr) +{ + int val; + printf("> 11\n"); + val = readl(&gcr->intcr2) & (1 << INTCR2_SELFTEST_PASSED); + printf("> get rSelfTestPassed flag %d, INTCR2= 0x%08x\n", val?1:0, readl(&gcr->intcr2)); + if (readl(&gcr->intcr2) & (1 << INTCR2_SELFTEST_PASSED)) { + printf("> 14\n"); + val = readl(&gcr->flockr1); + val |= (1 << FLOCKR1_UPDATE_APPROVE); + writel(val, &gcr->flockr1); + printf("> set rUpdateApprove flag 1, FLOCKR1 = 0x%08x\n", readl(&gcr->flockr1)); + update_flash(); + } else { + printf("> 12\n"); + val = readl(&gcr->intcr2); + val |= (1 << INTCR2_SELFTEST_REQUEST); + writel(val, &gcr->intcr2); + printf("> set rSelfTestRequest flag 1, INTCR2= 0x%08x\n", readl(&gcr->intcr2)); + writel((readl(&gcr->intcr2) | (0x1 << INTCR2_WDC)), &gcr->intcr2); + printf("> set WDC 1, INTCR2= 0x%08x\n", readl(&gcr->intcr2)); + lock_flash1(); + } +} + +void nist_boot(void) +{ + struct npcm_gcr *gcr = (struct npcm_gcr *)npcm_get_base_gcr(); + const u8 startTag[START_TAG_SIZE] = START_TAG_ARR_BOOTBLOCK; + u32 *BootBlockHeaderPtr, *secondBootBlockHeaderPtr; + u32 *uBootHeaderPtr, *seconduBootHeaderPtr; + u32 image = 0; + ROM_STATUS_MSG *msgPtrROM = (ROM_STATUS_MSG *)ROM_STATUS_MSG_ADDR; + ROM_STATUS_MSG *msgPtrBB = (ROM_STATUS_MSG *)BOOTBLK_STATUS_MSG_ADDR; + u32 bb_ver0, bb_ver1; + u32 uboot_ver0, uboot_ver1; + + reset_misc(); + + // Secure Boot Authentication Check are all failed + if (is_ROMCode_Status_Basic_mode()) { + printf(KRED "\n\n>Halt and catch fire.\n" KNRM ); + while(1); + } + + BOOTBLOCK_GetLoadedBootBlockHeader(&BootBlockHeaderPtr, &secondBootBlockHeaderPtr, &image); + uBootHeaderPtr = (u32 *)(0xFFFFF000 & + ((u32)BootBlockHeaderPtr + HEADER_SIZE + readl((u32)BootBlockHeaderPtr + HEADER_SIZE_OFFSET) + 0xFFF)); + seconduBootHeaderPtr = (u32 *)(0xFFFFF000 & + ((u32)secondBootBlockHeaderPtr + HEADER_SIZE + readl((u32)secondBootBlockHeaderPtr + HEADER_SIZE_OFFSET) + 0xFFF)); + printf("\n> NIST: bootblock at 0x%p, uboot at 0x%p, image num %d\n\n", + BootBlockHeaderPtr, uBootHeaderPtr, image); + + if (image == 0) { + bb_ver0 = readl((u32)BootBlockHeaderPtr + HEADER_VERSION_OFFSET); + bb_ver1 = readl((u32)secondBootBlockHeaderPtr + HEADER_VERSION_OFFSET); + uboot_ver0 = readl((u32)uBootHeaderPtr + HEADER_VERSION_OFFSET); + uboot_ver1 = readl((u32)seconduBootHeaderPtr + HEADER_VERSION_OFFSET); + } + else if (image == 2) { + bb_ver0 = readl((u32)secondBootBlockHeaderPtr + HEADER_VERSION_OFFSET); + bb_ver1 = readl((u32)BootBlockHeaderPtr + HEADER_VERSION_OFFSET); + uboot_ver0 = readl((u32)seconduBootHeaderPtr + HEADER_VERSION_OFFSET); + uboot_ver1 = readl((u32)uBootHeaderPtr + HEADER_VERSION_OFFSET); + } + printf("> BB ver0 = 0x%06x, ver1 = 0x%06x\n", bb_ver0, bb_ver1); + printf("> UBOOT ver0 0x%06x , ver1 0x%06x\n", uboot_ver0, uboot_ver1); + + if (image == 0) { //Run Active Bootblock from flash #0 + printf("> 4\n"); + if (memcmp((void *)(secondBootBlockHeaderPtr), startTag, START_TAG_SIZE)) { + printf(">bb : Check flash #1 start tag at 0x%p is invalid!\n", secondBootBlockHeaderPtr); + check_rSelfTestPass_status(gcr); + } + else { + printf(">bb : start tag OK at 0x%p\n", BootBlockHeaderPtr); + + printf("> 7\n"); + if(msgPtrBB->imageState.bytes[0]== IMAGE_OK) { + printf("image%d valid\n", image); + printf("> 10 Perform Version Control\n"); + + if (bb_ver0 < bb_ver1) { + printf("> 8 Core reset\n"); + writel((readl(&gcr->intcr2) | (0x1 << INTCR2_WDC)), &gcr->intcr2); + printf("> set WDC 1, INTCR2= 0x%08x\n", readl(&gcr->intcr2)); + reset_cpu(0); + } + else if (bb_ver0 > bb_ver1) { + check_rSelfTestPass_status(gcr); + } else { + lock_flash1(); + } + } + else { + printf("image%d invalid\n", image); + printf("> 8 Core reset\n"); + writel((readl(&gcr->intcr2) | (0x1 << INTCR2_WDC)), &gcr->intcr2); + printf("> set WDC 1, INTCR2= 0x%08x\n", readl(&gcr->intcr2)); + reset_cpu(0); + } + } + } + else if (image == 2) { //Run Recovery Bootblock from flash #1 + printf("> 5\n"); + if(msgPtrBB->imageState.bytes[2]== IMAGE_OK) { + printf("image%d valid\n", image); + recovery_flash(); + } + } +} diff --git a/board/nuvoton/poleg/nist_boot.h b/board/nuvoton/poleg/nist_boot.h new file mode 100644 index 000000000000..7699d13a027e --- /dev/null +++ b/board/nuvoton/poleg/nist_boot.h @@ -0,0 +1,6 @@ +#ifndef NIST_BOOT_H +#define NIST_BOOT_H + +void nist_boot(void); + +#endif diff --git a/board/nuvoton/poleg/poleg.c b/board/nuvoton/poleg/poleg.c index 08a85a869e37..783e1b60c11c 100644 --- a/board/nuvoton/poleg/poleg.c +++ b/board/nuvoton/poleg/poleg.c @@ -21,6 +21,7 @@ #include #include #include "../common/common.h" +#include "nist_boot.h" DECLARE_GLOBAL_DATA_PTR; @@ -79,8 +80,33 @@ static void poleg_uart_init(void) } } +bool is_security_enabled(void) +{ + struct npcm_gcr *gcr = (struct npcm_gcr *)(uintptr_t)npcm_get_base_gcr(); + u32 val = readl(FUSTRAP); + + if (IS_ENABLED(CONFIG_ARCH_NPCM7xx)) { + if (val & FUSTRAP_O_SECBOOT) { + printf("Security is enabled\n"); + return true; + } + } else { + if ((readl(&gcr->pwron) & (1 << PWRON_SECEN))) { + printf("Security is enabled\n"); + return true; + } + } + printf("Security is NOT enabled\n"); + + return false; +} + int board_init(void) { +#ifdef CONFIG_NPCM_NIST_BOOT + if (is_security_enabled()) + nist_boot(); +#endif poleg_gfx_init(); poleg_espi_init(); poleg_uart_init(); diff --git a/common/bootm.c b/common/bootm.c index defaed8426df..9c91b41db2e7 100644 --- a/common/bootm.c +++ b/common/bootm.c @@ -33,6 +33,11 @@ #include #include +#ifdef CONFIG_NPCM_NIST_BOOT +#include +#include +#endif + #ifndef CONFIG_SYS_BOOTM_LEN /* use 8MByte as default max gunzip size */ #define CONFIG_SYS_BOOTM_LEN 0x800000 @@ -922,8 +927,18 @@ static const void *boot_get_kernel(struct cmd_tbl *cmdtp, int flag, int argc, IH_ARCH_DEFAULT, IH_TYPE_KERNEL, BOOTSTAGE_ID_FIT_KERNEL_START, FIT_LOAD_IGNORED, os_data, os_len); - if (os_noffset < 0) + if (os_noffset < 0) { +#ifdef CONFIG_NPCM_NIST_BOOT + struct npcm_gcr *gcr = (struct npcm_gcr *)npcm_get_base_gcr(); + + printf("> 8 Core reset\n"); + writel((readl(&gcr->intcr2) | (0x1 << INTCR2_WDC)), &gcr->intcr2); + printf("> set WDC 1, INTCR2= 0x%08x\n", readl(&gcr->intcr2)); + reset_cpu(0); +#else return NULL; +#endif + } images->fit_hdr_os = map_sysmem(img_addr, 0); images->fit_uname_os = fit_uname_kernel;