diff options
author | Dongjin Kim <tobetter@gmail.com> | 2020-03-28 13:55:19 +0900 |
---|---|---|
committer | Dongjin Kim <tobetter@gmail.com> | 2020-03-28 23:56:10 +0900 |
commit | 25e589a2ae7f7dc01329a7431e651badcecf2e64 (patch) | |
tree | 138227c6459452ccf23cff93d6f3d4b3f9613edc | |
parent | 8c5681f3278858e505fd7308a9c577297930e24c (diff) | |
download | u-boot-odroid-c1-25e589a2ae7f7dc01329a7431e651badcecf2e64.tar.gz |
ODROID-C2: add buid package <fip_crate/amlbootsig> with bootstrap firmware
Change-Id: I4fd350871c0a55d6bb4faf5df059617673fcd50d
Signed-off-by: Dongjin Kim <tobetter@gmail.com>
29 files changed, 2024 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore index 2e1c8bf2bf..ff45f0a546 100644 --- a/.gitignore +++ b/.gitignore @@ -92,3 +92,14 @@ GTAGS *.orig *~ \#*# + +# binaries built with odroid-c2_defconfig +u-boot.bin.signed +u-boot.bin.bundle +u-boot.bin.fip +u-boot.bin.usb.bl2 +u-boot.bin.usb.tpl +fip_create +amlbootsig +amlinfo +unamlbootsig @@ -773,6 +773,7 @@ libs-y += $(if $(BOARDDIR),board/$(BOARDDIR)/) libs-y := $(sort $(libs-y)) u-boot-dirs := $(patsubst %/,%,$(filter %/, $(libs-y))) tools examples +u-boot-dirs += board/hardkernel/odroid-c2/fip_create board/hardkernel/odroid-c2/meson-tools u-boot-alldirs := $(sort $(u-boot-dirs) $(patsubst %/,%,$(filter %/, $(libs-)))) @@ -2173,3 +2174,7 @@ FORCE: ifneq ($(CONFIG_TARGET_ODROID_XU3),) include board/hardkernel/odroid-xu3/Makefile endif + +ifeq ($(shell echo $(CONFIG_IDENT_STRING) | tr -d ' '),odroid-c2) +include board/hardkernel/odroid-c2/Makefile +endif diff --git a/board/hardkernel/odroid-c2/Makefile b/board/hardkernel/odroid-c2/Makefile new file mode 100644 index 0000000000..69071e9207 --- /dev/null +++ b/board/hardkernel/odroid-c2/Makefile @@ -0,0 +1,37 @@ +# SPDX-License-Identifier: GPL-2.0+ +# +# Copyright (C) 2020 Dongjin Kim <tobetter@gmail.com> +# + +BOARD_DIR := $(srctree)/board/hardkernel/odroid-c2 + +files = bl1.bin.hardkernel \ + sd_fusing.sh + +targets = $(foreach blob, $(files), $(srctree)/sd_fuse/$(blob)) + +$(targets): + $(Q)cp $(BOARD_DIR)/$(shell basename $@) \ + $(shell dirname $@) + +prepare: + $(Q)mkdir -p $(srctree)/sd_fuse + +$(srctree)/sd_fuse/u-boot.bin: u-boot.bin + $(Q)$(BOARD_DIR)/fip_create/fip_create \ + --bl30 $(BOARD_DIR)/fip/gxb/bl30.bin \ + --bl301 $(BOARD_DIR)/fip/gxb/bl301.bin \ + --bl31 $(BOARD_DIR)/fip/gxb/bl31.bin \ + --bl33 u-boot.bin \ + $(BOARD_DIR)/u-boot.bin.fip + $(Q)$(BOARD_DIR)/fip_create/fip_create --dump \ + $(BOARD_DIR)/u-boot.bin.fip + $(Q)cat $(BOARD_DIR)/fip/gxb/bl2.bin \ + $(BOARD_DIR)/u-boot.bin.fip \ + > $(BOARD_DIR)/u-boot.bin.bundle + $(Q)$(BOARD_DIR)/meson-tools/amlbootsig \ + $(BOARD_DIR)/u-boot.bin.bundle \ + $(BOARD_DIR)/u-boot.bin.signed >/dev/null + $(Q)dd if=$(BOARD_DIR)/u-boot.bin.signed of=$@ bs=512 skip=96 + +all: $(srctree)/sd_fuse/u-boot.bin $(targets) diff --git a/board/hardkernel/odroid-c2/bl1.bin.hardkernel b/board/hardkernel/odroid-c2/bl1.bin.hardkernel Binary files differnew file mode 100644 index 0000000000..571fc4677b --- /dev/null +++ b/board/hardkernel/odroid-c2/bl1.bin.hardkernel diff --git a/board/hardkernel/odroid-c2/fip/bl2_fix.sh b/board/hardkernel/odroid-c2/fip/bl2_fix.sh new file mode 100755 index 0000000000..107d1ed6dc --- /dev/null +++ b/board/hardkernel/odroid-c2/fip/bl2_fix.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +declare -i bl2_size=`du -b $1 | awk '{print int($1)}'` + +declare -i zero_size=49152-$bl2_size + +dd if=/dev/zero of=$2 bs=1 count=$zero_size + +cat $1 $2 > $3 + +rm $2 diff --git a/board/hardkernel/odroid-c2/fip/gxb/aml_encrypt_gxb b/board/hardkernel/odroid-c2/fip/gxb/aml_encrypt_gxb Binary files differnew file mode 100755 index 0000000000..8ac4738411 --- /dev/null +++ b/board/hardkernel/odroid-c2/fip/gxb/aml_encrypt_gxb diff --git a/board/hardkernel/odroid-c2/fip/gxb/bl2.bin b/board/hardkernel/odroid-c2/fip/gxb/bl2.bin Binary files differnew file mode 100644 index 0000000000..23925f44f8 --- /dev/null +++ b/board/hardkernel/odroid-c2/fip/gxb/bl2.bin diff --git a/board/hardkernel/odroid-c2/fip/gxb/bl30.bin b/board/hardkernel/odroid-c2/fip/gxb/bl30.bin Binary files differnew file mode 100755 index 0000000000..353a9dba17 --- /dev/null +++ b/board/hardkernel/odroid-c2/fip/gxb/bl30.bin diff --git a/board/hardkernel/odroid-c2/fip/gxb/bl301.bin b/board/hardkernel/odroid-c2/fip/gxb/bl301.bin Binary files differnew file mode 100755 index 0000000000..b6ca8f795a --- /dev/null +++ b/board/hardkernel/odroid-c2/fip/gxb/bl301.bin diff --git a/board/hardkernel/odroid-c2/fip/gxb/bl31.bin b/board/hardkernel/odroid-c2/fip/gxb/bl31.bin Binary files differnew file mode 100755 index 0000000000..3e9d82d3e1 --- /dev/null +++ b/board/hardkernel/odroid-c2/fip/gxb/bl31.bin diff --git a/board/hardkernel/odroid-c2/fip/gxb/u-boot.bin.usb.bl2 b/board/hardkernel/odroid-c2/fip/gxb/u-boot.bin.usb.bl2 Binary files differnew file mode 100644 index 0000000000..56af908012 --- /dev/null +++ b/board/hardkernel/odroid-c2/fip/gxb/u-boot.bin.usb.bl2 diff --git a/board/hardkernel/odroid-c2/fip/gxb/u-boot.bin.usb.tpl b/board/hardkernel/odroid-c2/fip/gxb/u-boot.bin.usb.tpl Binary files differnew file mode 100644 index 0000000000..d7ace0229c --- /dev/null +++ b/board/hardkernel/odroid-c2/fip/gxb/u-boot.bin.usb.tpl diff --git a/board/hardkernel/odroid-c2/fip/meson/u-boot.bin.usb.bl2 b/board/hardkernel/odroid-c2/fip/meson/u-boot.bin.usb.bl2 Binary files differnew file mode 100644 index 0000000000..2aa58b560c --- /dev/null +++ b/board/hardkernel/odroid-c2/fip/meson/u-boot.bin.usb.bl2 diff --git a/board/hardkernel/odroid-c2/fip/meson/u-boot.bin.usb.tpl b/board/hardkernel/odroid-c2/fip/meson/u-boot.bin.usb.tpl Binary files differnew file mode 100644 index 0000000000..200f215a99 --- /dev/null +++ b/board/hardkernel/odroid-c2/fip/meson/u-boot.bin.usb.tpl diff --git a/board/hardkernel/odroid-c2/fip_create/Makefile b/board/hardkernel/odroid-c2/fip_create/Makefile new file mode 100644 index 0000000000..0aa3446806 --- /dev/null +++ b/board/hardkernel/odroid-c2/fip_create/Makefile @@ -0,0 +1,39 @@ +# +# Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# Neither the name of ARM nor the names of its contributors may be used +# to endorse or promote products derived from this software without specific +# prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +hostprogs-y := fip_create + +HOSTCFLAGS_fip_create.o := \ + -I$(srctree)/board/hardkernel/odroid-c2/fip_create \ + -O2 -Wall -pedantic -std=c99 -DXXX + +fip_create-objs := fip_create.o + +always := $(hostprogs-y) diff --git a/board/hardkernel/odroid-c2/fip_create/fip_create.c b/board/hardkernel/odroid-c2/fip_create/fip_create.c new file mode 100644 index 0000000000..255fab9c71 --- /dev/null +++ b/board/hardkernel/odroid-c2/fip_create/fip_create.c @@ -0,0 +1,678 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <linux/types.h> +#include <errno.h> +#include <getopt.h> /* getopt_long() is a GNU extention */ +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include "fip_create.h" +#include "firmware_image_package.h" + +/* Values returned by getopt() as part of the command line parsing */ +#define OPT_TOC_ENTRY 0 +#define OPT_DUMP 1 +#define OPT_HELP 2 + +file_info_t files[MAX_FILES]; +unsigned file_info_count = 0; +uuid_t uuid_null = {0}; + +/* + * TODO: Add ability to specify and flag different file types. + * Add flags to the toc_entry? + * const char* format_type_str[] = { "RAW", "ELF", "PIC" }; + */ + +/* The images used depends on the platform. */ +static entry_lookup_list_t toc_entry_lookup_list[] = { + { "Trusted Boot Firmware BL2", UUID_TRUSTED_BOOT_FIRMWARE_BL2, + "bl2", NULL, FLAG_FILENAME }, + { "SCP Firmware BL3-0", UUID_SCP_FIRMWARE_BL30, + "bl30", NULL, FLAG_FILENAME}, + { "SCP Firmware BL3-0-1", UUID_SCP_FIRMWARE_BL301, + "bl301", NULL, FLAG_FILENAME}, + { "EL3 Runtime Firmware BL3-1", UUID_EL3_RUNTIME_FIRMWARE_BL31, + "bl31", NULL, FLAG_FILENAME}, + { "Secure Payload BL3-2 (Trusted OS)", UUID_SECURE_PAYLOAD_BL32, + "bl32", NULL, FLAG_FILENAME}, + { "Non-Trusted Firmware BL3-3", UUID_NON_TRUSTED_FIRMWARE_BL33, + "bl33", NULL, FLAG_FILENAME}, + { NULL, {0}, 0 } +}; + + +/* Return 0 for equal uuids */ +static inline int compare_uuids(const uuid_t *uuid1, const uuid_t *uuid2) +{ + return memcmp(uuid1, uuid2, sizeof(uuid_t)); +} + + +static inline void copy_uuid(uuid_t *to_uuid, const uuid_t *from_uuid) +{ + memcpy(to_uuid, from_uuid, sizeof(uuid_t)); +} + + +static void print_usage(void) +{ + entry_lookup_list_t *entry = toc_entry_lookup_list; + + printf("Usage: fip_create [options] FIP_FILENAME\n\n"); + printf("\tThis tool is used to create a Firmware Image Package.\n\n"); + printf("Options:\n"); + printf("\t--help: Print this help message and exit\n"); + printf("\t--dump: Print contents of FIP\n\n"); + printf("\tComponents that can be added/updated:\n"); + for (; entry->command_line_name != NULL; entry++) { + printf("\t--%s%s\t\t%s", + entry->command_line_name, + (entry->flags & FLAG_FILENAME) ? " FILENAME" : "", + entry->name); + printf("\n"); + } +} + + +static entry_lookup_list_t *get_entry_lookup_from_uuid(const uuid_t *uuid) +{ + unsigned int lookup_index = 0; + + while (toc_entry_lookup_list[lookup_index].command_line_name != NULL) { + if (compare_uuids(&toc_entry_lookup_list[lookup_index].name_uuid, + uuid) == 0) { + return &toc_entry_lookup_list[lookup_index]; + } + lookup_index++; + } + return NULL; +} + + +static file_info_t *find_file_info_from_uuid(const uuid_t *uuid) +{ + int index; + + for (index = 0; index < file_info_count; index++) { + if (compare_uuids(&files[index].name_uuid, uuid) == 0) { + return &files[index]; + } + } + return NULL; +} + + +static int add_file_info_entry(entry_lookup_list_t *lookup_entry, char *filename) +{ + file_info_t *file_info_entry; + int error; + struct stat file_status; + bool is_new_entry = false; + + /* Check if the file already exists in the array */ + file_info_entry = find_file_info_from_uuid(&lookup_entry->name_uuid); + if (file_info_entry == NULL) { + /* The file does not exist in the current list; take the next + * one available in the file_info list. 'file_info_count' is + * incremented in case of successful update at the end of the + * function. + */ + file_info_entry = &files[file_info_count]; + is_new_entry = true; + + /* Copy the uuid for the new entry */ + copy_uuid(&file_info_entry->name_uuid, + &lookup_entry->name_uuid); + } + + /* Get the file information for entry */ + error = stat(filename, &file_status); + if (error != 0) { + printf("Error: Cannot get information for file \"%s\": %s\n", + filename, strerror(errno)); + return errno; + } + file_info_entry->filename = filename; + file_info_entry->size = (unsigned int)file_status.st_size; + file_info_entry->align_size = 0x4000 * ((file_info_entry->size / 0x4000) + 1); + file_info_entry->entry = lookup_entry; + + /* Increment the file_info counter on success if it is new file entry */ + if (is_new_entry) { + file_info_count++; + + /* Ensure we do not overflow */ + if (file_info_count > MAX_FILES) { + printf("ERROR: Too many files in Package\n"); + return 1; + } + } + + return 0; +} + + +static int write_memory_to_file(const uint8_t *start, const char *filename, + unsigned int size) +{ + FILE *stream; + unsigned int bytes_written; + + /* Write the packed file out to the filesystem */ + stream = fopen(filename, "r+"); + if (stream == NULL) { + stream = fopen(filename, "w"); + if (stream == NULL) { + printf("Error: Cannot create output file \"%s\": %s\n", + filename, strerror(errno)); + return errno; + } else { + printf("Creating \"%s\"\n", filename); + } + } else { + printf("Updating \"%s\"\n", filename); + } + + bytes_written = fwrite(start, sizeof(uint8_t), size, stream); + fclose(stream); + + if (bytes_written != size) { + printf("Error: Incorrect write for file \"%s\": Size=%u," + "Written=%u bytes.\n", filename, size, bytes_written); + return EIO; + } + + return 0; +} + + +static int read_file_to_memory(void *memory, const file_info_t *info) +{ + FILE *stream; + unsigned int bytes_read; + + /* If the file_info is defined by its filename we need to load it */ + if (info->filename) { + /* Read image from filesystem */ + stream = fopen(info->filename, "r"); + if (stream == NULL) { + printf("Error: Cannot open file \"%s\": %s\n", + info->filename, strerror(errno)); + return errno; + } + + bytes_read = (unsigned int)fread(memory, sizeof(uint8_t), + info->size, stream); + fclose(stream); + if (bytes_read != info->size) { + printf("Error: Incomplete read for file \"%s\":" + "Size=%u, Read=%u bytes.\n", info->filename, + info->size, bytes_read); + return EIO; + } + } else { + if (info->image_buffer == NULL) { + printf("ERROR: info->image_buffer = NULL\n"); + return EIO; + } + /* Copy the file_info buffer (extracted from the existing + * image package) into the new buffer. + */ + memcpy(memory, info->image_buffer, info->size); + } + + return 0; +} + + +/* Create the image package file */ +static int pack_images(const char *fip_filename) +{ + int status; + uint8_t *fip_base_address; + void *entry_address; + fip_toc_header_t *toc_header; + fip_toc_entry_t *toc_entry; + unsigned int entry_index; + unsigned int toc_size; + unsigned int fip_size; + unsigned int entry_offset_address; + unsigned int payload_size = 0; + + /* Validate filename */ + if ((fip_filename == NULL) || (strcmp(fip_filename, "") == 0)) { + return EINVAL; + } + + /* Payload size calculation */ + for (entry_index = 0; entry_index < file_info_count; entry_index++) { + payload_size += files[entry_index].align_size; + } + + /* Allocate memory for entire package, including the final null entry */ + //toc_size = (sizeof(fip_toc_header_t) + + //(sizeof(fip_toc_entry_t) * (file_info_count + 1))); + toc_size = 0x4000; + fip_size = toc_size + payload_size; + fip_base_address = malloc(fip_size); + if (fip_base_address == NULL) { + printf("Error: Can't allocate enough memory to create package." + "Process aborted.\n"); + return ENOMEM; + } + memset(fip_base_address, 0, fip_size); + + /* Create ToC Header */ + toc_header = (fip_toc_header_t *)fip_base_address; + toc_header->name = TOC_HEADER_NAME; + toc_header->serial_number = TOC_HEADER_SERIAL_NUMBER; + toc_header->flags = 0; + + toc_entry = (fip_toc_entry_t *)(fip_base_address + + sizeof(fip_toc_header_t)); + + /* Calculate the starting address of the first image, right after the + * toc header. + */ + entry_offset_address = toc_size; + entry_index = 0; + + /* Create the package in memory. */ + for (entry_index = 0; entry_index < file_info_count; entry_index++) { + entry_address = (fip_base_address + entry_offset_address); + status = read_file_to_memory(entry_address, + &files[entry_index]); + if (status != 0) { + printf("Error: While reading \"%s\" from filesystem.\n", + files[entry_index].filename); + return status; + } + + copy_uuid(&toc_entry->uuid, &files[entry_index].name_uuid); + toc_entry->offset_address = entry_offset_address; + toc_entry->size = files[entry_index].size; + toc_entry->flags = 0; + entry_offset_address += files[entry_index].align_size; + toc_entry++; + } + + /* Add a null uuid entry to mark the end of toc entries */ + copy_uuid(&toc_entry->uuid, &uuid_null); + toc_entry->offset_address = entry_offset_address; + toc_entry->size = 0; + toc_entry->flags = 0; + + /* Save the package to file */ + status = write_memory_to_file(fip_base_address, fip_filename, fip_size); + if (status != 0) { + printf("Error: Failed while writing package to file \"%s\" " + "with status=%d.\n", fip_filename, status); + return status; + } + return 0; +} + + +static void dump_toc(void) +{ + unsigned int index = 0; + unsigned int image_offset; + unsigned int image_size = 0; + + //image_offset = sizeof(fip_toc_header_t) + + //(sizeof(fip_toc_entry_t) * (file_info_count + 1)); + image_offset = 0x4000; + + printf("Firmware Image Package ToC:\n"); + printf("---------------------------\n"); + for (index = 0; index < file_info_count; index++) { + if (files[index].entry) { + printf("- %s: ", files[index].entry->name); + } else { + printf("- Unknown entry: "); + } + image_size = files[index].size; + + printf("offset=0x%X, size=0x%X\n", image_offset, image_size); + image_offset += files[index].align_size; + + if (files[index].filename) { + printf(" file: '%s'\n", files[index].filename); + } + } + printf("---------------------------\n"); +} + + +/* Read and load existing package into memory. */ +static int parse_fip(const char *fip_filename) +{ + FILE *fip; + char *fip_buffer; + char *fip_buffer_end; + int fip_size, read_fip_size; + fip_toc_header_t *toc_header; + fip_toc_entry_t *toc_entry; + bool found_last_toc_entry = false; + file_info_t *file_info_entry; + int status = -1; + struct stat st; + + fip = fopen(fip_filename, "r"); + if (fip == NULL) { + /* If the fip does not exist just return, it should not be + * considered as an error. The package will be created later + */ + status = 0; + goto parse_fip_return; + } + + if (stat(fip_filename, &st) != 0) { + status = errno; + goto parse_fip_fclose; + } else { + fip_size = (int)st.st_size; + } + + /* Allocate a buffer to read the package */ + fip_buffer = (char *)malloc(fip_size); + if (fip_buffer == NULL) { + printf("ERROR: Cannot allocate %d bytes.\n", fip_size); + status = errno; + goto parse_fip_fclose; + } + fip_buffer_end = fip_buffer + fip_size; + + /* Read the file */ + read_fip_size = fread(fip_buffer, sizeof(char), fip_size, fip); + if (read_fip_size != fip_size) { + printf("ERROR: Cannot read the FIP.\n"); + status = EIO; + goto parse_fip_free; + } + fclose(fip); + fip = NULL; + + /* The package must at least contain the ToC Header */ + if (fip_size < sizeof(fip_toc_header_t)) { + printf("ERROR: Given FIP is smaller than the ToC header.\n"); + status = EINVAL; + goto parse_fip_free; + } + /* Set the ToC Header at the base of the buffer */ + toc_header = (fip_toc_header_t *)fip_buffer; + /* The first toc entry should be just after the ToC header */ + toc_entry = (fip_toc_entry_t *)(toc_header + 1); + + /* While the ToC entry is contained into the buffer */ + int cnt = 0; + while (((char *)toc_entry + sizeof(fip_toc_entry_t)) < fip_buffer_end) { + cnt++; + /* Check if the ToC Entry is the last one */ + if (compare_uuids(&toc_entry->uuid, &uuid_null) == 0) { + found_last_toc_entry = true; + status = 0; + break; + } + + /* Add the entry into file_info */ + + /* Get the new entry in the array and clear it */ + file_info_entry = &files[file_info_count++]; + memset(file_info_entry, 0, sizeof(file_info_t)); + + /* Copy the info from the ToC entry */ + copy_uuid(&file_info_entry->name_uuid, &toc_entry->uuid); + file_info_entry->image_buffer = fip_buffer + + toc_entry->offset_address; + file_info_entry->size = toc_entry->size; + file_info_entry->align_size = 0x4000 * ((toc_entry->size / 0x4000) + 1); + + /* Check if there is a corresponding entry in lookup table */ + file_info_entry->entry = + get_entry_lookup_from_uuid(&toc_entry->uuid); + + /* Go to the next ToC entry */ + toc_entry++; + } + + if (!found_last_toc_entry) { + printf("ERROR: Given FIP does not have an end ToC entry.\n"); + status = EINVAL; + goto parse_fip_free; + } else { + /* All is well, we should not free any of the loaded images */ + goto parse_fip_fclose; + } + + parse_fip_free: + if (fip_buffer != NULL) { + free(fip_buffer); + fip_buffer = NULL; + } + + parse_fip_fclose: + if (fip != NULL) { + fclose(fip); + } + + parse_fip_return: + return status; +} + + +/* Parse all command-line options and return the FIP name if present. */ +static char *get_filename(int argc, char **argv, struct option *options) +{ + int c; + char *filename = NULL; + + /* Reset option pointer so we parse all args. starts at 1. + * The filename is the only argument that does not have an option flag. + */ + optind = 1; + while (1) { + c = getopt_long(argc, argv, "", options, NULL); + if (c == -1) + break; + + if (c == '?') { + /* Failed to parse an option. Fail. */ + return NULL; + } + } + + /* Only one argument left then it is the filename. + * We dont expect any other options + */ + if (optind + 1 == argc) + filename = argv[optind]; + + return filename; +} + + +/* Work through command-line options */ +static int parse_cmdline(int argc, char **argv, struct option *options, + int *do_pack) +{ + int c; + int status = 0; + int option_index = 0; + entry_lookup_list_t *lookup_entry; + int do_dump = 0; + + /* restart parse to process all options. starts at 1. */ + optind = 1; + while (1) { + c = getopt_long(argc, argv, "", options, &option_index); + if (c == -1) + break; + + switch (c) { + case OPT_TOC_ENTRY: + if (optarg) { + /* Does the option expect a filename. */ + lookup_entry = &toc_entry_lookup_list[option_index]; + if (lookup_entry->flags & FLAG_FILENAME) { + status = add_file_info_entry(lookup_entry, optarg); + if (status != 0) { + printf("Failed to process %s\n", + options[option_index].name); + break; + } else { + /* Update package */ + *do_pack = 1; + } + } + } + break; + + case OPT_DUMP: + do_dump = 1; + continue; + + case OPT_HELP: + print_usage(); + exit(0); + + default: + /* Unrecognised options are caught in get_filename() */ + break; + } + } + + + /* Do not dump toc if we have an error as it could hide the error */ + if ((status == 0) && (do_dump)) { + dump_toc(); + } + + return status; + +} + +int main(int argc, char **argv) +{ + int i; + int status; + char *fip_filename; + int do_pack = 0; + + /* Clear file list table. */ + memset(files, 0, sizeof(files)); + + /* Initialise for getopt_long(). + * Use image table as defined at top of file to get options. + * Add 'dump' option, 'help' option and end marker. + */ + static struct option long_options[(sizeof(toc_entry_lookup_list)/ + sizeof(entry_lookup_list_t)) + 2]; + + for (i = 0; + /* -1 because we dont want to process end marker in toc table */ + i < sizeof(toc_entry_lookup_list)/sizeof(entry_lookup_list_t) - 1; + i++) { + long_options[i].name = toc_entry_lookup_list[i].command_line_name; + /* The only flag defined at the moment is for a FILENAME */ + long_options[i].has_arg = toc_entry_lookup_list[i].flags ? 1 : 0; + long_options[i].flag = 0; + long_options[i].val = OPT_TOC_ENTRY; + } + + /* Add '--dump' option */ + long_options[i].name = "dump"; + long_options[i].has_arg = 0; + long_options[i].flag = 0; + long_options[i].val = OPT_DUMP; + + /* Add '--help' option */ + long_options[++i].name = "help"; + long_options[i].has_arg = 0; + long_options[i].flag = 0; + long_options[i].val = OPT_HELP; + + /* Zero the last entry (required) */ + long_options[++i].name = 0; + long_options[i].has_arg = 0; + long_options[i].flag = 0; + long_options[i].val = 0; + +#ifdef DEBUG + /* Print all supported options */ + for (i = 0; i < sizeof(long_options)/sizeof(struct option); i++) { + printf("long opt (%d) : name = %s\n", i, long_options[i].name); + } +#endif /* DEBUG */ + + /* As the package may already exist and is to be updated we need to get + * the filename from the arguments and load from it. + * NOTE: As this is the first function to look at the program arguments + * it causes a failure if bad options were provided. + */ + fip_filename = get_filename(argc, argv, long_options); + + /* Try to open the file and load it into memory */ + if (fip_filename != NULL) { + status = parse_fip(fip_filename); + if (status != 0) { + return status; + } + } + + /* Work through provided program arguments and perform actions */ + status = parse_cmdline(argc, argv, long_options, &do_pack); + if (status != 0) { + return status; + }; + + if (fip_filename == NULL) { + printf("ERROR: Missing FIP filename\n"); + print_usage(); + return 0; + } + + /* Processed all command line options. Create/update the package if + * required. + */ + if (do_pack) { + status = pack_images(fip_filename); + if (status != 0) { + printf("Failed to create package (status = %d).\n", + status); + } + } + + return status; +} diff --git a/board/hardkernel/odroid-c2/fip_create/fip_create.h b/board/hardkernel/odroid-c2/fip_create/fip_create.h new file mode 100644 index 0000000000..81e0897f98 --- /dev/null +++ b/board/hardkernel/odroid-c2/fip_create/fip_create.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __FIP_CREATE_H__ +#define __FIP_CREATE_H__ + +#include <stdint.h> +#include <uuid.h> + +#define MAX_FILES 10 + +/* TODO: Update this number as required */ +#define TOC_HEADER_SERIAL_NUMBER 0x12345678 + +#define FLAG_FILENAME (1 << 0) + +typedef struct entry_lookup_list { + const char *name; + uuid_t name_uuid; + const char *command_line_name; + struct file_info *info; + unsigned int flags; +} entry_lookup_list_t; + +typedef struct file_info { + uuid_t name_uuid; + const char *filename; + unsigned int size; + unsigned int align_size; + void *image_buffer; + entry_lookup_list_t *entry; +} file_info_t; + +#endif /* __FIP_CREATE_H__ */ diff --git a/board/hardkernel/odroid-c2/fip_create/firmware_image_package.h b/board/hardkernel/odroid-c2/fip_create/firmware_image_package.h new file mode 100644 index 0000000000..0a8a67d9ac --- /dev/null +++ b/board/hardkernel/odroid-c2/fip_create/firmware_image_package.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __FIRMWARE_IMAGE_PACKAGE_H__ +#define __FIRMWARE_IMAGE_PACKAGE_H__ + +#include <stdint.h> +#include <uuid.h> + +/* This is used as a signature to validate the blob header */ +#define TOC_HEADER_NAME 0xAA640001 + + +/* ToC Entry UUIDs */ +#define UUID_TRUSTED_BOOT_FIRMWARE_BL2 \ + {0x0becf95f, 0x224d, 0x4d3e, 0xa5, 0x44, {0xc3, 0x9d, 0x81, 0xc7, 0x3f, 0x0a} } +#define UUID_SCP_FIRMWARE_BL30 \ + {0x3dfd6697, 0xbe89, 0x49e8, 0xae, 0x5d, {0x78, 0xa1, 0x40, 0x60, 0x82, 0x13} } +#define UUID_SCP_FIRMWARE_BL301 \ + {0xAABBCCDD, 0xABCD, 0xEFEF, 0xAB, 0xCD, {0x12, 0x34, 0x56, 0x78, 0xAB, 0xCD} } +#define UUID_EL3_RUNTIME_FIRMWARE_BL31 \ + {0x6d08d447, 0xfe4c, 0x4698, 0x9b, 0x95, {0x29, 0x50, 0xcb, 0xbd, 0x5a, 0x00} } +#define UUID_SECURE_PAYLOAD_BL32 \ + {0x89e1d005, 0xdc53, 0x4713, 0x8d, 0x2b, {0x50, 0x0a, 0x4b, 0x7a, 0x3e, 0x38} } +#define UUID_NON_TRUSTED_FIRMWARE_BL33 \ + {0xa7eed0d6, 0xeafc, 0x4bd5, 0x97, 0x82, {0x99, 0x34, 0xf2, 0x34, 0xb6, 0xe4} } + +typedef struct fip_toc_header { + uint32_t name; + uint32_t serial_number; + uint64_t flags; +} fip_toc_header_t; + +typedef struct fip_toc_entry { + uuid_t uuid; + uint64_t offset_address; + uint64_t size; + uint64_t flags; +} fip_toc_entry_t; + +#endif /* __FIRMWARE_IMAGE_PACKAGE_H__ */ diff --git a/board/hardkernel/odroid-c2/fip_create/uuid.h b/board/hardkernel/odroid-c2/fip_create/uuid.h new file mode 100644 index 0000000000..5c4767b5b5 --- /dev/null +++ b/board/hardkernel/odroid-c2/fip_create/uuid.h @@ -0,0 +1,61 @@ +/*- + * Copyright (c) 2002 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * Portions copyright (c) 2014, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef _SYS_UUID_H_ +#define _SYS_UUID_H_ + +#include <sys/cdefs.h> + +/* Length of a node address (an IEEE 802 address). */ +#define _UUID_NODE_LEN 6 + +/* + * See also: + * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt + * http://www.opengroup.org/onlinepubs/009629399/apdxa.htm + * + * A DCE 1.1 compatible source representation of UUIDs. + */ +struct uuid { + uint32_t time_low; + uint16_t time_mid; + uint16_t time_hi_and_version; + uint8_t clock_seq_hi_and_reserved; + uint8_t clock_seq_low; + uint8_t node[_UUID_NODE_LEN]; +}; + +/* XXX namespace pollution? */ +typedef struct uuid uuid_t; + +#endif /* _SYS_UUID_H_ */ diff --git a/board/hardkernel/odroid-c2/meson-tools/COPYING b/board/hardkernel/odroid-c2/meson-tools/COPYING new file mode 100644 index 0000000000..d159169d10 --- /dev/null +++ b/board/hardkernel/odroid-c2/meson-tools/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/board/hardkernel/odroid-c2/meson-tools/Makefile b/board/hardkernel/odroid-c2/meson-tools/Makefile new file mode 100644 index 0000000000..758729de1c --- /dev/null +++ b/board/hardkernel/odroid-c2/meson-tools/Makefile @@ -0,0 +1,14 @@ +hostprogs-y := amlbootsig unamlbootsig amlinfo +always := $(hostprogs-y) + +COMMON_CFLAGS := -g -I/usr/include/openssl + +HOSTCFLAGS_amlbootsig.o := $(COMMON_CFLAGS) +HOSTLOADLIBES_amlbootsig = -lcrypto +amlbootsig-objs := amlbootsig.o + +HOSTCFLAGS_unamlbootsig.o := $(COMMON_CFLAGS) +unamlbootsig-objs := unamlbootsig.o + +HOSTCFLAGS_amlinfo.o := $(COMMON_CFLAGS) +amlinfo-objs := amlinfo.o diff --git a/board/hardkernel/odroid-c2/meson-tools/README.md b/board/hardkernel/odroid-c2/meson-tools/README.md new file mode 100644 index 0000000000..bdb1f83e1c --- /dev/null +++ b/board/hardkernel/odroid-c2/meson-tools/README.md @@ -0,0 +1,76 @@ +# meson-tools + +meson-tools is a collection of tools for use with the Amlogic Meson family of ARM based SoCs. + +Name-wise it was inspired by [sunxi-tools](https://github.com/linux-sunxi/sunxi-tools/). + +## amlbootsig + +Usage: +``` + amlbootsig boot_new.bin u-boot.img +``` + +This tool is supposed to provide equivalent output to: +``` + aml_encrypt_gxb --bootsig --input boot_new.bin --output u-boot.img +``` +with the tool version distributed by Hardkernel for their Odroid-C2 board (S905 / Meson GXBaby). + +### How to compare output + +``` + hexdump -C a/u-boot.img > a/u-boot.img.hex + hexdump -C b/u-boot.img > b/u-boot.img.hex + diff -u a/u-boot.img.hex b/u-boot.img.hex | less +``` + +This should result in a diff with only the following differences: + +* First 16 bytes will be random in original. +* The header for each FIP TOC entry will contain 4 bytes of random data. +* Due to FIP TOC entry headers differing, the SHA256 hash in the header will differ as well. + +For testing identity of output files, modify the code to use the random bytes from the file you are testing against. + +### Known limitations + +* Correctness: Since amlbootsig was designed to binary-match previously created output files, it may still have some numbers hard-coded or may do calculations in a way that happened to match tested input/output but may break for other input files. Please report such cases as GitHub issues. +* Endianness: Only Little Endian byte order has been considered. Running it on Big Endian hosts may misinterpret file input and/or result in wrong output and/or other misbehavior. The solution would be byte swaps, but those depend on the field width, which is guessed only and thus may change as the format is being better understood. +* Security: The tool was not designed to defend against invalid or evil file input. + +## unamlbootsig + +Usage: +``` +unamlbootsig u-boot.img boot_new.bin +``` + +This tool is supposed to do the reverse of `amlbootsig`, i.e. drop the boot signature. + +The output may differ from the original `aml_encrypt_gxb --bootsig`/`amlbootsig` input from 0xb000 to 0xbfff as well as in FIP TOC entry size 16-byte alignment. + +### Known limitations + +See `amlbootsig`. + +## amlinfo + +Usage: +``` + amlinfo u-boot.img +``` + +This tool dumps info about an existing image file. + +It supports the following inputs: +* `amlbootsig` output +* `aml_encrypt_gxb --bootsig` output, except when using `--amluserkey` or `--efuse` +* `dd if=u-boot.img bs=512 skip=96` output for either of them (FIP TOC with headered entries) +* `dd if=u-boot.img bs=1 skip=16` output, i.e. raw `@AML` header, of at least 64 bytes + +### Known limitations + +* Correctness: Since there seems to be no public documentation for the @AML headers, any field names printed are guesses and may need to be revised once their meaning becauses clearer. +* Endianness: Only Little Endian byte order has been considered, see above. +* Security: See above. diff --git a/board/hardkernel/odroid-c2/meson-tools/aml.h b/board/hardkernel/odroid-c2/meson-tools/aml.h new file mode 100644 index 0000000000..0a21f373ce --- /dev/null +++ b/board/hardkernel/odroid-c2/meson-tools/aml.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017 Andreas Färber + * + * SPDX-License-Identifier: GPL-2.0+ OR MIT + */ + +#ifndef AML_H +#define AML_H + +#include <stdint.h> + +#define AMLOGIC_SIGNATURE "@AML" + +struct __attribute((__packed__)) AmlogicHeader { + char sig[4]; + uint32_t size; + uint16_t header_size; + uint16_t header_version; + uint32_t id; + uint32_t encrypted; + uint32_t digest_offset; + uint32_t digest_size; + uint32_t data_offset; + uint32_t data_size; + uint32_t padding_offset; + uint32_t padding_size; + uint32_t _offset2; + uint32_t pad2; + uint32_t payload_offset; + uint32_t payload_size; + uint32_t unknown; +}; + +#endif diff --git a/board/hardkernel/odroid-c2/meson-tools/amlbootsig.c b/board/hardkernel/odroid-c2/meson-tools/amlbootsig.c new file mode 100644 index 0000000000..4d00548bc5 --- /dev/null +++ b/board/hardkernel/odroid-c2/meson-tools/amlbootsig.c @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2017 Andreas Färber + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <assert.h> +#include <inttypes.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +#include <openssl/sha.h> + +#include "meson.h" + +/* + * COMPARE_MODE: Define this and change values below to match files + * generated by aml_encrypt_gxb. + */ +#undef COMPARE_MODE + +#ifndef COMPARE_MODE +/* + * REPRODUCIBLE_OUTPUT: For the benefit of generating reproducible packages, + * deviate from aml_encrypt_gxb in not using random / time-based values. + */ +#define REPRODUCIBLE_OUTPUT +#endif + +static int do_fip(FILE *fout, FILE *fin) +{ + char *toc_buf, *buf; + struct FipHeader *ptoc; + int i, n; + long toc_pos; + + assert(sizeof(struct FipEntry) == 40); + + toc_buf = malloc(0x4000); + if (toc_buf == NULL) { + perror("malloc"); + return 1; + } + + ptoc = (struct FipHeader *)toc_buf; + toc_pos = ftell(fout); + fread(toc_buf, 1, 0x4000, fin); + n = 0; + while (ptoc->entries[n].size != 0) { + n++; + } + fwrite(toc_buf, 1, 0x4000, fout); + + buf = malloc(0x10000); + if (buf == NULL) { + perror("malloc"); + return 1; + } + + for (i = 0; i < n; i++) { + struct AmlogicHeader fip_hdr = { + .sig = AMLOGIC_SIGNATURE, + .size = 64, + .header_size = sizeof(struct AmlogicHeader), + .header_version = 1, + .digest_size = SHA256_DIGEST_LENGTH, + }; + SHA256_CTX sha256_ctx; + uint8_t sha256_digest[SHA256_DIGEST_LENGTH]; + size_t len; + long pos; + long remaining; + int padlen; + + pos = ftell(fout); + + printf("FIP TOC entry offset_address: %" PRIx64 "\n", ptoc->entries[i].offset_address); + printf("FIP TOC entry size: %" PRIx64 "\n", ptoc->entries[i].size); + + fseek(fin, toc_pos + ptoc->entries[i].offset_address, SEEK_SET); + printf("Input at %lx\n", ftell(fin)); + + len = ptoc->entries[i].size & (16 - 1); + padlen = (len != 0) ? (16 - len) : 0; + + memset(buf, 0, 0x10000); + fip_hdr.size += fip_hdr.digest_size + ptoc->entries[i].size + padlen; +#ifdef COMPARE_MODE + fip_hdr.id = 0x4ee06c7b; +#else +#ifdef REPRODUCIBLE_OUTPUT + fip_hdr.id = 0x42424200 + i; +#else +#error Non-reproducible FIP image IDs not implemented. +#endif +#endif + fip_hdr.digest_offset = fip_hdr.header_size; + fip_hdr.data_offset = fip_hdr.digest_offset + fip_hdr.digest_size; + fip_hdr.padding_offset = fip_hdr.data_offset; + fip_hdr._offset2 = fip_hdr.size - 0x60; + fip_hdr.payload_size = fip_hdr.size - 0x60; + fip_hdr.payload_offset = fip_hdr.header_size + SHA256_DIGEST_LENGTH; + memcpy(buf, &fip_hdr, sizeof(fip_hdr)); + + fwrite(buf, 1, fip_hdr.header_size + fip_hdr.digest_size, fout); + + SHA256_Init(&sha256_ctx); + SHA256_Update(&sha256_ctx, buf, fip_hdr.header_size); + SHA256_Update(&sha256_ctx, buf + fip_hdr.data_offset, 0); + remaining = ptoc->entries[i].size; + len = fread(buf, 1, fip_hdr.header_size + fip_hdr.digest_size, fin); + if (strncmp(buf + 16, "@AML", 4) == 0) { + fprintf(stderr, "@AML discovered in input FIP section %i!\n", i); + return 1; + } + SHA256_Update(&sha256_ctx, buf, len); + remaining -= len; + while (remaining > 0) { + len = fread(buf, 1, MIN(remaining, 0x4000), fin); + remaining -= len; + memset(buf + len, 0, len & 0xf); + SHA256_Update(&sha256_ctx, buf, ROUND_UP(len, 16)); + fwrite(buf, 1, ROUND_UP(len, 16), fout); + } + SHA256_Final(sha256_digest, &sha256_ctx); + fseek(fout, pos + fip_hdr.digest_offset, SEEK_SET); + fwrite(sha256_digest, 1, sizeof(sha256_digest), fout); + fseek(fout, 0, SEEK_END); + + fseek(fin, toc_pos + ptoc->entries[i].offset_address, SEEK_SET); + len = fread(buf, 1, fip_hdr.header_size + fip_hdr.digest_size, fin); + fwrite(buf, 1, len, fout); + + ptoc->entries[i].size += fip_hdr.header_size + fip_hdr.digest_size + padlen; + printf("FIP TOC entry size: %" PRIx64 "\n", ptoc->entries[i].size); + len = ptoc->entries[i].size & (0x4000 - 1); + if (len != 0) { + len = 0x4000 - len; + memset(buf, 0, len); + fwrite(buf, 1, len, fout); + } + } + free(buf); + fseek(fout, toc_pos, SEEK_SET); + fwrite(toc_buf, 1, 0x4000, fout); + fseek(fout, 0, SEEK_END); + free(toc_buf); + return 0; +} + +static int boot_sig(const char *input, const char *output) +{ + FILE *fin, *fout; + uint8_t random[16]; + char *src_buf, *buf; + struct AmlogicHeader hdr = { + .sig = AMLOGIC_SIGNATURE, + .size = 64, + .header_size = 64, + .header_version = 1, + .encrypted = 0, + .digest_offset = 64, + .digest_size = 512, + }; + SHA256_CTX sha256_ctx; + uint8_t sha256_digest[SHA256_DIGEST_LENGTH]; +#ifndef COMPARE_MODE + int i; +#endif + + assert(sizeof(struct AmlogicHeader) == 64); + + src_buf = malloc(0xb000); + if (src_buf == NULL) + return 1; + + fin = fopen(input, "rb"); + if (fin == NULL) { + perror(input); + return 1; + } + + fout = fopen(output, "wb"); + if (fout == NULL) { + perror(output); + return 1; + } + +#ifdef COMPARE_MODE + memcpy(random, (uint8_t[]){ 0xde, 0x49, 0x4c, 0x47, 0xe1, 0xd4, 0x86, 0xca, 0xb7, 0x4f, 0x10, 0xa4, 0x29, 0x3f, 0x28, 0x00 }, 16); +#else + for (i = 0; i < 16; i++) +#ifdef REPRODUCIBLE_OUTPUT + random[i] = 0x42; +#else + random[i] = rand(); +#endif +#endif + + (void)fwrite(random, 1, 16, fout); + + (void)fread(src_buf, 1, 0xb000, fin); + + if (strncmp(src_buf + 16, "@AML", 4) == 0) { + fprintf(stderr, "@AML discovered in input!\n"); + return 1; + } + + fseek(fin, 0xc000, SEEK_SET); + + hdr.size += hdr.digest_size; + hdr.size += 0xdb0; + hdr.size += 0xb000; + hdr.digest_offset = hdr.header_size; + hdr.data_offset = hdr.header_size + SHA256_DIGEST_LENGTH; + hdr.padding_offset = hdr.digest_offset + 512; + hdr.padding_size = 3504; + hdr._offset2 = hdr.size - hdr.data_offset; + hdr.payload_offset = hdr.padding_offset + hdr.padding_size; + hdr.payload_size = 0xb000; + + buf = malloc(hdr.size); + if (buf == NULL) { + perror("malloc"); + return 1; + } + + memset(buf, 0, hdr.size); + memcpy(buf, &hdr, sizeof(struct AmlogicHeader)); + memcpy(buf + hdr.padding_offset + hdr.padding_size, src_buf, 0xb000); + + SHA256_Init(&sha256_ctx); + SHA256_Update(&sha256_ctx, buf, hdr.header_size); + SHA256_Update(&sha256_ctx, buf + hdr.data_offset, hdr._offset2); + memset(sha256_digest, 0, sizeof(sha256_digest)); + SHA256_Final(sha256_digest, &sha256_ctx); + memcpy(buf + hdr.digest_offset, sha256_digest, sizeof(sha256_digest)); + + fwrite(buf, 1, hdr.size, fout); + + if (do_fip(fout, fin) != 0) + return 1; + + fclose(fout); + fclose(fin); + + free(src_buf); + + return 0; +} + +int main(int argc, char **argv) +{ + if (argc < 3) { + fprintf(stderr, "Usage: %s input output\n", argv[0]); + return 1; + } + + return boot_sig(argv[1], argv[2]); +} diff --git a/board/hardkernel/odroid-c2/meson-tools/amlinfo.c b/board/hardkernel/odroid-c2/meson-tools/amlinfo.c new file mode 100644 index 0000000000..06330c01d3 --- /dev/null +++ b/board/hardkernel/odroid-c2/meson-tools/amlinfo.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2017 Andreas Färber + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "meson.h" + +static void print_aml_header(const struct AmlogicHeader *hdr) +{ + printf("Size: 0x%" PRIx32 "\n", hdr->size); + printf("Header size: 0x%" PRIx16 "\n", hdr->header_size); + printf("Header version: %" PRIu16 "\n", hdr->header_version); + printf("ID: 0x%" PRIx32 "\n", hdr->id); + printf("Encrypted? %" PRIu32 "\n", hdr->encrypted); + printf("Digest @ 0x%" PRIx32 ", len %" PRIu32 "\n", hdr->digest_offset, hdr->digest_size); + printf("Data @ 0x%" PRIx32 ", len %" PRIu32 "\n", hdr->data_offset, hdr->data_size); + printf("Padding @ 0x%" PRIx32 ", len %" PRIu32 "\n", hdr->padding_offset, hdr->padding_size); + printf("_offset2: 0x%" PRIx32 "\n", hdr->_offset2); + printf("pad2: 0x%" PRIx32 "\n", hdr->pad2); + printf("Payload @ 0x%" PRIx32 ", len %" PRIu32 "\n", hdr->payload_offset, hdr->payload_size); + printf("unknown: 0x%" PRIx32 "\n", hdr->unknown); + printf("\n"); +} + +static int info(char *filename) +{ + uint8_t buf[16 + 64]; + struct AmlogicHeader *hdr; + FILE *f; + long pos; + int len; + + f = fopen(filename, "rb"); + if (f == NULL) + return 1; + + pos = 0; + do { + len = fread(buf, 1, 16 + 64, f); + if (len >= 4 && strncmp((const char*)buf, AMLOGIC_SIGNATURE, 4) == 0) { + hdr = (struct AmlogicHeader *)buf; + pos += 0; + } else if (len >= 16 + 4 && strncmp((const char*)buf + 16, AMLOGIC_SIGNATURE, 4) == 0) { + hdr = (struct AmlogicHeader *)(buf + 16); + pos += 16; + } else if (len >= 4 && ((struct FipHeader *)buf)->name == FIP_SIGNATURE) { + struct FipHeader *fip_hdr; + long toc_pos = pos; + int i = 0; + + fip_hdr = malloc(sizeof(struct FipHeader) + sizeof(struct FipEntry)); + if (fip_hdr == NULL) + return 1; + fseek(f, toc_pos, SEEK_SET); + len = fread(fip_hdr, 1, sizeof(struct FipHeader) + sizeof(struct FipEntry), f); + printf("FIP header @ 0x%" PRIx64 " (flags 0x%" PRIx64 ")\n", pos, fip_hdr->flags); + printf("\n"); + while (fip_hdr->entries[0].size > 0) { + printf("FIP TOC entry %u (flags 0x%" PRIx64 ")\n", i, fip_hdr->entries[0].flags); + fseek(f, toc_pos + fip_hdr->entries[0].offset_address, SEEK_SET); + len = fread(buf, 1, 64, f); + if (len >= 4 && strncmp((const char*)buf, AMLOGIC_SIGNATURE, 4) == 0) { + printf("@AML header @ 0x%" PRIx64 "\n", toc_pos + fip_hdr->entries[0].offset_address); + print_aml_header((struct AmlogicHeader *)buf); + } else { + fprintf(stderr, "Unexpected FIP TOC entry contents\n"); + } + + i++; + fseek(f, toc_pos + sizeof(struct FipHeader) + i * sizeof(struct FipEntry), SEEK_SET); + fread((void*)fip_hdr + sizeof(struct FipHeader), 1, sizeof(struct FipEntry), f); + } + free(fip_hdr); + break; + } else { + fclose(f); + return 1; + } + + printf("@AML header @ 0x%" PRIx64 "\n", pos); + print_aml_header(hdr); + + fseek(f, pos + hdr->size, SEEK_SET); + } while ((pos = ftell(f)) > 0); + + fclose(f); + return 0; +} + +int main(int argc, char **argv) +{ + if (argc < 2) { + fprintf(stderr, "Usage: %s filename\n", argv[0]); + return 1; + } + return info(argv[1]); +} diff --git a/board/hardkernel/odroid-c2/meson-tools/fip.h b/board/hardkernel/odroid-c2/meson-tools/fip.h new file mode 100644 index 0000000000..319a86ff8b --- /dev/null +++ b/board/hardkernel/odroid-c2/meson-tools/fip.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2017 Andreas Färber + * + * SPDX-License-Identifier: GPL-2.0+ OR MIT + */ + +#ifndef MESON_FIP_H +#define MESON_FIP_H + +#include <stdint.h> + +#define FIP_SIGNATURE 0xaa640001 + +struct __attribute((__packed__)) FipEntry { + uint64_t uuid[2]; + uint64_t offset_address; + uint64_t size; + uint64_t flags; +}; + +struct __attribute((__packed__)) FipHeader { + uint32_t name; + uint32_t serial_number; + uint64_t flags; + struct FipEntry entries[0]; +}; + +#endif diff --git a/board/hardkernel/odroid-c2/meson-tools/meson.h b/board/hardkernel/odroid-c2/meson-tools/meson.h new file mode 100644 index 0000000000..1fd1cb369e --- /dev/null +++ b/board/hardkernel/odroid-c2/meson-tools/meson.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2017 Andreas Färber + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef MESON_COMMON_H +#define MESON_COMMON_H + +#include "fip.h" +#include "aml.h" + +#ifndef MIN +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) +#endif + +#ifndef ROUND_UP +#define ROUND_UP(x, a) (((x) + ((a) - 1)) & ~((a) - 1)) +#endif + +#endif diff --git a/board/hardkernel/odroid-c2/meson-tools/unamlbootsig.c b/board/hardkernel/odroid-c2/meson-tools/unamlbootsig.c new file mode 100644 index 0000000000..523fc6f268 --- /dev/null +++ b/board/hardkernel/odroid-c2/meson-tools/unamlbootsig.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2017 Andreas Färber + * + * SPLX-License-Identifier: GPL-2.0+ + */ + +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include "meson.h" + +static int extract(const char *input, const char *output) +{ + uint8_t buf[16 + sizeof(struct AmlogicHeader)]; + struct AmlogicHeader *hdr; + FILE *fin, *fout; + long pos; + int len; + + fin = fopen(input, "rb"); + if (fin == NULL) + return 1; + + fout = fopen(output, "wb"); + if (fout == NULL) + return 1; + + pos = 0; + do { + len = fread(buf, 1, 16 + sizeof(struct AmlogicHeader), fin); + if (len >= 4 && strncmp((const char*)buf, AMLOGIC_SIGNATURE, 4) == 0) { + hdr = (struct AmlogicHeader *)buf; + } else if (len >= 16 + 4 && strncmp((const char*)buf + 16, AMLOGIC_SIGNATURE, 4) == 0) { + hdr = (struct AmlogicHeader *)(buf + 16); + pos += 16; + } else if (len >= 4 && ((struct FipHeader *)buf)->name == FIP_SIGNATURE) { + struct FipHeader *fip_hdr; + uint8_t *src_buf; + long toc_pos = pos; + int i, n; + + fip_hdr = malloc(sizeof(struct FipHeader) + sizeof(struct FipEntry)); + if (fip_hdr == NULL) + return 1; + fseek(fin, toc_pos, SEEK_SET); + len = fread(fip_hdr, 1, sizeof(struct FipHeader) + sizeof(struct FipEntry), fin); + printf("FIP header @ 0x%" PRIx64 " (flags 0x%" PRIx64 ")\n", pos, fip_hdr->flags); + fwrite(fip_hdr, 1, sizeof(struct FipHeader), fout); + n = 0; + while (fip_hdr->entries[0].size > 0) { + n++; + fread((void*)fip_hdr + sizeof(struct FipHeader), 1, sizeof(struct FipEntry), fin); + } + fip_hdr = realloc(fip_hdr, sizeof(struct FipHeader) + (n + 1) * sizeof(struct FipEntry)); + if (fip_hdr == NULL) + return 1; + + fseek(fin, toc_pos + sizeof(struct FipHeader), SEEK_SET); + fread((void*)fip_hdr + sizeof(struct FipHeader), 1, (n + 1) * sizeof(struct FipEntry), fin); + fwrite((void *)fip_hdr + sizeof(struct FipHeader), 1, (n + 1) * sizeof(struct FipEntry), fout); + src_buf = malloc(0x4000); + if (src_buf == NULL) + return 1; + + for (i = 0; i < n; i++) { + printf("FIP TOC entry %u (flags 0x%" PRIx64 ")\n", i, fip_hdr->entries[i].flags); + + fseek(fin, toc_pos + fip_hdr->entries[i].offset_address, SEEK_SET); + len = fread(buf, 1, sizeof(struct AmlogicHeader), fin); + if (len >= 4 && strncmp((const char*)buf, AMLOGIC_SIGNATURE, 4) == 0) { + long remaining; + + printf("@AML header @ 0x%" PRIx64 "\n", toc_pos + fip_hdr->entries[i].offset_address); + hdr = (struct AmlogicHeader *)buf; + fip_hdr->entries[i].size -= hdr->header_size + hdr->digest_size; + pos = ftell(fout); + pos = ROUND_UP(pos, 0x4000); + fseek(fout, pos, SEEK_SET); + fseek(fin, toc_pos + fip_hdr->entries[i].offset_address + fip_hdr->entries[i].size, SEEK_SET); + len = fread(src_buf, 1, hdr->header_size + hdr->digest_size, fin); + fwrite(src_buf, 1, len, fout); + + fseek(fin, toc_pos + fip_hdr->entries[i].offset_address + hdr->header_size + hdr->digest_size, SEEK_SET); + remaining = fip_hdr->entries[i].size - hdr->header_size - hdr->digest_size; + while (remaining > 0) { + len = fread(src_buf, 1, MIN(remaining, 0x4000), fin); + remaining -= len; + fwrite(src_buf, 1, len, fout); + } + } else { + fprintf(stderr, "Unexpected FIP TOC entry contents\n"); + } + } + fseek(fout, 0xc000, SEEK_SET); + fwrite(fip_hdr, 1, sizeof(struct FipHeader) + (n + 1) * sizeof(struct FipEntry), fout); + fseek(fout, 0, SEEK_END); + pos = ftell(fout); + pos = ROUND_UP(pos, 0x4000); + fseek(fout, pos - 1, SEEK_SET); + buf[0] = 0; + fwrite(buf, 1, 1, fout); + free(fip_hdr); + break; + } else { + fclose(fout); + fclose(fin); + return 1; + } + + printf("@AML header @ 0x%" PRIx64 "\n", pos); + + fseek(fin, pos + hdr->payload_offset, SEEK_SET); + uint8_t *src_buf = malloc(hdr->payload_size); + if (src_buf == NULL) { + fclose(fout); + fclose(fin); + return 1; + } + len = fread(src_buf, 1, hdr->payload_size, fin); + fwrite(src_buf, 1, len, fout); + free(src_buf); + + fseek(fin, pos + hdr->size, SEEK_SET); + fseek(fout, 0xc000, SEEK_SET); + } while ((pos = ftell(fin)) > 0); + + fclose(fout); + fclose(fin); + return 0; +} + +int main(int argc, char **argv) +{ + if (argc < 3) { + fprintf(stderr, "Usage: %s input output\n", argv[0]); + return 1; + } + return extract(argv[1], argv[2]); +} diff --git a/board/hardkernel/odroid-c2/sd_fusing.sh b/board/hardkernel/odroid-c2/sd_fusing.sh new file mode 100755 index 0000000000..c5a517ca75 --- /dev/null +++ b/board/hardkernel/odroid-c2/sd_fusing.sh @@ -0,0 +1,34 @@ +#!/bin/sh +# +# Copyright (C) 2015 Hardkernel Co,. Ltd +# Dongjin Kim <tobetter@gmail.com> +# +# SPDX-License-Identifier: GPL-2.0+ +# + +BL1=bl1.bin.hardkernel +UBOOT=u-boot.bin + +if [ -z $1 ]; then + echo "Usage ./sd_fusing.sh <SD card reader's device>" + exit 1 +fi + +if [ ! -f $BL1 ]; then + echo "error: $BL1 does not exist" + exit 1 +fi + +if [ ! -f $UBOOT ]; then + echo "error: $UBOOT does not exist" + exit 1 +fi + +sudo dd if=$BL1 of=$1 conv=fsync,notrunc bs=1 count=442 +sudo dd if=$BL1 of=$1 conv=fsync,notrunc bs=512 skip=1 seek=1 +sudo dd if=$UBOOT of=$1 conv=fsync,notrunc bs=512 seek=97 + +sync + +sudo eject $1 +echo Finished. |