file using BOOTP; see include/image.h for details.
* Added network support for IBM 40x (by Stefan Roese)
* Added binary download over serial line using kermit protocol
(optional)
Open Issues:
======================================================================
+* Boot with RAMDisk:
+
+ No need to copy ramdisk image when it's already in RAM ??? Or do we
+ have to move it out of the way if it's too low in memory?
+
+* Network Code:
+
+ After booting over BOOTP / RARP, any new network configuration
+ parameters like IP-Address, Server Address, ... should be
+ automatically stored in the environment for later use by the Linux
+ (or other RTOS) kernel and/or processes.
+
+* Network Code:
+
+ It should not be necessary to reboot the system just to set or to
+ change the network parameters (like "serverip" etc.).
+
* Timer:
don't use 'lr RX, const; mtdec RX" -> use:
Modifications since 0.5.0:
======================================================================
+* Added multi-file images to allow to boot a combined kernel+initrd
+ file using BOOTP; see include/image.h for details.
+
+* Added network support for IBM 40x (by Stefan Roese)
+
+* Added binary download over serial line using kermit protocol
+ (optional)
+
* Eliminated asc_to_hex() - replaced by simple_strtoul()
* Bug fixes:
- Changed mpc8xx/cpu_init.c again to allow for boot ROMS to be 8,
16 or 32 bit wide (lost this fix by accident)
- Allow to set the MF bits using the CFG_PLPRCR definition
+ - Fix BR0 reset handling for older CPU mask revisions: Clear every-
+ thing except Port Size bits, then add just the "Bank Valid" bit
======================================================================
Modifications for 0.5.0:
E: khaderlie@vividimage.com
D: Added TFTP to 8xxrom (-> 0.3.1)
+N: Murray Jensen
+E: Murray.Jensen@cmst.csiro.au
+D: Added port to the Cogent platform
+
N: Dan Malek
E: dan@netx4.com
D: FADSROM, the grandfather of all of this
OBJS = $(CPU)/start.o \
common/libcommon.a
-# Network support only for MPC8xx yet
-ifeq ($(CPU),mpc8xx)
OBJS += net/libnet.a
-endif
OBJS += $(BOARD)/lib$(BOARD).a \
$(CPU)/lib$(CPU).a \
#
# 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
+# 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
Directory Hierarchy:
====================
-- common Misc architecture independend functions
-- examples Example code for standalone applications, etc.
-- include Header Files
-- net Networking code
-- ppc Files generic to PowerPC architecture
-- tools Tools to build S-Record or PPCBoot images, etc.
+- common Misc architecture independend functions
+- examples Example code for standalone applications, etc.
+- include Header Files
+- net Networking code
+- ppc Files generic to PowerPC architecture
+- tools Tools to build S-Record or PPCBoot images, etc.
-- mpc8xx Files specific to Motorola MPC8xx CPUs
-- ppc4xx Files specific to IBM 4xx CPUs
+- mpc8xx Files specific to Motorola MPC8xx CPUs
+- ppc4xx Files specific to IBM 4xx CPUs
-- adciop Files specific to ADCIOP boards
-- cpci405 Files specific to CPCI405 boards
-- tqm8xx Files specific to TQM8xxL boards
-- etx094 Files specific to ETX_094 boards
+- adciop Files specific to ADCIOP boards
+- cpci405 Files specific to CPCI405 boards
+- tqm8xx Files specific to TQM8xxL boards
+- etx094 Files specific to ETX_094 boards
+- cogent Files specific to Cogent boards
+ (need further configuration)
Software Configuration:
Example: For a TQM823L module type:
- cd ppcboot
- make TQM823L_config
+ cd ppcboot
+ make TQM823L_config
+
+For the Cogent platform, you need to specify the cpu type as well;
+e.g. "make cogent_mpc8xx_config". And also configure the cogent
+directory according to the instructions in cogent/README.
Configuration Options:
The following options need to be configured:
-- CPU Type: Define exactly one of
- CONFIG_MPC823, CONFIG_MPC850, CONFIG_MPC855 or
- CONFIG_MPC860
+- CPU Type: Define exactly one of
+ CONFIG_MPC823, CONFIG_MPC850, CONFIG_MPC855 or
+ CONFIG_MPC860
-- Board Type: Define exactly one of
- CONFIG_TQM823L, CONFIG_TQM850L, CONFIG_TQM855L,
- CONFIG_TQM860L, CONFIG_ETX094, CONFIG_ADCIOP,
- CONFIG_CPCI405
+- Board Type: Define exactly one of
+ CONFIG_TQM823L, CONFIG_TQM850L, CONFIG_TQM855L,
+ CONFIG_TQM860L, CONFIG_ETX094, CONFIG_ADCIOP,
+ CONFIG_CPCI405, CONFIG_COGENT
--- FIXME --- not tested yet:
- CONFIG_TQM860, CONFIG_FPS850L, CONFIG_MBX,
- CONFIG_ADS, CONFIG_FADS, CONFIG_RPXLITE,
- CONFIG_RPXCLASSIC, CONFIG_BSEIP
+ CONFIG_TQM860, CONFIG_FPS850L, CONFIG_MBX,
+ CONFIG_ADS, CONFIG_FADS, CONFIG_RPXLITE,
+ CONFIG_RPXCLASSIC, CONFIG_BSEIP
+
- Console Interface:
- Define exactly one of
- CONFIG_8xx_CONS_SMC1, CONFIG_8xx_CONS_SMC2
+ Define exactly one of
+ CONFIG_8xx_CONS_SMC1, CONFIG_8xx_CONS_SMC2
- Console Baudrate:
- CONFIG_BAUDRATE - in bps
- Select one of 9600, 19200, 38400, 57600, 115200
+ CONFIG_BAUDRATE - in bps
+ Select one of 9600, 19200, 38400, 57600, 115200
-- Boot Delay: CONFIG_BOOTDELAY - in seconds
- Delay before automatically booting the default image;
- set to 0 to disable autoboot.
+- Boot Delay: CONFIG_BOOTDELAY - in seconds
+ Delay before automatically booting the default image;
+ set to 0 to disable autoboot.
- Autoboot Command:
- CONFIG_BOOTCOMMAND
- Only needed when CONFIG_BOOTDELAY is enabled;
- define a command string thatis automatically executed
- when no character is read on the console interface
- withing "Boot Delay" after reset.
+ CONFIG_BOOTCOMMAND
+ Only needed when CONFIG_BOOTDELAY is enabled;
+ define a command string thatis automatically executed
+ when no character is read on the console interface
+ withing "Boot Delay" after reset.
- Serial Download Echo Mode:
- CONFIG_LOADS_ECHO
-
- If defined to 1, all charcters received during a
- serial download (using the "loads" command) are
- echoed back. This might be needed by some terminal
- emulations (like "cu"), but may as well just take
- time on others. This setting #define's the initial
- value of the "loads_echo" environment variable.
-
+ CONFIG_LOADS_ECHO
+ If defined to 1, all characters received during a
+ serial download (using the "loads" command) are
+ echoed back. This might be needed by some terminal
+ emulations (like "cu"), but may as well just take
+ time on others. This setting #define's the initial
+ value of the "loads_echo" environment variable.
+
+- Binary File Download (Kermit mode):
+ CONFIG_LOADB
+ If defined, the "loadb" command will be added which
+ allows to download binary files over the serial line
+ using Kermit protocol.
Configuration Settings:
-----------------------
- CFG_LONGHELP: Defined when you want long help messages included;
- undefine this when you're short of memory.
+ undefine this when you're short of memory.
-- CFG_PROMPT: This is what PPCBoot prints on the console to
- prompt for user input.
+- CFG_PROMPT: This is what PPCBoot prints on the console to
+ prompt for user input.
-- CFG_CBSIZE: Buffer size for input from the Console
+- CFG_CBSIZE: Buffer size for input from the Console
-- CFG_PBSIZE: Buffer size for Console output
+- CFG_PBSIZE: Buffer size for Console output
-- CFG_MAXARGS: max. Number of arguments accepted for monitor commands
+- CFG_MAXARGS: max. Number of arguments accepted for monitor commands
- CFG_BARGSIZE: Buffer size for Boot Arguments which are passed to
- the application (usually a Linux kernel) when it is
- bootet
+ the application (usually a Linux kernel) when it is
+ bootet
- CFG_MEMTEST_START, CFG_MEMTEST_END:
- Begin and End addresses of the area used by the
- simple memory test.
+ Begin and End addresses of the area used by the
+ simple memory test.
- CFG_TFTP_LOADADDR:
- Default load address for network file downloads
+ Default load address for network file downloads
- CFG_LOADS_BAUD_CHANGE:
- Enable temporary baudrate change while serial download
+ Enable temporary baudrate change while serial download
- CFG_SDRAM_BASE:
- Physical start address of SDRAM. _Must_ be 0 here.
+ Physical start address of SDRAM. _Must_ be 0 here.
- CFG_FLASH_BASE:
- Physical start address of Flash memory.
+ Physical start address of Flash memory.
- CFG_MONITOR_LEN:
- Size of memory reserved for monitor code
+ Size of memory reserved for monitor code
- CFG_MALLOC_LEN:
- Size of DRAM reserved for malloc() use.
+ Size of DRAM reserved for malloc() use.
- CFG_BOOTMAPSZ:
- Maximum size of memory mapped by the startup code of
- the Linux kernel; all data that must be processed by
- the Linux kernel (bd_info, boot arguments, initrd
- image) must be put below this limit.
+ Maximum size of memory mapped by the startup code of
+ the Linux kernel; all data that must be processed by
+ the Linux kernel (bd_info, boot arguments, initrd
+ image) must be put below this limit.
- CFG_MAX_FLASH_BANKS:
- Max number of Flash memory banks
+ Max number of Flash memory banks
- CFG_MAX_FLASH_SECT:
- Max number of sectors on a Flash chip
+ Max number of sectors on a Flash chip
- CFG_FLASH_ERASE_TOUT:
- Timeout for Flash erase operations (in ms)
+ Timeout for Flash erase operations (in ms)
- CFG_FLASH_WRITE_TOUT:
- Timeout for Flash write operations (in ms)
+ Timeout for Flash write operations (in ms)
- CFG_FLASH_ENV_OFFSET
- Offset of envrionment data (aka NVRAM area) to the
- beginning of flash memory; for instance, to with
- bottom boot type flash chips the second sector will
- be used; in our example configuration, the offset for
- this sector is 0x8000.
+ Offset of envrionment data (aka NVRAM area) to the
+ beginning of flash memory; for instance, to with
+ bottom boot type flash chips the second sector will
+ be used; in our example configuration, the offset for
+ this sector is 0x8000.
- BE CAREFUL! Any changes to the flash layout, and some
- changes to the source code will make it necessary to
- adapt <board>/ppcboot.lds* accordingly!
+ BE CAREFUL! Any changes to the flash layout, and some
+ changes to the source code will make it necessary to
+ adapt <board>/ppcboot.lds* accordingly!
- CFG_FLASH_ENV_SIZE:
- Size of the flash sector(s) used for the environment
+ Size of the flash sector(s) used for the environment
Many of the remaining options are named exactly as the corresponding
Low Level (hardware related) configuration options:
- CFG_CACHELINE_SIZE:
- Cache Line Size of the CPU.
+ Cache Line Size of the CPU.
-- CFG_IMMR: Physical address of the Internal Memory Mapped
- Register; DO NOT CHANGE! (11-4)
- [MPC8xx systems only]
+- CFG_IMMR: Physical address of the Internal Memory Mapped
+ Register; DO NOT CHANGE! (11-4)
+ [MPC8xx systems only]
-- CFG_SIUMCR: SIU Module Configuration (11-6)
+- CFG_SIUMCR: SIU Module Configuration (11-6)
-- CFG_SYPCR: System Protection Control (11-9)
+- CFG_SYPCR: System Protection Control (11-9)
-- CFG_TBSCR: Time Base Status and Control (11-26)
+- CFG_TBSCR: Time Base Status and Control (11-26)
-- CFG_PISCR: Periodic Interrupt Status and Control (11-31)
+- CFG_PISCR: Periodic Interrupt Status and Control (11-31)
-- CFG_PLPRCR: PLL, Low-Power, and Reset Control Register (15-30)
+- CFG_PLPRCR: PLL, Low-Power, and Reset Control Register (15-30)
-- CFG_SCCR: System Clock and reset Control Register (15-27)
+- CFG_SCCR: System Clock and reset Control Register (15-27)
- CFG_OR_TIMING_SDRAM:
- SDRAM timing
+ SDRAM timing
- CFG_MAMR_PTA:
- periodic timer for refresh
+ periodic timer for refresh
-- CFG_DER: Debug Event Register (37-47)
+- CFG_DER: Debug Event Register (37-47)
- FLASH_BASE0_PRELIM, FLASH_BASE1_PRELIM, CFG_REMAP_OR_AM,
CFG_PRELIM_OR_AM, CFG_OR_TIMING_FLASH, CFG_OR0_REMAP,
CFG_OR0_PRELIM, CFG_BR0_PRELIM, CFG_OR1_REMAP, CFG_OR1_PRELIM,
CFG_BR1_PRELIM:
- Memory Controller Definitions: BR0/1 and OR0/1 (FLASH)
+ Memory Controller Definitions: BR0/1 and OR0/1 (FLASH)
- SDRAM_BASE2_PRELIM, SDRAM_BASE3_PRELIM, SDRAM_MAX_SIZE,
CFG_OR_TIMING_SDRAM, CFG_OR2_PRELIM, CFG_BR2_PRELIM,
CFG_OR3_PRELIM, CFG_BR3_PRELIM:
- Memory Controller Definitions: BR2/3 and OR2/3 (SDRAM)
+ Memory Controller Definitions: BR2/3 and OR2/3 (SDRAM)
- CFG_MAMR_PTA, CFG_MPTPR_2BK_4K, CFG_MPTPR_1BK_4K, CFG_MPTPR_2BK_8K,
CFG_MPTPR_1BK_8K, CFG_MAMR_8COL, CFG_MAMR_9COL:
- Machine Mode Register and Memory Periodic Timer
- Prescaler definitions (SDRAM timing)
+ Machine Mode Register and Memory Periodic Timer
+ Prescaler definitions (SDRAM timing)
Building the Software:
SPARC).
PPCBoot is intended to be simple to build. After installing the
-sources you must configure PPCBoot for one specific board type. This
+sources you must configure PPCBoot for one specific board type. This
is done by typing:
- make config_name
+ make config_name
where "config_name" is the name of one of the existing
configurations; the following names are suported:
- TQM823L_config
- TQM850L_config
- TQM860L_config
- ETX094_config
- CPCI405_config
- ADCIOP_config
+ TQM823L_config
+ TQM850L_config
+ TQM860L_config
+ ETX094_config
+ CPCI405_config
+ ADCIOP_config
If the system board that you have is not listed, then you will need
Monitor Commands - Overview:
============================
-go - start application at address 'addr'
-bootm - boot application image from memory
-bootp - boot image via network using BootP/TFTP protocol
+go - start application at address 'addr'
+bootm - boot application image from memory
+bootp - boot image via network using BootP/TFTP protocol
tftpboot- boot image via network using TFTP protocol
- and env variables ipaddr and serverip
+ and env variables ipaddr and serverip
rarpboot- boot image via network using RARP/TFTP protocol
-loads - load S-Record file over serial line
-md - memory display
-mm - memory modify (auto-incrementing)
-nm - memory modify (constant address)
-mw - memory write (fill)
-cp - memory copy
-crc32 - checksum calculation
-base - print or set address offset
+loads - load S-Record file over serial line
+md - memory display
+mm - memory modify (auto-incrementing)
+nm - memory modify (constant address)
+mw - memory write (fill)
+cp - memory copy
+crc32 - checksum calculation
+base - print or set address offset
printenv- print environment variables
-setenv - set environment variables
+setenv - set environment variables
saveenv - save environment variables to persistent storage
-bdinfo - print Board Info structure
-flinfo - print FLASH memory information
-iminfo - print header information for application image
-erase - erase FLASH memory
+bdinfo - print Board Info structure
+flinfo - print FLASH memory information
+iminfo - print header information for application image
+erase - erase FLASH memory
protect - enable or disable FLASH write protection
-loop - infinite loop on address range
-mtest - simple RAM test
-icache - enable or disable instruction cache
-dcache - enable or disable data cache
-reset - Perform RESET of the CPU
+loop - infinite loop on address range
+mtest - simple RAM test
+icache - enable or disable instruction cache
+dcache - enable or disable data cache
+reset - Perform RESET of the CPU
version - print monitor version
-help - print online help
-? - alias for 'help'
+help - print online help
+? - alias for 'help'
Monitor Commands - Detailed Description:
Some configuration options can be set using Environment Variables:
-bootdelay - see CONFIG_BOOTDELAY
-bootcmd - see CONFIG_BOOTCOMMAND
-baudrate - see CONFIG_BAUDRATE
-bootargs - Boot arguments when booting an RTOS image
-loads_echo - see CONFIG_LOADS_ECHO
+bootdelay - see CONFIG_BOOTDELAY
+bootcmd - see CONFIG_BOOTCOMMAND
+baudrate - see CONFIG_BAUDRATE
+bootargs - Boot arguments when booting an RTOS image
+loads_echo - see CONFIG_LOADS_ECHO
ipaddr - IP address; needed for tftpboot command
serverip - TFTP server IP address; needed for tftpboot command
autostart - if set to "yes", an image loaded using the "bootp",
- "rarpboot" or "tftpboot" commands will be
- automatically started (by internally calling
- "bootm")
+ "rarpboot" or "tftpboot" commands will be
+ automatically started (by internally calling
+ "bootm")
There are two special Environment Variables:
-serial# - contains hardware identification information such
- as type string and/or serial number
-ethaddr - Ethernet address
+serial# - contains hardware identification information such
+ as type string and/or serial number
+ethaddr - Ethernet address
These variables can be set only once (usually during manufacturing of
the board). PPCBoot refuses to delete or overwrite these variables
once they have been set once.
-Please note that changes to configuration parameters usually take
+Please note that changes to configuration parameters usually take
only effect after the next boot (yes, that's just like Windoze :-).
Just make sure your machine specific header file (for instance
include/asm-ppc/tqm8xx.h) includes the same definition of the Board
-Information structure as we define in include/ppcboot.h
+Information structure as we define in include/ppcboot.h, and make
+sure that your definition of IMAP_ADDR uses the same value as your
+PPCBoot configuration in CFG_IMMR.
Configuring the Linux kernel:
Example:
- make TQM850L_config
- make oldconfig
- make dep
- make zImage
+ make TQM850L_config
+ make oldconfig
+ make dep
+ make zImage
However, we don't use the 'zImage' (= 'arch/ppc/mbxboot/zvmlinux') we
build this way. The 'zImage' includes the old boot loader code which
contained in the header of an existing PPCBoot image; this includes
checksum verification:
- tools/mkimage -l image
- -l ==> list image header information
+ tools/mkimage -l image
+ -l ==> list image header information
The second form (with "-d" option) is used to build a PPCBoot image
from a "data file" which is used as image payload:
- tools/mkimage -A arch -O os -T type -C comp -a addr -e ep \
- -n name -d data_file image
- -A ==> set architecture to 'arch'
- -O ==> set operating system to 'os'
- -T ==> set image type to 'type'
- -C ==> set compression type 'comp'
- -a ==> set load address to 'addr' (hex)
- -e ==> set entry point to 'ep' (hex)
- -n ==> set image name to 'name'
- -d ==> use image data from 'datafile'
-
-Right now, all Linux kernels use the same load address (0x00000000)
+ tools/mkimage -A arch -O os -T type -C comp -a addr -e ep \
+ -n name -d data_file image
+ -A ==> set architecture to 'arch'
+ -O ==> set operating system to 'os'
+ -T ==> set image type to 'type'
+ -C ==> set compression type 'comp'
+ -a ==> set load address to 'addr' (hex)
+ -e ==> set entry point to 'ep' (hex)
+ -n ==> set image name to 'name'
+ -d ==> use image data from 'datafile'
+
+Right now, all Linux kernels use the same load address (0x00000000)
and entry point address (0x0000000C). So a typical call to build a
PPCBoot image would read:
- -> tools/mkimage -n '2.2.13 for initrd on TQM850L' \
- > -A ppc -O linux -T kernel -C gzip -a 00000000 -e 0000000C \
- > -d /opt/mpc8xx/src/linux-2.2.13/arch/ppc/coffboot/vmlinux.gz \
- > examples/image-2.2.13-initrd
- Image Name: 2.2.13 for initrd on TQM850L
- Created: Wed Jul 19 02:34:59 2000
- Image Type: PowerPC Linux Kernel Image (gzip compressed)
- Data Size: 335725 Bytes = 327.86 kB = 0.32 MB
- Load Address: 0x00000000
- Entry Point: 0x0000000c
+ -> tools/mkimage -n '2.2.13 for initrd on TQM850L' \
+ > -A ppc -O linux -T kernel -C gzip -a 00000000 -e 0000000C \
+ > -d /opt/mpc8xx/src/linux-2.2.13/arch/ppc/coffboot/vmlinux.gz \
+ > examples/image-2.2.13-initrd
+ Image Name: 2.2.13 for initrd on TQM850L
+ Created: Wed Jul 19 02:34:59 2000
+ Image Type: PowerPC Linux Kernel Image (gzip compressed)
+ Data Size: 335725 Bytes = 327.86 kB = 0.32 MB
+ Load Address: 0x00000000
+ Entry Point: 0x0000000c
To verify the contents of the image (or check for corruption):
- -> tools/mkimage -l examples/image-2.2.13-initrd
- Image Name: 2.2.13 for initrd on TQM850L
- Created: Wed Jul 19 02:34:59 2000
- Image Type: PowerPC Linux Kernel Image (gzip compressed)
- Data Size: 335725 Bytes = 327.86 kB = 0.32 MB
- Load Address: 0x00000000
- Entry Point: 0x0000000c
+ -> tools/mkimage -l examples/image-2.2.13-initrd
+ Image Name: 2.2.13 for initrd on TQM850L
+ Created: Wed Jul 19 02:34:59 2000
+ Image Type: PowerPC Linux Kernel Image (gzip compressed)
+ Data Size: 335725 Bytes = 327.86 kB = 0.32 MB
+ Load Address: 0x00000000
+ Entry Point: 0x0000000c
NOTE: for embedded systems where boot time is critical you can trade
speed for memory and install an UNCOMPRESSED image instead: this
needs more space in Flash, but boots much faster since it does not
need to be uncompressed:
- -> gunzip /opt/mpc8xx/src/linux-2.2.13/arch/ppc/coffboot/vmlinux.gz
- -> tools/mkimage -n '2.2.13 for initrd on TQM850L' \
- > -A ppc -O linux -T kernel -C none -a 00000000 -e 0000000C \
- > -d /opt/mpc8xx/src/linux-2.2.13/arch/ppc/coffboot/vmlinux \
- > examples/image-2.2.13-initrd-uncompressed
- Image Name: 2.2.13 for initrd on TQM850L
- Created: Wed Jul 19 02:34:59 2000
- Image Type: PowerPC Linux Kernel Image (uncompressed)
- Data Size: 792160 Bytes = 773.59 kB = 0.76 MB
- Load Address: 0x00000000
- Entry Point: 0x0000000c
+ -> gunzip /opt/mpc8xx/src/linux-2.2.13/arch/ppc/coffboot/vmlinux.gz
+ -> tools/mkimage -n '2.2.13 for initrd on TQM850L' \
+ > -A ppc -O linux -T kernel -C none -a 00000000 -e 0000000C \
+ > -d /opt/mpc8xx/src/linux-2.2.13/arch/ppc/coffboot/vmlinux \
+ > examples/image-2.2.13-initrd-uncompressed
+ Image Name: 2.2.13 for initrd on TQM850L
+ Created: Wed Jul 19 02:34:59 2000
+ Image Type: PowerPC Linux Kernel Image (uncompressed)
+ Data Size: 792160 Bytes = 773.59 kB = 0.76 MB
+ Load Address: 0x00000000
+ Entry Point: 0x0000000c
Similar you can build PPCBoot images from a 'ramdisk.image.gz' file
when your kernel is intended to use an initial ramdisk:
- -> tools/mkimage -n 'Simple Ramdisk Image' \
- > -A ppc -O linux -T ramdisk -C gzip \
- > -d /LinuxPPC/images/SIMPLE-ramdisk.image.gz examples/simple-initrd
- Image Name: Simple Ramdisk Image
- Created: Wed Jan 12 14:01:50 2000
- Image Type: PowerPC Linux RAMDisk Image (gzip compressed)
- Data Size: 566530 Bytes = 553.25 kB = 0.54 MB
- Load Address: 0x00000000
- Entry Point: 0x00000000
+ -> tools/mkimage -n 'Simple Ramdisk Image' \
+ > -A ppc -O linux -T ramdisk -C gzip \
+ > -d /LinuxPPC/images/SIMPLE-ramdisk.image.gz examples/simple-initrd
+ Image Name: Simple Ramdisk Image
+ Created: Wed Jan 12 14:01:50 2000
+ Image Type: PowerPC Linux RAMDisk Image (gzip compressed)
+ Data Size: 566530 Bytes = 553.25 kB = 0.54 MB
+ Load Address: 0x00000000
+ Entry Point: 0x00000000
Installing a Linux Image:
To downloading a PPCBoot image over the serial (console) interface,
you must convert the image to S-Record format:
- objcopy -I binary -O srec examples/image examples/image.srec
+ objcopy -I binary -O srec examples/image examples/image.srec
The 'objcopy' does not understand the information in the PPCBoot
image header, so the resulting S-Record file will be relative to
Example: install the image to address 0x40100000 (which on the
TQM8xxL is in the first Flash bank):
- => erase 40100000 401FFFFF
+ => erase 40100000 401FFFFF
- .......... done
- Erased 8 sectors
+ .......... done
+ Erased 8 sectors
- => loads 40100000
- ## Ready for S-Record download ...
- ~>examples/image.srec
- 1 2 3 4 5 6 7 8 9 10 11 12 13 ...
- ...
- 15989 15990 15991 15992
- [file transfer complete]
- [connected]
- ## Start Addr = 0x00000000
+ => loads 40100000
+ ## Ready for S-Record download ...
+ ~>examples/image.srec
+ 1 2 3 4 5 6 7 8 9 10 11 12 13 ...
+ ...
+ 15989 15990 15991 15992
+ [file transfer complete]
+ [connected]
+ ## Start Addr = 0x00000000
You can check the success of the download using the 'iminfo' command;
-this includes a checksum verification so you can be sure no data
+this includes a checksum verification so you can be sure no data
corruption happened:
- => imi 40100000
+ => imi 40100000
- ## Checking Image at 40100000 ...
- Image Name: 2.2.13 for initrd on TQM850L
- Image Type: PowerPC Linux Kernel Image (gzip compressed)
- Data Size: 335725 Bytes = 327 kB = 0 MB
- Load Address: 00000000
- Entry Point: 0000000c
- Verifying Checksum ... OK
+ ## Checking Image at 40100000 ...
+ Image Name: 2.2.13 for initrd on TQM850L
+ Image Type: PowerPC Linux Kernel Image (gzip compressed)
+ Data Size: 335725 Bytes = 327 kB = 0 MB
+ Load Address: 00000000
+ Entry Point: 0000000c
+ Verifying Checksum ... OK
"printenv" and "setenv" commands:
- => printenv bootargs
- bootargs=root=/dev/ram
+ => printenv bootargs
+ bootargs=root=/dev/ram
- => setenv bootargs root=/dev/nfs rw nfsroot=10.0.0.2:/LinuxPPC nfsaddrs=10.0.0.99:10.0.0.2
+ => setenv bootargs root=/dev/nfs rw nfsroot=10.0.0.2:/LinuxPPC nfsaddrs=10.0.0.99:10.0.0.2
- => printenv bootargs
- bootargs=root=/dev/nfs rw nfsroot=10.0.0.2:/LinuxPPC nfsaddrs=10.0.0.99:10.0.0.2
+ => printenv bootargs
+ bootargs=root=/dev/nfs rw nfsroot=10.0.0.2:/LinuxPPC nfsaddrs=10.0.0.99:10.0.0.2
- => bootm 40020000
- ## Booting Linux kernel at 40020000 ...
- Image Name: 2.2.13 for NFS on TQM850L
- Image Type: PowerPC Linux Kernel Image (gzip compressed)
- Data Size: 381681 Bytes = 372 kB = 0 MB
- Load Address: 00000000
- Entry Point: 0000000c
- Verifying Checksum ... OK
- Uncompressing Kernel Image ... OK
- Linux version 2.2.13 (wd@denx.local.net) (gcc version 2.95.2 19991024 (release)) #1 Wed Jul 19 02:35:17 MEST 2000
- Boot arguments: root=/dev/nfs rw nfsroot=10.0.0.2:/LinuxPPC nfsaddrs=10.0.0.99:10.0.0.2
- time_init: decrementer frequency = 187500000/60
- Calibrating delay loop... 49.77 BogoMIPS
- Memory: 15208k available (700k kernel code, 444k data, 32k init) [c0000000,c1000000]
- ...
+ => bootm 40020000
+ ## Booting Linux kernel at 40020000 ...
+ Image Name: 2.2.13 for NFS on TQM850L
+ Image Type: PowerPC Linux Kernel Image (gzip compressed)
+ Data Size: 381681 Bytes = 372 kB = 0 MB
+ Load Address: 00000000
+ Entry Point: 0000000c
+ Verifying Checksum ... OK
+ Uncompressing Kernel Image ... OK
+ Linux version 2.2.13 (wd@denx.local.net) (gcc version 2.95.2 19991024 (release)) #1 Wed Jul 19 02:35:17 MEST 2000
+ Boot arguments: root=/dev/nfs rw nfsroot=10.0.0.2:/LinuxPPC nfsaddrs=10.0.0.99:10.0.0.2
+ time_init: decrementer frequency = 187500000/60
+ Calibrating delay loop... 49.77 BogoMIPS
+ Memory: 15208k available (700k kernel code, 444k data, 32k init) [c0000000,c1000000]
+ ...
If you want to boot a Linux kernel with initial ram disk, you pass
the memory addreses of both the kernel and the initrd image (PPBCOOT
format!) to the "bootm" command:
- => imi 40100000 40200000
-
- ## Checking Image at 40100000 ...
- Image Name: 2.2.13 for initrd on TQM850L
- Image Type: PowerPC Linux Kernel Image (gzip compressed)
- Data Size: 335725 Bytes = 327 kB = 0 MB
- Load Address: 00000000
- Entry Point: 0000000c
- Verifying Checksum ... OK
-
- ## Checking Image at 40200000 ...
- Image Name: Simple Ramdisk Image
- Image Type: PowerPC Linux RAMDisk Image (gzip compressed)
- Data Size: 566530 Bytes = 553 kB = 0 MB
- Load Address: 00000000
- Entry Point: 00000000
- Verifying Checksum ... OK
-
- => bootm 40100000 40200000
- ## Booting Linux kernel at 40100000 ...
- Image Name: 2.2.13 for initrd on TQM850L
- Image Type: PowerPC Linux Kernel Image (gzip compressed)
- Data Size: 335725 Bytes = 327 kB = 0 MB
- Load Address: 00000000
- Entry Point: 0000000c
- Verifying Checksum ... OK
- Uncompressing Kernel Image ... OK
- ## Loading RAMDisk Image at 40200000 ...
- Image Name: Simple Ramdisk Image
- Image Type: PowerPC Linux RAMDisk Image (gzip compressed)
- Data Size: 566530 Bytes = 553 kB = 0 MB
- Load Address: 00000000
- Entry Point: 00000000
- Verifying Checksum ... OK
- Loading Ramdisk ... OK
- Linux version 2.2.13 (wd@denx.local.net) (gcc version 2.95.2 19991024 (release)) #1 Wed Jul 19 02:32:08 MEST 2000
- Boot arguments: root=/dev/ram
- time_init: decrementer frequency = 187500000/60
- Calibrating delay loop... 49.77 BogoMIPS
- ...
- RAMDISK: Compressed image found at block 0
- VFS: Mounted root (ext2 filesystem).
-
- bash#
+ => imi 40100000 40200000
+
+ ## Checking Image at 40100000 ...
+ Image Name: 2.2.13 for initrd on TQM850L
+ Image Type: PowerPC Linux Kernel Image (gzip compressed)
+ Data Size: 335725 Bytes = 327 kB = 0 MB
+ Load Address: 00000000
+ Entry Point: 0000000c
+ Verifying Checksum ... OK
+
+ ## Checking Image at 40200000 ...
+ Image Name: Simple Ramdisk Image
+ Image Type: PowerPC Linux RAMDisk Image (gzip compressed)
+ Data Size: 566530 Bytes = 553 kB = 0 MB
+ Load Address: 00000000
+ Entry Point: 00000000
+ Verifying Checksum ... OK
+
+ => bootm 40100000 40200000
+ ## Booting Linux kernel at 40100000 ...
+ Image Name: 2.2.13 for initrd on TQM850L
+ Image Type: PowerPC Linux Kernel Image (gzip compressed)
+ Data Size: 335725 Bytes = 327 kB = 0 MB
+ Load Address: 00000000
+ Entry Point: 0000000c
+ Verifying Checksum ... OK
+ Uncompressing Kernel Image ... OK
+ ## Loading RAMDisk Image at 40200000 ...
+ Image Name: Simple Ramdisk Image
+ Image Type: PowerPC Linux RAMDisk Image (gzip compressed)
+ Data Size: 566530 Bytes = 553 kB = 0 MB
+ Load Address: 00000000
+ Entry Point: 00000000
+ Verifying Checksum ... OK
+ Loading Ramdisk ... OK
+ Linux version 2.2.13 (wd@denx.local.net) (gcc version 2.95.2 19991024 (release)) #1 Wed Jul 19 02:32:08 MEST 2000
+ Boot arguments: root=/dev/ram
+ time_init: decrementer frequency = 187500000/60
+ Calibrating delay loop... 49.77 BogoMIPS
+ ...
+ RAMDISK: Compressed image found at block 0
+ VFS: Mounted root (ext2 filesystem).
+
+ bash#
Standalone HOWTO:
It's configured to run at address 0x00040004, so you can play with it
like that:
- => loads
- ## Ready for S-Record download ...
- ~>examples/hello_world.srec
- 1 2 3 4 5 6 7 8 9 10 11 ...
- [file transfer complete]
- [connected]
- ## Start Addr = 0x00040004
-
- => go 40004 Hello World! This is a test.
- ## Starting application at 0x00040004 ...
- Hello World
- argc = 7
- argv[0] = "40004"
- argv[1] = "Hello"
- argv[2] = "World!"
- argv[3] = "This"
- argv[4] = "is"
- argv[5] = "a"
- argv[6] = "test."
- argv[7] = "<NULL>"
- Hit any key to exit ...
-
- ## Application terminated, rc = 0x0
+ => loads
+ ## Ready for S-Record download ...
+ ~>examples/hello_world.srec
+ 1 2 3 4 5 6 7 8 9 10 11 ...
+ [file transfer complete]
+ [connected]
+ ## Start Addr = 0x00040004
+
+ => go 40004 Hello World! This is a test.
+ ## Starting application at 0x00040004 ...
+ Hello World
+ argc = 7
+ argv[0] = "40004"
+ argv[1] = "Hello"
+ argv[2] = "World!"
+ argv[3] = "This"
+ argv[4] = "is"
+ argv[5] = "a"
+ argv[6] = "test."
+ argv[7] = "<NULL>"
+ Hit any key to exit ...
+
+ ## Application terminated, rc = 0x0
Another example, which demonstrates how to register a CPM interrupt
handler with the PPCBoot code, can be found in 'examples/timer.c'.
character, but this is just a demo program. The application can be
controlled by the following keys:
- ? - print current values og the CPM Timer registers
- b - enable interrupts and start timer
- e - stop timer and disable interrupts
- q - quit application
-
- => loads
- ## Ready for S-Record download ...
- ~>examples/timer.srec
- 1 2 3 4 5 6 7 8 9 10 11 ...
- [file transfer complete]
- [connected]
- ## Start Addr = 0x00040004
-
- => go 40004
- ## Starting application at 0x00040004 ...
- TIMERS=0xfff00980
- Using timer 1
- tgcr @ 0xfff00980, tmr @ 0xfff00990, trr @ 0xfff00994, tcr @ 0xfff00998, tcn @ 0xfff0099c, ter @ 0xfff009b0
+ ? - print current values og the CPM Timer registers
+ b - enable interrupts and start timer
+ e - stop timer and disable interrupts
+ q - quit application
+
+ => loads
+ ## Ready for S-Record download ...
+ ~>examples/timer.srec
+ 1 2 3 4 5 6 7 8 9 10 11 ...
+ [file transfer complete]
+ [connected]
+ ## Start Addr = 0x00040004
+
+ => go 40004
+ ## Starting application at 0x00040004 ...
+ TIMERS=0xfff00980
+ Using timer 1
+ tgcr @ 0xfff00980, tmr @ 0xfff00990, trr @ 0xfff00994, tcr @ 0xfff00998, tcn @ 0xfff0099c, ter @ 0xfff009b0
Hit 'b':
- [q, b, e, ?] Set interval 1000000 us
- Enabling timer
+ [q, b, e, ?] Set interval 1000000 us
+ Enabling timer
Hit '?':
- [q, b, e, ?] ........
- tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0xef6, ter=0x0
+ [q, b, e, ?] ........
+ tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0xef6, ter=0x0
Hit '?':
- [q, b, e, ?] .
- tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0x2ad4, ter=0x0
+ [q, b, e, ?] .
+ tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0x2ad4, ter=0x0
Hit '?':
- [q, b, e, ?] .
- tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0x1efc, ter=0x0
+ [q, b, e, ?] .
+ tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0x1efc, ter=0x0
Hit '?':
- [q, b, e, ?] .
- tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0x169d, ter=0x0
+ [q, b, e, ?] .
+ tgcr=0x1, tmr=0xff1c, trr=0x3d09, tcr=0x0, tcn=0x169d, ter=0x0
Hit 'e':
- [q, b, e, ?] ...Stopping timer
+ [q, b, e, ?] ...Stopping timer
Hit 'q':
- [q, b, e, ?] ## Application terminated, rc = 0x0
+ [q, b, e, ?] ## Application terminated, rc = 0x0
So a typical memory configuration with 16 MB of DRAM could look like
this:
- 0x0000 0000 Exception Vector code
- :
- 0x0000 1FFF
- 0x0000 2000 Free for Application Use
- :
- :
-
- :
- :
- 0x00FB FF20 Monitor Stack (Growing downward)
- 0x00FB FFAC Board Info Data
- 0x00FC 0000 Malloc Arena
- :
- 0x00FD FFFF
- 0x00FE 0000 RAM Copy of Monitor Code
- 0x00FF FFFF [End of RAM]
+ 0x0000 0000 Exception Vector code
+ :
+ 0x0000 1FFF
+ 0x0000 2000 Free for Application Use
+ :
+ :
+
+ :
+ :
+ 0x00FB FF20 Monitor Stack (Growing downward)
+ 0x00FB FFAC Board Info Data
+ 0x00FC 0000 Malloc Arena
+ :
+ 0x00FD FFFF
+ 0x00FE 0000 RAM Copy of Monitor Code
+ 0x00FF FFFF [End of RAM]
System Initialization:
*p = '\0';
return (p - buf);
}
+
+
+#ifdef CONFIG_LOADB /* loadb command (load binary) included */
+
+#define XON_CHAR 17
+#define XOFF_CHAR 19
+#define START_CHAR 0x01
+#define END_CHAR 0x0D
+#define SPACE 0x20
+#define K_ESCAPE 0x23
+#define SEND_TYPE 'S'
+#define DATA_TYPE 'D'
+#define ACK_TYPE 'Y'
+#define NACK_TYPE 'N'
+#define BREAK_TYPE 'B'
+#define tochar(x) ((char) (((x) + SPACE) & 0xff))
+#define untochar(x) ((int) (((x) - SPACE) & 0xff))
+
+extern int os_data_count;
+extern int os_data_header[8];
+
+void set_kerm_bin_mode(unsigned long *);
+int k_recv(void);
+int s1boot(unsigned long *, unsigned long *, int *);
+static ulong load_serial_bin (ulong offset);
+
+
+char his_eol; /* character he needs at end of packet */
+int his_pad_count; /* number of pad chars he needs */
+char his_pad_char; /* pad chars he needs */
+char his_quote; /* quote chars he'll use */
+
+
+void do_load_serial_bin (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
+{
+ ulong offset = 0;
+ ulong addr;
+ int i;
+ int loadb_baudrate = bd->bi_baudrate;
+
+ if (argc >= 2) {
+ offset = simple_strtoul(argv[1], NULL, 16);
+ }
+ if (argc == 3) {
+ loadb_baudrate = (int)simple_strtoul(argv[2], NULL, 10);
+
+ /* default to current baudrate */
+ if (loadb_baudrate == 0)
+ loadb_baudrate = bd->bi_baudrate;
+ }
+
+ command_repeat_off();
+
+ if (loadb_baudrate != bd->bi_baudrate) {
+ printf ("## Switch baudrate to %d bps and press ENTER ...\n",
+ loadb_baudrate);
+ udelay(50000);
+ serial_setbrg (bd->bi_intfreq, loadb_baudrate);
+ udelay(50000);
+ for (;;) {
+ if (serial_getc() == '\r')
+ break;
+ }
+ }
+ printf ("## Ready for binary (kermit) download ...\n");
+
+ addr = load_serial_bin (offset);
+
+ /*
+ * Gather any trailing characters (for instance, the ^D which
+ * is sent by 'cu' after sending a file), and give the
+ * box some time (100 * 1 ms)
+ */
+ for (i=0; i<100; ++i) {
+ if (serial_tstc()) {
+ (void) serial_getc();
+ }
+ udelay(1000);
+ }
+
+ if (addr == ~0) {
+ printf ("## Binary (kermit) download aborted\n");
+ } else {
+ printf ("## Start Addr = 0x%08lx\n", addr);
+ }
+
+ if (loadb_baudrate != bd->bi_baudrate) {
+ printf ("## Switch baudrate to %d bps and press ESC ...\n",
+ (int)bd->bi_baudrate);
+ udelay (50000);
+ serial_setbrg (bd->bi_intfreq, bd->bi_baudrate);
+ udelay (50000);
+ for (;;) {
+ if (serial_getc() == 0x1B) /* ESC */
+ break;
+ }
+ }
+}
+
+
+static ulong
+load_serial_bin (ulong offset)
+{
+ set_kerm_bin_mode((ulong *)offset);
+ k_recv();
+ return offset;
+}
+
+void send_pad(void)
+{
+ int count = his_pad_count;
+ while (count-- > 0) serial_putc(his_pad_char);
+}
+
+/* converts escaped kermit char to binary char */
+char ktrans(char in)
+{
+ if ((in & 0x60) == 0x40)
+ {
+ return (char) (in & ~0x40);
+ }
+ else if ((in & 0x7f) == 0x3f)
+ {
+ return (char) (in | 0x40);
+ }
+ else return in;
+}
+
+int chk1(char *buffer)
+{
+ int total = 0;
+ while (*buffer)
+ {
+ total += *buffer++;
+ }
+ return (int) ((total + ((total >> 6) & 0x03)) & 0x3f);
+}
+
+void s1_sendpacket(char *packet)
+{
+ send_pad();
+ while (*packet)
+ {
+ serial_putc(*packet++);
+ }
+}
+
+static char a_b[24];
+void send_ack(int n)
+{
+ a_b[0] = START_CHAR;
+ a_b[1] = tochar(3);
+ a_b[2] = tochar(n);
+ a_b[3] = ACK_TYPE;
+ a_b[4] = '\0';
+ a_b[4] = tochar(chk1(&a_b[1]));
+ a_b[5] = his_eol;
+ a_b[6] = '\0';
+ s1_sendpacket(a_b);
+}
+
+void send_nack(int n)
+{
+ a_b[0] = START_CHAR;
+ a_b[1] = tochar(3);
+ a_b[2] = tochar(n);
+ a_b[3] = NACK_TYPE;
+ a_b[4] = '\0';
+ a_b[4] = tochar(chk1(&a_b[1]));
+ a_b[5] = his_eol;
+ a_b[6] = '\0';
+ s1_sendpacket(a_b);
+}
+
+
+
+/* os_data_* takes an OS Open image and puts it into memory, and
+ puts the boot header in an array named os_data_header
+
+ if image is binary, no header is stored in os_data_header.
+*/
+void (*os_data_init)(void);
+void (*os_data_char)(char new_char);
+static int os_data_state, os_data_state_saved;
+int os_data_count;
+static int os_data_count_saved;
+static char *os_data_addr, *os_data_addr_saved;
+static char *bin_start_address;
+int os_data_header[8];
+void image_data_init(void)
+{
+ os_data_state = 0;
+ os_data_count = 32;
+ os_data_addr = (char *) os_data_header;
+}
+void bin_data_init(void)
+{
+ os_data_state = 0;
+ os_data_count = 0;
+ os_data_addr = bin_start_address;
+}
+void os_data_save(void)
+{
+ os_data_state_saved = os_data_state;
+ os_data_count_saved = os_data_count;
+ os_data_addr_saved = os_data_addr;
+}
+void os_data_restore(void)
+{
+ os_data_state = os_data_state_saved;
+ os_data_count = os_data_count_saved;
+ os_data_addr = os_data_addr_saved;
+}
+void bin_data_char(char new_char)
+{
+ switch (os_data_state)
+ {
+ case 0: /* data */
+ *os_data_addr++ = new_char;
+ --os_data_count;
+ break;
+ }
+}
+void set_kerm_bin_mode(unsigned long *addr)
+{
+ bin_start_address = (char *) addr;
+ os_data_init = bin_data_init;
+ os_data_char = bin_data_char;
+}
+
+
+/* k_data_* simply handles the kermit escape translations */
+static int k_data_escape, k_data_escape_saved;
+void k_data_init(void)
+{
+ k_data_escape = 0;
+ os_data_init();
+}
+void k_data_save(void)
+{
+ k_data_escape_saved = k_data_escape;
+ os_data_save();
+}
+void k_data_restore(void)
+{
+ k_data_escape = k_data_escape_saved;
+ os_data_restore();
+}
+void k_data_char(char new_char)
+{
+ if (k_data_escape)
+ {
+ /* last char was escape - translate this character */
+ os_data_char(ktrans(new_char));
+ k_data_escape = 0;
+ }
+ else
+ {
+ if (new_char == his_quote)
+ {
+ /* this char is escape - remember */
+ k_data_escape = 1;
+ }
+ else
+ {
+ /* otherwise send this char as-is */
+ os_data_char(new_char);
+ }
+ }
+}
+
+#define SEND_DATA_SIZE 20
+char send_parms[SEND_DATA_SIZE];
+char *send_ptr;
+
+/* handle_send_packet interprits the protocol info and builds and
+ sends an appropriate ack for what we can do */
+void handle_send_packet(int n)
+{
+ int length = 3;
+ int bytes;
+
+ /* initialize some protocol parameters */
+ his_eol = END_CHAR; /* default end of line character */
+ his_pad_count = 0;
+ his_pad_char = '\0';
+ his_quote = K_ESCAPE;
+
+ /* ignore last character if it filled the buffer */
+ if (send_ptr == &send_parms[SEND_DATA_SIZE - 1]) --send_ptr;
+ bytes = send_ptr - send_parms; /* how many bytes we'll process */
+ do
+ {
+ if (bytes-- <= 0) break;
+ /* handle MAXL - max length */
+ /* ignore what he says - most I'll take (here) is 94 */
+ a_b[++length] = tochar(94);
+ if (bytes-- <= 0) break;
+ /* handle TIME - time you should wait for my packets */
+ /* ignore what he says - don't wait for my ack longer than 1 second */
+ a_b[++length] = tochar(1);
+ if (bytes-- <= 0) break;
+ /* handle NPAD - number of pad chars I need */
+ /* remember what he says - I need none */
+ his_pad_count = untochar(send_parms[2]);
+ a_b[++length] = tochar(0);
+ if (bytes-- <= 0) break;
+ /* handle PADC - pad chars I need */
+ /* remember what he says - I need none */
+ his_pad_char = ktrans(send_parms[3]);
+ a_b[++length] = 0x40; /* He should ignore this */
+ if (bytes-- <= 0) break;
+ /* handle EOL - end of line he needs */
+ /* remember what he says - I need CR */
+ his_eol = untochar(send_parms[4]);
+ a_b[++length] = tochar(END_CHAR);
+ if (bytes-- <= 0) break;
+ /* handle QCTL - quote control char he'll use */
+ /* remember what he says - I'll use '#' */
+ his_quote = send_parms[5];
+ a_b[++length] = '#';
+ if (bytes-- <= 0) break;
+ /* handle QBIN - 8-th bit prefixing */
+ /* ignore what he says - I refuse */
+ a_b[++length] = 'N';
+ if (bytes-- <= 0) break;
+ /* handle CHKT - the clock check type */
+ /* ignore what he says - I do type 1 (for now) */
+ a_b[++length] = '1';
+ if (bytes-- <= 0) break;
+ /* handle REPT - the repeat prefix */
+ /* ignore what he says - I refuse (for now) */
+ a_b[++length] = 'N';
+ if (bytes-- <= 0) break;
+ /* handle CAPAS - the capabilities mask */
+ /* ignore what he says - I only do long packets - I don't do windows */
+ a_b[++length] = tochar(2); /* only long packets */
+ a_b[++length] = tochar(0); /* no windows */
+ a_b[++length] = tochar(94); /* large packet msb */
+ a_b[++length] = tochar(94); /* large packet lsb */
+ } while (0);
+
+ a_b[0] = START_CHAR;
+ a_b[1] = tochar(length);
+ a_b[2] = tochar(n);
+ a_b[3] = ACK_TYPE;
+ a_b[++length] = '\0';
+ a_b[length] = tochar(chk1(&a_b[1]));
+ a_b[++length] = his_eol;
+ a_b[++length] = '\0';
+ s1_sendpacket(a_b);
+}
+
+/* k_recv receives a OS Open image file over kermit line */
+int k_recv(void)
+{
+ char new_char;
+ char k_state, k_state_saved;
+ int sum;
+ int done;
+ int length;
+ int n, last_n;
+ int z = 0;
+ int len_lo, len_hi;
+
+ /* initialize some protocol parameters */
+ his_eol = END_CHAR; /* default end of line character */
+ his_pad_count = 0;
+ his_pad_char = '\0';
+ his_quote = K_ESCAPE;
+
+ /* initialize the k_recv and k_data state machine */
+ done = 0;
+ k_state = 0;
+ k_data_init();
+ k_state_saved = k_state;
+ k_data_save();
+ n = 0; /* just to get rid of a warning */
+ last_n = -1;
+
+ /* expect this "type" sequence (but don't check):
+ S: send initiate
+ F: file header
+ D: data (multiple)
+ Z: end of file
+ B: break transmission
+ */
+
+ /* enter main loop */
+ while (!done)
+ {
+ /* set the send packet pointer to begining of send packet parms */
+ send_ptr = send_parms;
+
+ /* With each packet, start summing the bytes starting with the length.
+ Save the current sequence number.
+ Note the type of the packet.
+ If a character less than SPACE (0x20) is received - error.
+ */
+
+#if 0
+ /* OLD CODE, Prior to checking sequence numbers */
+ /* first have all state machines save current states */
+ k_state_saved = k_state;
+ k_data_save();
+#endif
+
+ /* get a packet */
+ /* wait for the starting character */
+ while (serial_getc() != START_CHAR);
+ /* get length of packet */
+ sum = 0;
+ new_char = serial_getc();
+ if ((new_char & 0xE0) == 0) goto packet_error;
+ sum += new_char & 0xff;
+ length = untochar(new_char);
+ /* get sequence number */
+ new_char = serial_getc();
+ if ((new_char & 0xE0) == 0) goto packet_error;
+ sum += new_char & 0xff;
+ n = untochar(new_char);
+ --length;
+
+ /* NEW CODE - check sequence numbers for retried packets */
+ /* Note - this new code assumes that the sequence number is correctly
+ received. Handling an invalid sequence number adds another layer
+ of complexity that may not be needed - yet! At this time, I'm hoping
+ that I don't need to buffer the incoming data packets and can write
+ the data into memory in real time. */
+ if (n == last_n)
+ {
+ /* same sequence number, restore the previous state */
+ k_state = k_state_saved;
+ k_data_restore();
+ }
+ else
+ {
+ /* new sequence number, checkpoint the download */
+ last_n = n;
+ k_state_saved = k_state;
+ k_data_save();
+ }
+ /* END NEW CODE */
+
+ /* get packet type */
+ new_char = serial_getc();
+ if ((new_char & 0xE0) == 0) goto packet_error;
+ sum += new_char & 0xff;
+ k_state = new_char;
+ --length;
+ /* check for extended length */
+ if (length == -2)
+ {
+ /* (length byte was 0, decremented twice) */
+ /* get the two length bytes */
+ new_char = serial_getc();
+ if ((new_char & 0xE0) == 0) goto packet_error;
+ sum += new_char & 0xff;
+ len_hi = untochar(new_char);
+ new_char = serial_getc();
+ if ((new_char & 0xE0) == 0) goto packet_error;
+ sum += new_char & 0xff;
+ len_lo = untochar(new_char);
+ length = len_hi * 95 + len_lo;
+ /* check header checksum */
+ new_char = serial_getc();
+ if ((new_char & 0xE0) == 0) goto packet_error;
+ if (new_char != tochar((sum + ((sum >> 6) & 0x03)) & 0x3f))
+ goto packet_error;
+ sum += new_char & 0xff;
+ /* --length; *//* new length includes only data and block check to come */
+ }
+ /* bring in rest of packet */
+ while (length > 1)
+ {
+ new_char = serial_getc();
+ if ((new_char & 0xE0) == 0) goto packet_error;
+ sum += new_char & 0xff;
+ --length;
+ if (k_state == DATA_TYPE)
+ {
+ /* pass on the data if this is a data packet */
+ k_data_char(new_char);
+ }
+ else if (k_state == SEND_TYPE)
+ {
+ /* save send pack in buffer as is */
+ *send_ptr++ = new_char;
+ /* if too much data, back off the pointer */
+ if (send_ptr >= &send_parms[SEND_DATA_SIZE]) --send_ptr;
+ }
+ }
+ /* get and validate checksum character */
+ new_char = serial_getc();
+ if ((new_char & 0xE0) == 0) goto packet_error;
+ if (new_char != tochar((sum + ((sum >> 6) & 0x03)) & 0x3f))
+ goto packet_error;
+ /* get END_CHAR */
+ new_char = serial_getc();
+ if (new_char != END_CHAR)
+ {
+packet_error:
+ /* restore state machines */
+ k_state = k_state_saved;
+ k_data_restore();
+ /* send a negative acknowledge packet in */
+ send_nack(n);
+ }
+ else if (k_state == SEND_TYPE)
+ {
+ /* crack the protocol parms, build an appropriate ack packet */
+ handle_send_packet(n);
+ }
+ else
+ {
+ /* send simple acknowledge packet in */
+ send_ack(n);
+ /* quit if end of transmission */
+ if (k_state == BREAK_TYPE) done = 1;
+ }
+ ++z;
+ }
+ return 0;
+}
+
+#endif /* CONFIG_LOADB */
image_header_t header;
+
void do_bootm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[])
{
ulong iflag;
ulong data, len, checksum;
ulong initrd_start, initrd_end;
ulong cmd_start, cmd_end;
- int verify;
+ ulong *len_ptr;
+ int i, verify;
char *cmdline;
char *name, *s;
bd_t *kbd;
return;
}
- print_header (hdr);
+ /* for multi-file images we need the data part, too */
+ print_header ((image_header_t *)addr);
data = addr + sizeof(image_header_t);
len = hdr->ih_size;
printf ("OK\n");
}
+ len_ptr = (ulong *)data;
+
if ((hdr->ih_os != IH_OS_LINUX) || (hdr->ih_arch != IH_CPU_PPC)) {
printf ("Unsupported OS or Architecture\n");
return;
break;
case IH_TYPE_KERNEL: name = "Kernel Image";
break;
+ case IH_TYPE_MULTI: name = "Multi-File Image";
+ len = len_ptr[0];
+ /* OS kernel is always the first image */
+ data += 8; /* kernel_len + terminator */
+ for (i=1; len_ptr[i]; ++i)
+ data += 4;
+ break;
default: printf ("Wrong Image Type for %s command\n", cmdtp->name);
return;
}
/*
- * We have reached the point of no return: we are going to
- * overwrite all exception vector code, so we cannot easily
- * recover from any failures any more...
+ * We have reached the point of no return: we are going to
+ * overwrite all exception vector code, so we cannot easily
+ * recover from any failures any more...
*/
iflag = disable_interrupts();
switch (hdr->ih_type) {
case IH_TYPE_STANDALONE:
- appl = (int (*)(cmd_tbl_t *, bd_t *, int, int, char *[]))hdr->ih_ep;
+ appl = (int (*)(cmd_tbl_t *, bd_t *, int, int, char *[]))hdr->ih_ep;
(*appl)(cmdtp, bd, flag, argc-1, &argv[1]);
/* just in case we return */
enable_interrupts();
break;
case IH_TYPE_KERNEL:
+ case IH_TYPE_MULTI:
/* handled below */
break;
default:
/*
* Booting a (Linux) kernel image
*
- * Allocate space for command line and board info - the
- * address should be as high as possible within the reach of
- * the kernel (see CFG_BOOTMAPSZ settings), but in unused
- * memory, which means far enough below the current stack
- * pointer.
+ * Allocate space for command line and board info - the
+ * address should be as high as possible within the reach of
+ * the kernel (see CFG_BOOTMAPSZ settings), but in unused
+ * memory, which means far enough below the current stack
+ * pointer.
*/
asm( "mr %0,1": "=r"(sp) : );
initrd_start = (ulong)kbd - hdr->ih_size;
initrd_start &= ~(4096 - 1); /* align on page */
initrd_end = initrd_start + hdr->ih_size;
- printf (" Loading Ramdisk ... ");
+ printf (" Loading Ramdisk to %08lx ... ", initrd_start);
memcpy ((void *)initrd_start,
(void *)(addr + sizeof(image_header_t)),
hdr->ih_size );
printf ("OK\n");
+ } else if ((hdr->ih_type==IH_TYPE_MULTI) && (len_ptr[1])) {
+ u_long i_start = data + len_ptr[0];
+ u_long tail = len_ptr[0] % 4;
+
+ if (tail) {
+ i_start += 4 - tail;
+ }
+
+ initrd_start = (ulong)kbd - len_ptr[1];
+ initrd_start &= ~(4096 - 1); /* align on page */
+ initrd_end = initrd_start + len_ptr[1];
+ printf (" Loading Ramdisk to %08lx ... ", initrd_start);
+ memcpy ((void *)initrd_start, (void *)i_start, len_ptr[1]);
+ printf ("OK\n");
} else {
/*
* no initrd image
continue;
}
- print_header (hdr);
+ /* for multi-file images we need the data part, too */
+ print_header ((image_header_t *)addr);
data = addr + sizeof(image_header_t);
len = hdr->ih_size;
hdr->ih_size, hdr->ih_size>>10, hdr->ih_size>>20);
printf (" Load Address: %08x\n", hdr->ih_load);
printf (" Entry Point: %08x\n", hdr->ih_ep);
+
+ if (hdr->ih_type == IH_TYPE_MULTI) {
+ int i;
+ ulong *len_ptr = (ulong *)((ulong)hdr + sizeof(image_header_t));
+
+ printf (" Contents:\n");
+ for (i=0; *len_ptr; ++i, ++len_ptr) {
+ printf (" Image %d: %8ld Bytes = %ld kB = %ld MB\n",
+ i, *len_ptr, *len_ptr>>10, *len_ptr>>20);
+ }
+ }
}
switch (hdr->ih_os) {
case IH_OS_INVALID: os = "Invalid OS"; break;
- case IH_OS_LINUX: os = "Linux"; break;
+ case IH_OS_LINUX: os = "Linux"; break;
default: os = "Unknown OS"; break;
}
switch (hdr->ih_arch) {
- case IH_CPU_INVALID: arch = "Invalid CPU"; break;
+ case IH_CPU_INVALID: arch = "Invalid CPU"; break;
case IH_CPU_ALPHA: arch = "Alpha"; break;
case IH_CPU_ARM: arch = "ARM"; break;
case IH_CPU_I386: arch = "Intel x86"; break;
case IH_TYPE_STANDALONE:type = "Standalone Program"; break;
case IH_TYPE_KERNEL: type = "Kernel Image"; break;
case IH_TYPE_RAMDISK: type = "RAMDisk Image"; break;
+ case IH_TYPE_MULTI: type = "Multi-File Image"; break;
default: type = "Unknown Image"; break;
}
{
z_stream s;
int r, i, flags;
-
+
/* skip header */
i = 10;
flags = src[3];
printf ("Error: gunzip out of data in header\n");
return (-1);
}
-
+
s.zalloc = zalloc;
s.zfree = zfree;
r = inflateInit2(&s, -MAX_WBITS);
}
*lenp = s.next_out - (unsigned char *) dst;
inflateEnd(&s);
-
+
return (0);
}
static void
netboot_common (int proto, cmd_tbl_t *cmdtp, bd_t *bd, int argc, char *argv[])
{
-#ifdef CONFIG_8xx
ulong addr;
int rc;
char *s;
do_bootm (cmdtp, bd, 0, 2, local_args);
}
-
-#else
- printf ("Network Support not implemented yet on this architecture\n");
-#endif
}
int rc;
extern void flash_sect_protect (int p, ulong addr_first, ulong addr_last);
extern void flash_sect_erase (ulong addr_first, ulong addr_last);
+#ifdef CONFIG_CPCI405
+ ulong sector_flash_addr;
+ ulong sector_flash_size;
+ ulong sector_flash_offs;
+ int i;
+ flash_info_t *info;
env_init();
+ /*
+ * Calculate environment variables sector address and size
+ */
+ info = addr2info((ulong)flash_addr);
+ for (i=0; i<info->sector_count; i++)
+ {
+ if (info->start[i] >= (ulong)flash_addr)
+ break;
+ }
+ sector_flash_addr = info->start[i-1];
+ sector_flash_size = info->start[i] - info->start[i-1];
+ sector_flash_offs = (ulong)flash_addr - info->start[i-1];
+
+#if 1
+ printf("\nflash_addr = %08lx sector_addr=%08lx size=%08lx offs=%08lx\n",
+ (ulong)flash_addr, sector_flash_addr, sector_flash_size, sector_flash_offs);
+#endif
+
+ /*
+ * Copy sector down to ram
+ */
+ memcpy((uchar *)0x10000, (uchar *)sector_flash_addr, sector_flash_size);
+
+ /*
+ * Copy new environment variables to ram image of flash sector
+ */
+ memcpy((uchar *)(0x10000+sector_flash_offs), (uchar *)environment, env_size);
+
+ flash_sect_protect (0, sector_flash_addr, sector_flash_addr+sector_flash_size-1);
+
+ printf ("Erasing Flash...");
+ flash_sect_erase (sector_flash_addr, sector_flash_addr+sector_flash_size-1);
+
+ printf ("Saving Environment to Flash...\n");
+ switch (rc = flash_write ((uchar *)0x10000, sector_flash_addr, sector_flash_size)) {
+ case 0: break;
+ case 1: printf ("Timeout writing to Flash\n");
+ break;
+ case 2: printf ("Flash not Erased\n");
+ break;
+ case 4: printf ("Can't write to protected Flash sectors\n");
+ break;
+ default:
+ printf ("%s[%d] FIXME: rc=%d\n",__FILE__,__LINE__,rc);
+ }
+
+ flash_sect_protect (1, sector_flash_addr, sector_flash_addr+sector_flash_size-1);
+#else
+ env_init();
+
flash_sect_protect (0, (ulong)flash_addr, (ulong)flash_addr+env_size-1);
printf ("Erasing Flash...");
}
flash_sect_protect (1, (ulong)flash_addr, (ulong)flash_addr+env_size-1);
+#endif
}
/*
CMD_TBL_TFTPB,
CMD_TBL_RARPB,
CMD_TBL_LOADS,
+#ifdef CONFIG_LOADB
+ CMD_TBL_LOADB,
+#endif
CMD_TBL_MD,
CMD_TBL_MM,
CMD_TBL_NM,
void flash_erase (flash_info_t *info, int s_first, int s_last)
{
volatile FLASH_WORD_SIZE *addr = (FLASH_WORD_SIZE *)(info->start[0]);
+ volatile FLASH_WORD_SIZE *addr2;
int flag, prot, sect, l_sect;
ulong start, now, last;
/* Disable interrupts which might cause a timeout here */
flag = disable_interrupts();
- addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
- addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
- addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;
- addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
- addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
-
/* Start erase on unprotected sectors */
for (sect = s_first; sect<=s_last; sect++) {
if (info->protect[sect] == 0) { /* not protected */
- addr = (FLASH_WORD_SIZE *)(info->start[sect]);
+ addr2 = (FLASH_WORD_SIZE *)(info->start[sect]);
if (info->flash_id & FLASH_MAN_SST)
{
addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;
addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
- addr[0] = (FLASH_WORD_SIZE)0x00500050; /* block erase */
- udelay(30000); /* wait 30 ms */
+ addr2[0] = (FLASH_WORD_SIZE)0x00500050; /* block erase */
+ udelay(50000); /* wait 50 ms */
}
else
- addr[0] = (FLASH_WORD_SIZE)0x00300030; /* sector erase */
+ {
+ addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
+ addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
+ addr[ADDR0] = (FLASH_WORD_SIZE)0x00800080;
+ addr[ADDR0] = (FLASH_WORD_SIZE)0x00AA00AA;
+ addr[ADDR1] = (FLASH_WORD_SIZE)0x00550055;
+ addr2[0] = (FLASH_WORD_SIZE)0x00300030; /* sector erase */
+ }
l_sect = sect;
}
}
void do_load_serial (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+#ifdef CONFIG_LOADB
+
+#define CMD_TBL_LOADB MK_CMD_TBL_ENTRY( \
+ "loadb", 5, 3, do_load_serial_bin, \
+ "loadb - load binary file over serial line (kermit mode)\n", \
+ "[ off ] [ baud ]\n" \
+ " - load binary file over serial line" \
+ " with offset 'off' and baudrate 'baud'\n" \
+)
+
+void do_load_serial_bin (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]);
+
+#endif /* CONFIG_LOADB */
+
#define CMD_TBL_RESET MK_CMD_TBL_ENTRY( \
"reset", 5, 1, do_reset, \
"reset - Perform RESET of the CPU\n", \
#define PROFF_ENET PROFF_SCC2
#define CPM_CR_ENET CPM_CR_CH_SCC2
#define SCC_ENET 1
-#define PA_ENET_RXD ((ushort)0x0004) /* PA 13 */
-#define PA_ENET_TXD ((ushort)0x0008) /* PA 12 */
+#define PA_ENET_RXD ((ushort)0x0004) /* PA 13 */
+#define PA_ENET_TXD ((ushort)0x0008) /* PA 12 */
#define PA_ENET_RCLK ((ushort)0x0200) /* PA 6 */
#define PA_ENET_TCLK ((ushort)0x0800) /* PA 4 */
#define PB_ENET_TENA ((uint)0x00002000) /* PB 18 */
/*
* Image Types
+ *
+ * "Standalone Programs" are directly runnable in the environment
+ * provided by PPCBoot; it is expected that (if they behave
+ * well) you can continue to work in PPCBoot after return from
+ * the Standalone Program.
+ * "OS Kernel Images" are usually images of some Embedded OS which
+ * will take over control completely. Usually these programs
+ * will install their own set of exception handlers, device
+ * drivers, set up the MMU, etc. - this means, that you cannot
+ * expect to re-enter PPCBoot except by resetting the CPU.
+ * "RAMDisk Images" are more or less just data blocks, and their
+ * parameters (address, size) are passed to an OS kernel that is
+ * being started.
+ * "Multi-File Images" contain several images, typically an OS
+ * (Linux) kernel image and one or more data images like
+ * RAMDisks. This construct is useful for instance when you want
+ * to boot over the network using BOOTP etc., where the boot
+ * server provides just a single image file, but you want to get
+ * for instance an OS kernel and a RAMDisk image.
+ *
+ * "Multi-File Images" start with a list of image sizes, each
+ * image size (in bytes) specified by an "uint32_t" in network
+ * byte order. This list is terminated by an "(uint32_t)0".
+ * Immediately after the terminating 0 follow the images, one by
+ * one, all aligned on "uint32_t" boundaries (size rounded up to
+ * a multiple of 4 bytes).
*/
+
#define IH_TYPE_INVALID 0 /* Invalid Image */
#define IH_TYPE_STANDALONE 1 /* Standalone Program */
#define IH_TYPE_KERNEL 2 /* OS Kernel Image */
#define IH_TYPE_RAMDISK 3 /* RAMDisk Image */
+#define IH_TYPE_MULTI 4 /* Multi-File Image */
/*
* Compression Types
static RTXBD *rtx;
-void
-dumpdata(void *buf, int nbytes)
-{
- unsigned int offset = 0;
- unsigned char *cp = buf;
- int i;
-
- printf("\n");
- while (nbytes > 0) {
- printf("%04x ", offset);
- for (i = 0; i < 16; i++) {
- if ((nbytes - i) < 0)
- break;
- printf(" %02x", *(cp+offset));
- offset++;
- }
- printf("\n");
- nbytes -= i;
- }
-}
int eth_send(volatile void *packet, int length)
{
+++ /dev/null
-/*
- * LiMon - "Files"
- *
- * Copyright 2000 Neil Russell.
- * (See License)
- */
-
-#ifndef __FILES_H__
-#define __FILES_H__
-
-
-/*
- * LiMon looks for load images in "files", embedded inside a single
- * image that was downloaded from the network, loaded from disk or
- * found in ROM. This is most commonly used to store a linux kernel
- * and a file system image. Fields in this structure are in network
- * byte order (big-endian).
- *
- * There are several requirements: The image is loaded from the
- * network or from disk into memory starting at 4MB; there must be
- * sufficient memory to load the image. If there is an initrd
- * file system, it must be last in the image. Kernel images that
- * are to be moved down in memory must be no larger than 4MB-1KB.
- * Kernels that are run in place can be any size. Since there is
- * no explicit handling of overlaps, these restrictions are to
- * prevent the downloaded image getting overwritten when copying
- * parts to their final resting place.
- */
-
-typedef struct
-{
- ulong magic; /* Head magic number */
- ulong addr; /* Load address */
- ulong size; /* This file size */
- ulong tag; /* Type of image */
-
- ulong total; /* Total image size (1st file only) */
- // ulong cksum; /* Total image checksum (1st only) */
-}
- Fhdr_t;
-
-
-#define F_MAGIC 0x6e6a725e
-
-/*
- * Tags - used to identify what kind of file this is.
- */
-#define T_KERN_0 0x6b657230 /* Linux kernel loaded at 0 */
-#define T_KERN_X 0x6b657278 /* Linux kernel loaded anywhere */
-#define T_INITRD 0x696e7264 /* FS image for initrd (end of mem) */
-
-#endif /* __FILES_H__ */
* for our ethernet address. We can only respond if we
* know our IP address.
*/
+#ifdef ET_DEBUG
printf("Got ARP\n");
+#endif
arp = (ARP_t *)ip;
if (len < ARP_HDR_SIZE)
{
#include "net.h"
#include "tftp.h"
#include "bootp.h"
-#include "files.h"
#define WELL_KNOWN_PORT 69 /* Well known TFTP port # */
/* ImageSize += len; */
store_block(TftpBlock - 1, pkt + 2, len);
- if (TftpBlock == 1)
- {
- Fhdr_t * hp;
-
- /*
- * This is the first block. Check the magic
- * number as a sanity check for the following.
- */
- hp = (Fhdr_t *)TftpLoadAddress;
- if (hp->magic == F_MAGIC)
- {
- int i;
-
- /*
- * Get the image size and calculate
- * the number of 512 byte blocks in
- * the image. If we see that the
- * image is too large, send an error
- * and quit.
- */
- TftpSize = (hp->total + 511) / 512;
-
- printf(">");
- for (i = 0; i < NDOTS; i++)
- printf(" ");
- printf("<\rLoading: >");
- }
- else
- {
- TftpSize = 0;
- printf("-");
- }
- }
-
- if (TftpSize)
- {
- int i;
-
- i = (TftpBlock * NDOTS) / TftpSize -
- ((TftpBlock - 1) * NDOTS) / TftpSize;
- while (i-- > 0)
- printf(".");
- }
- else
- {
- if (TftpBlock % 8 == 0)
- printf("%c\b", "\\|/-"[TftpBlock / 8 % 4]);
- }
-
/*
* Acknoledge the block just received, which will prompt
* the server for the next one.
static volatile int rx_ptr = -1;
-static char emac_hwd_addr[ENET_ADDR_LENGTH]=
-{0x00, 0x02, 0x27, 0x11, 0x22, 0x33};
+static char emac_hwd_addr[ENET_ADDR_LENGTH];
static void enet_rcv (unsigned long malisr);
#endif
}
+ memcpy(emac_hwd_addr, bis->bi_enetaddr, ENET_ADDR_LENGTH);
+
reg = 0x00000000;
reg |= emac_hwd_addr[0]; /* set high address */
* Wolfgang Denk, wd@denx.de
* All rights reserved.
*
- * $Date: 2000/08/10 23:19:49 $
- * $Revision: 1.4 $
+ * $Date: 2000/10/07 13:34:15 $
+ * $Revision: 1.6 $
*/
#include <errno.h>
{ IH_TYPE_STANDALONE, "standalone", "Standalone Program", },
{ IH_TYPE_KERNEL, "kernel", "Kernel Image", },
{ IH_TYPE_RAMDISK, "ramdisk", "RAMDisk Image", },
+ { IH_TYPE_MULTI, "multi", "Multi-File Image", },
{ -1, "", "", },
};
{ -1, "", "", },
};
+static void copy_file (int, const char *, int);
static void usage (void);
static void print_header (image_header_t *);
static void print_type (image_header_t *);
int dflag = 0;
int eflag = 0;
int lflag = 0;
+int vflag = 0;
int opt_os = IH_OS_LINUX;
int opt_arch = IH_CPU_PPC;
int opt_type = IH_TYPE_KERNEL;
int
main (int argc, char **argv)
{
- int ifd, dfd;
+ int ifd;
uint32_t checksum;
uint32_t addr;
uint32_t ep;
usage ();
name = *++argv;
goto NXTARG;
+ case 'v':
+ vflag++;
+ break;
default:
usage ();
}
if (lflag) {
ifd = open(imagefile, O_RDONLY);
} else {
- ifd = open(imagefile, O_WRONLY|O_CREAT|O_TRUNC, 0666);
+ ifd = open(imagefile, O_RDWR|O_CREAT|O_TRUNC, 0666);
}
if (ifd < 0) {
imagefile);
}
- print_header (hdr);
+ /* for multi-file images we need the data part, too */
+ print_header ((image_header_t *)ptr);
(void) munmap(ptr, sbuf.st_size);
(void) close (ifd);
/*
* Must be -w then:
*
- * Create new image file
+ * write dummy header, to be fixed later
*/
+ memset (hdr, 0, sizeof(image_header_t));
- if ((dfd = open(datafile, O_RDONLY)) < 0) {
- fprintf (stderr, "%s: Can't open %s: %s\n",
- cmdname, datafile, strerror(errno));
+ if (write(ifd, hdr, sizeof(image_header_t)) != sizeof(image_header_t)) {
+ fprintf (stderr, "%s: Write error on %s: %s\n",
+ cmdname, imagefile, strerror(errno));
exit (EXIT_FAILURE);
}
- if (fstat(dfd, &sbuf) < 0) {
+ if (opt_type == IH_TYPE_MULTI) {
+ char *file = datafile;
+ ulong size;
+
+ for (;;) {
+ char *sep = NULL;
+
+ if (file) {
+ if ((sep = strchr(file, ':')) != NULL) {
+ *sep = '\0';
+ }
+
+ if (stat (file, &sbuf) < 0) {
+ fprintf (stderr, "%s: Can't stat %s: %s\n",
+ cmdname, file, strerror(errno));
+ exit (EXIT_FAILURE);
+ }
+ size = htonl(sbuf.st_size);
+ } else {
+ size = 0;
+ }
+
+ if (write(ifd, (char *)&size, sizeof(size)) != sizeof(size)) {
+ fprintf (stderr, "%s: Write error on %s: %s\n",
+ cmdname, imagefile, strerror(errno));
+ exit (EXIT_FAILURE);
+ }
+
+ if (!file) {
+ break;
+ }
+
+ if (sep) {
+ *sep = ':';
+ file = sep + 1;
+ } else {
+ file = NULL;
+ }
+ }
+
+ file = datafile;
+
+ for (;;) {
+ char *sep = strchr(file, ':');
+ if (sep) {
+ *sep = '\0';
+ copy_file (ifd, file, 1);
+ *sep++ = ':';
+ file = sep;
+ } else {
+ copy_file (ifd, file, 0);
+ break;
+ }
+ }
+ } else {
+ copy_file (ifd, datafile, 0);
+ }
+
+#ifdef _POSIX_SYNCHRONIZED_IO /* We're a bit of paranoid */
+ (void) fdatasync (ifd);
+#else
+ (void) fsync (ifd);
+#endif
+
+ if (fstat(ifd, &sbuf) < 0) {
fprintf (stderr, "%s: Can't stat %s: %s\n",
- cmdname, datafile, strerror(errno));
+ cmdname, imagefile, strerror(errno));
exit (EXIT_FAILURE);
}
- ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, dfd, 0);
- if ((caddr_t)ptr == (caddr_t)-1) {
- fprintf (stderr, "%s: Can't read %s: %s\n",
- cmdname, datafile, strerror(errno));
+ ptr = mmap(0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, ifd, 0);
+ if (ptr == MAP_FAILED) {
+ fprintf (stderr, "%s: Can't map %s: %s\n",
+ cmdname, imagefile, strerror(errno));
exit (EXIT_FAILURE);
}
- checksum = crc32 (0, (const char *)ptr, sbuf.st_size);
+ hdr = (image_header_t *)ptr;
+
+ checksum = crc32 (0,
+ (const char *)(ptr + sizeof(image_header_t)),
+ sbuf.st_size - sizeof(image_header_t)
+ );
/* Build new header */
- memset (hdr, 0, sizeof(image_header_t));
hdr->ih_magic = htonl(IH_MAGIC);
hdr->ih_time = htonl(sbuf.st_mtime);
- hdr->ih_size = htonl(sbuf.st_size);
+ hdr->ih_size = htonl(sbuf.st_size - sizeof(image_header_t));
hdr->ih_load = htonl(addr);
hdr->ih_ep = htonl(ep);
hdr->ih_dcrc = htonl(checksum);
hdr->ih_hcrc = htonl(checksum);
- if ((ifd = open(imagefile, O_WRONLY | O_CREAT)) < 0) {
- fprintf (stderr, "%s: Can't open %s: %s\n",
+ if (close(ifd)) {
+ fprintf (stderr, "%s: Write error on %s: %s\n",
cmdname, imagefile, strerror(errno));
exit (EXIT_FAILURE);
}
- if ((write(ifd, hdr, sizeof(image_header_t)) != sizeof(image_header_t)) ||
- (write(ifd, ptr, sbuf.st_size) != sbuf.st_size) ) {
- fprintf (stderr, "%s: Write error on %s: %s\n",
- cmdname, imagefile, strerror(errno));
+ print_header (hdr);
+
+ (void) munmap(ptr, sbuf.st_size);
+
+ exit (EXIT_SUCCESS);
+}
+
+static void
+copy_file (int ifd, const char *datafile, int pad)
+{
+ int dfd;
+ struct stat sbuf;
+ unsigned char *ptr;
+ int tail;
+ int zero = 0;
+
+ if (vflag) {
+ fprintf (stderr, "Adding Image %s\n", datafile);
+ }
+
+ if ((dfd = open(datafile, O_RDONLY)) < 0) {
+ fprintf (stderr, "%s: Can't open %s: %s\n",
+ cmdname, datafile, strerror(errno));
exit (EXIT_FAILURE);
}
- (void) munmap(ptr, sbuf.st_size);
- (void) close (dfd);
- if (close(ifd)) {
+ if (fstat(dfd, &sbuf) < 0) {
+ fprintf (stderr, "%s: Can't stat %s: %s\n",
+ cmdname, datafile, strerror(errno));
+ exit (EXIT_FAILURE);
+ }
+
+ ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, dfd, 0);
+ if (ptr == MAP_FAILED) {
+ fprintf (stderr, "%s: Can't read %s: %s\n",
+ cmdname, datafile, strerror(errno));
+ exit (EXIT_FAILURE);
+ }
+
+ if (write(ifd, ptr, sbuf.st_size) != sbuf.st_size) {
fprintf (stderr, "%s: Write error on %s: %s\n",
cmdname, imagefile, strerror(errno));
exit (EXIT_FAILURE);
}
- print_header (hdr);
+ if (pad && ((tail = sbuf.st_size % 4) != 0)) {
- exit (EXIT_SUCCESS);
+ if (write(ifd, (char *)&zero, 4-tail) != 4-tail) {
+ fprintf (stderr, "%s: Write error on %s: %s\n",
+ cmdname, imagefile, strerror(errno));
+ exit (EXIT_FAILURE);
+ }
+ }
+
+ (void) munmap(ptr, sbuf.st_size);
+ (void) close (dfd);
}
void
fprintf (stderr, "Usage: %s -l image\n"
" -l ==> list image header information\n"
" %s -A arch -O os -T type -C comp "
- "-a addr -e ep -n name -d data_file image\n"
+ "-a addr -e ep -n name -d data_file[:data_file...] image\n"
" -A ==> set architecture to 'arch'\n"
" -O ==> set operating system to 'os'\n"
" -T ==> set image type to 'type'\n"
size, (double)size / 1.024e3, (double)size / 1.048576e6 );
printf ("Load Address: 0x%08x\n", ntohl(hdr->ih_load));
printf ("Entry Point: 0x%08x\n", ntohl(hdr->ih_ep));
+
+ if (hdr->ih_type == IH_TYPE_MULTI) {
+ int i;
+ ulong *len_ptr = (ulong *)((ulong)hdr + sizeof(image_header_t));
+
+ printf ("Contents:\n");
+ for (i=0; *len_ptr; ++i, ++len_ptr) {
+ size = ntohl(*len_ptr);
+
+ printf (" Image %d: %8d Bytes = %4d kB = %d MB\n",
+ i, size, size>>10, size>>20);
+ }
+ }
}