Patchwork cbfs locate function

login
register
about
Submitter Patrick Georgi
Date 2009-10-15 22:56:25
Message ID <1255647385.30349.29.camel@tetris>
Download mbox | patch
Permalink /patch/411/
State Accepted
Commit r4929
Headers show

Comments

Patrick Georgi - 2009-10-15 22:56:25
Hi,

attached patch adds a "locate" function cbfstool, which helps you find
out a suitable address to put a XIP stage to.

Specifically, you pass it the file (to get its filesize), its filename
(as the header has a variable length that depends on it), and the
granularity requirement it has to fit in (for XIP).
The granularity is MTRR-style: when you request 0x10000, cbfstool looks
for a suitable place in a 64kb-aligned 64kb block.

cbfstool simply prints out a hex value which is the start address of a
suitably located free memory block. That value can then be used with
cbfs add-stage to store the file in the ROM image.

I need this function for my "newfailover" project, which will push most
of the current bootblock code into CBFS (everything but enable_rom).

It's a two-step operation (instead of being merged into cbfs add-stage)
because the image must be linked twice: First, with some bogus, but safe
base address (eg. 0) to figure out the target address (based on file
size). Then a second time at the target address.
The approximative code flow is: link file, cbfstool locate, link file
again, cbfstool add-stage.

I'm not quite sure about the failure modes yet, so all it does for now
is returning an address of "0" if no suitable place could be found.
Maybe returning "1" is a better idea, as "0" is the value used when
cbfstool add-stage can freely choose the location. "1" should already
lead to an error.


Signed-off-by: Patrick Georgi <patrick.georgi@coresystems.de>


Patrick
Patrick Georgi - 2009-11-09 16:54:37
Am 16.10.2009 00:56, schrieb Patrick Georgi:
> attached patch adds a "locate" function cbfstool, which helps you find
> out a suitable address to put a XIP stage to.
>    
*ping*


Patrick
Stefan Reinauer - 2009-11-09 17:00:20
Patrick Georgi wrote:
> Hi,
>
> attached patch adds a "locate" function cbfstool, which helps you find
> out a suitable address to put a XIP stage to.
>
> Specifically, you pass it the file (to get its filesize), its filename
> (as the header has a variable length that depends on it), and the
> granularity requirement it has to fit in (for XIP).
> The granularity is MTRR-style: when you request 0x10000, cbfstool looks
> for a suitable place in a 64kb-aligned 64kb block.
>
> cbfstool simply prints out a hex value which is the start address of a
> suitably located free memory block. That value can then be used with
> cbfs add-stage to store the file in the ROM image.
>
> I need this function for my "newfailover" project, which will push most
> of the current bootblock code into CBFS (everything but enable_rom).
>
> It's a two-step operation (instead of being merged into cbfs add-stage)
> because the image must be linked twice: First, with some bogus, but safe
> base address (eg. 0) to figure out the target address (based on file
> size). Then a second time at the target address.
> The approximative code flow is: link file, cbfstool locate, link file
> again, cbfstool add-stage.
>
> I'm not quite sure about the failure modes yet, so all it does for now
> is returning an address of "0" if no suitable place could be found.
> Maybe returning "1" is a better idea, as "0" is the value used when
> cbfstool add-stage can freely choose the location. "1" should already
> lead to an error.
>
>
> Signed-off-by: Patrick Georgi <patrick.georgi@coresystems.de>
>   
We need a new and working failover..

Acked-by: Stefan Reinauer <stepan@coresystems.de>

Patch

Index: util/cbfstool/common.c
===================================================================
--- util/cbfstool/common.c	(Revision 4779)
+++ util/cbfstool/common.c	(Arbeitskopie)
@@ -27,6 +27,16 @@ 
 
 #define dprintf
 
+uint32_t getfilesize(const char *filename)
+{
+	uint32_t size;
+	FILE *file = fopen(filename, "rb");
+	fseek(file, 0, SEEK_END);
+	size = ftell(file);
+	fclose(file);
+	return size;
+}
+
 void *loadfile(const char *filename, uint32_t * romsize_p, void *content,
 	       int place)
 {
@@ -323,3 +333,58 @@ 
 	writerom(romfile, romarea, romsize);
 	return 0;
 }
