clk: - Fix zynqmp clock driver common: - Handle CMD_RET_USAGE in cmd_process_error - Use return macros in cmd_process_error - Fix duplication of CONFIG_SYS_PROMPT_HUSH_PS2 - Support watchdog in usb_kbd.c - Fix name usage in usb_kbd.c - Support systems with non zero memory start initialized from DT only gpio: - Add support for manual relocation in uclass - zynq - use live tree - zynq - fix match data reading - zynq - setup bank name - xilinx - convert driver to DM microblaze: - Use generic iounmap/ioremap implementations - Redesign reset logic with sysreset features - Use watchdog and gpio over DM - Remove unused macros and fix some checkpatch issues - Fix timer initialization not to be called twice serial: - zynq - Use platdata intead of priv data sysreset: - Add support for manual relocation in uclass - Add gpio-restart driver - Add microblaze soft reset driver watchdog: - Add support for aliases in uclass - Add support for manual relocation in uclass - Convert xilinx driver to DM - cadence - update info in the driver and not stop wdt in probe xilinx: - Enable LED gpio for some targets with gpio-leds DT node - Setup variables via Kconfig zynq: - Add support for watchdog aliases - Add support for mini nand/nor configurations - Wire FPGA initalization in SPL zynqmp: - Enable mass storage for zcu100 - Handle external pmufw files - Add support for secure images - Some Kconfig movements and alignments - Add support for watchdog aliases - Use subcommands style for platform command - Add mmio_read/write platform commands - DT updates - Add support for mini qspi configuration -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iEYEABECAAYFAltQpksACgkQykllyylKDCGYKACbBI40gkB8xDUQSxppUzUF/j5I kOAAn3cpArSMEIyCjex0pZ079egJXmM4 =Au+p -----END PGP SIGNATURE----- Merge tag 'xilinx-for-v2018.09' of git://git.denx.de/u-boot-microblaze Xilinx changes for v2018.09 clk: - Fix zynqmp clock driver common: - Handle CMD_RET_USAGE in cmd_process_error - Use return macros in cmd_process_error - Fix duplication of CONFIG_SYS_PROMPT_HUSH_PS2 - Support watchdog in usb_kbd.c - Fix name usage in usb_kbd.c - Support systems with non zero memory start initialized from DT only gpio: - Add support for manual relocation in uclass - zynq - use live tree - zynq - fix match data reading - zynq - setup bank name - xilinx - convert driver to DM microblaze: - Use generic iounmap/ioremap implementations - Redesign reset logic with sysreset features - Use watchdog and gpio over DM - Remove unused macros and fix some checkpatch issues - Fix timer initialization not to be called twice serial: - zynq - Use platdata intead of priv data sysreset: - Add support for manual relocation in uclass - Add gpio-restart driver - Add microblaze soft reset driver watchdog: - Add support for aliases in uclass - Add support for manual relocation in uclass - Convert xilinx driver to DM - cadence - update info in the driver and not stop wdt in probe xilinx: - Enable LED gpio for some targets with gpio-leds DT node - Setup variables via Kconfig zynq: - Add support for watchdog aliases - Add support for mini nand/nor configurations - Wire FPGA initalization in SPL zynqmp: - Enable mass storage for zcu100 - Handle external pmufw files - Add support for secure images - Some Kconfig movements and alignments - Add support for watchdog aliases - Use subcommands style for platform command - Add mmio_read/write platform commands - DT updates - Add support for mini qspi configurationlime2-spi
commit
f7e48c54b2
@ -0,0 +1,80 @@ |
||||
// SPDX-License-Identifier: GPL-2.0+ |
||||
/* |
||||
* Xilinx CSE NAND board DTS |
||||
* |
||||
* Copyright (C) 2018 Xilinx, Inc. |
||||
*/ |
||||
/dts-v1/; |
||||
|
||||
/ { |
||||
#address-cells = <1>; |
||||
#size-cells = <1>; |
||||
model = "Zynq CSE NAND Board"; |
||||
compatible = "xlnx,zynq-cse-nand", "xlnx,zynq-7000"; |
||||
|
||||
aliases { |
||||
serial0 = &dcc; |
||||
}; |
||||
|
||||
memory@0 { |
||||
device_type = "memory"; |
||||
reg = <0x0 0x400000>; |
||||
}; |
||||
|
||||
chosen { |
||||
stdout-path = "serial0:115200n8"; |
||||
}; |
||||
|
||||
dcc: dcc { |
||||
compatible = "arm,dcc"; |
||||
status = "disabled"; |
||||
u-boot,dm-pre-reloc; |
||||
}; |
||||
|
||||
amba: amba { |
||||
u-boot,dm-pre-reloc; |
||||
compatible = "simple-bus"; |
||||
#address-cells = <1>; |
||||
#size-cells = <1>; |
||||
ranges; |
||||
|
||||
slcr: slcr@f8000000 { |
||||
u-boot,dm-pre-reloc; |
||||
#address-cells = <1>; |
||||
#size-cells = <1>; |
||||
compatible = "xlnx,zynq-slcr", "syscon", "simple-bus"; |
||||
reg = <0xF8000000 0x1000>; |
||||
ranges; |
||||
clkc: clkc@100 { |
||||
u-boot,dm-pre-reloc; |
||||
#clock-cells = <1>; |
||||
compatible = "xlnx,ps7-clkc"; |
||||
clock-output-names = "armpll", "ddrpll", |
||||
"iopll", "cpu_6or4x", |
||||
"cpu_3or2x", "cpu_2x", "cpu_1x", |
||||
"ddr2x", "ddr3x", "dci", |
||||
"lqspi", "smc", "pcap", "gem0", |
||||
"gem1", "fclk0", "fclk1", |
||||
"fclk2", "fclk3", "can0", |
||||
"can1", "sdio0", "sdio1", |
||||
"uart0", "uart1", "spi0", |
||||
"spi1", "dma", "usb0_aper", |
||||
"usb1_aper", "gem0_aper", |
||||
"gem1_aper", "sdio0_aper", |
||||
"sdio1_aper", "spi0_aper", |
||||
"spi1_aper", "can0_aper", |
||||
"can1_aper", "i2c0_aper", |
||||
"i2c1_aper", "uart0_aper", |
||||
"uart1_aper", "gpio_aper", |
||||
"lqspi_aper", "smc_aper", |
||||
"swdt", "dbg_trc", "dbg_apb"; |
||||
reg = <0x100 0x100>; |
||||
}; |
||||
}; |
||||
}; |
||||
|
||||
}; |
||||
|
||||
&dcc { |
||||
status = "okay"; |
||||
}; |
@ -0,0 +1,88 @@ |
||||
// SPDX-License-Identifier: GPL-2.0+ |
||||
/* |
||||
* Xilinx CSE NOR board DTS |
||||
* |
||||
* Copyright (C) 2018 Xilinx, Inc. |
||||
*/ |
||||
/dts-v1/; |
||||
#include "zynq-7000.dtsi" |
||||
|
||||
/ { |
||||
#address-cells = <1>; |
||||
#size-cells = <1>; |
||||
model = "Zynq CSE NOR Board"; |
||||
compatible = "xlnx,zynq-cse-nor", "xlnx,zynq-7000"; |
||||
|
||||
aliases { |
||||
serial0 = &dcc; |
||||
}; |
||||
|
||||
memory@fffc0000 { |
||||
device_type = "memory"; |
||||
reg = <0xFFFC0000 0x40000>; |
||||
}; |
||||
|
||||
chosen { |
||||
stdout-path = "serial0:115200n8"; |
||||
}; |
||||
|
||||
dcc: dcc { |
||||
compatible = "arm,dcc"; |
||||
status = "disabled"; |
||||
u-boot,dm-pre-reloc; |
||||
}; |
||||
|
||||
amba: amba { |
||||
compatible = "simple-bus"; |
||||
#address-cells = <1>; |
||||
#size-cells = <1>; |
||||
interrupt-parent = <&intc>; |
||||
ranges; |
||||
|
||||
intc: interrupt-controller@f8f01000 { |
||||
compatible = "arm,cortex-a9-gic"; |
||||
#interrupt-cells = <3>; |
||||
interrupt-controller; |
||||
reg = <0xF8F01000 0x1000>, |
||||
<0xF8F00100 0x100>; |
||||
}; |
||||
|
||||
slcr: slcr@f8000000 { |
||||
#address-cells = <1>; |
||||
#size-cells = <1>; |
||||
compatible = "xlnx,zynq-slcr", "syscon", "simple-bus"; |
||||
reg = <0xF8000000 0x1000>; |
||||
ranges; |
||||
clkc: clkc@100 { |
||||
#clock-cells = <1>; |
||||
compatible = "xlnx,ps7-clkc"; |
||||
fclk-enable = <0xf>; |
||||
clock-output-names = "armpll", "ddrpll", |
||||
"iopll", "cpu_6or4x", |
||||
"cpu_3or2x", "cpu_2x", "cpu_1x", |
||||
"ddr2x", "ddr3x", "dci", |
||||
"lqspi", "smc", "pcap", "gem0", |
||||
"gem1", "fclk0", "fclk1", |
||||
"fclk2", "fclk3", "can0", |
||||
"can1", "sdio0", "sdio1", |
||||
"uart0", "uart1", "spi0", |
||||
"spi1", "dma", "usb0_aper", |
||||
"usb1_aper", "gem0_aper", |
||||
"gem1_aper", "sdio0_aper", |
||||
"sdio1_aper", "spi0_aper", |
||||
"spi1_aper", "can0_aper", |
||||
"can1_aper", "i2c0_aper", |
||||
"i2c1_aper", "uart0_aper", |
||||
"uart1_aper", "gpio_aper", |
||||
"lqspi_aper", "smc_aper", |
||||
"swdt", "dbg_trc", "dbg_apb"; |
||||
reg = <0x100 0x100>; |
||||
}; |
||||
}; |
||||
}; |
||||
|
||||
}; |
||||
|
||||
&dcc { |
||||
status = "okay"; |
||||
}; |
@ -0,0 +1,79 @@ |
||||
// SPDX-License-Identifier: GPL-2.0+ |
||||
/* |
||||
* dts file for Xilinx ZynqMP Mini Configuration |
||||
* |
||||
* (C) Copyright 2015 - 2018, Xilinx, Inc. |
||||
* |
||||
* Siva Durga Prasad <siva.durga.paladugu@xilinx.com> |
||||
* Michal Simek <michal.simek@xilinx.com> |
||||
*/ |
||||
|
||||
/dts-v1/; |
||||
|
||||
/ { |
||||
model = "ZynqMP MINI QSPI"; |
||||
compatible = "xlnx,zynqmp"; |
||||
#address-cells = <2>; |
||||
#size-cells = <1>; |
||||
|
||||
aliases { |
||||
serial0 = &dcc; |
||||
spi0 = &qspi; |
||||
}; |
||||
|
||||
chosen { |
||||
stdout-path = "serial0:115200n8"; |
||||
}; |
||||
|
||||
memory@fffc0000 { |
||||
device_type = "memory"; |
||||
reg = <0x0 0xfffc0000 0x40000>; |
||||
}; |
||||
|
||||
dcc: dcc { |
||||
compatible = "arm,dcc"; |
||||
status = "disabled"; |
||||
u-boot,dm-pre-reloc; |
||||
}; |
||||
|
||||
amba: amba { |
||||
compatible = "simple-bus"; |
||||
#address-cells = <2>; |
||||
#size-cells = <1>; |
||||
ranges; |
||||
|
||||
qspi: spi@ff0f0000 { |
||||
compatible = "xlnx,zynqmp-qspi-1.0"; |
||||
status = "disabled"; |
||||
clock-names = "ref_clk", "pclk"; |
||||
clocks = <&misc_clk &misc_clk>; |
||||
num-cs = <1>; |
||||
reg = <0x0 0xff0f0000 0x1000 0x0 0xc0000000 0x8000000>; |
||||
#address-cells = <1>; |
||||
#size-cells = <0>; |
||||
}; |
||||
|
||||
misc_clk: misc_clk { |
||||
compatible = "fixed-clock"; |
||||
#clock-cells = <0>; |
||||
clock-frequency = <125000000>; |
||||
}; |
||||
}; |
||||
}; |
||||
|
||||
&qspi { |
||||
status = "okay"; |
||||
flash@0 { |
||||
compatible = "n25q512a11"; |
||||
#address-cells = <1>; |
||||
#size-cells = <1>; |
||||
reg = <0x0>; |
||||
spi-tx-bus-width = <1>; |
||||
spi-rx-bus-width = <4>; |
||||
spi-max-frequency = <10000000>; |
||||
}; |
||||
}; |
||||
|
||||
&dcc { |
||||
status = "okay"; |
||||
}; |
@ -0,0 +1,41 @@ |
||||
# SPDX-License-Identifier: GPL-2.0 |
||||
# |
||||
# Copyright (c) 2018, Luca Ceresoli <luca@lucaceresoli.net> |
||||
|
||||
if ARCH_ZYNQ || ARCH_ZYNQMP |
||||
|
||||
config XILINX_PS_INIT_FILE |
||||
string "Zynq/ZynqMP PS init file(s) location" |
||||
help |
||||
On Zynq and ZynqMP U-Boot SPL (or U-Boot proper if |
||||
ZYNQMP_PSU_INIT_ENABLED is set) is responsible for some |
||||
basic initializations, such as enabling peripherals and |
||||
configuring pinmuxes. The PS init file (called |
||||
psu_init_gpl.c on ZynqMP, ps7_init_gpl.c for Zynq-7000) |
||||
contains the code for such initializations. |
||||
|
||||
U-Boot contains PS init files for some boards, but each of |
||||
them describes only one specific configuration. Users of a |
||||
different board, or needing a different configuration, can |
||||
generate custom files using the Xilinx development tools. |
||||
|
||||
There are three ways to give a PS init file to U-Boot: |
||||
|
||||
1. Set this variable to the path, either relative to the |
||||
source tree or absolute, where the psu_init_gpl.c or |
||||
ps7_init_gpl.c file is located. U-Boot will build this |
||||
file. |
||||
|
||||
2. If you leave an empty string here, U-Boot will use |
||||
board/xilinx/zynq/$(CONFIG_DEFAULT_DEVICE_TREE)/ps7_init_gpl.c |
||||
for Zynq-7000, or |
||||
board/xilinx/zynqmp/$(CONFIG_DEFAULT_DEVICE_TREE)/psu_init_gpl.c |
||||
for ZynqMP. |
||||
|
||||
3. If the above file does not exist, U-Boot will use |
||||
board/xilinx/zynq/ps7_init_gpl.c for Zynq-7000, or |
||||
board/xilinx/zynqmp/psu_init_gpl.c for ZynqMP. This file |
||||
is not provided by U-Boot, you have to copy it there |
||||
before the build. |
||||
|
||||
endif |
@ -0,0 +1,33 @@ |
||||
# SPDX-License-Identifier: GPL-2.0 |
||||
# |
||||
# Copyright (c) 2018, Xilinx, Inc. |
||||
|
||||
if ARCH_ZYNQ |
||||
|
||||
config CMD_ZYNQ |
||||
bool "Enable Zynq specific commands" |
||||
default y |
||||
help |
||||
Enables Zynq specific commands. |
||||
|
||||
config CMD_ZYNQ_AES |
||||
bool "Enable zynq aes command for decryption of encrypted images" |
||||
depends on CMD_ZYNQ |
||||
depends on FPGA_ZYNQPL |
||||
help |
||||
Decrypts the encrypted image present in source address |
||||
and places the decrypted image at destination address. |
||||
|
||||
config CMD_ZYNQ_RSA |
||||
bool "Enable zynq rsa command for loading secure images" |
||||
default y |
||||
depends on CMD_ZYNQ |
||||
depends on CMD_ZYNQ_AES |
||||
help |
||||
Enabling this will support zynq secure image verification. |
||||
The secure image is a xilinx specific BOOT.BIN with |
||||
either authentication or encryption or both encryption |
||||
and authentication feature enabled while generating |
||||
BOOT.BIN using Xilinx bootgen tool. |
||||
|
||||
endif |
@ -0,0 +1,143 @@ |
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2018 Xilinx, Inc. |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <asm/io.h> |
||||
#include <asm/arch/hardware.h> |
||||
#include <asm/arch/sys_proto.h> |
||||
#include <u-boot/md5.h> |
||||
#include <zynq_bootimg.h> |
||||
|
||||
DECLARE_GLOBAL_DATA_PTR; |
||||
|
||||
#define ZYNQ_IMAGE_PHDR_OFFSET 0x09C |
||||
#define ZYNQ_IMAGE_FSBL_LEN_OFFSET 0x040 |
||||
#define ZYNQ_PART_HDR_CHKSUM_WORD_COUNT 0x0F |
||||
#define ZYNQ_PART_HDR_WORD_COUNT 0x10 |
||||
#define ZYNQ_MAXIMUM_IMAGE_WORD_LEN 0x40000000 |
||||
#define MD5_CHECKSUM_SIZE 16 |
||||
|
||||
struct headerarray { |
||||
u32 fields[16]; |
||||
}; |
||||
|
||||
/*
|
||||
* Check whether the given partition is last partition or not |
||||
*/ |
||||
static int zynq_islastpartition(struct headerarray *head) |
||||
{ |
||||
int index; |
||||
|
||||
debug("%s\n", __func__); |
||||
if (head->fields[ZYNQ_PART_HDR_CHKSUM_WORD_COUNT] != 0xFFFFFFFF) |
||||
return -1; |
||||
|
||||
for (index = 0; index < ZYNQ_PART_HDR_WORD_COUNT - 1; index++) { |
||||
if (head->fields[index] != 0x0) |
||||
return -1; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/*
|
||||
* Get the partition count from the partition header |
||||
*/ |
||||
int zynq_get_part_count(struct partition_hdr *part_hdr_info) |
||||
{ |
||||
u32 count; |
||||
struct headerarray *hap; |
||||
|
||||
debug("%s\n", __func__); |
||||
|
||||
for (count = 0; count < ZYNQ_MAX_PARTITION_NUMBER; count++) { |
||||
hap = (struct headerarray *)&part_hdr_info[count]; |
||||
if (zynq_islastpartition(hap) != -1) |
||||
break; |
||||
} |
||||
|
||||
return count; |
||||
} |
||||
|
||||
/*
|
||||
* Get the partition info of all the partitions available. |
||||
*/ |
||||
int zynq_get_partition_info(u32 image_base_addr, u32 *fsbl_len, |
||||
struct partition_hdr *part_hdr) |
||||
{ |
||||
u32 parthdroffset; |
||||
|
||||
*fsbl_len = *((u32 *)(image_base_addr + ZYNQ_IMAGE_FSBL_LEN_OFFSET)); |
||||
|
||||
parthdroffset = *((u32 *)(image_base_addr + ZYNQ_IMAGE_PHDR_OFFSET)); |
||||
|
||||
parthdroffset += image_base_addr; |
||||
|
||||
memcpy(part_hdr, (u32 *)parthdroffset, |
||||
(sizeof(struct partition_hdr) * ZYNQ_MAX_PARTITION_NUMBER)); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/*
|
||||
* Check whether the partition header is valid or not |
||||
*/ |
||||
int zynq_validate_hdr(struct partition_hdr *header) |
||||
{ |
||||
struct headerarray *hap; |
||||
u32 index; |
||||
u32 checksum; |
||||
|
||||
debug("%s\n", __func__); |
||||
|
||||
hap = (struct headerarray *)header; |
||||
|
||||
for (index = 0; index < ZYNQ_PART_HDR_WORD_COUNT; index++) { |
||||
if (hap->fields[index]) |
||||
break; |
||||
} |
||||
if (index == ZYNQ_PART_HDR_WORD_COUNT) |
||||
return -1; |
||||
|
||||
checksum = 0; |
||||
for (index = 0; index < ZYNQ_PART_HDR_CHKSUM_WORD_COUNT; index++) |
||||
checksum += hap->fields[index]; |
||||
|
||||
checksum ^= 0xFFFFFFFF; |
||||
|
||||
if (hap->fields[ZYNQ_PART_HDR_CHKSUM_WORD_COUNT] != checksum) { |
||||
printf("Error: Checksum 0x%8.8x != 0x%8.8x\n", |
||||
checksum, hap->fields[ZYNQ_PART_HDR_CHKSUM_WORD_COUNT]); |
||||
return -1; |
||||
} |
||||
|
||||
if (header->imagewordlen > ZYNQ_MAXIMUM_IMAGE_WORD_LEN) { |
||||
printf("INVALID_PARTITION_LENGTH\n"); |
||||
return -1; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
/*
|
||||
* Validate the partition by calculationg the md5 checksum for the |
||||
* partition and compare with checksum present in checksum offset of |
||||
* partition |
||||
*/ |
||||
int zynq_validate_partition(u32 start_addr, u32 len, u32 chksum_off) |
||||
{ |
||||
u8 checksum[MD5_CHECKSUM_SIZE]; |
||||
u8 calchecksum[MD5_CHECKSUM_SIZE]; |
||||
|
||||
memcpy(&checksum[0], (u32 *)chksum_off, MD5_CHECKSUM_SIZE); |
||||
|
||||
md5_wd((u8 *)start_addr, len, &calchecksum[0], 0x10000); |
||||
|
||||
if (!memcmp(checksum, calchecksum, MD5_CHECKSUM_SIZE)) |
||||
return 0; |
||||
|
||||
printf("Error: Partition DataChecksum\n"); |
||||
return -1; |
||||
} |
@ -0,0 +1,513 @@ |
||||
// SPDX-License-Identifier: GPL-2.0+
|
||||
/*
|
||||
* Copyright (C) 2018 Xilinx, Inc. |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <asm/io.h> |
||||
#include <asm/arch/hardware.h> |
||||
#include <asm/arch/sys_proto.h> |
||||
#include <malloc.h> |
||||
#include <u-boot/md5.h> |
||||
#include <u-boot/rsa.h> |
||||
#include <u-boot/rsa-mod-exp.h> |
||||
#include <u-boot/sha256.h> |
||||
#include <zynqpl.h> |
||||
#include <fpga.h> |
||||
#include <zynq_bootimg.h> |
||||
|
||||
DECLARE_GLOBAL_DATA_PTR; |
||||
|
||||
#ifdef CONFIG_CMD_ZYNQ_RSA |
||||
|
||||
#define ZYNQ_EFUSE_RSA_ENABLE_MASK 0x400 |
||||
#define ZYNQ_ATTRIBUTE_PL_IMAGE_MASK 0x20 |
||||
#define ZYNQ_ATTRIBUTE_CHECKSUM_TYPE_MASK 0x7000 |
||||
#define ZYNQ_ATTRIBUTE_RSA_PRESENT_MASK 0x8000 |
||||
#define ZYNQ_ATTRIBUTE_RSA_PART_OWNER_MASK 0x30000 |
||||
|
||||
#define ZYNQ_RSA_MODULAR_SIZE 256 |
||||
#define ZYNQ_RSA_MODULAR_EXT_SIZE 256 |
||||
#define ZYNQ_RSA_EXPO_SIZE 64 |
||||
#define ZYNQ_RSA_SPK_SIGNATURE_SIZE 256 |
||||
#define ZYNQ_RSA_PARTITION_SIGNATURE_SIZE 256 |
||||
#define ZYNQ_RSA_SIGNATURE_SIZE 0x6C0 |
||||
#define ZYNQ_RSA_HEADER_SIZE 4 |
||||
#define ZYNQ_RSA_MAGIC_WORD_SIZE 60 |
||||
#define ZYNQ_RSA_PART_OWNER_UBOOT 1 |
||||
#define ZYNQ_RSA_ALIGN_PPK_START 64 |
||||
|
||||
#define WORD_LENGTH_SHIFT 2 |
||||
|
||||
static u8 *ppkmodular; |
||||
static u8 *ppkmodularex; |
||||
|
||||
struct zynq_rsa_public_key { |
||||
uint len; /* Length of modulus[] in number of u32 */ |
||||
u32 n0inv; /* -1 / modulus[0] mod 2^32 */ |
||||
u32 *modulus; /* modulus as little endian array */ |
||||
u32 *rr; /* R^2 as little endian array */ |
||||
}; |
||||
|
||||
static struct zynq_rsa_public_key public_key; |
||||
|
||||
static struct partition_hdr part_hdr[ZYNQ_MAX_PARTITION_NUMBER]; |
||||
|
||||
/*
|
||||
* Extract the primary public key components from already autheticated FSBL |
||||
*/ |
||||
static void zynq_extract_ppk(u32 fsbl_len) |
||||
{ |
||||
u32 padsize; |
||||
u8 *ppkptr; |
||||
|
||||
debug("%s\n", __func__); |
||||
|
||||
/*
|
||||
* Extract the authenticated PPK from OCM i.e at end of the FSBL |
||||
*/ |
||||
ppkptr = (u8 *)(fsbl_len + ZYNQ_OCM_BASEADDR); |
||||
padsize = ((u32)ppkptr % ZYNQ_RSA_ALIGN_PPK_START); |
||||
if (padsize) |
||||
ppkptr += (ZYNQ_RSA_ALIGN_PPK_START - padsize); |
||||
|
||||
ppkptr += ZYNQ_RSA_HEADER_SIZE; |
||||
|
||||
ppkptr += ZYNQ_RSA_MAGIC_WORD_SIZE; |
||||
|
||||
ppkmodular = (u8 *)ppkptr; |
||||
ppkptr += ZYNQ_RSA_MODULAR_SIZE; |
||||
ppkmodularex = (u8 *)ppkptr; |
||||
ppkptr += ZYNQ_RSA_MODULAR_EXT_SIZE; |
||||
} |
||||
|
||||
/*
|
||||
* Calculate the inverse(-1 / modulus[0] mod 2^32 ) for the PPK |
||||
*/ |
||||
static u32 zynq_calc_inv(void) |
||||
{ |
||||
u32 modulus = public_key.modulus[0]; |
||||
u32 tmp = BIT(1); |
||||
u32 inverse; |
||||
|
||||
inverse = modulus & BIT(0); |
||||
|
||||
while (tmp) { |
||||
inverse *= 2 - modulus * inverse; |
||||
tmp *= tmp; |
||||
} |
||||
|
||||
return ~(inverse - 1); |
||||
} |
||||
|
||||
/*
|
||||
* Recreate the signature by padding the bytes and verify with hash value |
||||
*/ |
||||
static int zynq_pad_and_check(u8 *signature, u8 *hash) |
||||
{ |
||||
u8 padding[] = {0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48, |
||||
0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04, |
||||
0x20}; |
||||
u8 *pad_ptr = signature + 256; |
||||
u32 pad = 202; |
||||
u32 ii; |
||||
|
||||
/*
|
||||
* Re-Create PKCS#1v1.5 Padding |
||||
* MSB ----------------------------------------------------LSB |
||||
* 0x0 || 0x1 || 0xFF(for 202 bytes) || 0x0 || T_padding || SHA256 Hash |
||||
*/ |
||||
if (*--pad_ptr != 0 || *--pad_ptr != 1) |
||||
return -1; |
||||
|
||||
for (ii = 0; ii < pad; ii++) { |
||||
if (*--pad_ptr != 0xFF) |
||||
return -1; |
||||
} |
||||
|
||||
if (*--pad_ptr != 0) |
||||
return -1; |
||||
|
||||
for (ii = 0; ii < sizeof(padding); ii++) { |
||||
if (*--pad_ptr != padding[ii]) |
||||
return -1; |
||||
} |
||||
|
||||
for (ii = 0; ii < 32; ii++) { |
||||
if (*--pad_ptr != hash[ii]) |
||||
return -1; |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
/*
|
||||
* Verify and extract the hash value from signature using the public key |
||||
* and compare it with calculated hash value. |
||||
*/ |
||||
static int zynq_rsa_verify_key(const struct zynq_rsa_public_key *key, |
||||
const u8 *sig, const u32 sig_len, const u8 *hash) |
||||
{ |
||||
int status; |
||||
void *buf; |
||||
|
||||
if (!key || !sig || !hash) |
||||
return -1; |
||||
|
||||
if (sig_len != (key->len * sizeof(u32))) { |
||||
printf("Signature is of incorrect length %d\n", sig_len); |
||||
return -1; |
||||
} |
||||
|
||||
/* Sanity check for stack size */ |
||||
if (sig_len > ZYNQ_RSA_SPK_SIGNATURE_SIZE) { |
||||
printf("Signature length %u exceeds maximum %d\n", sig_len, |
||||
ZYNQ_RSA_SPK_SIGNATURE_SIZE); |
||||
return -1; |
||||
} |
||||
|
||||
buf = malloc(sig_len); |
||||
if (!buf) |
||||
return -1; |
||||
|
||||
memcpy(buf, sig, sig_len); |
||||
|
||||
status = zynq_pow_mod((u32 *)key, (u32 *)buf); |
||||
if (status == -1) { |
||||
free(buf); |
||||
return status; |
||||
} |
||||
|
||||
status = zynq_pad_and_check((u8 *)buf, (u8 *)hash); |
||||
|
||||
free(buf); |
||||
return status; |
||||
} |
||||
|
||||
/*
|
||||
* Authenticate the partition |
||||
*/ |
||||
static int zynq_authenticate_part(u8 *buffer, u32 size) |
||||
{ |
||||
u8 hash_signature[32]; |
||||
u8 *spk_modular; |
||||
u8 *spk_modular_ex; |
||||
u8 *signature_ptr; |
||||
u32 status; |
||||
|
||||
debug("%s\n", __func__); |
||||
|
||||
signature_ptr = (u8 *)(buffer + size - ZYNQ_RSA_SIGNATURE_SIZE); |
||||
|
||||
signature_ptr += ZYNQ_RSA_HEADER_SIZE; |
||||
|
||||
signature_ptr += ZYNQ_RSA_MAGIC_WORD_SIZE; |
||||
|
||||
ppkmodular = (u8 *)signature_ptr; |
||||
signature_ptr += ZYNQ_RSA_MODULAR_SIZE; |
||||
ppkmodularex = signature_ptr; |
||||
signature_ptr += ZYNQ_RSA_MODULAR_EXT_SIZE; |
||||
signature_ptr += ZYNQ_RSA_EXPO_SIZE; |
||||
|
||||
sha256_csum_wd((const unsigned char *)signature_ptr, |
||||
(ZYNQ_RSA_MODULAR_EXT_SIZE + ZYNQ_RSA_EXPO_SIZE + |
||||
ZYNQ_RSA_MODULAR_SIZE), |
||||
(unsigned char *)hash_signature, 0x1000); |
||||
|
||||
spk_modular = (u8 *)signature_ptr; |
||||
signature_ptr += ZYNQ_RSA_MODULAR_SIZE; |
||||
spk_modular_ex = (u8 *)signature_ptr; |
||||
signature_ptr += ZYNQ_RSA_MODULAR_EXT_SIZE; |
||||
signature_ptr += ZYNQ_RSA_EXPO_SIZE; |
||||
|
||||
public_key.len = ZYNQ_RSA_MODULAR_SIZE / sizeof(u32); |
||||
public_key.modulus = (u32 *)ppkmodular; |
||||
public_key.rr = (u32 *)ppkmodularex; |
||||
public_key.n0inv = zynq_calc_inv(); |
||||
|
||||
status = zynq_rsa_verify_key(&public_key, signature_ptr, |
||||
ZYNQ_RSA_SPK_SIGNATURE_SIZE, |
||||
hash_signature); |
||||
if (status) |
||||
return status; |
||||
|
||||
signature_ptr += ZYNQ_RSA_SPK_SIGNATURE_SIZE; |
||||
|
||||
sha256_csum_wd((const unsigned char *)buffer, |
||||
(size - ZYNQ_RSA_PARTITION_SIGNATURE_SIZE), |
||||
(unsigned char *)hash_signature, 0x1000); |
||||
|
||||
public_key.len = ZYNQ_RSA_MODULAR_SIZE / sizeof(u32); |
||||
public_key.modulus = (u32 *)spk_modular; |
||||
public_key.rr = (u32 *)spk_modular_ex; |
||||
public_key.n0inv = zynq_calc_inv(); |
||||
|
||||
return zynq_rsa_verify_key(&public_key, (u8 *)signature_ptr, |
||||
ZYNQ_RSA_PARTITION_SIGNATURE_SIZE, |
||||
(u8 *)hash_signature); |
||||
} |
||||
|
||||
/*
|
||||
* Parses the partition header and verfies the authenticated and |
||||
* encrypted image. |
||||
*/ |
||||
static int zynq_verify_image(u32 src_ptr) |
||||
{ |
||||
u32 silicon_ver, image_base_addr, status; |
||||
u32 partition_num = 0; |
||||
u32 efuseval, srcaddr, size, fsbl_len; |
||||
struct partition_hdr *hdr_ptr; |
||||
u32 part_data_len, part_img_len, part_attr; |
||||
u32 part_load_addr, part_dst_addr, part_chksum_offset; |
||||
u32 part_start_addr, part_total_size, partitioncount; |
||||
bool encrypt_part_flag = false; |
||||
bool part_chksum_flag = false; |
||||
bool signed_part_flag = false; |
||||
|
||||
image_base_addr = src_ptr; |
||||
|
||||
silicon_ver = zynq_get_silicon_version(); |
||||
|
||||
/* RSA not supported in silicon versions 1.0 and 2.0 */ |
||||
if (silicon_ver == 0 || silicon_ver == 1) |
||||
return -1; |
||||
|
||||
zynq_get_partition_info(image_base_addr, &fsbl_len, |
||||
&part_hdr[0]); |
||||
|
||||
/* Extract ppk if efuse was blown Otherwise return error */ |
||||
efuseval = readl(&efuse_base->status); |
||||
if (!(efuseval & ZYNQ_EFUSE_RSA_ENABLE_MASK)) |
||||
return -1; |
||||
|
||||
zynq_extract_ppk(fsbl_len); |
||||
|
||||
partitioncount = zynq_get_part_count(&part_hdr[0]); |
||||
|
||||
/*
|
||||
* As the first two partitions are related to fsbl, |
||||
* we can ignore those two in bootimage and the below |
||||
* code doesn't need to validate it as fsbl is already |
||||
* done by now |
||||
*/ |
||||
if (partitioncount <= 2 || |
||||
partitioncount > ZYNQ_MAX_PARTITION_NUMBER) |
||||
return -1; |
||||
|
||||
while (partition_num < partitioncount) { |
||||
if (((part_hdr[partition_num].partitionattr & |
||||
ZYNQ_ATTRIBUTE_RSA_PART_OWNER_MASK) >> 16) != |
||||
ZYNQ_RSA_PART_OWNER_UBOOT) { |
||||
printf("UBOOT is not Owner for partition %d\n", |
||||
partition_num); |
||||
partition_num++; |
||||
continue; |
||||
} |
||||
hdr_ptr = &part_hdr[partition_num]; |
||||
status = zynq_validate_hdr(hdr_ptr); |
||||
if (status) |
||||
return status; |
||||
|
||||
part_data_len = hdr_ptr->datawordlen; |
||||
part_img_len = hdr_ptr->imagewordlen; |
||||
part_attr = hdr_ptr->partitionattr; |
||||
part_load_addr = hdr_ptr->loadaddr; |
||||
part_chksum_offset = hdr_ptr->checksumoffset; |
||||
part_start_addr = hdr_ptr->partitionstart; |
||||
part_total_size = hdr_ptr->partitionwordlen; |
||||
|
||||
if (part_data_len != part_img_len) { |
||||
debug("Encrypted\n"); |
||||
encrypt_part_flag = true; |
||||
} |
||||
|
||||
if (part_attr & ZYNQ_ATTRIBUTE_CHECKSUM_TYPE_MASK) |
||||
part_chksum_flag = true; |
||||
|
||||
if (part_attr & ZYNQ_ATTRIBUTE_RSA_PRESENT_MASK) { |
||||
debug("RSA Signed\n"); |
||||
signed_part_flag = true; |
||||
size = part_total_size << WORD_LENGTH_SHIFT; |
||||
} else { |
||||
size = part_img_len; |
||||
} |
||||
|
||||
if (!signed_part_flag && !part_chksum_flag) { |
||||
printf("Partition not signed & no chksum\n"); |
||||
partition_num++; |
||||
continue; |
||||
} |
||||
|
||||
srcaddr = image_base_addr + |
||||
(part_start_addr << WORD_LENGTH_SHIFT); |
||||
|
||||
/*
|
||||
* This validation is just for PS DDR. |
||||
* TODO: Update this for PL DDR check as well. |
||||
*/ |
||||
if (part_load_addr < gd->bd->bi_dram[0].start && |
||||
((part_load_addr + part_data_len) > |
||||
(gd->bd->bi_dram[0].start + |
||||
gd->bd->bi_dram[0].size))) { |
||||
printf("INVALID_LOAD_ADDRESS_FAIL\n"); |
||||
return -1; |
||||
} |
||||
|
||||
if (part_attr & ZYNQ_ATTRIBUTE_PL_IMAGE_MASK) |
||||
part_load_addr = srcaddr; |
||||
else |
||||
memcpy((u32 *)part_load_addr, (u32 *)srcaddr, |
||||
size); |
||||
|
||||
if (part_chksum_flag) { |
||||
part_chksum_offset = image_base_addr + |
||||
(part_chksum_offset << |
||||
WORD_LENGTH_SHIFT); |
||||
status = zynq_validate_partition(part_load_addr, |
||||
(part_total_size << |
||||
WORD_LENGTH_SHIFT), |
||||
part_chksum_offset); |
||||
if (status != 0) { |
||||
printf("PART_CHKSUM_FAIL\n"); |
||||
return -1; |
||||
} |
||||
debug("Partition Validation Done\n"); |
||||
} |
||||
|
||||
if (signed_part_flag) { |
||||
status = zynq_authenticate_part((u8 *)part_load_addr, |
||||
size); |
||||
if (status != 0) { |
||||
printf("AUTHENTICATION_FAIL\n"); |
||||
return -1; |
||||
} |
||||
debug("Authentication Done\n"); |
||||
} |
||||
|
||||
if (encrypt_part_flag) { |
||||
debug("DECRYPTION\n"); |
||||
|
||||
part_dst_addr = part_load_addr; |
||||
|
||||
if (part_attr & ZYNQ_ATTRIBUTE_PL_IMAGE_MASK) { |
||||
partition_num++; |
||||
continue; |
||||
} |
||||
|
||||
status = zynq_decrypt_load(part_load_addr, |
||||
part_img_len, |
||||
part_dst_addr, |
||||
part_data_len); |
||||
if (status != 0) { |
||||
printf("DECRYPTION_FAIL\n"); |
||||
return -1; |
||||
} |
||||
} |
||||
partition_num++; |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int do_zynq_rsa(cmd_tbl_t *cmdtp, int flag, int argc, |
||||
char * const argv[]) |
||||
{ |
||||
u32 src_ptr; |
||||
char *endp; |
||||
|
||||
src_ptr = simple_strtoul(argv[2], &endp, 16); |
||||
if (*argv[2] == 0 || *endp != 0) |
||||
return CMD_RET_USAGE; |
||||
if (zynq_verify_image(src_ptr)) |
||||
return CMD_RET_FAILURE; |
||||
|
||||
return CMD_RET_SUCCESS; |
||||
} |
||||
#endif |
||||
|
||||
#ifdef CONFIG_CMD_ZYNQ_AES |
||||
static int zynq_decrypt_image(cmd_tbl_t *cmdtp, int flag, int argc, |
||||
char * const argv[]) |
||||
{ |
||||
char *endp; |
||||
u32 srcaddr, srclen, dstaddr, dstlen; |
||||
int status; |
||||
|
||||
srcaddr = simple_strtoul(argv[2], &endp, 16); |
||||
if (*argv[2] == 0 || *endp != 0) |
||||
return CMD_RET_USAGE; |
||||
srclen = simple_strtoul(argv[3], &endp, 16); |
||||
if (*argv[3] == 0 || *endp != 0) |
||||
return CMD_RET_USAGE; |
||||
dstaddr = simple_strtoul(argv[4], &endp, 16); |
||||
if (*argv[4] == 0 || *endp != 0) |
||||
return CMD_RET_USAGE; |
||||
dstlen = simple_strtoul(argv[5], &endp, 16); |
||||
if (*argv[5] == 0 || *endp != 0) |
||||
return CMD_RET_USAGE; |
||||
|
||||
/*
|
||||
* Roundup source and destination lengths to |
||||
* word size |
||||
*/ |
||||
if (srclen % 4) |
||||
srclen = roundup(srclen, 4); |
||||
if (dstlen % 4) |
||||
dstlen = roundup(dstlen, 4); |
||||
|
||||
status = zynq_decrypt_load(srcaddr, srclen >> 2, dstaddr, dstlen >> 2); |
||||
if (status != 0) |
||||
return CMD_RET_FAILURE; |
||||
|
||||
return CMD_RET_SUCCESS; |
||||
} |
||||
#endif |
||||
|
||||
static cmd_tbl_t zynq_commands[] = { |
||||
#ifdef CONFIG_CMD_ZYNQ_RSA |
||||
U_BOOT_CMD_MKENT(rsa, 3, 1, do_zynq_rsa, "", ""), |
||||
#endif |
||||
#ifdef CONFIG_CMD_ZYNQ_AES |
||||
U_BOOT_CMD_MKENT(aes, 6, 1, zynq_decrypt_image, "", ""), |
||||
#endif |
||||
}; |
||||
|
||||
static int do_zynq(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) |
||||
{ |
||||
cmd_tbl_t *zynq_cmd; |
||||
int ret; |
||||
|
||||
if (!ARRAY_SIZE(zynq_commands)) { |
||||
puts("No zynq specific command enabled\n"); |
||||
return CMD_RET_USAGE; |
||||
} |
||||
|
||||
if (argc < 2) |
||||
return CMD_RET_USAGE; |
||||
zynq_cmd = find_cmd_tbl(argv[1], zynq_commands, |
||||
ARRAY_SIZE(zynq_commands)); |
||||
if (!zynq_cmd || argc != zynq_cmd->maxargs) |
||||
return CMD_RET_USAGE; |
||||
|
||||
ret = zynq_cmd->cmd(zynq_cmd, flag, argc, argv); |
||||
|
||||
return cmd_process_error(zynq_cmd, ret); |
||||
} |
||||
|
||||
static char zynq_help_text[] = |
||||
"" |
||||
#ifdef CONFIG_CMD_ZYNQ_RSA |
||||
"rsa <baseaddr> - Verifies the authenticated and encrypted\n" |
||||
" zynq images and loads them back to load\n" |
||||
" addresses as specified in BOOT image(BOOT.BIN)\n" |
||||
#endif |
||||
#ifdef CONFIG_CMD_ZYNQ_AES |
||||
"aes <srcaddr> <srclen> <dstaddr> <dstlen>\n" |
||||
" - Decrypts the encrypted image present in source\n" |
||||
" address and places the decrypted image at\n" |
||||
" destination address\n" |
||||
#endif |
||||
; |
||||
|
||||
U_BOOT_CMD(zynq, 6, 0, do_zynq, |
||||
"Zynq specific commands", zynq_help_text |
||||
); |
@ -0,0 +1,62 @@ |
||||
CONFIG_ARM=y |
||||
CONFIG_SYS_CONFIG_NAME="xilinx_zynqmp_mini_qspi" |
||||
CONFIG_ARCH_ZYNQMP=y |
||||
CONFIG_SYS_TEXT_BASE=0xFFFC0000 |
||||
CONFIG_ENV_SIZE=0x578 |
||||
CONFIG_SYS_MEM_RSVD_FOR_MMU=y |
||||
CONFIG_ZYNQMP_NO_DDR=y |
||||
# CONFIG_CMD_ZYNQMP is not set |
||||
CONFIG_DEFAULT_DEVICE_TREE="zynqmp-mini-qspi" |
||||
# CONFIG_IMAGE_FORMAT_LEGACY is not set |
||||
CONFIG_BOOTDELAY=-1 |
||||
# CONFIG_DISPLAY_CPUINFO is not set |
||||
# CONFIG_CMDLINE_EDITING is not set |
||||
# CONFIG_AUTO_COMPLETE is not set |
||||
# CONFIG_SYS_LONGHELP is not set |
||||
CONFIG_SYS_PROMPT="ZynqMP> " |
||||
# CONFIG_CMD_BDI is not set |
||||
# CONFIG_CMD_CONSOLE is not set |
||||
# CONFIG_CMD_BOOTD is not set |
||||
# CONFIG_CMD_BOOTM is not set |
||||
# CONFIG_CMD_BOOTI is not set |
||||
# CONFIG_CMD_ELF is not set |
||||
# CONFIG_CMD_FDT is not set |
||||
# CONFIG_CMD_GO is not set |
||||
# CONFIG_CMD_RUN is not set |
||||
# CONFIG_CMD_IMI is not set |
||||
# CONFIG_CMD_XIMG is not set |
||||
# CONFIG_CMD_EXPORTENV is not set |
||||
# CONFIG_CMD_IMPORTENV is not set |
||||
# CONFIG_CMD_EDITENV is not set |
||||
# CONFIG_CMD_SAVEENV is not set |
||||
# CONFIG_CMD_ENV_EXISTS is not set |
||||
# CONFIG_CMD_CRC32 is not set |
||||
# CONFIG_CMD_DM is not set |
||||
# CONFIG_CMD_FLASH is not set |
||||
# CONFIG_CMD_LOADB is not set |
||||
# CONFIG_CMD_LOADS is not set |
||||
CONFIG_CMD_SF=y |
||||
# CONFIG_CMD_ECHO is not set |
||||
# CONFIG_CMD_ITEST is not set |
||||
# CONFIG_CMD_SOURCE is not set |
||||
# CONFIG_CMD_SETEXPR is not set |
||||
# CONFIG_CMD_MISC is not set |
||||
CONFIG_MP=y |
||||
# CONFIG_PARTITIONS is not set |
||||
CONFIG_OF_EMBED=y |
||||
# CONFIG_NET is not set |
||||
# CONFIG_DM_WARN is not set |
||||
# CONFIG_DM_DEVICE_REMOVE is not set |
||||
# CONFIG_MMC is not set |
||||
CONFIG_DM_SPI_FLASH=y |
||||
CONFIG_SPI_FLASH=y |
||||
CONFIG_SPI_FLASH_BAR=y |
||||
CONFIG_SF_DUAL_FLASH=y |
||||
CONFIG_SPI_FLASH_MACRONIX=y |
||||
CONFIG_SPI_FLASH_SPANSION=y |
||||
CONFIG_SPI_FLASH_STMICRO=y |
||||
CONFIG_SPI_FLASH_WINBOND=y |
||||
CONFIG_SPI=y |
||||
CONFIG_DM_SPI=y |
||||
CONFIG_ZYNQMP_GQSPI=y |
||||
# CONFIG_EFI_LOADER is not set |
@ -0,0 +1,48 @@ |
||||
CONFIG_ARM=y |
||||
CONFIG_SYS_CONFIG_NAME="zynq_cse" |
||||
CONFIG_ARCH_ZYNQ=y |
||||
CONFIG_SYS_TEXT_BASE=0x100000 |
||||
CONFIG_ENV_SIZE=0x190 |
||||
CONFIG_SPL=y |
||||
CONFIG_SPL_STACK_R_ADDR=0x200000 |
||||
CONFIG_DEFAULT_DEVICE_TREE="zynq-cse-nand" |
||||
# CONFIG_DISPLAY_CPUINFO is not set |
||||
CONFIG_SPL_STACK_R=y |
||||
CONFIG_SYS_PROMPT="Zynq> " |
||||
# CONFIG_CMD_BDI is not set |
||||
# CONFIG_CMD_CONSOLE is not set |
||||
# CONFIG_CMD_BOOTD is not set |
||||
# CONFIG_CMD_BOOTM is not set |
||||
# CONFIG_CMD_ELF is not set |
||||
# CONFIG_CMD_FDT is not set |
||||
# CONFIG_CMD_GO is not set |
||||
# CONFIG_CMD_RUN is not set |
||||
# CONFIG_CMD_IMI is not set |
||||
# CONFIG_CMD_XIMG is not set |
||||
# CONFIG_CMD_SPL is not set |
||||
# CONFIG_CMD_EXPORTENV is not set |
||||
# CONFIG_CMD_IMPORTENV is not set |
||||
# CONFIG_CMD_EDITENV is not set |
||||
# CONFIG_CMD_SAVEENV is not set |
||||
# CONFIG_CMD_ENV_EXISTS is not set |
||||
# CONFIG_CMD_CRC32 is not set |
||||
# CONFIG_CMD_CLK is not set |
||||
# CONFIG_CMD_DM is not set |
||||
# CONFIG_CMD_FLASH is not set |
||||
# CONFIG_CMD_LOADB is not set |
||||
# CONFIG_CMD_LOADS is not set |
||||
# CONFIG_CMD_ECHO is not set |
||||
# CONFIG_CMD_ITEST is not set |
||||
# CONFIG_CMD_SOURCE is not set |
||||
# CONFIG_CMD_SETEXPR is not set |
||||
# CONFIG_CMD_NET is not set |
||||
# CONFIG_CMD_MISC is not set |
||||
# CONFIG_PARTITIONS is not set |
||||
CONFIG_OF_EMBED=y |
||||
# CONFIG_DM_WARN is not set |
||||
# CONFIG_DM_DEVICE_REMOVE is not set |
||||
CONFIG_SPL_DM_SEQ_ALIAS=y |
||||
# CONFIG_MMC is not set |
||||
CONFIG_NAND=y |
||||
CONFIG_NAND_ZYNQ=y |
||||
# CONFIG_EFI_LOADER is not set |
@ -0,0 +1,47 @@ |
||||
CONFIG_ARM=y |
||||
CONFIG_SYS_CONFIG_NAME="zynq_cse" |
||||
CONFIG_ARCH_ZYNQ=y |
||||
CONFIG_SYS_TEXT_BASE=0xFFFC0000 |
||||
CONFIG_ENV_SIZE=0x190 |
||||
CONFIG_SPL=y |
||||
CONFIG_SPL_STACK_R_ADDR=0x200000 |
||||
CONFIG_DEFAULT_DEVICE_TREE="zynq-cse-nor" |
||||
CONFIG_BOOTDELAY=-1 |
||||
# CONFIG_DISPLAY_CPUINFO is not set |
||||
CONFIG_SPL_STACK_R=y |
||||
CONFIG_SYS_PROMPT="Zynq> " |
||||
# CONFIG_CMD_BDI is not set |
||||
# CONFIG_CMD_CONSOLE is not set |
||||
# CONFIG_CMD_BOOTD is not set |
||||
# CONFIG_CMD_BOOTM is not set |
||||
# CONFIG_CMD_ELF is not set |
||||
# CONFIG_CMD_FDT is not set |
||||
# CONFIG_CMD_GO is not set |
||||
# CONFIG_CMD_RUN is not set |
||||
# CONFIG_CMD_IMI is not set |
||||
# CONFIG_CMD_XIMG is not set |
||||
# CONFIG_CMD_SPL is not set |
||||
# CONFIG_CMD_EXPORTENV is not set |
||||
# CONFIG_CMD_IMPORTENV is not set |
||||
# CONFIG_CMD_EDITENV is not set |
||||
# CONFIG_CMD_SAVEENV is not set |
||||
# CONFIG_CMD_ENV_EXISTS is not set |
||||
# CONFIG_CMD_CRC32 is not set |
||||
# CONFIG_CMD_CLK is not set |
||||
# CONFIG_CMD_DM is not set |
||||
# CONFIG_CMD_LOADB is not set |
||||
# CONFIG_CMD_LOADS is not set |
||||
# CONFIG_CMD_ECHO is not set |
||||
# CONFIG_CMD_ITEST is not set |
||||
# CONFIG_CMD_SOURCE is not set |
||||
# CONFIG_CMD_SETEXPR is not set |
||||
# CONFIG_CMD_NET is not set |
||||
# CONFIG_CMD_MISC is not set |
||||
# CONFIG_PARTITIONS is not set |
||||
CONFIG_OF_EMBED=y |
||||
# CONFIG_DM_WARN is not set |
||||
# CONFIG_DM_DEVICE_REMOVE is not set |
||||
CONFIG_SPL_DM_SEQ_ALIAS=y |
||||
# CONFIG_MMC is not set |
||||
CONFIG_MTD_NOR_FLASH=y |
||||
# CONFIG_EFI_LOADER is not set |
@ -0,0 +1,59 @@ |
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2018 Xilinx, Inc. - Michal Simek |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <dm.h> |
||||
#include <errno.h> |
||||
#include <sysreset.h> |
||||
#include <asm/gpio.h> |
||||
|
||||
struct gpio_reboot_priv { |
||||
struct gpio_desc gpio; |
||||
}; |
||||
|
||||
static int gpio_reboot_request(struct udevice *dev, enum sysreset_t type) |
||||
{ |
||||
struct gpio_reboot_priv *priv = dev_get_priv(dev); |
||||
|
||||
/*
|
||||
* When debug log is enabled please make sure that chars won't end up |
||||
* in output fifo. Or you can append udelay(); to get enough time |
||||
* to HW to emit output fifo. |
||||
*/ |
||||
debug("GPIO reset\n"); |
||||
|
||||
/* Writing 1 respects polarity (active high/low) based on gpio->flags */ |
||||
return dm_gpio_set_value(&priv->gpio, 1); |
||||
} |
||||
|
||||
static struct sysreset_ops gpio_reboot_ops = { |
||||
.request = gpio_reboot_request, |
||||
}; |
||||
|
||||
int gpio_reboot_probe(struct udevice *dev) |
||||
{ |
||||
struct gpio_reboot_priv *priv = dev_get_priv(dev); |
||||
|
||||
/*
|
||||
* Linux kernel DT binding contain others optional properties |
||||
* which are not supported now |
||||
*/ |
||||
|
||||
return gpio_request_by_name(dev, "gpios", 0, &priv->gpio, GPIOD_IS_OUT); |
||||
} |
||||
|
||||
static const struct udevice_id led_gpio_ids[] = { |
||||
{ .compatible = "gpio-restart" }, |
||||
{ } |
||||
}; |
||||
|
||||
U_BOOT_DRIVER(gpio_reboot) = { |
||||
.id = UCLASS_SYSRESET, |
||||
.name = "gpio_restart", |
||||
.of_match = led_gpio_ids, |
||||
.ops = &gpio_reboot_ops, |
||||
.priv_auto_alloc_size = sizeof(struct gpio_reboot_priv), |
||||
.probe = gpio_reboot_probe, |
||||
}; |
@ -0,0 +1,30 @@ |
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (C) 2018 Xilinx, Inc. - Michal Simek |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <dm.h> |
||||
#include <errno.h> |
||||
#include <sysreset.h> |
||||
#include <linux/err.h> |
||||
|
||||
static int microblaze_sysreset_request(struct udevice *dev, |
||||
enum sysreset_t type) |
||||
{ |
||||
puts("Microblaze soft reset sysreset\n"); |
||||
__asm__ __volatile__ (" mts rmsr, r0;" \
|
||||
"bra r0"); |
||||
|
||||
return -EINPROGRESS; |
||||
} |
||||
|
||||
static struct sysreset_ops microblaze_sysreset = { |
||||
.request = microblaze_sysreset_request, |
||||
}; |
||||
|
||||
U_BOOT_DRIVER(sysreset_microblaze) = { |
||||
.id = UCLASS_SYSRESET, |
||||
.name = "mb_soft_reset", |
||||
.ops = µblaze_sysreset, |
||||
}; |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue