From 7816f2cf813326505970922021b3ed6490863e78 Mon Sep 17 00:00:00 2001 From: Heiko Schocher Date: Sat, 16 Jul 2011 00:06:42 +0000 Subject: [PATCH] mkimage: add UBL header support for booting davinci cpus creating an u-boot.ubl file, which contains the UBL Header needed for booting from NAND with the RBL from TI. For more information read doc/README.ublimage. Signed-off-by: Heiko Schocher --- .gitignore | 1 + Makefile | 5 + common/image.c | 1 + doc/README.ublimage | 141 +++++++++++++++++++++++ include/image.h | 1 + tools/Makefile | 2 + tools/mkimage.c | 2 + tools/mkimage.h | 1 + tools/ublimage.c | 275 ++++++++++++++++++++++++++++++++++++++++++++ tools/ublimage.h | 103 +++++++++++++++++ 10 files changed, 532 insertions(+) create mode 100644 doc/README.ublimage create mode 100644 tools/ublimage.c create mode 100644 tools/ublimage.h diff --git a/.gitignore b/.gitignore index 34a2ca96fc..dbf545f2d1 100644 --- a/.gitignore +++ b/.gitignore @@ -33,6 +33,7 @@ /u-boot.sha1 /u-boot.dis /u-boot.lds +/u-boot.ubl # # Generated files diff --git a/Makefile b/Makefile index c9e1053da1..53bffd0106 100644 --- a/Makefile +++ b/Makefile @@ -394,6 +394,10 @@ $(obj)u-boot.sha1: $(obj)u-boot.bin $(obj)u-boot.dis: $(obj)u-boot $(OBJDUMP) -d $< > $@ +$(obj)u-boot.ubl: $(obj)u-boot-nand.bin + $(obj)tools/mkimage -n $(UBL_CONFIG) -T ublimage \ + -e $(CONFIG_SYS_TEXT_BASE) -d $< $@ + GEN_UBOOT = \ UNDEF_SYM=`$(OBJDUMP) -x $(LIBBOARD) $(LIBS) | \ sed -n -e 's/.*\($(SYM_PREFIX)__u_boot_cmd_.*\)/-u\1/p'|sort|uniq`;\ @@ -1102,6 +1106,7 @@ clobber: clean @rm -f $(obj)u-boot $(obj)u-boot.map $(obj)u-boot.hex $(ALL-y) @rm -f $(obj)u-boot.kwb @rm -f $(obj)u-boot.imx + @rm -f $(obj)u-boot.ubl @rm -f $(obj)tools/{env/crc32.c,inca-swap-bytes} @rm -f $(obj)arch/powerpc/cpu/mpc824x/bedbug_603e.c @rm -fr $(obj)include/asm/proc $(obj)include/asm/arch $(obj)include/asm diff --git a/common/image.c b/common/image.c index 5c7d4f42f3..f1755410cd 100644 --- a/common/image.c +++ b/common/image.c @@ -141,6 +141,7 @@ static const table_entry_t uimage_type[] = { { IH_TYPE_FLATDT, "flat_dt", "Flat Device Tree", }, { IH_TYPE_KWBIMAGE, "kwbimage", "Kirkwood Boot Image",}, { IH_TYPE_IMXIMAGE, "imximage", "Freescale i.MX Boot Image",}, + { IH_TYPE_UBLIMAGE, "ublimage", "Davinci UBL image",}, { -1, "", "", }, }; diff --git a/doc/README.ublimage b/doc/README.ublimage new file mode 100644 index 0000000000..add24d649b --- /dev/null +++ b/doc/README.ublimage @@ -0,0 +1,141 @@ +--------------------------------------------- +UBL image Boot Image generation using mkimage +--------------------------------------------- + +This document describes how to set up an U-Boot image that can be directly +booted by a DaVinci processor via NAND boot mode, using an UBL header, +but without need for UBL. + +For more details see section 11.2 "ARM ROM Boot Modes" of +http://focus.ti.com/lit/ug/sprufg5a/sprufg5a.pdf + +Command syntax: +-------------- +./tools/mkimage -l + to list the UBL image file details + +./tools/mkimage -T ublimage \ + -n \ + -d + +For example, for the davinci dm365evm board: +./tools/mkimage -n ./board/davinci/dm365evm/ublimage.cfg \ + -T ublimage \ + -d u-boot-nand.bin u-boot.ubl + +You can generate the image directly when you compile u-boot with: + +$ make u-boot.ubl + +The output image can be flashed into the NAND. + +Please check the DaVinci documentation for further details. + +Board specific configuration file specifications: +------------------------------------------------- +1. This file must present in the $(BOARDDIR) and the name should be + ublimage.cfg (since this is used in Makefile). +2. This file can have empty lines and lines starting with "#" as first + character to put comments. +3. This file can have configuration command lines as mentioned below, + any other information in this file is treated as invalid. + +Configuration command line syntax: +--------------------------------- +1. Each command line must have two strings, first one command or address + and second one data string +2. Following are the valid command strings and associated data strings:- + Command string data string + -------------- ----------- + MODE UBL special mode, on of: + safe + Example: + MODE safe + + ENTRY Entry point address for the user + bootloader (absolute address) = TEXT_BASE + nand_spl loader. + Example: + ENTRY 0x00000020 + + PAGES Number of pages (size of user bootloader + in number of pages) + Example: + PAGES 27 + + START_BLOCK Block number where user bootloader is present + Example: + START_BLOCK 5 + + START_PAGE Page number where user bootloader is present + (for RBL always 0) + Example: + START_PAGE 0 + +------------------------------------------------ + +Structure of the u-boot.ubl binary: + +compile steps: + +1) nand_spl code compile, with pad_to = (TEXT_BASE + + (CONFIG_SYS_NROF_PAGES_NAND_SPL * pagesize)) + Example: cam_enc_4xx pad_to = 0x20 + (6 * 0x800) = 0x3020 = 12320 + -> u-boot-spl-16k.bin + + !! TEXT_BASE = 0x20, as the RBL starts at 0x20 + +2) compile u-boot.bin ("normal" u-boot) + -> u-boot.bin + +3) create u-boot-nand.bin = u-boot-spl-16k.bin + u-boot.bin + +4) create u-boot.ubl, size = 1 page size NAND + create UBL header and paste it before u-boot.bin + +This steps are done automagically if you do a "make all" + +-> You get an u-boot.ubl binary, which you can flash + into your NAND. + +Structure of this binary (Example for the cam_enc_4xx board with a NAND +page size = 0x800): + +offset : 0x00000 | 0x800 | 0x3800 +content: UBL | nand_spl | u-boot code + Header | code | + +The NAND layout looks for example like this: + +(Example for the cam_enc_4xx board with a NAND page size = 0x800, block +size = 0x20000 and CONFIG_SYS_NROF_UBL_HEADER 5): + +offset : 0x80000 | 0xa0000 | 0xa3000 +content: UBL | nand_spl | u-boot code + Header | code | + ^ ^ + ^ 0xa0000 = CONFIG_SYS_NROF_UBL_HEADER * 0x20000 + ^ + 0x80000 = Block 4 * 0x20000 + +If the cpu starts in NAND boot mode, it checks the UBL descriptor +starting with block 1 (page 0). When a valid UBL signature is found, +the corresponding block number (from 1 to 24) is written to the last 32 +bits of ARM internal memory (0x7ffc-0x8000). This feature is provided +as a basic debug mechanism. If not found, it continues with block 2 +... last possible block is 24 + +If a valid UBL descriptor is found, the UBL descriptor is read and +processed. The descriptor gives the information required for loading +and control transfer to the nand_spl code. The nand_spl code is then +read and processed. + +Once the user-specified start-up conditions are set, the RBL copies the +nand_spl into ARM internal RAM, starting at address 0x0000: 0020. + ^^^^ + +The nand_spl code itself now does necessary intializations, and at least, +copies the u-boot code from NAND into RAM, and jumps to it ... + +------------------------------------------------ +Author: Heiko Schocher diff --git a/include/image.h b/include/image.h index c31e862d32..3c528a4aa8 100644 --- a/include/image.h +++ b/include/image.h @@ -157,6 +157,7 @@ #define IH_TYPE_FLATDT 8 /* Binary Flat Device Tree Blob */ #define IH_TYPE_KWBIMAGE 9 /* Kirkwood Boot Image */ #define IH_TYPE_IMXIMAGE 10 /* Freescale IMXBoot Image */ +#define IH_TYPE_UBLIMAGE 11 /* Davinci UBL Image */ /* * Compression Types diff --git a/tools/Makefile b/tools/Makefile index de96e34d52..9733db42e3 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -92,6 +92,7 @@ NOPED_OBJ_FILES-y += mkimage.o OBJ_FILES-$(CONFIG_NETCONSOLE) += ncb.o NOPED_OBJ_FILES-y += os_support.o OBJ_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1.o +NOPED_OBJ_FILES-y += ublimage.o # Don't build by default #ifeq ($(ARCH),ppc) @@ -192,6 +193,7 @@ $(obj)mkimage$(SFX): $(obj)crc32.o \ $(obj)mkimage.o \ $(obj)os_support.o \ $(obj)sha1.o \ + $(obj)ublimage.o \ $(LIBFDT_OBJS) $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ $(HOSTSTRIP) $@ diff --git a/tools/mkimage.c b/tools/mkimage.c index 60f726303c..7215d0f2ea 100644 --- a/tools/mkimage.c +++ b/tools/mkimage.c @@ -158,6 +158,8 @@ main (int argc, char **argv) init_fit_image_type (); /* Init Default image generation/list support */ init_default_image_type (); + /* Init Davinci UBL support */ + init_ubl_image_type(); params.cmdname = *argv; params.addr = params.ep = 0; diff --git a/tools/mkimage.h b/tools/mkimage.h index 9033a7d230..d109d403ff 100644 --- a/tools/mkimage.h +++ b/tools/mkimage.h @@ -143,5 +143,6 @@ void init_kwb_image_type (void); void init_imx_image_type (void); void init_default_image_type (void); void init_fit_image_type (void); +void init_ubl_image_type(void); #endif /* _MKIIMAGE_H_ */ diff --git a/tools/ublimage.c b/tools/ublimage.c new file mode 100644 index 0000000000..99874622d0 --- /dev/null +++ b/tools/ublimage.c @@ -0,0 +1,275 @@ +/* + * (C) Copyright 2011 + * Heiko Schocher, DENX Software Engineering, hs@denx.de. + * + * Based on: + * (C) Copyright 2009 + * Stefano Babic, DENX Software Engineering, sbabic@denx.de. + * + * (C) Copyright 2008 + * Marvell Semiconductor + * Written-by: Prafulla Wadaskar + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* Required to obtain the getline prototype from stdio.h */ +#define _GNU_SOURCE + +#include "mkimage.h" +#include +#include "ublimage.h" + +/* + * Supported commands for configuration file + */ +static table_entry_t ublimage_cmds[] = { + {CMD_BOOT_MODE, "MODE", "UBL special modes", }, + {CMD_ENTRY, "ENTRY", "Entry point addr for bootloader", }, + {CMD_PAGE, "PAGES", + "number of pages (size of bootloader)", }, + {CMD_ST_BLOCK, "START_BLOCK", + "block number where bootloader is present", }, + {CMD_ST_PAGE, "START_PAGE", + "page number where bootloader is present", }, + {CMD_LD_ADDR, "LD_ADDR", + "load addr", }, + {-1, "", "", }, +}; + +/* + * Supported Boot options for configuration file + * this is needed to set the correct flash offset + */ +static table_entry_t ublimage_bootops[] = { + {UBL_MAGIC_SAFE, "safe", "Safe boot mode", }, + {-1, "", "Invalid", }, +}; + +static struct ubl_header ublimage_header; + +static uint32_t get_cfg_value(char *token, char *name, int linenr) +{ + char *endptr; + uint32_t value; + + errno = 0; + value = strtoul(token, &endptr, 16); + if (errno || (token == endptr)) { + fprintf(stderr, "Error: %s[%d] - Invalid hex data(%s)\n", + name, linenr, token); + exit(EXIT_FAILURE); + } + return value; +} + +static void print_hdr(struct ubl_header *ubl_hdr) +{ + printf("Image Type : Davinci UBL Boot Image\n"); + printf("UBL magic : %08x\n", ubl_hdr->magic); + printf("Entry Point: %08x\n", ubl_hdr->entry); + printf("nr of pages: %08x\n", ubl_hdr->pages); + printf("start block: %08x\n", ubl_hdr->block); + printf("start page : %08x\n", ubl_hdr->page); +} + +static void parse_cfg_cmd(struct ubl_header *ublhdr, int32_t cmd, char *token, + char *name, int lineno, int fld, int dcd_len) +{ + static int cmd_ver_first = ~0; + + switch (cmd) { + case CMD_BOOT_MODE: + ublhdr->magic = get_table_entry_id(ublimage_bootops, + "ublimage special boot mode", token); + if (ublhdr->magic == -1) { + fprintf(stderr, "Error: %s[%d] -Invalid boot mode" + "(%s)\n", name, lineno, token); + exit(EXIT_FAILURE); + } + ublhdr->magic += UBL_MAGIC_BASE; + if (unlikely(cmd_ver_first != 1)) + cmd_ver_first = 0; + break; + case CMD_ENTRY: + ublhdr->entry = get_cfg_value(token, name, lineno); + break; + case CMD_PAGE: + ublhdr->pages = get_cfg_value(token, name, lineno); + break; + case CMD_ST_BLOCK: + ublhdr->block = get_cfg_value(token, name, lineno); + break; + case CMD_ST_PAGE: + ublhdr->page = get_cfg_value(token, name, lineno); + break; + case CMD_LD_ADDR: + ublhdr->pll_m = get_cfg_value(token, name, lineno); + break; + } +} + +static void parse_cfg_fld(struct ubl_header *ublhdr, int32_t *cmd, + char *token, char *name, int lineno, int fld, int *dcd_len) +{ + + switch (fld) { + case CFG_COMMAND: + *cmd = get_table_entry_id(ublimage_cmds, + "ublimage commands", token); + if (*cmd < 0) { + fprintf(stderr, "Error: %s[%d] - Invalid command" + "(%s)\n", name, lineno, token); + exit(EXIT_FAILURE); + } + break; + case CFG_REG_VALUE: + parse_cfg_cmd(ublhdr, *cmd, token, name, lineno, fld, *dcd_len); + break; + default: + break; + } +} +static uint32_t parse_cfg_file(struct ubl_header *ublhdr, char *name) +{ + FILE *fd = NULL; + char *line = NULL; + char *token, *saveptr1, *saveptr2; + int lineno = 0; + int i; + char *ptr = (char *)ublhdr; + int fld; + size_t len; + int dcd_len = 0; + int32_t cmd; + int ublhdrlen = sizeof(struct ubl_header); + + fd = fopen(name, "r"); + if (fd == 0) { + fprintf(stderr, "Error: %s - Can't open DCD file\n", name); + exit(EXIT_FAILURE); + } + + /* Fill header with 0xff */ + for (i = 0; i < ublhdrlen; i++) { + *ptr = 0xff; + ptr++; + } + + /* + * Very simple parsing, line starting with # are comments + * and are dropped + */ + while ((getline(&line, &len, fd)) > 0) { + lineno++; + + token = strtok_r(line, "\r\n", &saveptr1); + if (token == NULL) + continue; + + /* Check inside the single line */ + for (fld = CFG_COMMAND, cmd = CMD_INVALID, + line = token; ; line = NULL, fld++) { + token = strtok_r(line, " \t", &saveptr2); + if (token == NULL) + break; + + /* Drop all text starting with '#' as comments */ + if (token[0] == '#') + break; + + parse_cfg_fld(ublhdr, &cmd, token, name, + lineno, fld, &dcd_len); + } + } + fclose(fd); + + return dcd_len; +} + +static int ublimage_check_image_types(uint8_t type) +{ + if (type == IH_TYPE_UBLIMAGE) + return EXIT_SUCCESS; + else + return EXIT_FAILURE; +} + +static int ublimage_verify_header(unsigned char *ptr, int image_size, + struct mkimage_params *params) +{ + return 0; +} + +static void ublimage_print_header(const void *ptr) +{ + struct ubl_header *ubl_hdr = (struct ubl_header *) ptr; + + print_hdr(ubl_hdr); +} + +static void ublimage_set_header(void *ptr, struct stat *sbuf, int ifd, + struct mkimage_params *params) +{ + struct ubl_header *ublhdr = (struct ubl_header *)ptr; + + /* Parse configuration file */ + parse_cfg_file(ublhdr, params->imagename); +} + +int ublimage_check_params(struct mkimage_params *params) +{ + if (!params) + return CFG_INVALID; + if (!strlen(params->imagename)) { + fprintf(stderr, "Error: %s - Configuration file not" + "specified, it is needed for ublimage generation\n", + params->cmdname); + return CFG_INVALID; + } + /* + * Check parameters: + * XIP is not allowed and verify that incompatible + * parameters are not sent at the same time + * For example, if list is required a data image must not be provided + */ + return (params->dflag && (params->fflag || params->lflag)) || + (params->fflag && (params->dflag || params->lflag)) || + (params->lflag && (params->dflag || params->fflag)) || + (params->xflag) || !(strlen(params->imagename)); +} + +/* + * ublimage parameters + */ +static struct image_type_params ublimage_params = { + .name = "Davinci UBL boot support", + .header_size = sizeof(struct ubl_header), + .hdr = (void *)&ublimage_header, + .check_image_type = ublimage_check_image_types, + .verify_header = ublimage_verify_header, + .print_header = ublimage_print_header, + .set_header = ublimage_set_header, + .check_params = ublimage_check_params, +}; + +void init_ubl_image_type(void) +{ + mkimage_register(&ublimage_params); +} diff --git a/tools/ublimage.h b/tools/ublimage.h new file mode 100644 index 0000000000..c9266890ce --- /dev/null +++ b/tools/ublimage.h @@ -0,0 +1,103 @@ +/* + * (C) Copyright 2011 + * Heiko Schocher, DENX Software Engineering, hs@denx.de. + * + * Vased on: + * (C) Copyright 2009 + * Stefano Babic, DENX Software Engineering, sbabic@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _UBLIMAGE_H_ +#define _UBLIMAGE_H_ + +#include + +#if !defined(CONFIG_SYS_UBL_BLOCK) +#define CONFIG_SYS_UBL_BLOCK 512 +#endif + +enum ublimage_cmd { + CMD_INVALID, + CMD_BOOT_MODE, + CMD_ENTRY, + CMD_PAGE, + CMD_ST_BLOCK, + CMD_ST_PAGE, + CMD_LD_ADDR +}; + +enum ublimage_fld_types { + CFG_INVALID = -1, + CFG_COMMAND, + CFG_REG_VALUE +}; + +/* + * from sprufg5a.pdf Table 110 + * Used by RBL when doing NAND boot + */ +#define UBL_MAGIC_BASE (0xA1ACED00) +/* Safe boot mode */ +#define UBL_MAGIC_SAFE (0x00) +/* DMA boot mode */ +#define UBL_MAGIC_DMA (0x11) +/* I Cache boot mode */ +#define UBL_MAGIC_IC (0x22) +/* Fast EMIF boot mode */ +#define UBL_MAGIC_FAST (0x33) +/* DMA + ICache boot mode */ +#define UBL_MAGIC_DMA_IC (0x44) +/* DMA + ICache + Fast EMIF boot mode */ +#define UBL_MAGIC_DMA_IC_FAST (0x55) + +/* Define max UBL image size */ +#define UBL_IMAGE_SIZE (0x00003800u) + +/* from sprufg5a.pdf Table 109 */ +struct ubl_header { + uint32_t magic; /* Magic Number, see UBL_* defines */ + uint32_t entry; /* entry point address for bootloader */ + uint32_t pages; /* number of pages (size of bootloader) */ + uint32_t block; /* + * blocknumber where user bootloader is + * present + */ + uint32_t page; /* + * page number where user bootloader is + * present. + */ + uint32_t pll_m; /* + * PLL setting -Multiplier (only valid if + * Magic Number indicates PLL enable). + */ + uint32_t pll_n; /* + * PLL setting -Divider (only valid if + * Magic Number indicates PLL enable). + */ + uint32_t emif; /* + * fast EMIF setting (only valid if + * Magic Number indicates fast EMIF boot). + */ + /* to fit in one nand block */ + unsigned char res[CONFIG_SYS_UBL_BLOCK - 8 * 4]; +}; + +#endif /* _UBLIMAGE_H_ */