+
+static int in_segment(int addr, int size, int gran)
+{
+	return ((addr & ~(gran - 1)) == ((addr + size) & ~(gran - 1)));
+}
+
+uint32_t cbfs_find_location(const char *romfile, uint32_t filesize,
+			    const char *filename, uint32_t alignment)
+{
+	void *rom = loadrom(romfile);
+	int filename_size = strlen(filename);
+
+	int headersize =
+	    sizeof(struct cbfs_file) + ALIGN(filename_size + 1,
+					     16) + sizeof(struct cbfs_stage);
+	int totalsize = headersize + filesize;
+
+	uint32_t current = phys_start;
+	while (current < phys_end) {
+		if (!cbfs_file_header(current)) {
+			current += align;
+			continue;
+		}
+		struct cbfs_file *thisfile =
+		    (struct cbfs_file *)phys_to_virt(current);
+
+		uint32_t top =
+		    current + ntohl(thisfile->len) + ntohl(thisfile->offset);
+		if (((ntohl(thisfile->type) == 0x0)
+		     || (ntohl(thisfile->type) == 0xffffffff))
+		    && (ntohl(thisfile->len) + ntohl(thisfile->offset) >=
+			totalsize)) {
+			if (in_segment
+			    (current + headersize, filesize, alignment))
+				return current + headersize;
+			if ((ALIGN(current, alignment) + filesize < top)
+			    && (ALIGN(current, alignment) - headersize >
+				current)
+			    && in_segment(ALIGN(current, alignment), filesize,
+					  alignment))
+				return ALIGN(current, alignment);
+			if ((ALIGN(current, alignment) + alignment + filesize <
+			     top)
+			    && (ALIGN(current, alignment) + alignment -
+				headersize > current)
+			    && in_segment(ALIGN(current, alignment) + alignment,
+					  filesize, alignment))
+				return ALIGN(current, alignment) + alignment;
+		}
+		current =
+		    ALIGN(current + ntohl(thisfile->len) +
+			  ntohl(thisfile->offset), align);
+	}
+	return 0;
+}
Index: util/cbfstool/cbfstool.c
===================================================================
--- util/cbfstool/cbfstool.c	(Revision 4779)
+++ util/cbfstool/cbfstool.c	(Arbeitskopie)
@@ -28,6 +28,7 @@ 
 	CMD_ADD_PAYLOAD,
 	CMD_ADD_STAGE,
 	CMD_CREATE,
+	CMD_LOCATE,
 	CMD_PRINT
 } cmd_t;
 
@@ -78,8 +79,7 @@ 
 	if (argc > 6) {
 		base = strtoul(argv[6], NULL, 0);
 	}
-	cbfsfile =
-	    create_cbfs_file(cbfsname, filedata, &filesize, type, &base);
+	cbfsfile = create_cbfs_file(cbfsname, filedata, &filesize, type, &base);
 	if (add_file_to_cbfs(cbfsfile, filesize, base))
 		return 1;
 	writerom(romname, rom, romsize);
@@ -203,6 +203,23 @@ 
 	return create_cbfs_image(romname, size, bootblock, align);
 }
 
+static int cbfs_locate(int argc, char **argv)
+{
+	char *romname = argv[1];
+	if (argc < 6) {
+		printf("not enough arguments to 'locate'.\n");
+		return 1;
+	}
+
+	const char *file = argv[3];
+	uint32_t filesize = getfilesize(file);
+	const char *filename = argv[4];
+	int align = strtoul(argv[5], NULL, 0);
+
+	printf("%x\n", cbfs_find_location(romname, filesize, filename, align));
+	return 0;
+}
+
 static int cbfs_print(int argc, char **argv)
 {
 	char *romname = argv[1];
@@ -223,6 +240,7 @@ 
 	{CMD_ADD_PAYLOAD, "add-payload", cbfs_add_payload},
 	{CMD_ADD_STAGE, "add-stage", cbfs_add_stage},
 	{CMD_CREATE, "create", cbfs_create},
+	{CMD_LOCATE, "locate", cbfs_locate},
 	{CMD_PRINT, "print", cbfs_print}
 };
 
@@ -238,6 +256,7 @@ 
 	     "add-payload FILE NAME [COMP] [base]  Add a payload to the ROM\n"
 	     "add-stage FILE NAME [COMP] [base]    Add a stage to the ROM\n"
 	     "create SIZE BSIZE BOOTBLOCK [ALIGN]  Create a ROM file\n"
+	     "locate FILE NAME ALIGN               Find a place for a file of that size\n"
 	     "print                                Show the contents of the ROM\n");
 }
 
Index: util/cbfstool/common.h
===================================================================
--- util/cbfstool/common.h	(Revision 4779)
+++ util/cbfstool/common.h	(Arbeitskopie)
@@ -34,6 +34,7 @@ 
 
 #define ALIGN(val, by) (((val) + (by)-1)&~((by)-1))
 
+uint32_t getfilesize(const char *filename);
 void *loadfile(const char *filename, uint32_t * romsize_p, void *content,
 	       int place);
 void *loadrom(const char *filename);
@@ -62,4 +63,7 @@ 
 int add_file_to_cbfs(void *content, uint32_t contentsize, uint32_t location);
 void print_cbfs_directory(const char *filename);
 
+uint32_t cbfs_find_location(const char *romfile, uint32_t filesize,
+			    const char *filename, uint32_t align);
+
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))