Add multi-architecture support to cbfstool
This is an initial re-factoring of CBFS code to enable multiple architectures. To achieve a clean solution, an additional field describing the architecture has to be added to the master header. Hence we also increase the version number in the master header. Change-Id: Icda681673221f8c27efbc46f16c2c5682b16a265 Signed-off-by: Stefan Reinauer <reinauer@google.com> Signed-off-by: Hung-Te Lin <hungte@chromium.org> Signed-off-by: David Hendricks <dhendrix@chromium.org> Reviewed-on: http://review.coreboot.org/1944 Tested-by: build bot (Jenkins)
This commit is contained in:
parent
11a20b614e
commit
90ca3b6bd7
|
@ -144,11 +144,15 @@ need to read the pointer and do the appropriate math to locate the header.
|
||||||
The following is the structure of the master header:
|
The following is the structure of the master header:
|
||||||
|
|
||||||
struct cbfs_header {
|
struct cbfs_header {
|
||||||
unsigned int magic;
|
u32 magic;
|
||||||
unsigned int size;
|
u32 version;
|
||||||
unsigned int align;
|
u32 romsize;
|
||||||
unsigned int offset;
|
u32 bootblocksize;
|
||||||
};
|
u32 align;
|
||||||
|
u32 offset;
|
||||||
|
u32 architecture;
|
||||||
|
u32 pad[1];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
The meaning of each member is as follows:
|
The meaning of each member is as follows:
|
||||||
|
|
||||||
|
@ -156,9 +160,14 @@ The meaning of each member is as follows:
|
||||||
magic
|
magic
|
||||||
number is 0x4F524243, which is 'ORBC' in ASCII.
|
number is 0x4F524243, which is 'ORBC' in ASCII.
|
||||||
|
|
||||||
'size' is the size of the ROM in bytes. Coreboot will subtract 'size' from
|
'version' is a version number for CBFS header. cbfs_header structure may be
|
||||||
|
different if version is not matched.
|
||||||
|
|
||||||
|
'romsize' is the size of the ROM in bytes. Coreboot will subtract 'size' from
|
||||||
0xFFFFFFFF to locate the beginning of the ROM in memory.
|
0xFFFFFFFF to locate the beginning of the ROM in memory.
|
||||||
|
|
||||||
|
'bootblocksize' is the size of bootblock reserved in firmware image.
|
||||||
|
|
||||||
'align' is the number of bytes that each component is aligned to within the
|
'align' is the number of bytes that each component is aligned to within the
|
||||||
ROM. This is used to make sure that each component is aligned correctly
|
ROM. This is used to make sure that each component is aligned correctly
|
||||||
with
|
with
|
||||||
|
@ -169,6 +178,9 @@ component at runtime without disturbing the others.
|
||||||
the ROM). This is to allow for arbitrary space to be left at the beginning
|
the ROM). This is to allow for arbitrary space to be left at the beginning
|
||||||
of the ROM for things like embedded controller firmware.
|
of the ROM for things like embedded controller firmware.
|
||||||
|
|
||||||
|
'architecture' describes which architecture (x86, arm, ...) this CBFS is created
|
||||||
|
for.
|
||||||
|
|
||||||
= Bootblock =
|
= Bootblock =
|
||||||
The bootblock is a mandatory component in the ROM. It is located in the
|
The bootblock is a mandatory component in the ROM. It is located in the
|
||||||
last
|
last
|
||||||
|
|
|
@ -41,7 +41,8 @@ struct cbheader {
|
||||||
u32 bootblocksize;
|
u32 bootblocksize;
|
||||||
u32 align;
|
u32 align;
|
||||||
u32 offset;
|
u32 offset;
|
||||||
u32 pad[2];
|
u32 architecture;
|
||||||
|
u32 pad[1];
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
struct cbfile {
|
struct cbfile {
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* This file is part of the coreboot project.
|
* This file is part of the coreboot project.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2008 Jordan Crouse <jordan@cosmicpenguin.net>
|
* Copyright (C) 2008 Jordan Crouse <jordan@cosmicpenguin.net>
|
||||||
|
* Copyright (C) 2012 Google, Inc.
|
||||||
*
|
*
|
||||||
* This file is dual-licensed. You can choose between:
|
* This file is dual-licensed. You can choose between:
|
||||||
* - The GNU GPL, version 2, as published by the Free Software Foundation
|
* - The GNU GPL, version 2, as published by the Free Software Foundation
|
||||||
|
@ -76,13 +77,17 @@
|
||||||
|
|
||||||
/** this is the master cbfs header - it need to be
|
/** this is the master cbfs header - it need to be
|
||||||
located somewhere in the bootblock. Where it
|
located somewhere in the bootblock. Where it
|
||||||
actually lives is up to coreboot. A pointer to
|
actually lives is up to coreboot. On x86, a
|
||||||
this header will live at 0xFFFFFFFc, so we can
|
pointer to this header will live at 0xFFFFFFFC,
|
||||||
easily find it. */
|
so we can easily find it. */
|
||||||
|
|
||||||
#define CBFS_HEADER_MAGIC 0x4F524243
|
#define CBFS_HEADER_MAGIC 0x4F524243
|
||||||
#define CBFS_HEADPTR_ADDR 0xFFFFFFFc
|
#if CONFIG_ARCH_X86
|
||||||
|
#define CBFS_HEADPTR_ADDR 0xFFFFFFFC
|
||||||
|
#endif
|
||||||
#define VERSION1 0x31313131
|
#define VERSION1 0x31313131
|
||||||
|
#define VERSION2 0x31313132
|
||||||
|
#define VERSION VERSION2
|
||||||
|
|
||||||
struct cbfs_header {
|
struct cbfs_header {
|
||||||
uint32_t magic;
|
uint32_t magic;
|
||||||
|
@ -91,9 +96,17 @@ struct cbfs_header {
|
||||||
uint32_t bootblocksize;
|
uint32_t bootblocksize;
|
||||||
uint32_t align;
|
uint32_t align;
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
uint32_t pad[2];
|
uint32_t architecture;
|
||||||
|
uint32_t pad[1];
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/* "Unknown" refers to CBFS headers version 1,
|
||||||
|
* before the architecture was defined (i.e., x86 only).
|
||||||
|
*/
|
||||||
|
#define CBFS_ARCHITECTURE_UNKNOWN 0xFFFFFFFF
|
||||||
|
#define CBFS_ARCHITECTURE_X86 0x00000001
|
||||||
|
#define CBFS_ARCHITECTURE_ARMV7 0x00000010
|
||||||
|
|
||||||
/** This is a component header - every entry in the CBFS
|
/** This is a component header - every entry in the CBFS
|
||||||
will have this header.
|
will have this header.
|
||||||
|
|
||||||
|
@ -178,4 +191,3 @@ void *cbfs_find_file(const char *name, int type);
|
||||||
int cbfs_decompress(int algo, void *src, void *dst, int len);
|
int cbfs_decompress(int algo, void *src, void *dst, int len);
|
||||||
struct cbfs_header *get_cbfs_header(void);
|
struct cbfs_header *get_cbfs_header(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -65,7 +65,7 @@ prebuild-files = \
|
||||||
prebuilt-files = $(foreach file,$(cbfs-files), $(call extract_nth,1,$(file)))
|
prebuilt-files = $(foreach file,$(cbfs-files), $(call extract_nth,1,$(file)))
|
||||||
|
|
||||||
$(obj)/coreboot.pre1: $(objcbfs)/bootblock.bin $$(prebuilt-files) $(CBFSTOOL)
|
$(obj)/coreboot.pre1: $(objcbfs)/bootblock.bin $$(prebuilt-files) $(CBFSTOOL)
|
||||||
$(CBFSTOOL) $@.tmp create -s $(CONFIG_COREBOOT_ROMSIZE_KB)K \
|
$(CBFSTOOL) $@.tmp create -m x86 -s $(CONFIG_COREBOOT_ROMSIZE_KB)K \
|
||||||
-B $(objcbfs)/bootblock.bin -a 64 \
|
-B $(objcbfs)/bootblock.bin -a 64 \
|
||||||
-o $$(( $(CONFIG_ROM_SIZE) - $(CONFIG_CBFS_SIZE) ))
|
-o $$(( $(CONFIG_ROM_SIZE) - $(CONFIG_CBFS_SIZE) ))
|
||||||
$(prebuild-files) true
|
$(prebuild-files) true
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* This file is part of the coreboot project.
|
* This file is part of the coreboot project.
|
||||||
*
|
*
|
||||||
* Copyright (C) 2008 Jordan Crouse <jordan@cosmicpenguin.net>
|
* Copyright (C) 2008 Jordan Crouse <jordan@cosmicpenguin.net>
|
||||||
|
* Copyright (C) 2012 Google, Inc.
|
||||||
*
|
*
|
||||||
* This file is dual-licensed. You can choose between:
|
* This file is dual-licensed. You can choose between:
|
||||||
* - The GNU GPL, version 2, as published by the Free Software Foundation
|
* - The GNU GPL, version 2, as published by the Free Software Foundation
|
||||||
|
@ -49,8 +50,6 @@
|
||||||
#ifndef _CBFS_CORE_H_
|
#ifndef _CBFS_CORE_H_
|
||||||
#define _CBFS_CORE_H_
|
#define _CBFS_CORE_H_
|
||||||
|
|
||||||
#include <arch/byteorder.h>
|
|
||||||
|
|
||||||
/** These are standard values for the known compression
|
/** These are standard values for the known compression
|
||||||
alogrithms that coreboot knows about for stages and
|
alogrithms that coreboot knows about for stages and
|
||||||
payloads. Of course, other CBFS users can use whatever
|
payloads. Of course, other CBFS users can use whatever
|
||||||
|
@ -78,13 +77,17 @@
|
||||||
|
|
||||||
/** this is the master cbfs header - it need to be
|
/** this is the master cbfs header - it need to be
|
||||||
located somewhere in the bootblock. Where it
|
located somewhere in the bootblock. Where it
|
||||||
actually lives is up to coreboot. A pointer to
|
actually lives is up to coreboot. On x86, a
|
||||||
this header will live at 0xFFFFFFFc, so we can
|
pointer to this header will live at 0xFFFFFFFC,
|
||||||
easily find it. */
|
so we can easily find it. */
|
||||||
|
|
||||||
#define CBFS_HEADER_MAGIC 0x4F524243
|
#define CBFS_HEADER_MAGIC 0x4F524243
|
||||||
#define CBFS_HEADPTR_ADDR 0xFFFFFFFc
|
#if CONFIG_ARCH_X86
|
||||||
|
#define CBFS_HEADPTR_ADDR 0xFFFFFFFC
|
||||||
|
#endif
|
||||||
#define VERSION1 0x31313131
|
#define VERSION1 0x31313131
|
||||||
|
#define VERSION2 0x31313132
|
||||||
|
#define VERSION VERSION2
|
||||||
|
|
||||||
struct cbfs_header {
|
struct cbfs_header {
|
||||||
uint32_t magic;
|
uint32_t magic;
|
||||||
|
@ -93,9 +96,17 @@ struct cbfs_header {
|
||||||
uint32_t bootblocksize;
|
uint32_t bootblocksize;
|
||||||
uint32_t align;
|
uint32_t align;
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
uint32_t pad[2];
|
uint32_t architecture;
|
||||||
|
uint32_t pad[1];
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
/* "Unknown" refers to CBFS headers version 1,
|
||||||
|
* before the architecture was defined (i.e., x86 only).
|
||||||
|
*/
|
||||||
|
#define CBFS_ARCHITECTURE_UNKNOWN 0xFFFFFFFF
|
||||||
|
#define CBFS_ARCHITECTURE_X86 0x00000001
|
||||||
|
#define CBFS_ARCHITECTURE_ARMV7 0x00000010
|
||||||
|
|
||||||
/** This is a component header - every entry in the CBFS
|
/** This is a component header - every entry in the CBFS
|
||||||
will have this header.
|
will have this header.
|
||||||
|
|
||||||
|
@ -180,4 +191,3 @@ void *cbfs_find_file(const char *name, int type);
|
||||||
int cbfs_decompress(int algo, void *src, void *dst, int len);
|
int cbfs_decompress(int algo, void *src, void *dst, int len);
|
||||||
struct cbfs_header *get_cbfs_header(void);
|
struct cbfs_header *get_cbfs_header(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ int parse_elf_to_payload(unsigned char *input, unsigned char **output,
|
||||||
comp_algo algo)
|
comp_algo algo)
|
||||||
{
|
{
|
||||||
Elf32_Phdr *phdr;
|
Elf32_Phdr *phdr;
|
||||||
Elf32_Ehdr *ehdr;
|
Elf32_Ehdr *ehdr = (Elf32_Ehdr *) input;
|
||||||
Elf32_Shdr *shdr;
|
Elf32_Shdr *shdr;
|
||||||
char *header;
|
char *header;
|
||||||
char *strtab;
|
char *strtab;
|
||||||
|
@ -48,16 +48,20 @@ int parse_elf_to_payload(unsigned char *input, unsigned char **output,
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if(!iself(input)){
|
if(!iself(input)){
|
||||||
printf("Fatal error: the payload file is not in ELF format!\n");
|
fprintf(stderr, "E: The payload file is not in ELF format!\n");
|
||||||
exit(1);
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!((ehdr->e_machine == EM_ARM) && (arch == CBFS_ARCHITECTURE_ARMV7)) &&
|
||||||
|
!((ehdr->e_machine == EM_386) && (arch == CBFS_ARCHITECTURE_X86))) {
|
||||||
|
fprintf(stderr, "E: The payload file has the wrong architecture\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
comp_func_ptr compress = compression_function(algo);
|
comp_func_ptr compress = compression_function(algo);
|
||||||
if (!compress)
|
if (!compress)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
ehdr = (Elf32_Ehdr *) input;
|
|
||||||
headers = ehdr->e_phnum;
|
headers = ehdr->e_phnum;
|
||||||
header = (char *)ehdr;
|
header = (char *)ehdr;
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
* Copyright (C) 2008 Jordan Crouse <jordan@cosmicpenguin.net>
|
* Copyright (C) 2008 Jordan Crouse <jordan@cosmicpenguin.net>
|
||||||
* 2009 coresystems GmbH
|
* 2009 coresystems GmbH
|
||||||
* written by Patrick Georgi <patrick.georgi@coresystems.de>
|
* written by Patrick Georgi <patrick.georgi@coresystems.de>
|
||||||
|
* Copyright (C) 2012 Google, Inc.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -67,7 +68,13 @@ int parse_elf_to_stage(unsigned char *input, unsigned char **output,
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (!iself(input)) {
|
if (!iself(input)) {
|
||||||
fprintf(stderr, "E: The incoming file is not an ELF\n");
|
fprintf(stderr, "E: The stage file is not in ELF format!\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!((ehdr->e_machine == EM_ARM) && (arch == CBFS_ARCHITECTURE_ARMV7)) &&
|
||||||
|
!((ehdr->e_machine == EM_386) && (arch == CBFS_ARCHITECTURE_X86))) {
|
||||||
|
fprintf(stderr, "E: The stage file has the wrong architecture\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,12 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define CBFS_HEADER_MAGIC 0x4F524243
|
||||||
|
#define CBFS_HEADPTR_ADDR_X86 0xFFFFFFFC
|
||||||
|
#define VERSION1 0x31313131
|
||||||
|
#define VERSION2 0x31313132
|
||||||
|
#define VERSION VERSION2
|
||||||
|
|
||||||
struct cbfs_header {
|
struct cbfs_header {
|
||||||
uint32_t magic;
|
uint32_t magic;
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
|
@ -28,9 +34,14 @@ struct cbfs_header {
|
||||||
uint32_t bootblocksize;
|
uint32_t bootblocksize;
|
||||||
uint32_t align;
|
uint32_t align;
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
uint32_t pad[2];
|
uint32_t architecture; /* Version 2 */
|
||||||
|
uint32_t pad[1];
|
||||||
} __attribute__ ((packed));
|
} __attribute__ ((packed));
|
||||||
|
|
||||||
|
#define CBFS_ARCHITECTURE_UNKNOWN 0xFFFFFFFF
|
||||||
|
#define CBFS_ARCHITECTURE_X86 0x00000001
|
||||||
|
#define CBFS_ARCHITECTURE_ARMV7 0x00000010
|
||||||
|
|
||||||
struct cbfs_file {
|
struct cbfs_file {
|
||||||
uint8_t magic[8];
|
uint8_t magic[8];
|
||||||
uint32_t len;
|
uint32_t len;
|
||||||
|
@ -94,7 +105,7 @@ struct cbfs_payload {
|
||||||
*/
|
*/
|
||||||
#define CBFS_COMPONENT_NULL 0xFFFFFFFF
|
#define CBFS_COMPONENT_NULL 0xFFFFFFFF
|
||||||
|
|
||||||
int cbfs_file_header(uint32_t physaddr);
|
int cbfs_file_header(unsigned long physaddr);
|
||||||
struct cbfs_file *cbfs_create_empty_file(uint32_t physaddr, uint32_t size);
|
struct cbfs_file *cbfs_create_empty_file(uint32_t physaddr, uint32_t size);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009 coresystems GmbH
|
* Copyright (C) 2009 coresystems GmbH
|
||||||
* written by Patrick Georgi <patrick.georgi@coresystems.de>
|
* written by Patrick Georgi <patrick.georgi@coresystems.de>
|
||||||
|
* Copyright (C) 2012 Google, Inc.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -372,6 +373,11 @@ static int cbfs_create(void)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (arch == CBFS_ARCHITECTURE_UNKNOWN) {
|
||||||
|
fprintf(stderr, "E: You need to specify -m/--machine arch\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
return create_cbfs_image(cbfs_name, rom_size, rom_bootblock,
|
return create_cbfs_image(cbfs_name, rom_size, rom_bootblock,
|
||||||
rom_alignment, rom_offset);
|
rom_alignment, rom_offset);
|
||||||
}
|
}
|
||||||
|
@ -450,7 +456,7 @@ static const struct command commands[] = {
|
||||||
{"add-stage", "f:n:t:c:b:h?", cbfs_add_stage},
|
{"add-stage", "f:n:t:c:b:h?", cbfs_add_stage},
|
||||||
{"add-flat-binary", "f:n:l:e:c:b:h?", cbfs_add_flat_binary},
|
{"add-flat-binary", "f:n:l:e:c:b:h?", cbfs_add_flat_binary},
|
||||||
{"remove", "n:h?", cbfs_remove},
|
{"remove", "n:h?", cbfs_remove},
|
||||||
{"create", "s:B:a:o:h?", cbfs_create},
|
{"create", "s:B:a:o:m:h?", cbfs_create},
|
||||||
{"locate", "f:n:a:h?", cbfs_locate},
|
{"locate", "f:n:a:h?", cbfs_locate},
|
||||||
{"print", "h?", cbfs_print},
|
{"print", "h?", cbfs_print},
|
||||||
{"extract", "n:f:h?", cbfs_extract},
|
{"extract", "n:f:h?", cbfs_extract},
|
||||||
|
@ -468,6 +474,7 @@ static struct option long_options[] = {
|
||||||
{"alignment", required_argument, 0, 'a' },
|
{"alignment", required_argument, 0, 'a' },
|
||||||
{"offset", required_argument, 0, 'o' },
|
{"offset", required_argument, 0, 'o' },
|
||||||
{"file", required_argument, 0, 'f' },
|
{"file", required_argument, 0, 'f' },
|
||||||
|
{"arch", required_argument, 0, 'm' },
|
||||||
{"verbose", no_argument, 0, 'v' },
|
{"verbose", no_argument, 0, 'v' },
|
||||||
{"help", no_argument, 0, 'h' },
|
{"help", no_argument, 0, 'h' },
|
||||||
{NULL, 0, 0, 0 }
|
{NULL, 0, 0, 0 }
|
||||||
|
@ -492,7 +499,7 @@ static void usage(char *name)
|
||||||
"Add a 32bit flat mode binary\n"
|
"Add a 32bit flat mode binary\n"
|
||||||
" remove -n NAME "
|
" remove -n NAME "
|
||||||
"Remove a component\n"
|
"Remove a component\n"
|
||||||
" create -s size -B bootblock [-a align] [-o offset] "
|
" create -s size -B bootblock -m ARCH [-a align] [-o offset] "
|
||||||
"Create a ROM file\n"
|
"Create a ROM file\n"
|
||||||
" locate -f FILE -n NAME -a align "
|
" locate -f FILE -n NAME -a align "
|
||||||
"Find a place for a file of that size\n"
|
"Find a place for a file of that size\n"
|
||||||
|
@ -501,6 +508,8 @@ static void usage(char *name)
|
||||||
" extract -n NAME -f FILE "
|
" extract -n NAME -f FILE "
|
||||||
"Extracts a raw payload from ROM\n"
|
"Extracts a raw payload from ROM\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
"ARCHes:\n"
|
||||||
|
" armv7, x86\n"
|
||||||
"TYPEs:\n", name, name
|
"TYPEs:\n", name, name
|
||||||
);
|
);
|
||||||
print_supported_filetypes();
|
print_supported_filetypes();
|
||||||
|
@ -610,6 +619,9 @@ int main(int argc, char **argv)
|
||||||
case 'v':
|
case 'v':
|
||||||
verbose++;
|
verbose++;
|
||||||
break;
|
break;
|
||||||
|
case 'm':
|
||||||
|
arch = string_to_arch(optarg);
|
||||||
|
break;
|
||||||
case 'h':
|
case 'h':
|
||||||
case '?':
|
case '?':
|
||||||
usage(argv[0]);
|
usage(argv[0]);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
*
|
*
|
||||||
* Copyright (C) 2009 coresystems GmbH
|
* Copyright (C) 2009 coresystems GmbH
|
||||||
* written by Patrick Georgi <patrick.georgi@coresystems.de>
|
* written by Patrick Georgi <patrick.georgi@coresystems.de>
|
||||||
|
* Copyright (C) 2012 Google, Inc.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -73,16 +74,101 @@ static struct cbfs_header *master_header;
|
||||||
static uint32_t phys_start, phys_end, align;
|
static uint32_t phys_start, phys_end, align;
|
||||||
uint32_t romsize;
|
uint32_t romsize;
|
||||||
void *offset;
|
void *offset;
|
||||||
|
uint32_t arch = CBFS_ARCHITECTURE_UNKNOWN;
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
uint32_t arch;
|
||||||
|
const char *name;
|
||||||
|
} arch_names[] = {
|
||||||
|
{ CBFS_ARCHITECTURE_ARMV7, "armv7" },
|
||||||
|
{ CBFS_ARCHITECTURE_X86, "x86" },
|
||||||
|
{ CBFS_ARCHITECTURE_UNKNOWN, "unknown" }
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t string_to_arch(const char *arch_string)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
uint32_t ret = CBFS_ARCHITECTURE_UNKNOWN;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(arch_names); i++) {
|
||||||
|
if (!strcasecmp(arch_string, arch_names[i].name)) {
|
||||||
|
ret = arch_names[i].arch;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *arch_to_string(uint32_t a)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
const char *ret = NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(arch_names); i++) {
|
||||||
|
if (a == arch_names[i].arch) {
|
||||||
|
ret = arch_names[i].name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int find_master_header(void *romarea, size_t size)
|
||||||
|
{
|
||||||
|
size_t offset;
|
||||||
|
|
||||||
|
if (master_header)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (offset = 0; offset < size - sizeof(struct cbfs_header); offset++) {
|
||||||
|
struct cbfs_header *tmp = romarea + offset;
|
||||||
|
|
||||||
|
if (tmp->magic == ntohl(CBFS_HEADER_MAGIC)) {
|
||||||
|
master_header = tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return master_header ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
void recalculate_rom_geometry(void *romarea)
|
void recalculate_rom_geometry(void *romarea)
|
||||||
{
|
{
|
||||||
|
if (find_master_header(romarea, romsize)) {
|
||||||
|
fprintf(stderr, "E: Cannot find master header\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update old headers */
|
||||||
|
if (master_header->version == VERSION1 &&
|
||||||
|
ntohl(master_header->architecture) == CBFS_ARCHITECTURE_UNKNOWN) {
|
||||||
|
printf("Updating CBFS master header to version 2\n");
|
||||||
|
master_header->architecture = htonl(CBFS_ARCHITECTURE_X86);
|
||||||
|
}
|
||||||
|
|
||||||
|
arch = ntohl(master_header->architecture);
|
||||||
|
|
||||||
|
switch (arch) {
|
||||||
|
case CBFS_ARCHITECTURE_ARMV7:
|
||||||
|
offset = romarea;
|
||||||
|
phys_start = (0 + ntohl(master_header->offset)) & 0xffffffff;
|
||||||
|
phys_end = romsize & 0xffffffff;
|
||||||
|
break;
|
||||||
|
case CBFS_ARCHITECTURE_X86:
|
||||||
offset = romarea + romsize - 0x100000000ULL;
|
offset = romarea + romsize - 0x100000000ULL;
|
||||||
master_header = (struct cbfs_header *)
|
phys_start = (0 - romsize + ntohl(master_header->offset)) &
|
||||||
phys_to_virt(*((uint32_t *) phys_to_virt(0xfffffffc)));
|
0xffffffff;
|
||||||
phys_start = (0 - romsize + ntohl(master_header->offset)) & 0xffffffff;
|
phys_end = (0 - ntohl(master_header->bootblocksize) -
|
||||||
phys_end =
|
|
||||||
(0 - ntohl(master_header->bootblocksize) -
|
|
||||||
sizeof(struct cbfs_header)) & 0xffffffff;
|
sizeof(struct cbfs_header)) & 0xffffffff;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
fprintf(stderr, "E: Unknown architecture\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
align = ntohl(master_header->align);
|
align = ntohl(master_header->align);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +200,7 @@ int writerom(const char *filename, void *start, uint32_t size)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cbfs_file_header(uint32_t physaddr)
|
int cbfs_file_header(unsigned long physaddr)
|
||||||
{
|
{
|
||||||
/* maybe improve this test */
|
/* maybe improve this test */
|
||||||
return (strncmp(phys_to_virt(physaddr), "LARCHIVE", 8) == 0);
|
return (strncmp(phys_to_virt(physaddr), "LARCHIVE", 8) == 0);
|
||||||
|
@ -188,9 +274,10 @@ uint64_t intfiletype(const char *name)
|
||||||
void print_cbfs_directory(const char *filename)
|
void print_cbfs_directory(const char *filename)
|
||||||
{
|
{
|
||||||
printf
|
printf
|
||||||
("%s: %d kB, bootblocksize %d, romsize %d, offset 0x%x\nAlignment: %d bytes\n\n",
|
("%s: %d kB, bootblocksize %d, romsize %d, offset 0x%x\n"
|
||||||
|
"Alignment: %d bytes, architecture: %s\n\n",
|
||||||
basename((char *)filename), romsize / 1024, ntohl(master_header->bootblocksize),
|
basename((char *)filename), romsize / 1024, ntohl(master_header->bootblocksize),
|
||||||
romsize, ntohl(master_header->offset), align);
|
romsize, ntohl(master_header->offset), align, arch_to_string(arch));
|
||||||
printf("%-30s %-10s %-12s Size\n", "Name", "Offset", "Type");
|
printf("%-30s %-10s %-12s Size\n", "Name", "Offset", "Type");
|
||||||
uint32_t current = phys_start;
|
uint32_t current = phys_start;
|
||||||
while (current < phys_end) {
|
while (current < phys_end) {
|
||||||
|
@ -206,8 +293,8 @@ void print_cbfs_directory(const char *filename)
|
||||||
fname = "(empty)";
|
fname = "(empty)";
|
||||||
|
|
||||||
printf("%-30s 0x%-8x %-12s %d\n", fname,
|
printf("%-30s 0x%-8x %-12s %d\n", fname,
|
||||||
current - phys_start, strfiletype(ntohl(thisfile->type)),
|
current - phys_start + ntohl(master_header->offset),
|
||||||
length);
|
strfiletype(ntohl(thisfile->type)), length);
|
||||||
current =
|
current =
|
||||||
ALIGN(current + ntohl(thisfile->len) +
|
ALIGN(current + ntohl(thisfile->len) +
|
||||||
ntohl(thisfile->offset), align);
|
ntohl(thisfile->offset), align);
|
||||||
|
@ -466,9 +553,6 @@ int create_cbfs_image(const char *romfile, uint32_t _romsize,
|
||||||
}
|
}
|
||||||
memset(romarea, 0xff, romsize);
|
memset(romarea, 0xff, romsize);
|
||||||
|
|
||||||
// Set up physical/virtual mapping
|
|
||||||
offset = romarea + romsize - 0x100000000ULL;
|
|
||||||
|
|
||||||
if (align == 0)
|
if (align == 0)
|
||||||
align = 64;
|
align = 64;
|
||||||
|
|
||||||
|
@ -481,16 +565,68 @@ int create_cbfs_image(const char *romfile, uint32_t _romsize,
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
master_header =
|
// TODO(hungte) Replace magic numbers by named constants.
|
||||||
(struct cbfs_header *)(romarea + romsize - bootblocksize -
|
switch (arch) {
|
||||||
sizeof(struct cbfs_header));
|
case CBFS_ARCHITECTURE_ARMV7:
|
||||||
master_header->magic = ntohl(0x4f524243);
|
/* Set up physical/virtual mapping */
|
||||||
master_header->version = ntohl(0x31313131);
|
offset = romarea;
|
||||||
|
|
||||||
|
// should be aligned to align but then we need to dynamically
|
||||||
|
// create the jump to the bootblock
|
||||||
|
loadfile(bootblock, &bootblocksize, romarea + 0x20 +
|
||||||
|
sizeof(struct cbfs_header), SEEK_SET);
|
||||||
|
master_header = (struct cbfs_header *)(romarea + 0x20);
|
||||||
|
uint32_t *arm_vec = (uint32_t *)romarea;
|
||||||
|
/*
|
||||||
|
* Encoding for this branch instruction is:
|
||||||
|
* 31:28 - condition (0xe for always/unconditional)
|
||||||
|
* 27:24 - 0xa
|
||||||
|
* 23: 0 - sign-extended offset (in multiples of 4)
|
||||||
|
*
|
||||||
|
* When executing the branch, the PC will read as the address
|
||||||
|
* of current instruction + 8.
|
||||||
|
*/
|
||||||
|
arm_vec[0] = htonl(0x0e0000ea); // branch to . + 64 bytes
|
||||||
|
|
||||||
|
master_header->magic = ntohl(CBFS_HEADER_MAGIC);
|
||||||
|
master_header->version = ntohl(VERSION);
|
||||||
|
master_header->romsize = htonl(romsize);
|
||||||
|
master_header->bootblocksize = htonl(bootblocksize);
|
||||||
|
master_header->align = htonl(align);
|
||||||
|
master_header->offset = htonl(
|
||||||
|
ALIGN((0x40 + bootblocksize), align));
|
||||||
|
master_header->architecture = htonl(CBFS_ARCHITECTURE_ARMV7);
|
||||||
|
|
||||||
|
((uint32_t *) phys_to_virt(0x4))[0] =
|
||||||
|
virt_to_phys(master_header);
|
||||||
|
|
||||||
|
recalculate_rom_geometry(romarea);
|
||||||
|
|
||||||
|
cbfs_create_empty_file(
|
||||||
|
ALIGN((0x40 + bootblocksize), align),
|
||||||
|
romsize - ALIGN((bootblocksize + 0x40), align)
|
||||||
|
//- sizeof(struct cbfs_header)
|
||||||
|
- sizeof(struct cbfs_file) );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CBFS_ARCHITECTURE_X86:
|
||||||
|
// Set up physical/virtual mapping
|
||||||
|
offset = romarea + romsize - 0x100000000ULL;
|
||||||
|
|
||||||
|
loadfile(bootblock, &bootblocksize, romarea + romsize,
|
||||||
|
SEEK_END);
|
||||||
|
master_header = (struct cbfs_header *)(romarea + romsize -
|
||||||
|
bootblocksize - sizeof(struct cbfs_header));
|
||||||
|
|
||||||
|
master_header->magic = ntohl(CBFS_HEADER_MAGIC);
|
||||||
|
master_header->version = ntohl(VERSION);
|
||||||
master_header->romsize = htonl(romsize);
|
master_header->romsize = htonl(romsize);
|
||||||
master_header->bootblocksize = htonl(bootblocksize);
|
master_header->bootblocksize = htonl(bootblocksize);
|
||||||
master_header->align = htonl(align);
|
master_header->align = htonl(align);
|
||||||
master_header->offset = htonl(offs);
|
master_header->offset = htonl(offs);
|
||||||
((uint32_t *) phys_to_virt(0xfffffffc))[0] =
|
master_header->architecture = htonl(CBFS_ARCHITECTURE_X86);
|
||||||
|
|
||||||
|
((uint32_t *) phys_to_virt(CBFS_HEADPTR_ADDR_X86))[0] =
|
||||||
virt_to_phys(master_header);
|
virt_to_phys(master_header);
|
||||||
|
|
||||||
recalculate_rom_geometry(romarea);
|
recalculate_rom_geometry(romarea);
|
||||||
|
@ -499,6 +635,13 @@ int create_cbfs_image(const char *romfile, uint32_t _romsize,
|
||||||
romsize - offs - bootblocksize -
|
romsize - offs - bootblocksize -
|
||||||
sizeof(struct cbfs_header) -
|
sizeof(struct cbfs_header) -
|
||||||
sizeof(struct cbfs_file) - 16);
|
sizeof(struct cbfs_file) - 16);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Should not happen.
|
||||||
|
fprintf(stderr, "E: You found a bug in cbfstool.\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
writerom(romfile, romarea, romsize);
|
writerom(romfile, romarea, romsize);
|
||||||
free(romarea);
|
free(romarea);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2009 coresystems GmbH
|
* Copyright (C) 2009 coresystems GmbH
|
||||||
* written by Patrick Georgi <patrick.georgi@coresystems.de>
|
* written by Patrick Georgi <patrick.georgi@coresystems.de>
|
||||||
|
* Copyright (C) 2012 Google, Inc.
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* 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
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
@ -29,6 +30,10 @@
|
||||||
extern void *offset;
|
extern void *offset;
|
||||||
extern uint32_t romsize;
|
extern uint32_t romsize;
|
||||||
extern int host_bigendian;
|
extern int host_bigendian;
|
||||||
|
extern uint32_t arch;
|
||||||
|
|
||||||
|
const char *arch_to_string(uint32_t a);
|
||||||
|
uint32_t string_to_arch(const char *arch_string);
|
||||||
|
|
||||||
static inline void *phys_to_virt(uint32_t addr)
|
static inline void *phys_to_virt(uint32_t addr)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue