make pRAM feature work.
- Added IH_OS_PPCBOOT and IH_TYPE_FIRMWARE to the image definitions
to allow PPCBoot updates with CRC check.
+* Added CONFIG_PRAM option which allows to reserve some memory at the
+ upper end of memory which will remain unchanged by PPCBoot and
+ Linux ("protected RAM")
+
+* Added CONFIG_OVERWRITE_ETHADDR_ONCE option, which allows for a
+ default ethernet address that can be overwritten exactly ONCE by
+ the user
+
* Added keyboard support to LWMON board (uses special I2C keyboard)
-* Fix bug in calculation of initrd size
+* Fixed bug in calculation of initrd size
Patch by Hannes Fertala, 2 Jul 2001
-* Fix bug in environment offset handling
+* Fixed bug in environment offset handling
(when environment starts not at the beginning of EEPROM).
+* Fixed bug in printenv command (when called with list of names)
+
======================================================================
Modifications for 1.0.1:
======================================================================
If defined, this string will be added to the PPCBoot
version information (PPCBOOT_VERSION)
+- Vendor Parameter Protection:
+
+ PPCBoot considers the values of the environment
+ variables "serial#" (Board Serial Number) and
+ "ethaddr" (Ethernet Address) to bb parameters that
+ are set once by the board vendor / manufacturer, and
+ protects these variables from casual modification by
+ the user. Once set, these variables are read-only,
+ and write or delete attempts are rejected. You can
+ change this behviour:
+
+ If CONFIG_ENV_OVERWRITE is #defined in your config
+ file, the write protection for vendor parameters is
+ completely disabled. Anybody can change or delte
+ these parameters.
+
+ Alternatively, if you #define _both_ CONFIG_ETHADDR
+ _and_ CONFIG_OVERWRITE_ETHADDR_ONCE, a default
+ ethernet address is installed in the environment,
+ which can be changed exactly ONCE by the user. [The
+ serial# is unaffected by this, i. e. it remains
+ read-only.]
+
+- Protected RAM:
+ CONFIG_PRAM
+
+ Define this variable to enable the reservation of
+ "protected RAM", i. e. RAM which is not overwritten
+ by PPCBoot. Define CONFIG_PRAM to hold the number of
+ kB you want to reserve for pRAM. You can overwrite
+ this default value by defining an environment
+ variable "pram" to the number of kB you want to
+ reserve. Note that the board info structure will
+ still show the full amount of RAM. If pRAM is
+ reserved, a new environment variable "mem" will
+ automatically be defined to hold the amount of
+ remaining RAM in a form that can be passed as boot
+ argument to Linux, for instance like that:
+
+ setenv bootargs ... mem=\$(mem)
+ saveenv
+
+ This way you can tell Linux not to use this memory,
+ either, which results in a memory region that will
+ not be affected by reboots.
+
+ *WARNING* If your board configuration uses automatic
+ detection of the RAM size, you must make sure that
+ this memory test is non-destructive. So far, the
+ following board configurations are known to be
+ "pRAM-clean":
+
+ ETX094, IVMS8, IVML24, SPD8xx, TQM8xxL,
+ HERMES, IP860, RPXlite, LWMON, LANTEC,
+ PCU_E, FLAGADM, TQM8260
+
+
Configuration Settings:
-----------------------
volatile immap_t *immap = (immap_t *)CFG_IMMR;
volatile memctl8xx_t *memctl = &immap->im_memctl;
volatile long int *addr;
- long int cnt, val;
+ ulong cnt, val;
+ ulong save[32]; /* to make test non-destructive */
+ unsigned char i = 0;
memctl->memc_mamr = mamr_value;
for (cnt = maxsize/sizeof(long); cnt > 0; cnt >>= 1) {
addr = base + cnt; /* pointer arith! */
+ save[i++] = *addr;
*addr = ~cnt;
}
/* write 0 to base address */
addr = base;
+ save[i] = *addr;
*addr = 0;
/* check at base address */
if ((val = *addr) != 0) {
+ *addr = save[i];
return (0);
}
- for (cnt = 1; ; cnt <<= 1) {
+ for (cnt = 1; cnt <= maxsize/sizeof(long); cnt <<= 1) {
addr = base + cnt; /* pointer arith! */
val = *addr;
+ *addr = save[--i];
if (val != (~cnt)) {
return (cnt * sizeof(long));
}
}
- /* NOTREACHED */
+ return (maxsize);
}
volatile immap_t *immap = (immap_t *)CFG_IMMR;
volatile memctl8xx_t *memctl = &immap->im_memctl;
volatile long int *addr;
- long int cnt, val;
+ ulong cnt, val;
+ ulong save[32]; /* to make test non-destructive */
+ unsigned char i = 0;
memctl->memc_mamr = mamr_value;
for (cnt = maxsize/sizeof(long); cnt > 0; cnt >>= 1) {
addr = base + cnt; /* pointer arith! */
+ save[i++] = *addr;
*addr = ~cnt;
}
/* write 0 to base address */
addr = base;
+ save[i] = *addr;
*addr = 0;
/* check at base address */
if ((val = *addr) != 0) {
+ *addr = save[i];
return (0);
}
- for (cnt = 1; ; cnt <<= 1) {
+ for (cnt = 1; cnt <= maxsize/sizeof(long); cnt <<= 1) {
addr = base + cnt; /* pointer arith! */
val = *addr;
+ *addr = save[--i];
if (val != (~cnt)) {
return (cnt * sizeof(long));
}
}
- /* NOTREACHED */
+ return (maxsize);
}
/* ------------------------------------------------------------------------- */
volatile immap_t *immap = (immap_t *)CFG_IMMR;
volatile memctl8xx_t *memctl = &immap->im_memctl;
volatile long int *addr;
- long int cnt, val;
+ ulong cnt, val;
+ ulong save[32]; /* to make test non-destructive */
+ unsigned char i = 0;
memctl->memc_mamr = mamr_value;
for (cnt = maxsize/sizeof(long); cnt > 0; cnt >>= 1) {
addr = base + cnt; /* pointer arith! */
+ save[i++] = *addr;
*addr = ~cnt;
}
/* write 0 to base address */
addr = base;
+ save[i] = *addr;
*addr = 0;
/* check at base address */
if ((val = *addr) != 0) {
+ *addr = save[i];
return (0);
}
- for (cnt = 1; ; cnt <<= 1) {
+ for (cnt = 1; cnt <= maxsize/sizeof(long); cnt <<= 1) {
addr = base + cnt; /* pointer arith! */
val = *addr;
+ *addr = save[--i];
if (val != (~cnt)) {
return (cnt * sizeof(long));
}
}
- /* NOTREACHED */
+ return (maxsize);
}
volatile immap_t *immap = (immap_t *)CFG_IMMR;
volatile memctl8xx_t *memctl = &immap->im_memctl;
volatile long int *addr;
- long int cnt, val;
+ ulong cnt, val;
+ ulong save[32]; /* to make test non-destructive */
+ unsigned char i = 0;
memctl->memc_mamr = mamr_value;
for (cnt = maxsize/sizeof(long); cnt > 0; cnt >>= 1) {
addr = base + cnt; /* pointer arith! */
+ save[i++] = *addr;
*addr = ~cnt;
}
/* write 0 to base address */
addr = base;
+ save[i] = *addr;
*addr = 0;
/* check at base address */
if ((val = *addr) != 0) {
+ *addr = save[i];
return (0);
}
- for (cnt = 1; ; cnt <<= 1) {
+ for (cnt = 1; cnt <= maxsize/sizeof(long); cnt <<= 1) {
addr = base + cnt; /* pointer arith! */
val = *addr;
+ *addr = save[--i];
if (val != (~cnt)) {
return (cnt * sizeof(long));
}
}
- /* NOTREACHED */
+ return (maxsize);
}
/* ------------------------------------------------------------------------- */
volatile immap_t *immap = (immap_t *)CFG_IMMR;
volatile memctl8xx_t *memctl = &immap->im_memctl;
volatile long int *addr;
- long int cnt, val;
+ ulong cnt, val;
+ ulong save[32]; /* to make test non-destructive */
+ unsigned char i = 0;
memctl->memc_mamr = mamr_value;
for (cnt = maxsize/sizeof(long); cnt > 0; cnt >>= 1) {
addr = base + cnt; /* pointer arith! */
+ save[i++] = *addr;
*addr = ~cnt;
}
/* write 0 to base address */
addr = base;
+ save[i] = *addr;
*addr = 0;
/* check at base address */
if ((val = *addr) != 0) {
+ *addr = save[i];
return (0);
}
- for (cnt = 1; ; cnt <<= 1) {
+ for (cnt = 1; cnt <= maxsize/sizeof(long); cnt <<= 1) {
addr = base + cnt; /* pointer arith! */
val = *addr;
+ *addr = save[--i];
if (val != (~cnt)) {
return (cnt * sizeof(long));
}
}
- /* NOTREACHED */
+ return (maxsize);
}
/* ------------------------------------------------------------------------- */
volatile immap_t *immr = (immap_t *)CFG_IMMR;
volatile memctl8xx_t *memctl = &immr->im_memctl;
volatile long int *addr;
- long int cnt, val;
+ ulong cnt, val;
+ ulong save[32]; /* to make test non-destructive */
+ unsigned char i = 0;
memctl->memc_mbmr = mamr_value;
for (cnt = maxsize/sizeof(long); cnt > 0; cnt >>= 1) {
addr = base + cnt; /* pointer arith! */
+ save[i++] = *addr;
*addr = ~cnt;
}
/* write 0 to base address */
addr = base;
+ save[i] = *addr;
*addr = 0;
/* check at base address */
if ((val = *addr) != 0) {
+ *addr = save[i];
return (0);
}
- for (cnt = 1; ; cnt <<= 1) {
+ for (cnt = 1; cnt <= maxsize/sizeof(long); cnt <<= 1) {
addr = base + cnt; /* pointer arith! */
val = *addr;
+ *addr = save[--i];
if (val != (~cnt)) {
return (cnt * sizeof(long));
}
}
- /* NOTREACHED */
+ return (maxsize);
}
/* ------------------------------------------------------------------------- */
volatile immap_t *immap = (immap_t *)CFG_IMMR;
volatile memctl8xx_t *memctl = &immap->im_memctl;
volatile long int *addr;
- long int cnt, val;
+ ulong cnt, val;
+ ulong save[32]; /* to make test non-destructive */
+ unsigned char i = 0;
memctl->memc_mamr = mamr_value;
for (cnt = maxsize/sizeof(long); cnt > 0; cnt >>= 1) {
addr = base + cnt; /* pointer arith! */
+ save[i++] = *addr;
*addr = ~cnt;
}
/* write 0 to base address */
addr = base;
+ save[i] = *addr;
*addr = 0;
/* check at base address */
if ((val = *addr) != 0) {
+ *addr = save[i];
return (0);
}
- for (cnt = 1; ; cnt <<= 1) {
+ for (cnt = 1; cnt <= maxsize/sizeof(long); cnt <<= 1) {
addr = base + cnt; /* pointer arith! */
val = *addr;
+ *addr = save[--i];
if (val != (~cnt)) {
return (cnt * sizeof(long));
}
}
- /* NOTREACHED */
+ return (maxsize);
}
volatile immap_t *immr = (immap_t *)CFG_IMMR;
volatile memctl8xx_t *memctl = &immr->im_memctl;
volatile long int *addr;
- long int cnt, val;
+ ulong cnt, val;
+ ulong save[32]; /* to make test non-destructive */
+ unsigned char i = 0;
memctl->memc_mamr = mamr_value;
for (cnt = maxsize/sizeof(long); cnt > 0; cnt >>= 1) {
addr = base + cnt; /* pointer arith! */
+ save[i++] = *addr;
*addr = ~cnt;
}
/* write 0 to base address */
addr = base;
+ save[i] = *addr;
*addr = 0;
/* check at base address */
if ((val = *addr) != 0) {
+ *addr = save[i];
return (0);
}
- for (cnt = 1; ; cnt <<= 1) {
+ for (cnt = 1; cnt <= maxsize/sizeof(long); cnt <<= 1) {
addr = base + cnt; /* pointer arith! */
val = *addr;
+ *addr = save[--i];
if (val != (~cnt)) {
return (cnt * sizeof(long));
}
}
- /* NOTREACHED */
+ return (maxsize);
}
/* ------------------------------------------------------------------------- */
volatile immap_t *immr = (immap_t *)CFG_IMMR;
volatile memctl8xx_t *memctl = &immr->im_memctl;
volatile long int *addr;
- long int cnt, val;
+ ulong cnt, val;
+ ulong save[32]; /* to make test non-destructive */
+ unsigned char i = 0;
memctl->memc_mamr = mamr_value;
for (cnt = maxsize/sizeof(long); cnt > 0; cnt >>= 1) {
addr = base + cnt; /* pointer arith! */
+ save[i++] = *addr;
*addr = ~cnt;
}
/* write 0 to base address */
addr = base;
+ save[i] = *addr;
*addr = 0;
/* check at base address */
if ((val = *addr) != 0) {
+ *addr = save[i];
return (0);
}
- for (cnt = 1; ; cnt <<= 1) {
+ for (cnt = 1; cnt <= maxsize/sizeof(long); cnt <<= 1) {
addr = base + cnt; /* pointer arith! */
val = *addr;
+ *addr = save[--i];
if (val != (~cnt)) {
return (cnt * sizeof(long));
}
}
- /* NOTREACHED */
+ return (maxsize);
}
/* ------------------------------------------------------------------------- */
volatile immap_t *immap = (immap_t *)CFG_IMMR;
volatile memctl8xx_t *memctl = &immap->im_memctl;
volatile long int *addr;
- long int cnt, val;
+ ulong cnt, val;
+ ulong save[32]; /* to make test non-destructive */
+ unsigned char i = 0;
memctl->memc_mbmr = mamr_value;
for (cnt = maxsize/sizeof(long); cnt > 0; cnt >>= 1) {
addr = base + cnt; /* pointer arith! */
+ save[i++] = *addr;
*addr = ~cnt;
}
/* write 0 to base address */
addr = base;
+ save[i] = *addr;
*addr = 0;
/* check at base address */
if ((val = *addr) != 0) {
+ *addr = save[i];
return (0);
}
- for (cnt = 1; ; cnt <<= 1) {
+ for (cnt = 1; cnt <= maxsize/sizeof(long); cnt <<= 1) {
addr = base + cnt; /* pointer arith! */
val = *addr;
+ *addr = save[--i];
if (val != (~cnt)) {
return (cnt * sizeof(long));
}
}
- /* NOTREACHED */
+ return (maxsize);
}
/* ------------------------------------------------------------------------- */
volatile uint * sdmr_ptr;
volatile uint * orx_ptr;
int i;
+ ulong save[32]; /* to make test non-destructive */
/* Since CFG_SDRAM_BASE is always 0 (??), we assume that
* we are configuring CS1 if base != 0
*/
sdmr_ptr = base ? &memctl->memc_lsdmr : &memctl->memc_psdmr;
- orx_ptr = base ? &memctl->memc_or2 : &memctl->memc_or1;
+ orx_ptr = base ? &memctl->memc_or2 : &memctl->memc_or1;
*orx_ptr = orx;
* - short between address lines
* - short between data lines
*/
- for (cnt = 0x04000000/sizeof(long); cnt > 0; cnt >>= 1)
- {
+#define MAXSIZE 0x04000000
+ i = 0;
+ for (cnt = MAXSIZE/sizeof(long); cnt > 0; cnt >>= 1) {
addr = (volatile ulong *)base + cnt; /* pointer arith! */
+ save[i++] = *addr;
*addr = ~cnt;
}
addr = (volatile ulong *)base;
+ save[i] = *addr;
*addr = 0;
- if ((val = *addr) != 0)
- {
+ if ((val = *addr) != 0) {
+ *addr = save[i];
+ return (0);
+ }
+
+ for (cnt = 1; cnt <= MAXSIZE/sizeof(long); cnt <<= 1) {
return (0);
}
- for (cnt = 1; ; cnt <<=1)
- {
+ for (cnt = 1; ; cnt <<=1) {
addr = (volatile ulong *)base + cnt; /* pointer arith! */
val = *addr;
- if (val != ~cnt)
- {
+ *addr = save[--i];
+ if (val != ~cnt) {
/* Write the actual size to ORx
*/
*orx_ptr = orx | ~(cnt * sizeof(long) - 1);
return (cnt * sizeof(long));
}
}
- /* NOTREACHED */
+ return (MAXSIZE);
}
long int initdram(int board_type)
size9 = try_init(memctl, CFG_PSDMR_9COL, CFG_OR1_9COL,
(uchar *) CFG_SDRAM_BASE);
- if (size8 < size9)
- {
+ if (size8 < size9) {
psize = size9;
printf("(60x:9COL - %ld MB, ", psize >> 20);
- }
- else
- {
+ } else {
psize = try_init(memctl, CFG_PSDMR_8COL, CFG_OR1_8COL,
(uchar *) CFG_SDRAM_BASE);
printf("(60x:8COL - %ld MB, ", psize >> 20);
size9 = try_init(memctl, CFG_LSDMR_9COL, CFG_OR2_9COL,
(uchar *) SDRAM_BASE2_PRELIM);
- if (size8 < size9)
- {
+ if (size8 < size9) {
lsize = size9;
printf("Local:9COL - %ld MB) using ", lsize >> 20);
- }
- else
- {
+ } else {
lsize = try_init(memctl, CFG_LSDMR_8COL, CFG_OR2_8COL,
(uchar *) SDRAM_BASE2_PRELIM);
printf("Local:8COL - %ld MB) using ", lsize >> 20);
return (psize);
}
-
volatile immap_t *immap = (immap_t *)CFG_IMMR;
volatile memctl8xx_t *memctl = &immap->im_memctl;
volatile long int *addr;
- long int cnt, val;
+ ulong cnt, val;
+ ulong save[32]; /* to make test non-destructive */
+ unsigned char i = 0;
memctl->memc_mamr = mamr_value;
for (cnt = maxsize/sizeof(long); cnt > 0; cnt >>= 1) {
addr = base + cnt; /* pointer arith! */
+ save[i++] = *addr;
*addr = ~cnt;
}
/* write 0 to base address */
addr = base;
+ save[i] = *addr;
*addr = 0;
/* check at base address */
if ((val = *addr) != 0) {
+ *addr = save[i];
return (0);
}
- for (cnt = 1; ; cnt <<= 1) {
+ for (cnt = 1; cnt <= maxsize/sizeof(long); cnt <<= 1) {
addr = base + cnt; /* pointer arith! */
val = *addr;
+ *addr = save[--i];
if (val != (~cnt)) {
return (cnt * sizeof(long));
}
}
- /* NOTREACHED */
+ return (maxsize);
}
len, CFG_MONITOR_LEN);
hang();
}
+
if (CFG_MONITOR_LEN > len)
len = CFG_MONITOR_LEN;
+
+#ifdef CONFIG_PRAM /* reserve protected RAM at top of memory */
+ i = getenv_r ("pram", tmp, sizeof(tmp));
+ reg = (i > 0) ? simple_strtoul(tmp, NULL, 10) : CONFIG_PRAM;
+# ifdef DEBUG
+ printf (" Reserving %ldk for protected RAM\n", reg);
+# endif
+ len += (reg << 10); /* size is in kB */
+#endif /* CONFIG_PRAM */
+
/* round up to next 4 kB limit */
len = (len + (4096 - 1)) & ~(4096 - 1);
putc('\n');
/**********************/
+#ifdef CONFIG_PRAM
+ /*
+ * Export available size of memory for Linux,
+ * taking into account the protected RAM at top of memory
+ */
+ {
+ ulong pram;
+ char *s;
+ uchar memsz[32];
+
+ if ((s = getenv("pram")) != NULL) {
+ pram = simple_strtoul(s, NULL, 10);
+ } else {
+ pram = CONFIG_PRAM;
+ }
+ sprintf (memsz, "%ldk", (bd->bi_memsize / 1024) - pram);
+ setenv ("mem", memsz);
+ }
+#endif
+
/* Initialization complete - start the monitor */
/* main_loop() can return to retry autoboot, if so just run it again. */
void do_printenv (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
- int i, k, nxt;
+ int i, j, k, nxt;
if (argc == 1) { /* Print all env variables */
for (i=0; get_env_char(i) != '\0'; i=nxt+1) {
k = -1;
- for (i=0; get_env_char(i) != '\0'; i=nxt+1) {
+ for (j=0; get_env_char(j) != '\0'; j=nxt+1) {
- for (nxt=i; get_env_char(nxt) != '\0'; ++nxt)
+ for (nxt=j; get_env_char(nxt) != '\0'; ++nxt)
;
- k = envmatch(name, i);
+ k = envmatch(name, j);
if (k < 0) {
continue;
}
*/
if (oldval >= 0) {
#ifndef CONFIG_ENV_OVERWRITE
+
/*
* Ethernet Address and serial# can be set only once
*/
- if ((strcmp (name, "ethaddr") == 0) ||
- (strcmp (name, "serial#") == 0) ) {
+ if ( (strcmp (name, "serial#") == 0) ||
+ ((strcmp (name, "ethaddr") == 0)
+#if defined(CONFIG_OVERWRITE_ETHADDR_ONCE) && defined(CONFIG_ETHADDR)
+ && (strcmp (get_env_addr(oldval),MK_STR(CONFIG_ETHADDR)) != 0)
+#endif /* CONFIG_OVERWRITE_ETHADDR_ONCE && CONFIG_ETHADDR */
+ ) ) {
printf ("Can't overwrite \"%s\"\n", name);
return;
}
* Match a name / name=value pair
*
* s1 is either a simple 'name', or a 'name=value' pair.
- * i2 is the environment index for a 'name=value' pair.
- * If the names match, return the value of s2, else NULL.
+ * i2 is the environment index for a 'name2=value2' pair.
+ * If the names match, return the index for the value2, else NULL.
*/
static int
#define CONFIG_RAMBOOTCOMMAND \
"bootp; " \
"setenv bootargs root=/dev/ram rw ramdisk_size=4690 " \
- "ppcboot_version=ppcboot-1.0.0-June_14_2001 " \
+ "ppcboot_version=ppcboot-1.0.x-Date " \
"panic=1 " \
"ip=$(ipaddr):$(serverip):$(gatewayip):$(netmask):$(hostname)::off; " \
"bootm"
#define CONFIG_STATUS_LED /* Status LED enabled */
+#define CONFIG_PRAM 2048 /* reserve 2 MB "protected RAM" */
+
#define CONFIG_RTC_MPC8xx /* use internal RTC of MPC8xx */
#define CONFIG_SPI /* enable SPI driver */