From: wdenk Date: Sat, 7 Oct 2000 13:55:17 +0000 (+0000) Subject: * Added multi-file images to allow to boot a combined kernel+initrd X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=f231e460baa4cf3eccf9851e7a107b5a79f07c61;p=users%2Frw%2Fppcboot.git * 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) --- diff --git a/CHANGELOG b/CHANGELOG index 9e8f32e..bb0480c 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,23 @@ 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: @@ -50,6 +67,14 @@ Open Issues: 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: @@ -58,6 +83,8 @@ Modifications since 0.5.0: - 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: diff --git a/CREDITS b/CREDITS index 4a79d68..8acd301 100644 --- a/CREDITS +++ b/CREDITS @@ -47,6 +47,10 @@ N: Kirk Haderlie 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 diff --git a/Makefile b/Makefile index 48f85da..e9a05fd 100644 --- a/Makefile +++ b/Makefile @@ -53,10 +53,7 @@ SUBDIRS = $(ARCH) $(CPU) $(BOARD) common net examples tools 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 \ diff --git a/README b/README index 5ca7b7e..91a73c8 100644 --- a/README +++ b/README @@ -12,7 +12,7 @@ # # 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 @@ -58,20 +58,22 @@ Where we come from: 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: @@ -106,8 +108,12 @@ configurations available; just type "make _config". 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: @@ -123,121 +129,126 @@ Example: For a TQM823L module, all configuration settings are in 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 /ppcboot.lds* accordingly! + BE CAREFUL! Any changes to the flash layout, and some + changes to the source code will make it necessary to + adapt /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 @@ -247,47 +258,47 @@ easier to build a config tool - later. 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: @@ -299,20 +310,20 @@ PowerBook G# running LinuxPPC 2000) and in cross environments 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 @@ -335,36 +346,36 @@ steps: 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: @@ -390,30 +401,30 @@ environment is erased by accident, a default environment is provided. 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 :-). @@ -487,7 +498,9 @@ But now you can ignore ALL boot loader code (in arch/ppc/mbxboot). 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: @@ -506,10 +519,10 @@ intend to run it with initial ramdisk. 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 @@ -524,78 +537,78 @@ In the first form (with "-l" option) mkimage lists the information 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: @@ -604,7 +617,7 @@ 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 @@ -615,35 +628,35 @@ command. 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 @@ -657,78 +670,78 @@ parameters. You can check and modify this vriable using the "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: @@ -748,29 +761,29 @@ application; it is automatically compiled when you build PPCBoot. 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] = "" - 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] = "" + 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'. @@ -779,44 +792,44 @@ The interrupt service routine is trivial, just printing a '.' 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 @@ -855,22 +868,22 @@ of DRAM (0x00000000 ... 0x00001FFF). 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: diff --git a/common/cmd_boot.c b/common/cmd_boot.c index 72d803a..d6cf440 100644 --- a/common/cmd_boot.c +++ b/common/cmd_boot.c @@ -287,3 +287,529 @@ read_record (char *buf, ulong len) *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 */ diff --git a/common/cmd_bootm.c b/common/cmd_bootm.c index 4e0d1d0..aa509a3 100644 --- a/common/cmd_bootm.c +++ b/common/cmd_bootm.c @@ -41,6 +41,7 @@ static void print_type (image_header_t *hdr); image_header_t header; + void do_bootm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) { ulong iflag; @@ -49,7 +50,8 @@ void do_bootm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) 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; @@ -88,7 +90,8 @@ void do_bootm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) 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; @@ -102,6 +105,8 @@ void do_bootm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) 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; @@ -112,14 +117,21 @@ void do_bootm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) 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(); @@ -147,7 +159,7 @@ void do_bootm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) 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 */ @@ -155,6 +167,7 @@ void do_bootm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) enable_interrupts(); break; case IH_TYPE_KERNEL: + case IH_TYPE_MULTI: /* handled below */ break; default: @@ -167,11 +180,11 @@ void do_bootm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) /* * 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) : ); @@ -247,11 +260,25 @@ void do_bootm (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) 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 @@ -306,7 +333,8 @@ void do_iminfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) 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; @@ -332,6 +360,17 @@ print_header (image_header_t *hdr) 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); + } + } } @@ -342,12 +381,12 @@ print_type (image_header_t *hdr) 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; @@ -367,6 +406,7 @@ print_type (image_header_t *hdr) 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; } @@ -411,7 +451,7 @@ int gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) { z_stream s; int r, i, flags; - + /* skip header */ i = 10; flags = src[3]; @@ -433,7 +473,7 @@ int gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) printf ("Error: gunzip out of data in header\n"); return (-1); } - + s.zalloc = zalloc; s.zfree = zfree; r = inflateInit2(&s, -MAX_WBITS); @@ -452,6 +492,6 @@ int gunzip(void *dst, int dstlen, unsigned char *src, int *lenp) } *lenp = s.next_out - (unsigned char *) dst; inflateEnd(&s); - + return (0); } diff --git a/common/cmd_net.c b/common/cmd_net.c index 8f68b54..88afd66 100644 --- a/common/cmd_net.c +++ b/common/cmd_net.c @@ -50,7 +50,6 @@ void do_rarpb (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) 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; @@ -86,8 +85,4 @@ netboot_common (int proto, cmd_tbl_t *cmdtp, bd_t *bd, int argc, char *argv[]) do_bootm (cmdtp, bd, 0, 2, local_args); } - -#else - printf ("Network Support not implemented yet on this architecture\n"); -#endif } diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index 013c117..0e6a62d 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -213,9 +213,65 @@ void do_saveenv (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) 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; isector_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..."); @@ -237,6 +293,7 @@ void do_saveenv (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) } flash_sect_protect (1, (ulong)flash_addr, (ulong)flash_addr+env_size-1); +#endif } /* diff --git a/common/command.c b/common/command.c index 50624d3..9b1ae61 100644 --- a/common/command.c +++ b/common/command.c @@ -126,6 +126,9 @@ cmd_tbl_t cmd_tbl[] = { 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, diff --git a/cpci405/flash.c b/cpci405/flash.c index ea7fa37..3ebd229 100644 --- a/cpci405/flash.c +++ b/cpci405/flash.c @@ -521,6 +521,7 @@ ulong flash_get_size (vu_long *addr, flash_info_t *info) 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; @@ -558,16 +559,10 @@ void flash_erase (flash_info_t *info, int s_first, int s_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; @@ -575,11 +570,18 @@ void flash_erase (flash_info_t *info, int s_first, int s_last) 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; } } diff --git a/include/cmd_boot.h b/include/cmd_boot.h index 0968761..53b9225 100644 --- a/include/cmd_boot.h +++ b/include/cmd_boot.h @@ -66,6 +66,20 @@ void do_go (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]); 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", \ diff --git a/include/commproc.h b/include/commproc.h index 4837639..a32b654 100644 --- a/include/commproc.h +++ b/include/commproc.h @@ -437,8 +437,8 @@ typedef struct scc_enet { #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 */ diff --git a/include/image.h b/include/image.h index 7119f0c..2c5c061 100644 --- a/include/image.h +++ b/include/image.h @@ -63,11 +63,39 @@ /* * 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 diff --git a/mpc8xx/scc.c b/mpc8xx/scc.c index 4125cbc..aa664fc 100644 --- a/mpc8xx/scc.c +++ b/mpc8xx/scc.c @@ -73,26 +73,6 @@ typedef volatile struct CommonBufferDescriptor { 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) { diff --git a/net/files.h b/net/files.h deleted file mode 100644 index df4f1d1..0000000 --- a/net/files.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * 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__ */ diff --git a/net/net.c b/net/net.c index be3f892..4a73c83 100644 --- a/net/net.c +++ b/net/net.c @@ -272,7 +272,9 @@ NetReceive(volatile uchar * pkt, int len) * 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) { diff --git a/net/tftp.c b/net/tftp.c index 246c96f..f27db22 100644 --- a/net/tftp.c +++ b/net/tftp.c @@ -9,7 +9,6 @@ #include "net.h" #include "tftp.h" #include "bootp.h" -#include "files.h" #define WELL_KNOWN_PORT 69 /* Well known TFTP port # */ @@ -165,55 +164,6 @@ TftpHandler(uchar * pkt, unsigned dest, unsigned src, unsigned len) /* 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. diff --git a/ppc4xx/405gp_enet.c b/ppc4xx/405gp_enet.c index ba373f5..bb7f437 100644 --- a/ppc4xx/405gp_enet.c +++ b/ppc4xx/405gp_enet.c @@ -165,8 +165,7 @@ static int tx_run[NUM_TX_BUFF]; /* Transmit Running Queue */ 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); @@ -265,6 +264,8 @@ int eth_init (bd_t *bis) #endif } + memcpy(emac_hwd_addr, bis->bi_enetaddr, ENET_ADDR_LENGTH); + reg = 0x00000000; reg |= emac_hwd_addr[0]; /* set high address */ diff --git a/tools/mkimage.c b/tools/mkimage.c index af91666..8cb4e5a 100644 --- a/tools/mkimage.c +++ b/tools/mkimage.c @@ -4,8 +4,8 @@ * 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 @@ -75,6 +75,7 @@ table_entry_t type_name[] = { { 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, "", "", }, }; @@ -85,6 +86,7 @@ table_entry_t comp_name[] = { { -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 *); @@ -106,6 +108,7 @@ char *imagefile; 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; @@ -117,7 +120,7 @@ image_header_t *hdr = &header; int main (int argc, char **argv) { - int ifd, dfd; + int ifd; uint32_t checksum; uint32_t addr; uint32_t ep; @@ -190,6 +193,9 @@ main (int argc, char **argv) usage (); name = *++argv; goto NXTARG; + case 'v': + vflag++; + break; default: usage (); } @@ -208,7 +214,7 @@ NXTARG: ; 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) { @@ -278,7 +284,8 @@ NXTARG: ; 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); @@ -289,35 +296,104 @@ NXTARG: ; /* * 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); @@ -332,30 +408,68 @@ NXTARG: ; 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 @@ -364,7 +478,7 @@ usage () 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" @@ -393,6 +507,19 @@ print_header (image_header_t *hdr) 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); + } + } }