summaryrefslogtreecommitdiff
path: root/cleopatre/u-boot-1.1.6/common
diff options
context:
space:
mode:
authordraskovic2009-07-16 15:44:03 +0000
committerdraskovic2009-07-16 15:44:03 +0000
commit69f005d9f0ae5ac843c4896b44b31a5171f91e34 (patch)
tree75b9f011d4aafe33389adf1e63bb189630372434 /cleopatre/u-boot-1.1.6/common
parentc0c1b9723c0a6654349f937bc3fc084a88b84130 (diff)
[CLEO][U-BOOT] Added multiboot support. Number of images is now read from nvram.
git-svn-id: svn+ssh://pessac/svn/cesar/trunk@4997 017c9cb6-072f-447c-8318-d5b54f68fe89
Diffstat (limited to 'cleopatre/u-boot-1.1.6/common')
-rw-r--r--cleopatre/u-boot-1.1.6/common/cmd_spidboot.c309
1 files changed, 125 insertions, 184 deletions
diff --git a/cleopatre/u-boot-1.1.6/common/cmd_spidboot.c b/cleopatre/u-boot-1.1.6/common/cmd_spidboot.c
index 29139c2788..f94178489e 100644
--- a/cleopatre/u-boot-1.1.6/common/cmd_spidboot.c
+++ b/cleopatre/u-boot-1.1.6/common/cmd_spidboot.c
@@ -52,6 +52,10 @@ extern flash_info_t flash_info[]; /* info for SPI FLASH chip */
#define IMG_0_ADDR (char *)0x00140000
#define IMG_1_ADDR (char *)0x004a0000
+#define MAX_IMG 10 /* supported num of images */
+static unsigned long img_addr[MAX_IMG] = {0};
+static spidcom_image_desc_t img_desc[MAX_IMG];
+
#define LINUX_LOAD_ADDR (char *)0x40008000
#define BAD_MAGIC_NUMBER 1
@@ -61,10 +65,7 @@ extern flash_info_t flash_info[]; /* info for SPI FLASH chip */
#define WRONG_IMAGE_TYPE 5
#define UPD_NOT_FINISHED 6
#define IMAGE_OK 7
-
-
-static spidcom_image_desc_t img_0_desc; /* in single-boot mode we use just img_0_desc */
-static spidcom_image_desc_t img_1_desc; /* needed for dual-boot mode */
+#define NO_VALID_IMAGE 8
/* Util functions */
#if defined (CONFIG_SETUP_MEMORY_TAGS) || \
@@ -187,33 +188,6 @@ static void setup_end_tag (bd_t *bd)
#endif /* CONFIG_SETUP_MEMORY_TAGS || CONFIG_CMDLINE_TAG || CONFIG_INITRD_TAG */
-static int
-find_nb_images (bd_t *bd)
-{
- flash_info_t * flinfo = &( flash_info[0] ); /* we expect HW to have only one flash, thus only one flinfo */
- spc300_nvram_t *nvram = NULL;
- uint32_t nb_images = 0;
-
- nvram = (spc300_nvram_t *)(gd->bd->bi_nvram_addr);
- if ( nvram == NULL )
- {
- printf ("Error : NVRAM not found in flash.\n");
- return 0;
- }
- printf("sizeof(nb_images) = %d\n", sizeof(nb_images) );
-
- /* read begining of the sector in local array variable */
- if ( flash_read_spi ( (unsigned char *)( &(nvram->nb_images) ), (unsigned char *)(&nb_images), sizeof(nb_images), 1, 0) != ERR_OK )
- {
- printf("ERROR : read from SPI flash failed.\n");
- return 0;
- }
-
- //printf("nb_images = %d (NVRAM at addr %#x)\n", (int)nb_images, nvram);
-
- return (int)nb_images;
-}
-
static void
print_img_desc (spidcom_image_desc_t *hdr)
{
@@ -296,7 +270,7 @@ static int load_header(spidcom_image_desc_t *desc, char *addr)
}
}
-static int check_img(spidcom_image_desc_t *desc)
+static int check_img(spidcom_image_desc_t *desc, char *addr)
{
if ( strcmp(desc->magic, SPIDCOM_IMG_DESC_MAGIC) )
{
@@ -345,25 +319,14 @@ static int check_img(spidcom_image_desc_t *desc)
/* image is corrupted : invalidate it !!! */
if(desc->is_valid)
{
- char *dest = NULL;
-
printf("Previous boot failed: set image as invalid\n");
desc->is_valid = 0;
- /* find a correct dest addr... */
- if (desc == &img_0_desc)
- {
- dest = IMG_0_ADDR;
- }
- else
- {
- dest = IMG_1_ADDR;
- }
- /* ..and write back to flash.
- * Replacing 1s with 0s is allowed without erase.
+
+ /* Replacing 1s with 0s is allowed without erase.
* We will write whole structure (it is allowed to write unchanged parts,
* just transition 0->1 is impossible without erase
*/
- flash_write( (char *)desc, (ulong)dest, sizeof(spidcom_image_desc_t) );
+ flash_write( (char *)desc, (ulong)addr, sizeof(spidcom_image_desc_t) );
}
return IMAGE_NOT_VALID;
}
@@ -372,89 +335,113 @@ static int check_img(spidcom_image_desc_t *desc)
return IMAGE_OK;
}
-static int select_image(void)
+static int select_image(int img_nb)
{
- int sel_img = 0; /* will hold the nb of selected image */
- int img0_state = 0;
- int img1_state = 0;
- int upd_state = 0;
-
- spidcom_image_desc_t *desc0 = &img_0_desc;
- spidcom_image_desc_t *desc1 = &img_1_desc;
-
- load_header(desc0, IMG_0_ADDR);
- load_header(desc1, IMG_1_ADDR);
+ int sel_img = -1; /* will hold the index of selected image */
+ spidcom_image_desc_t *desc[MAX_IMG];
+ int img_state[MAX_IMG] = {0};
+ int max_index = 0;
+ int i;
- if ( (img0_state = check_img(desc0)) != IMAGE_OK )
+ for (i=0; i<img_nb; i++)
{
- puts ("IMG_0 is not OK.\n");
- if ( (img1_state = check_img(desc1)) != IMAGE_OK )
+ desc[i] = &img_desc[i];
+ load_header(desc[i], (char *)img_addr[i]);
+ img_state[i] = check_img(desc[i], (char *)img_addr[i]);
+
+ if (img_state[i] == IMAGE_OK)
{
- /*
- * Both images are corrupted - we have no bootable image.
- * Launch the update procedure (which will always in the case
- * when there is none image put the new image on IMG_0 addr,
- * so we can use desc0 pointer to approach new image)
- */
- /* which image will be updated? */
- if (img0_state == BAD_MAGIC_NUMBER)
+ if (desc[i]->index >= max_index)
{
- /* there is no IMG_0 => we will be writing here */
- sel_img = 0;
+ max_index = desc[i]->index;
+ sel_img = i;
}
- else /* IMG_0 exists */
- {
- if (img1_state == BAD_MAGIC_NUMBER)
- {
- /* there is no IMG_1 => we will be writing here */
- sel_img = 1;
- }
- else /* both images exist */
- {
- sel_img = desc0->index > desc1->index ? 0 : 1;
- }
- }
- do
- {
- do_spidupd();
- switch (sel_img)
- {
- case 0:
- load_header(desc0, IMG_0_ADDR);
- upd_state = check_img(desc0);
- break;
- case 1:
- load_header(desc1, IMG_1_ADDR);
- upd_state = check_img(desc1);
- break;
- }
- } while ( upd_state != IMAGE_OK );
- }
- else /* IMG_1 is OK */
- {
- /* take IMG_1, the only good image */
- puts ("IMG_1 is OK. Selecting IMG_1.\n");
- sel_img = 1;
}
}
- else /* IMG_0 is OK */
+
+ return sel_img;
+}
+
+static int
+find_nb_images (void)
+{
+ spc300_nvram_t *nvram = NULL;
+ uint32_t nb_images = 0;
+
+ nvram = (spc300_nvram_t *)(gd->bd->bi_nvram_addr);
+ if ( nvram == NULL )
{
- puts ("IMG_0 is OK.\n");
- if ( check_img(desc1) != IMAGE_OK )
+ printf ("Error : NVRAM not found in flash.\n");
+ return 0;
+ }
+ printf("sizeof(nb_images) = %d\n", sizeof(nb_images) );
+
+ /* read begining of the sector in local array variable */
+ if ( flash_read_spi ( (unsigned char *)( &(nvram->nb_images) ), (unsigned char *)(&nb_images), sizeof(nb_images), 1, 0) != ERR_OK )
+ {
+ printf("ERROR : read from SPI flash failed.\n");
+ return 0;
+ }
+
+ //printf("nb_images = %d (NVRAM at addr %#x)\n", (int)nb_images, nvram);
+
+ return (int)nb_images;
+}
+
+int
+find_images(int img_nb)
+{
+ flash_info_t * flinfo = &( flash_info[0] ); /* we expect HW to have only one flash, thus only one flinfo */
+ char img_magic[8]; /* to match with magic number = "SPIDIMG\0" */
+ int i = 0;
+ int start = 0;
+ spc300_nvram_t *nvram = NULL;
+ int sect = 0;
+
+ nvram = (spc300_nvram_t *)(gd->bd->bi_nvram_addr);
+ if ( nvram == NULL )
+ {
+ printf ("Error : NVRAM not found in flash.\n");
+ return -1;
+ }
+
+
+ /* search for the "SPIDIMG\0" string on the begining of the each sector */
+ for (sect=0; sect < flinfo->sector_count; ++sect)
+ {
+ if (flinfo->start[sect] < nvram->img_0_offset)
+ continue;
+
+ /* read begining of the sector in local array variable */
+ if ( flash_read_spi ((unsigned char *)flinfo->start[sect], (unsigned char *)img_magic, 8, 1, 0) != ERR_OK )
+ {
+ printf("ERROR : read from SPI flash failed.\n");
+ return -1;
+ }
+ /* compare this with magic word (for SPC300 that is "SPIDIMG\0") */
+ if ( memcmp( img_magic, SPIDCOM_IMG_DESC_MAGIC, 8 ) != 0 )
{
- /* IMG_1 is not OK, so we do not have to compare indexes,
- * we automatically take IMG_0, the only good image */
- puts ("IMG_1 is not OK - selecting IMG_0.\n");
- sel_img = 0;
+ continue;
}
- else /* both images are OK => compare the indexes */
+ else
{
- sel_img = desc0->index > desc1->index ? 0 : 1;
- printf ("IMG_%d selected.\n", sel_img);
+ /* found it! */
+ img_addr[i] = flinfo->start[sect];
+
+#ifndef CONFIG_EXEC_FROM_SPI
+ img_addr[i] -= 0x78000000; /* FCM3 fix when executed from Flash NOR -- remove later!!! */
+#endif /* CONFIG_EXEC_FROM_SPI */
+
+ printf ("FOUND image %d at address %#x\n", i, img_addr[i]);
+ i++; /* number of images found, and index for next image */
+
+ /* check if we found all images */
+ if (i == img_nb)
+ {
+ return i;
+ }
}
- }
-
- return sel_img;
+ } /* for */
}
int do_spidboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
@@ -468,9 +455,10 @@ int do_spidboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
void (*appl)(int zero, int arch, uint params);
spidcom_image_desc_t *hdr = NULL;
int use_spi_flash = 0;
- int dual_boot = 0; /* marks if we are in the single or dual boot mode */
char *img_load_addr = NULL;
bd_t *bd = gd->bd;
+ int img_nb = 0;
+ int sel_img = -1; /* image selected for boot after all the checks */
#ifdef CONFIG_CMDLINE_TAG
char *commandline = getenv ("bootargs");
@@ -482,73 +470,36 @@ int do_spidboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
s = getenv ("verify");
verify = (s && (*s == 'n')) ? 0 : 1;
- if (argc < 2)
- {
-#ifdef SPC300_NVRAM
- /* read mb_images from NVRAM */
- if (find_nb_images(bd) == 2)
- {
- dual_boot = 1;
- }
- else
- {
- dual_boot = 0;
- }
-#else
- /* no NVRAM and only command spidbootm is given, no address =>
- * we are in the dual boot mode */
- dual_boot = 1;
+ img_nb = find_nb_images();
+ if (argc < 2) /* no address was given - normal multiboot */
+ {
/* give a chance of 1sec tomeout for user to initiate the update */
do_spidupd();
-#endif /* SPC300_NVRAM */
+ find_images(img_nb);
+ sel_img = select_image(img_nb);
+ while(sel_img < 0)
+ {
+ do_spidupd();
+ sel_img = select_image(img_nb);
+ }
+
+ addr = img_addr[sel_img];
+ hdr = &img_desc[sel_img];
}
else
{
- find_nb_images(bd); // to be suppressed
/* address was given, so we want to boot this exact image =>
* we are in the single boot mode;
* we are also in developer mode, trying to force the boot of
* chosen image => we will not call do_update() here */
- dual_boot = 0;
addr = simple_strtoul(argv[1], NULL, 16);
- }
-
- if (dual_boot)
- {
- switch ( select_image() )
- {
- case 0:
- addr = (ulong)IMG_0_ADDR;
- hdr = &img_0_desc;
- break;
- case 1:
- addr = (ulong)IMG_1_ADDR;
- hdr = &img_1_desc;
- break;
- default:
- puts ("Boot aborted.\n");
- return 1;
- }
- }
- else /* single boot mode */
- {
- hdr = &img_0_desc; /* we will use img_0_desc structure for single boot */
+ hdr = &img_desc[0]; /* we will use img_0_desc structure for single boot */
load_header(hdr, (char *)addr);
- if (argc < 2)
- {
- if ( check_img(hdr) != IMAGE_OK )
- {
- puts("Image corrupted - boot aborted.\n");
- return 1;
- }
- }
- else
- {
- /* do nothing - we are in developer mode, trying to force boot of
- * selected image => we will not check it's validity */
- }
+
+ /* do no checking - we are in developer mode, trying to force boot of
+ * selected image => we will not check it's validity */
}
printf ("## Booting image at %08lx ...\n", addr);
@@ -690,21 +641,11 @@ int do_spidboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
hdr->is_1st_boot = 0;
- /* find a correct dest addr... */
- if (hdr == &img_0_desc)
- {
- dest = IMG_0_ADDR;
- }
- else
- {
- dest = IMG_1_ADDR;
- }
- /* ...and write back to flash.
- * Replacing 1s with 0s is allowed without erase.
+ /* Replacing 1s with 0s is allowed without erase.
* We will write whole structure (it is allowed to write unchanged parts,
* just transition 0->1 is impossible without erase
*/
- flash_write( (char *)hdr, (ulong)dest, sizeof(spidcom_image_desc_t) );
+ flash_write( (char *)hdr, (ulong)img_addr[sel_img], sizeof(spidcom_image_desc_t) );
}
/*
@@ -715,7 +656,7 @@ int do_spidboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
iflag = disable_interrupts();
- printf (" XIP %s ... ", name);
+ printf (" BOOTING %s ... ", name);
puts ("OK\n");
switch (hdr->type) {