diff options
Diffstat (limited to 'u-boot/tools')
99 files changed, 13882 insertions, 0 deletions
diff --git a/u-boot/tools/.gitignore b/u-boot/tools/.gitignore new file mode 100644 index 0000000..07f21a3 --- /dev/null +++ b/u-boot/tools/.gitignore @@ -0,0 +1,16 @@ +/bmp_logo +/envcrc +/gen_eth_addr +/img2srec +/mkimage +/mpc86x_clk +/ncb +/ncp +/ubsha1 +/inca-swap-bytes +/*.exe +/easylogo/easylogo +/env/crc32.c +/env/fw_printenv +/gdb/gdbcont +/gdb/gdbsend diff --git a/u-boot/tools/Makefile b/u-boot/tools/Makefile new file mode 100644 index 0000000..623f908 --- /dev/null +++ b/u-boot/tools/Makefile @@ -0,0 +1,235 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# 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 +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +TOOLSUBDIRS = + +# +# Include this after HOSTOS HOSTARCH check +# so that we can act intelligently. +# +include $(TOPDIR)/config.mk + +# +# toolchains targeting win32 generate .exe files +# +ifneq (,$(findstring WIN32 ,$(shell $(HOSTCC) -E -dM -xc /dev/null))) +SFX = .exe +else +SFX = +endif + +# Enable all the config-independent tools +ifneq ($(HOST_TOOLS_ALL),) +CONFIG_LCD_LOGO = y +CONFIG_CMD_LOADS = y +CONFIG_CMD_NET = y +CONFIG_INCA_IP = y +CONFIG_NETCONSOLE = y +CONFIG_SHA1_CHECK_UB_IMG = y +endif + +# Generated executable files +BIN_FILES-$(CONFIG_LCD_LOGO) += bmp_logo$(SFX) +BIN_FILES-$(CONFIG_VIDEO_LOGO) += bmp_logo$(SFX) +BIN_FILES-$(CONFIG_ENV_IS_EMBEDDED) += envcrc$(SFX) +BIN_FILES-$(CONFIG_ENV_IS_IN_DATAFLASH) += envcrc$(SFX) +BIN_FILES-$(CONFIG_ENV_IS_IN_EEPROM) += envcrc$(SFX) +BIN_FILES-$(CONFIG_ENV_IS_IN_FLASH) += envcrc$(SFX) +BIN_FILES-$(CONFIG_ENV_IS_IN_ONENAND) += envcrc$(SFX) +BIN_FILES-$(CONFIG_ENV_IS_IN_NAND) += envcrc$(SFX) +BIN_FILES-$(CONFIG_ENV_IS_IN_NVRAM) += envcrc$(SFX) +BIN_FILES-$(CONFIG_ENV_IS_IN_SPI_FLASH) += envcrc$(SFX) +BIN_FILES-$(CONFIG_CMD_NET) += gen_eth_addr$(SFX) +BIN_FILES-$(CONFIG_CMD_LOADS) += img2srec$(SFX) +BIN_FILES-$(CONFIG_INCA_IP) += inca-swap-bytes$(SFX) +BIN_FILES-y += mkimage$(SFX) +BIN_FILES-$(CONFIG_NETCONSOLE) += ncb$(SFX) +BIN_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1$(SFX) + +# Source files which exist outside the tools directory +EXT_OBJ_FILES-y += common/env_embedded.o +EXT_OBJ_FILES-y += common/image.o +EXT_OBJ_FILES-y += lib/crc32.o +EXT_OBJ_FILES-y += lib/md5.o +EXT_OBJ_FILES-y += lib/sha1.o + +# Source files located in the tools directory +OBJ_FILES-$(CONFIG_LCD_LOGO) += bmp_logo.o +OBJ_FILES-$(CONFIG_VIDEO_LOGO) += bmp_logo.o +NOPED_OBJ_FILES-y += default_image.o +OBJ_FILES-y += envcrc.o +NOPED_OBJ_FILES-y += fit_image.o +OBJ_FILES-$(CONFIG_CMD_NET) += gen_eth_addr.o +OBJ_FILES-$(CONFIG_CMD_LOADS) += img2srec.o +OBJ_FILES-$(CONFIG_INCA_IP) += inca-swap-bytes.o +NOPED_OBJ_FILES-y += kwbimage.o +NOPED_OBJ_FILES-y += imximage.o +NOPED_OBJ_FILES-y += mkimage.o +OBJ_FILES-$(CONFIG_NETCONSOLE) += ncb.o +NOPED_OBJ_FILES-y += os_support.o +OBJ_FILES-$(CONFIG_SHA1_CHECK_UB_IMG) += ubsha1.o + +# Don't build by default +#ifeq ($(ARCH),ppc) +#BIN_FILES-y += mpc86x_clk$(SFX) +#OBJ_FILES-y += mpc86x_clk.o +#endif + +# Flattened device tree objects +LIBFDT_OBJ_FILES-y += fdt.o +LIBFDT_OBJ_FILES-y += fdt_ro.o +LIBFDT_OBJ_FILES-y += fdt_rw.o +LIBFDT_OBJ_FILES-y += fdt_strerror.o +LIBFDT_OBJ_FILES-y += fdt_wip.o + +# Generated LCD/video logo +LOGO_H = $(OBJTREE)/include/bmp_logo.h +LOGO-$(CONFIG_LCD_LOGO) += $(LOGO_H) +LOGO-$(CONFIG_VIDEO_LOGO) += $(LOGO_H) + +ifeq ($(LOGO_BMP),) +LOGO_BMP= logos/denx.bmp +endif +ifeq ($(VENDOR),atmel) +LOGO_BMP= logos/atmel.bmp +endif +ifeq ($(VENDOR),esd) +LOGO_BMP= logos/esd.bmp +endif +ifeq ($(VENDOR),freescale) +LOGO_BMP= logos/freescale.bmp +endif +ifeq ($(VENDOR),ronetix) +LOGO_BMP= logos/ronetix.bmp +endif +ifeq ($(VENDOR),syteco) +LOGO_BMP= logos/syteco.bmp +endif + +# now $(obj) is defined +HOSTSRCS += $(addprefix $(SRCTREE)/,$(EXT_OBJ_FILES-y:.o=.c)) +HOSTSRCS += $(addprefix $(SRCTREE)/tools/,$(OBJ_FILES-y:.o=.c)) +HOSTSRCS += $(addprefix $(SRCTREE)/lib/libfdt/,$(LIBFDT_OBJ_FILES-y:.o=.c)) +BINS := $(addprefix $(obj),$(sort $(BIN_FILES-y))) +LIBFDT_OBJS := $(addprefix $(obj),$(LIBFDT_OBJ_FILES-y)) + +HOSTOBJS := $(addprefix $(obj),$(OBJ_FILES-y)) +NOPEDOBJS := $(addprefix $(obj),$(NOPED_OBJ_FILES-y)) + +# +# Use native tools and options +# Define __KERNEL_STRICT_NAMES to prevent typedef overlaps +# +HOSTCPPFLAGS = -idirafter $(SRCTREE)/include \ + -idirafter $(OBJTREE)/include2 \ + -idirafter $(OBJTREE)/include \ + -I $(SRCTREE)/lib/libfdt \ + -I $(SRCTREE)/tools \ + -DCONFIG_SYS_TEXT_BASE=$(CONFIG_SYS_TEXT_BASE) \ + -DUSE_HOSTCC \ + -D__KERNEL_STRICT_NAMES + + +all: $(obj).depend $(BINS) $(LOGO-y) subdirs + +$(obj)bin2header$(SFX): $(obj)bin2header.o + $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ + $(HOSTSTRIP) $@ + +$(obj)bmp_logo$(SFX): $(obj)bmp_logo.o + $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ + $(HOSTSTRIP) $@ + +$(obj)envcrc$(SFX): $(obj)crc32.o $(obj)env_embedded.o $(obj)envcrc.o $(obj)sha1.o + $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ + +$(obj)gen_eth_addr$(SFX): $(obj)gen_eth_addr.o + $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ + $(HOSTSTRIP) $@ + +$(obj)img2srec$(SFX): $(obj)img2srec.o + $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ + $(HOSTSTRIP) $@ + +$(obj)inca-swap-bytes$(SFX): $(obj)inca-swap-bytes.o + $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ + $(HOSTSTRIP) $@ + +$(obj)mkimage$(SFX): $(obj)crc32.o \ + $(obj)default_image.o \ + $(obj)fit_image.o \ + $(obj)image.o \ + $(obj)imximage.o \ + $(obj)kwbimage.o \ + $(obj)md5.o \ + $(obj)mkimage.o \ + $(obj)os_support.o \ + $(obj)sha1.o \ + $(LIBFDT_OBJS) + $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ + $(HOSTSTRIP) $@ + +$(obj)mpc86x_clk$(SFX): $(obj)mpc86x_clk.o + $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ + $(HOSTSTRIP) $@ + +$(obj)ncb$(SFX): $(obj)ncb.o + $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ + $(HOSTSTRIP) $@ + +$(obj)ubsha1$(SFX): $(obj)os_support.o $(obj)sha1.o $(obj)ubsha1.o + $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ + +# Some of the tool objects need to be accessed from outside the tools directory +$(obj)%.o: $(SRCTREE)/common/%.c + $(HOSTCC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $< + +$(obj)%.o: $(SRCTREE)/lib/%.c + $(HOSTCC) -g $(HOSTCFLAGS) -c -o $@ $< + +$(obj)%.o: $(SRCTREE)/lib/libfdt/%.c + $(HOSTCC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $< + +subdirs: +ifeq ($(TOOLSUBDIRS),) + @: +else + @for dir in $(TOOLSUBDIRS) ; do \ + $(MAKE) \ + HOSTOS=$(HOSTOS) \ + HOSTARCH=$(HOSTARCH) \ + -C $$dir || exit 1 ; \ + done +endif + +$(LOGO_H): $(obj)bmp_logo $(LOGO_BMP) + $(obj)./bmp_logo $(LOGO_BMP) >$@ + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/u-boot/tools/bddb/README b/u-boot/tools/bddb/README new file mode 100644 index 0000000..9bee59a --- /dev/null +++ b/u-boot/tools/bddb/README @@ -0,0 +1,116 @@ +Hymod Board Database + +(C) Copyright 2001 +Murray Jensen <Murray.Jensen@csiro.au> +CSIRO Manufacturing Science and Technology, Preston Lab + +25-Jun-01 + +This stuff is a set of PHP/MySQL scripts to implement a custom board +database. It will need *extensive* hacking to modify it to keep the +information about your custom boards that you want, however it is a good +starting point. + +How it is used: + + 1. a board has gone through all the hardware testing etc and is + ready to have the flash programmed for the first time - first you + go to a web page and fill in information about the board in a form + to register it in a database + + 2. the web stuff allocates a (unique) serial number and (optionally) + a (locally administered) ethernet address and stores the information + in a database using the serial number as the key (can do whole + batches of boards in one go and/or use a previously registered board + as defaults for the new board(s)) + + 3. it then creates a file in the tftp area of a server somewhere + containing the board information in a simple text format (one + per serial number) + + 4. all hymod boards have an i2c eeprom, and when U-Boot sees that + the eeprom is unitialised, it prompts for a serial number and + ethernet address (if not set), then transfers the file created + in step 3 from the server and initialises the eeprom from its + contents + +What this means is you can't boot the board until you have allocated a serial +number, but you don't have to type it all twice - you do it once on the web +and the board then finds the info it needs to initialise its eeprom. The +other side of the coin is the reading of the eeprom and how it gets passed +to Linux (or another O/S). + +To see how this is all done for the hymod boards look at the code in the +"board/hymod" directory and in the file "include/asm/hymod.h". Hymod boards +can have a mezzanine card which also have an eeprom that needs allocating, +the same process is used for these as well - just a different i2c address. + +Other forms provide the following functions: + + - browsing the board database + - editing board information (one at a time) + - maintaining/browsing a (simple) per board event log + +You will need: MySQL (I use version 3.23.7-alpha), PHP4 (with MySQL +support enabled) and a web server (I use Apache 1.3.x). + +I originally started by using phpMyBuilder (http://kyber.dk/phpMyBuilder) +but it soon got far more complicated than that could handle (but I left +the copyright messages in there anyway). Most of the code resides in the +common defs.php file, which shouldn't need much alteration - all the work +will be in shaping the front-end php files to your liking. + +Here's a quick summary of what needs doing to use it for your boards: + +1. get phpMyAdmin (http://phpwizard.net/projects/phpMyAdmin/) - it's an + invaluable tool for this sort of stuff (this step is optional of course) + +2. edit "bddb.css" to your taste, if you could be bothered - I have no + idea what is in there or what it does - I copied it from somewhere else + ("user.css" from the phpMyEdit (http://phpmyedit.sourcerforge.net) package, + I think) - I figure one day I'll see what sort of things I can change + in there. + +3. create a mysql database - call it whatever you like + +4. edit "create_tables.sql" and modify the "boards" table schema to + reflect the information you want to keep about your boards. It may or + may not be easier to do this and the next step in phpMyAdmin. Check out + the MySQL documentation at http://www.mysql.com/doc/ in particular the + column types at http://www.mysql.com/doc/C/o/Column_types.html - Note + there is only support for a few data types: + + int - presented as an html text input + char/text - presented as an html text input + date - presented as an html text input + enum - presented as an html radio input + + I also have what I call "enum_multi" which is a set of enums with the + same name, but suffixed with a number e.g. fred0, fred1, fred2. These + are presented as a number of html select's with a single label "fred" + this is useful for board characteristics that have multiple items of + the same type e.g. multiple banks of sdram. + +5. use the "create_tables.sql" file to create the "boards" table in the + database e.g. mysql dbname < create_tables.sql + +6. create a user and password for the web server to log into the MySQL + database with; give this user select, insert and update privileges + to the database created in 3 (and delete, if you want the "delete" + functions in the edit forms to work- I have this turned off). phpMyAdmin + helps in this step. + +7. edit "config.php" and set the variables: $mysql_user, $mysql_pw, $mysql_db, + $bddb_cfgdir and $bddb_label - keep the contents of this file secret - it + contains the web servers username and password (the three $mysql_* vars + are set from the previous step) + +8. edit "defs.php" and a. adjust the various enum value arrays and b. edit + the function "pg_foot()" to remove my email address :-) + +9. do major hacking on the following files: browse.php, doedit.php, donew.php, + edit.php and new.php to reflect your database schema - fortunately the + hacking is fairly straight-forward, but it is boring and time-consuming. + +These notes were written rather hastily - if you find any obvious problems +please let me know. diff --git a/u-boot/tools/bddb/badsubmit.php b/u-boot/tools/bddb/badsubmit.php new file mode 100644 index 0000000..5092a31 --- /dev/null +++ b/u-boot/tools/bddb/badsubmit.php @@ -0,0 +1,23 @@ +<?php // php pages made with phpMyBuilder <http://kyber.dk/phpMyBuilder> ?> +<?php + // (C) Copyright 2001 + // Murray Jensen <Murray.Jensen@csiro.au> + // CSIRO Manufacturing Science and Technology, Preston Lab + + require("defs.php"); + pg_head("$bddb_label - Unknown Submit Type"); +?> +<center> + <font size="+4"> + <b> + The <?php echo "$bddb_label"; ?> form was submitted with an + unknown SUBMIT type <?php echo "(value was '$submit')" ?>. + <br></br> + Perhaps you typed the URL in directly? Click here to go to the + home page of the <a href="index.php"><?php echo "$bddb_label"; ?></a>. + </b> + </font> +</center> +<?php + pg_foot(); +?> diff --git a/u-boot/tools/bddb/bddb.css b/u-boot/tools/bddb/bddb.css new file mode 100644 index 0000000..dee2b2e --- /dev/null +++ b/u-boot/tools/bddb/bddb.css @@ -0,0 +1,207 @@ +BODY { + background: #e0ffff; + color: #000000; + font-family: Arial, Verdana, Helvetica; +} +H1 { + font-family: "Copperplate Gothic Bold"; + background: transparent; + color: #993300; + text-align: center; +} +H2, H3, H4, H5 { + background: transparent; + color: #993300; + margin-top: 4%; + text-align: center; +} +Body.Plain Div.Abstract, Body.Plain P.Abstract { + background: #cccc99; + color: #333300; + border: white; + padding: 3%; + font-family: Times, Verdana; +} +TH.Nav { + background: #0000cc; + color: #ff9900; +} +TH.Menu { + background: #3366cc; + color: #ff9900; +} +A:hover { + color: #ff6600; +} +A.Menu:hover { + color: #ff6600; +} +A.HoMe:hover { + color: #ff6600; +} +A.Menu { + background: transparent; + color: #ffcc33; + font-family: Verdana, Helvetica, Arial; + font-size: smaller; + text-decoration: none; +} +A.Menu:visited { + background: transparent; + color: #ffcc99; +} +A.HoMe { + background: transparent; + color: #ffcc33; + font-family: Verdana, Helvetica, Arial; + text-decoration:none; +} +A.HoMe:visited { + background: transparent; + color: #ffcc99; +} +TH.Xmp { + background: #eeeeee; + color: #330066; + font-family: courier; + font-weight: normal; +} +TH.LuT { + background: #cccccc; + color: #000000; +} +TD.LuT { + background: #ffffcc; + color: #000000; + font-size: 85%; +} +TH.Info, TD.Info { + background: #ffffcc; + color: #660000; + font-family: "Comic Sans MS", Cursive, Verdana; + font-size: smaller; +} +Div.Info, P.Info { + background: #ffff99; + color: #990033; + text-align: left; + padding: 2%; + font-family: "Comic Sans MS", Cursive, Verdana; + font-size: 85%; + } +Div.Info A { + background: transparent; + color: #ff6600; +} +.HL { + background: #ffff99; + color: #000000; +} +TD.HL { + background: #ccffff; + color: #000000; +} +Div.Margins { + width: 512px; + text-align: center; +} +TD.Plain { + background: #ffffcc; + color: #000033; +} +.Type { + background: #cccccc; + color: #660000; +} +.Name { + background: #eeeeee; + color: #660000; + vertical-align: top; + text-align: right; +} +.Value { + background: #ffffee; + color: #000066; +} +.Drop { + background: #333366; + color: #ffcc33; + font-family: "Copperplate Gothic Light", Helvetica, Verdana, Arial; +} +A.Button:hover { + color: #ff6600; +} +A.Button { + text-decoration:none; + color: #003366; + background: #ffcc66; +} +.Button { + font-size: 9pt; + text-align: center; + text-decoration:none; + color: #003366; + background: #ffcc66; + margin-bottom: 2pt; + border-top: 2px solid #ffff99; + border-left: 2px solid #ffff99; + border-right: 2px solid #cc9933; + border-bottom: 2px solid #cc9933; + font-family: Verdana, Arial, "Comic Sans MS"; +} +.Banner { + width: 468; + font-size: 12pt; + text-align: center; + text-decoration:none; + color: #003366; + background: #ffcc66; + border-top: 4px solid #ffff99; + border-left: 4px solid #ffff99; + border-right: 4px solid #cc9933; + border-bottom: 4px solid #cc9933; + font-family: Verdana, Arial, "Comic Sans MS"; +} +TD.Nova, Body.Nova { + background: #000000; + font-family: "Times New Roman"; + font-weight: light; + color: #ffcc00; +} +Body.Nova A.Button { + background: gold; + color: #003366; +} +Body.Nova A.Banner { + background: transparent; + color: #003366; +} +Body.Nova A { + background: transparent; + text-decoration:none; + color: #ffd766; +} +Body.Nova H1, Body.Nova H2, Body.Nova H3, Body.Nova H4 { + background: transparent; + color: white; + margin-top: 4%; + text-align: center; + filter: Blur(Add=1, Direction=0, Strength=8); +} +Body.Nova Div.Abstract { + background: #000000; + color: #ffffff; + font-family: Times, Verdana; +} +Body.Nova A.Abstract { + background: transparent; + color: #ffeedd; +} +Body.Nova TH.LuT { + background: black; + color: #ffff99; +} +Body.Nova TD.LuT { + background: navy; + color: #ffff99; +} diff --git a/u-boot/tools/bddb/brlog.php b/u-boot/tools/bddb/brlog.php new file mode 100644 index 0000000..fccfbd0 --- /dev/null +++ b/u-boot/tools/bddb/brlog.php @@ -0,0 +1,109 @@ +<?php // php pages made with phpMyBuilder <http://kyber.dk/phpMyBuilder> ?> +<?php + // (C) Copyright 2001 + // Murray Jensen <Murray.Jensen@csiro.au> + // CSIRO Manufacturing Science and Technology, Preston Lab + + // list page (hymod_bddb / boards) + + require("defs.php"); + + pg_head("$bddb_label - Browse Board Log"); + + $serno=intval($serno); + if ($serno == 0) + die("serial number not specified or invalid!"); + + function print_cell($str) { + if ($str == '') + $str = ' '; + echo "\t<td>$str</td>\n"; + } +?> +<table align=center border=1 cellpadding=10> +<tr> +<th>serno / edit</th> +<th>ethaddr</th> +<th>date</th> +<th>batch</th> +<th>type</th> +<th>rev</th> +<th>location</th> +</tr> +<?php + $r=mysql_query("select * from boards where serno=$serno"); + + while($row=mysql_fetch_array($r)){ + foreach ($columns as $key) { + if (!key_in_array($key, $row)) + $row[$key] = ''; + } + + echo "<tr>\n"; + print_cell("<a href=\"edit.php?serno=$row[serno]\">$row[serno]</a>"); + print_cell($row['ethaddr']); + print_cell($row['date']); + print_cell($row['batch']); + print_cell($row['type']); + print_cell($row['rev']); + print_cell($row['location']); + echo "</tr>\n"; + } + + mysql_free_result($r); +?> +</table> +<hr></hr> +<p></p> +<?php + $limit=abs(isset($_REQUEST['limit'])?$_REQUEST['limit']:20); + $offset=abs(isset($_REQUEST['offset'])?$_REQUEST['offset']:0); + $lr=mysql_query("select count(*) as n from log where serno=$serno"); + $lrow=mysql_fetch_array($lr); + if($lrow['n']>$limit){ + $preoffset=max(0,$offset-$limit); + $postoffset=$offset+$limit; + echo "<table width=\"100%\">\n<tr align=center>\n"; + printf("<td><%sa href=\"%s?submit=Log&serno=$serno&offset=%d\"><img border=0 alt=\"<\" src=\"/icons/left.gif\"></a></td>\n", $offset>0?"":"no", $PHP_SELF, $preoffset); + printf("<td><%sa href=\"%s?submit=Log&serno=$serno&offset=%d\"><img border=0 alt=\">\" src=\"/icons/right.gif\"></a></td>\n", $postoffset<$lrow['n']?"":"no", $PHP_SELF, $postoffset); + echo "</tr>\n</table>\n"; + } + mysql_free_result($lr); +?> +<table width="100%" border=1 cellpadding=10> +<tr valign=top> +<th>logno / edit</th> +<th>date</th> +<th>who</th> +<th width="70%">details</th> +</tr> +<?php + $r=mysql_query("select * from log where serno=$serno order by logno limit $offset,$limit"); + + while($row=mysql_fetch_array($r)){ + echo "<tr>\n"; + print_cell("<a href=\"edlog.php?serno=$row[serno]&logno=$row[logno]\">$row[logno]</a>"); + print_cell($row['date']); + print_cell($row['who']); + print_cell("<pre>" . urldecode($row['details']) . "</pre>"); + echo "</tr>\n"; + } + + mysql_free_result($r); +?> +</table> +<hr></hr> +<p></p> +<table width="100%"> +<tr> + <td align=center> + <a href="newlog.php?serno=<?php echo "$serno"; ?>">Add to Log</a> + </td> + <td align=center> + <a href="index.php">Back to Start</a> + </td> +</tr> +</table> +<?php + pg_foot(); +?> diff --git a/u-boot/tools/bddb/browse.php b/u-boot/tools/bddb/browse.php new file mode 100644 index 0000000..675dfab --- /dev/null +++ b/u-boot/tools/bddb/browse.php @@ -0,0 +1,147 @@ +<?php // php pages made with phpMyBuilder <http://kyber.dk/phpMyBuilder> ?> +<?php + // (C) Copyright 2001 + // Murray Jensen <Murray.Jensen@csiro.au> + // CSIRO Manufacturing Science and Technology, Preston Lab + + // list page (hymod_bddb / boards) + + require("defs.php"); + + $serno=isset($_REQUEST['serno'])?$_REQUEST['serno']:''; + + $verbose=isset($_REQUEST['verbose'])?intval($_REQUEST['verbose']):0; + + pg_head("$bddb_label - Browse database" . ($verbose?" (verbose)":"")); +?> +<p></p> +<?php + $limit=isset($_REQUEST['limit'])?abs(intval($_REQUEST['limit'])):20; + $offset=isset($_REQUEST['offset'])?abs(intval($_REQUEST['offset'])):0; + + if ($serno == '') { + + $lr=mysql_query("select count(*) as n from boards"); + $lrow=mysql_fetch_array($lr); + + if($lrow['n']>$limit){ + $preoffset=max(0,$offset-$limit); + $postoffset=$offset+$limit; + echo "<table width=\"100%\">\n<tr>\n"; + printf("<td align=left><%sa href=\"%s?submit=Browse&offset=%d&verbose=%d\"><img border=0 alt=\"<\" src=\"/icons/left.gif\"></a></td>\n", $offset>0?"":"no", $PHP_SELF, $preoffset, $verbose); + printf("<td align=right><%sa href=\"%s?submit=Browse&offset=%d&verbose=%d\"><img border=0 alt=\">\" src=\"/icons/right.gif\"></a></td>\n", $postoffset<$lrow['n']?"":"no", $PHP_SELF, $postoffset, $offset); + echo "</tr>\n</table>\n"; + } + + mysql_free_result($lr); + } +?> +<table align=center border=1 cellpadding=10> +<tr> +<th></th> +<th>serno / edit</th> +<th>ethaddr</th> +<th>date</th> +<th>batch</th> +<th>type</th> +<th>rev</th> +<th>location</th> +<?php + if ($verbose) { + echo "<th>comments</th>\n"; + echo "<th>sdram</th>\n"; + echo "<th>flash</th>\n"; + echo "<th>zbt</th>\n"; + echo "<th>xlxtyp</th>\n"; + echo "<th>xlxspd</th>\n"; + echo "<th>xlxtmp</th>\n"; + echo "<th>xlxgrd</th>\n"; + echo "<th>cputyp</th>\n"; + echo "<th>cpuspd</th>\n"; + echo "<th>cpmspd</th>\n"; + echo "<th>busspd</th>\n"; + echo "<th>hstype</th>\n"; + echo "<th>hschin</th>\n"; + echo "<th>hschout</th>\n"; + } +?> +</tr> +<?php + $query = "select * from boards"; + if ($serno != '') { + $pre = " where "; + foreach (preg_split("/[\s,]+/", $serno) as $s) { + if (preg_match('/^[0-9]+$/',$s)) + $query .= $pre . "serno=" . $s; + else if (preg_match('/^([0-9]+)-([0-9]+)$/',$s,$m)) { + $m1 = intval($m[1]); $m2 = intval($m[2]); + if ($m2 <= $m1) + die("bad serial number range ($s)"); + $query .= $pre . "(serno>=$m[1] and serno<=$m[2])"; + } + else + die("illegal serial number ($s)"); + $pre = " or "; + } + } + $query .= " order by serno"; + if ($serno == '') + $query .= " limit $offset,$limit"; + + $r = mysql_query($query); + + function print_cell($str) { + if ($str == '') + $str = ' '; + echo "\t<td>$str</td>\n"; + } + + while($row=mysql_fetch_array($r)){ + foreach ($columns as $key) { + if (!key_in_array($key, $row)) + $row[$key] = ''; + } + + echo "<tr>\n"; + print_cell("<a href=\"brlog.php?serno=$row[serno]\">Log</a>"); + print_cell("<a href=\"edit.php?serno=$row[serno]\">$row[serno]</a>"); + print_cell($row['ethaddr']); + print_cell($row['date']); + print_cell($row['batch']); + print_cell($row['type']); + print_cell($row['rev']); + print_cell($row['location']); + if ($verbose) { + print_cell("<pre>\n" . urldecode($row['comments']) . + "\n\t</pre>"); + print_cell(gather_enum_multi_print("sdram", 4, $row)); + print_cell(gather_enum_multi_print("flash", 4, $row)); + print_cell(gather_enum_multi_print("zbt", 16, $row)); + print_cell(gather_enum_multi_print("xlxtyp", 4, $row)); + print_cell(gather_enum_multi_print("xlxspd", 4, $row)); + print_cell(gather_enum_multi_print("xlxtmp", 4, $row)); + print_cell(gather_enum_multi_print("xlxgrd", 4, $row)); + print_cell($row['cputyp']); + print_cell($row['cpuspd']); + print_cell($row['cpmspd']); + print_cell($row['busspd']); + print_cell($row['hstype']); + print_cell($row['hschin']); + print_cell($row['hschout']); + } + echo "</tr>\n"; + } +?> +</table> +<p></p> +<table width="100%"> +<tr> + <td align=center><?php + printf("<a href=\"%s?submit=Browse&offset=%d&verbose=%d%s\">%s Listing</a>\n", $PHP_SELF, $offset, $verbose?0:1, $serno!=''?"&serno=$serno":'', $verbose?"Terse":"Verbose"); + ?></td> + <td align=center><a href="index.php">Back to Start</a></td> +</tr> +</table> +<?php + pg_foot(); +?> diff --git a/u-boot/tools/bddb/config.php b/u-boot/tools/bddb/config.php new file mode 100644 index 0000000..6725757 --- /dev/null +++ b/u-boot/tools/bddb/config.php @@ -0,0 +1,16 @@ +<?php + // (C) Copyright 2001 + // Murray Jensen <Murray.Jensen@csiro.au> + // CSIRO Manufacturing Science and Technology, Preston Lab + + // mysql database access info + $mysql_user="fred"; + $mysql_pw="apassword"; + $mysql_db="mydbname"; + + // where to put the eeprom config files + $bddb_cfgdir = '/tftpboot/bddb'; + + // what this database is called + $bddb_label = 'Hymod Board Database'; +?> diff --git a/u-boot/tools/bddb/create_tables.sql b/u-boot/tools/bddb/create_tables.sql new file mode 100644 index 0000000..a2a5788 --- /dev/null +++ b/u-boot/tools/bddb/create_tables.sql @@ -0,0 +1,90 @@ +# phpMyAdmin MySQL-Dump +# http://phpwizard.net/phpMyAdmin/ +# +# Host: localhost Database : hymod_bddb + +# (C) Copyright 2001 +# Murray Jensen <Murray.Jensen@csiro.au> +# CSIRO Manufacturing and Infrastructure Technology, Preston Lab + +# -------------------------------------------------------- +# +# Table structure for table 'boards' +# + +DROP TABLE IF EXISTS boards; +CREATE TABLE boards ( + serno int(10) unsigned zerofill NOT NULL auto_increment, + ethaddr char(17), + date date NOT NULL, + batch char(32), + type enum('IO','CLP','DSP','INPUT','ALT-INPUT','DISPLAY') NOT NULL, + rev tinyint(3) unsigned zerofill NOT NULL, + location char(64), + comments text, + sdram0 enum('32M','64M','128M','256M','512M','1G','2G','4G'), + sdram1 enum('32M','64M','128M','256M','512M','1G','2G','4G'), + sdram2 enum('32M','64M','128M','256M','512M','1G','2G','4G'), + sdram3 enum('32M','64M','128M','256M','512M','1G','2G','4G'), + flash0 enum('4M','8M','16M','32M','64M','128M','256M','512M','1G'), + flash1 enum('4M','8M','16M','32M','64M','128M','256M','512M','1G'), + flash2 enum('4M','8M','16M','32M','64M','128M','256M','512M','1G'), + flash3 enum('4M','8M','16M','32M','64M','128M','256M','512M','1G'), + zbt0 enum('512K','1M','2M','4M','8M','16M'), + zbt1 enum('512K','1M','2M','4M','8M','16M'), + zbt2 enum('512K','1M','2M','4M','8M','16M'), + zbt3 enum('512K','1M','2M','4M','8M','16M'), + zbt4 enum('512K','1M','2M','4M','8M','16M'), + zbt5 enum('512K','1M','2M','4M','8M','16M'), + zbt6 enum('512K','1M','2M','4M','8M','16M'), + zbt7 enum('512K','1M','2M','4M','8M','16M'), + zbt8 enum('512K','1M','2M','4M','8M','16M'), + zbt9 enum('512K','1M','2M','4M','8M','16M'), + zbta enum('512K','1M','2M','4M','8M','16M'), + zbtb enum('512K','1M','2M','4M','8M','16M'), + zbtc enum('512K','1M','2M','4M','8M','16M'), + zbtd enum('512K','1M','2M','4M','8M','16M'), + zbte enum('512K','1M','2M','4M','8M','16M'), + zbtf enum('512K','1M','2M','4M','8M','16M'), + xlxtyp0 enum('XCV300E','XCV400E','XCV600E','XC2V2000','XC2V3000','XC2V4000','XC2V6000','XC2VP2','XC2VP4','XC2VP7','XC2VP20','XC2VP30','XC2VP50','XC4VFX20','XC4VFX40','XC4VFX60','XC4VFX100','XC4VFX140'), + xlxtyp1 enum('XCV300E','XCV400E','XCV600E','XC2V2000','XC2V3000','XC2V4000','XC2V6000','XC2VP2','XC2VP4','XC2VP7','XC2VP20','XC2VP30','XC2VP50','XC4VFX20','XC4VFX40','XC4VFX60','XC4VFX100','XC4VFX140'), + xlxtyp2 enum('XCV300E','XCV400E','XCV600E','XC2V2000','XC2V3000','XC2V4000','XC2V6000','XC2VP2','XC2VP4','XC2VP7','XC2VP20','XC2VP30','XC2VP50','XC4VFX20','XC4VFX40','XC4VFX60','XC4VFX100','XC4VFX140'), + xlxtyp3 enum('XCV300E','XCV400E','XCV600E','XC2V2000','XC2V3000','XC2V4000','XC2V6000','XC2VP2','XC2VP4','XC2VP7','XC2VP20','XC2VP30','XC2VP50','XC4VFX20','XC4VFX40','XC4VFX60','XC4VFX100','XC4VFX140'), + xlxspd0 enum('6','7','8','4','5','9','10','11','12'), + xlxspd1 enum('6','7','8','4','5','9','10','11','12'), + xlxspd2 enum('6','7','8','4','5','9','10','11','12'), + xlxspd3 enum('6','7','8','4','5','9','10','11','12'), + xlxtmp0 enum('COM','IND'), + xlxtmp1 enum('COM','IND'), + xlxtmp2 enum('COM','IND'), + xlxtmp3 enum('COM','IND'), + xlxgrd0 enum('NORMAL','ENGSAMP'), + xlxgrd1 enum('NORMAL','ENGSAMP'), + xlxgrd2 enum('NORMAL','ENGSAMP'), + xlxgrd3 enum('NORMAL','ENGSAMP'), + cputyp enum('MPC8260(HIP3)','MPC8260A(HIP4)','MPC8280(HIP7)','MPC8560'), + cpuspd enum('33MHZ','66MHZ','100MHZ','133MHZ','166MHZ','200MHZ','233MHZ','266MHZ','300MHZ','333MHZ','366MHZ','400MHZ','433MHZ','466MHZ','500MHZ','533MHZ','566MHZ','600MHZ','633MHZ','666MHZ','700MHZ','733MHZ','766MHZ','800MHZ','833MHZ','866MHZ','900MHZ','933MHZ','966MHZ','1000MHZ','1033MHZ','1066MHZ','1100MHZ','1133MHZ','1166MHZ','1200MHZ','1233MHZ','1266MHZ','1300MHZ','1333MHZ'), + cpmspd enum('33MHZ','66MHZ','100MHZ','133MHZ','166MHZ','200MHZ','233MHZ','266MHZ','300MHZ','333MHZ','366MHZ','400MHZ','433MHZ','466MHZ','500MHZ','533MHZ','566MHZ','600MHZ','633MHZ','666MHZ','700MHZ','733MHZ','766MHZ','800MHZ','833MHZ','866MHZ','900MHZ','933MHZ','966MHZ','1000MHZ','1033MHZ','1066MHZ','1100MHZ','1133MHZ','1166MHZ','1200MHZ','1233MHZ','1266MHZ','1300MHZ','1333MHZ'), + busspd enum('33MHZ','66MHZ','100MHZ','133MHZ','166MHZ','200MHZ','233MHZ','266MHZ','300MHZ','333MHZ','366MHZ','400MHZ','433MHZ','466MHZ','500MHZ','533MHZ','566MHZ','600MHZ','633MHZ','666MHZ','700MHZ','733MHZ','766MHZ','800MHZ','833MHZ','866MHZ','900MHZ','933MHZ','966MHZ','1000MHZ','1033MHZ','1066MHZ','1100MHZ','1133MHZ','1166MHZ','1200MHZ','1233MHZ','1266MHZ','1300MHZ','1333MHZ'), + hstype enum('AMCC-S2064A','Xilinx-Rockets'), + hschin enum('0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16'), + hschout enum('0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16'), + PRIMARY KEY (serno), + KEY serno (serno), + UNIQUE serno_2 (serno) +); + +# +# Table structure for table 'log' +# + +DROP TABLE IF EXISTS log; +CREATE TABLE log ( + logno int(10) unsigned zerofill NOT NULL auto_increment, + serno int(10) unsigned zerofill NOT NULL, + date date NOT NULL, + details text NOT NULL, + PRIMARY KEY (logno), + KEY logno (logno, serno, date), + UNIQUE logno_2 (logno) +); diff --git a/u-boot/tools/bddb/defs.php b/u-boot/tools/bddb/defs.php new file mode 100644 index 0000000..b7518e3 --- /dev/null +++ b/u-boot/tools/bddb/defs.php @@ -0,0 +1,710 @@ +<?php // php pages made with phpMyBuilder <http://kyber.dk/phpMyBuilder> ?> +<?php + // (C) Copyright 2001 + // Murray Jensen <Murray.Jensen@csiro.au> + // CSIRO Manufacturing Science and Technology, Preston Lab + + // contains mysql user id and password - keep secret + require("config.php"); + + if (isset($_REQUEST['logout'])) { + Header("status: 401 Unauthorized"); + Header("HTTP/1.0 401 Unauthorized"); + Header("WWW-authenticate: basic realm=\"$bddb_label\""); + + echo "<html><head><title>" . + "Access to '$bddb_label' Denied" . + "</title></head>\n"; + echo "<body bgcolor=#ffffff><br></br><br></br><center><h1>" . + "You must be an Authorised User " . + "to access the '$bddb_label'" . + "</h1>\n</center></body></html>\n"; + exit; + } + + // contents of the various enumerated types - if first item is + // empty ('') then the enum is allowed to be null (ie "not null" + // is not set on the column) + + // all column names in the database table + $columns = array( + 'serno','ethaddr','date','batch', + 'type','rev','location','comments', + 'sdram0','sdram1','sdram2','sdram3', + 'flash0','flash1','flash2','flash3', + 'zbt0','zbt1','zbt2','zbt3','zbt4','zbt5','zbt6','zbt7', + 'zbt8','zbt9','zbta','zbtb','zbtc','zbtd','zbte','zbtf', + 'xlxtyp0','xlxtyp1','xlxtyp2','xlxtyp3', + 'xlxspd0','xlxspd1','xlxspd2','xlxspd3', + 'xlxtmp0','xlxtmp1','xlxtmp2','xlxtmp3', + 'xlxgrd0','xlxgrd1','xlxgrd2','xlxgrd3', + 'cputyp','cpuspd','cpmspd','busspd', + 'hstype','hschin','hschout' + ); + + // board type + $type_vals = array('IO','CLP','DSP','INPUT','ALT-INPUT','DISPLAY'); + + // Xilinx fpga types + $xlxtyp_vals = array('','XCV300E','XCV400E','XCV600E','XC2V2000','XC2V3000','XC2V4000','XC2V6000','XC2VP2','XC2VP4','XC2VP7','XC2VP20','XC2VP30','XC2VP50','XC4VFX20','XC4VFX40','XC4VFX60','XC4VFX100','XC4VFX140'); + + // Xilinx fpga speeds + $xlxspd_vals = array('','6','7','8','4','5','9','10','11','12'); + + // Xilinx fpga temperatures (commercial or industrial) + $xlxtmp_vals = array('','COM','IND'); + + // Xilinx fpga grades (normal or engineering sample) + $xlxgrd_vals = array('','NORMAL','ENGSAMP'); + + // CPU types + $cputyp_vals = array('','MPC8260(HIP3)','MPC8260A(HIP4)','MPC8280(HIP7)','MPC8560'); + + // CPU/BUS/CPM clock speeds + $clk_vals = array('','33MHZ','66MHZ','100MHZ','133MHZ','166MHZ','200MHZ','233MHZ','266MHZ','300MHZ','333MHZ','366MHZ','400MHZ','433MHZ','466MHZ','500MHZ','533MHZ','566MHZ','600MHZ','633MHZ','666MHZ','700MHZ','733MHZ','766MHZ','800MHZ','833MHZ','866MHZ','900MHZ','933MHZ','966MHZ','1000MHZ','1033MHZ','1066MHZ','1100MHZ','1133MHZ','1166MHZ','1200MHZ','1233MHZ','1266MHZ','1300MHZ','1333MHZ'); + + // sdram sizes (nbits array is for eeprom config file) + $sdram_vals = array('','32M','64M','128M','256M','512M','1G','2G','4G'); + $sdram_nbits = array(0,25,26,27,28,29,30,31,32); + + // flash sizes (nbits array is for eeprom config file) + $flash_vals = array('','4M','8M','16M','32M','64M','128M','256M','512M','1G'); + $flash_nbits = array(0,22,23,24,25,26,27,28,29,30); + + // zbt ram sizes (nbits array is for write into eeprom config file) + $zbt_vals = array('','512K','1M','2M','4M','8M','16M'); + $zbt_nbits = array(0,19,20,21,22,23,24); + + // high-speed serial attributes + $hstype_vals = array('','AMCC-S2064A','Xilinx-Rockets'); + $hschin_vals = array('0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16'); + $hschout_vals = array('0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16'); + + // value filters - used when outputting html + function rev_filter($num) { + if ($num == 0) + return "001"; + else + return sprintf("%03d", $num); + } + + function text_filter($str) { + return urldecode($str); + } + + mt_srand(time() | getmypid()); + + // set up MySQL connection + mysql_connect("", $mysql_user, $mysql_pw) || die("cannot connect"); + mysql_select_db($mysql_db) || die("cannot select db"); + + // page header + function pg_head($title) + { + echo "<html>\n<head>\n"; + echo "<link rel=stylesheet href=\"bddb.css\" type=\"text/css\" title=\"style sheet\"></link>\n"; + echo "<title>$title</title>\n"; + echo "</head>\n"; + echo "<body>\n"; + echo "<center><h1>$title</h1></center>\n"; + echo "<hr></hr>\n"; + } + + // page footer + function pg_foot() + { + echo "<hr></hr>\n"; + echo "<table width=\"100%\"><tr><td align=left>\n<address>" . + "If you have any problems, email " . + "<a href=\"mailto:Murray.Jensen@csiro.au\">" . + "Murray Jensen" . + "</a></address>\n" . + "</td><td align=right>\n" . + "<a href=\"index.php?logout=true\">logout</a>\n" . + "</td></tr></table>\n"; + echo "<p><small><i>Made with " . + "<a href=\"http://kyber.dk/phpMyBuilder/\">" . + "Kyber phpMyBuilder</a></i></small></p>\n"; + echo "</body>\n"; + echo "</html>\n"; + } + + // some support functions + + if (!function_exists('array_search')) { + + function array_search($needle, $haystack, $strict = false) { + + if (is_array($haystack) && count($haystack)) { + + $ntype = gettype($needle); + + foreach ($haystack as $key => $value) { + + if ($value == $needle && (!$strict || + gettype($value) == $ntype)) + return $key; + } + } + + return false; + } + } + + if (!function_exists('in_array')) { + + function in_array($needle, $haystack, $strict = false) { + + if (is_array($haystack) && count($haystack)) { + + $ntype = gettype($needle); + + foreach ($haystack as $key => $value) { + + if ($value == $needle && (!$strict || + gettype($value) == $ntype)) + return true; + } + } + + return false; + } + } + + function key_in_array($key, $array) { + return in_array($key, array_keys($array), true); + } + + function enum_to_index($name, $vals) { + $index = array_search($GLOBALS[$name], $vals); + if ($vals[0] != '') + $index++; + return $index; + } + + // fetch a value from an array - return empty string is not present + function get_key_value($key, $array) { + if (key_in_array($key, $array)) + return $array[$key]; + else + return ''; + } + + function fprintf() { + $n = func_num_args(); + if ($n < 2) + return FALSE; + $a = func_get_args(); + $fp = array_shift($a); + $x = "\$s = sprintf"; + $sep = '('; + foreach ($a as $z) { + $x .= "$sep'$z'"; + $sep = ','; + } + $x .= ');'; + eval($x); + $l = strlen($s); + $r = fwrite($fp, $s, $l); + if ($r != $l) + return FALSE; + else + return TRUE; + } + + // functions to display (print) a database table and its columns + + function begin_table($ncols) { + global $table_ncols; + $table_ncols = $ncols; + echo "<table align=center width=\"100%\"" + . " border=1 cellpadding=4 cols=$table_ncols>\n"; + } + + function begin_field($name, $span = 0) { + global $table_ncols; + echo "<tr valign=top>\n"; + echo "\t<th align=center>$name</th>\n"; + if ($span <= 0) + $span = $table_ncols - 1; + if ($span > 1) + echo "\t<td colspan=$span>\n"; + else + echo "\t<td>\n"; + } + + function cont_field($span = 1) { + echo "\t</td>\n"; + if ($span > 1) + echo "\t<td colspan=$span>\n"; + else + echo "\t<td>\n"; + } + + function end_field() { + echo "\t</td>\n"; + echo "</tr>\n"; + } + + function end_table() { + echo "</table>\n"; + } + + function print_field($name, $array, $size = 0, $filt='') { + + begin_field($name); + + if (key_in_array($name, $array)) + $value = $array[$name]; + else + $value = ''; + + if ($filt != '') + $value = $filt($value); + + echo "\t\t<input name=$name value=\"$value\""; + if ($size > 0) + echo " size=$size maxlength=$size"; + echo "></input>\n"; + + end_field(); + } + + function print_field_multiline($name, $array, $cols, $rows, $filt='') { + + begin_field($name); + + if (key_in_array($name, $array)) + $value = $array[$name]; + else + $value = ''; + + if ($filt != '') + $value = $filt($value); + + echo "\t\t<textarea name=$name " . + "cols=$cols rows=$rows wrap=off>\n"; + echo "$value"; + echo "</textarea>\n"; + + end_field(); + } + + // print a mysql ENUM as an html RADIO INPUT + function print_enum($name, $array, $vals, $def = -1) { + + begin_field($name); + + if (key_in_array($name, $array)) + $chk = array_search($array[$name], $vals, FALSE); + else + $chk = $def; + + $nval = count($vals); + + for ($i = 0; $i < $nval; $i++) { + + $val = $vals[$i]; + if ($val == '') + $pval = "none"; + else + $pval = "$val"; + + printf("\t\t<input type=radio name=$name" + . " value=\"$val\"%s>$pval</input>\n", + $i == $chk ? " checked" : ""); + } + + end_field(); + } + + // print a mysql ENUM as an html SELECT INPUT + function print_enum_select($name, $array, $vals, $def = -1) { + + begin_field($name); + + echo "\t\t<select name=$name>\n"; + + if (key_in_array($name, $array)) + $chk = array_search($array[$name], $vals, FALSE); + else + $chk = $def; + + $nval = count($vals); + + for ($i = 0; $i < $nval; $i++) { + + $val = $vals[$i]; + if ($val == '') + $pval = "none"; + else + $pval = "$val"; + + printf("\t\t\t<option " . + "value=\"%s\"%s>%s</option>\n", + $val, $i == $chk ? " selected" : "", $pval); + } + + echo "\t\t</select>\n"; + + end_field(); + } + + // print a group of mysql ENUMs (e.g. name0,name1,...) as an html SELECT + function print_enum_multi($base, $array, $vals, $cnt, $defs, $grp = 0) { + + global $table_ncols; + + if ($grp <= 0) + $grp = $cnt; + $ncell = $cnt / $grp; + $span = ($table_ncols - 1) / $ncell; + + begin_field($base, $span); + + $nval = count($vals); + + for ($i = 0; $i < $cnt; $i++) { + + if ($i > 0 && ($i % $grp) == 0) + cont_field($span); + + $name = sprintf("%s%x", $base, $i); + + echo "\t\t<select name=$name>\n"; + + if (key_in_array($name, $array)) + $ai = array_search($array[$name], $vals, FALSE); + else { + if (key_in_array($i, $defs)) + $ai = $defs[$i]; + else + $ai = 0; + } + + for ($j = 0; $j < $nval; $j++) { + + $val = $vals[$j]; + if ($val == '') + $pval = " "; + else + $pval = "$val"; + + printf("\t\t\t<option " . + "value=\"%s\"%s>%s</option>\n", + $val, + $j == $ai ? " selected" : "", + $pval); + } + + echo "\t\t</select>\n"; + } + + end_field(); + } + + // functions to handle the form input + + // fetch all the parts of an "enum_multi" into a string suitable + // for a MySQL query + function gather_enum_multi_query($base, $cnt) { + + $retval = ''; + + for ($i = 0; $i < $cnt; $i++) { + + $name = sprintf("%s%x", $base, $i); + + if (isset($_REQUEST[$name])) { + $retval .= sprintf(", %s='%s'", + $name, $_REQUEST[$name]); + } + } + + return $retval; + } + + // fetch all the parts of an "enum_multi" into a string suitable + // for a display e.g. in an html table cell + function gather_enum_multi_print($base, $cnt, $array) { + + $retval = ''; + + for ($i = 0; $i < $cnt; $i++) { + + $name = sprintf("%s%x", $base, $i); + + if ($array[$name] != '') { + if ($retval != '') + $retval .= ','; + $retval .= $array[$name]; + } + } + + return $retval; + } + + // fetch all the parts of an "enum_multi" into a string suitable + // for writing to the eeprom data file + function gather_enum_multi_write($base, $cnt, $vals, $xfrm = array()) { + + $retval = ''; + + for ($i = 0; $i < $cnt; $i++) { + + $name = sprintf("%s%x", $base, $i); + + if ($GLOBALS[$name] != '') { + if ($retval != '') + $retval .= ','; + $index = enum_to_index($name, $vals); + if ($xfrm != array()) + $retval .= $xfrm[$index]; + else + $retval .= $index; + } + } + + return $retval; + } + + // count how many parts of an "enum_multi" are actually set + function count_enum_multi($base, $cnt) { + + $retval = 0; + + for ($i = 0; $i < $cnt; $i++) { + + $name = sprintf("%s%x", $base, $i); + + if (isset($_REQUEST[$name])) + $retval++; + } + + return $retval; + } + + // ethernet address functions + + // generate a (possibly not unique) random vendor ethernet address + // (setting bit 6 in the ethernet address - motorola wise i.e. bit 0 + // is the most significant bit - means it is not an assigned ethernet + // address - it is a "locally administered" address). Also, make sure + // it is NOT a multicast ethernet address (by setting bit 7 to 0). + // e.g. the first byte of all ethernet addresses generated here will + // have 2 in the bottom two bits (incidentally, these are the first + // two bits transmitted on the wire, since the octets in ethernet + // addresses are transmitted LSB first). + + function gen_eth_addr($serno) { + + $ethaddr_hgh = (mt_rand(0, 65535) & 0xfeff) | 0x0200; + $ethaddr_mid = mt_rand(0, 65535); + $ethaddr_low = mt_rand(0, 65535); + + return sprintf("%02lx:%02lx:%02lx:%02lx:%02lx:%02lx", + $ethaddr_hgh >> 8, $ethaddr_hgh & 0xff, + $ethaddr_mid >> 8, $ethaddr_mid & 0xff, + $ethaddr_low >> 8, $ethaddr_low & 0xff); + } + + // check that an ethernet address is valid + function eth_addr_is_valid($ethaddr) { + + $ethbytes = split(':', $ethaddr); + + if (count($ethbytes) != 6) + return FALSE; + + for ($i = 0; $i < 6; $i++) { + $ethbyte = $ethbytes[$i]; + if (!ereg('^[0-9a-f][0-9a-f]$', $ethbyte)) + return FALSE; + } + + return TRUE; + } + + // write a simple eeprom configuration file + function write_eeprom_cfg_file() { + + global $sernos, $nsernos, $bddb_cfgdir, $numerrs, $cfgerrs; + global $date, $batch, $type_vals, $rev; + global $sdram_vals, $sdram_nbits; + global $flash_vals, $flash_nbits; + global $zbt_vals, $zbt_nbits; + global $xlxtyp_vals, $xlxspd_vals, $xlxtmp_vals, $xlxgrd_vals; + global $cputyp, $cputyp_vals, $clk_vals; + global $hstype, $hstype_vals, $hschin, $hschout; + + $numerrs = 0; + $cfgerrs = array(); + + for ($i = 0; $i < $nsernos; $i++) { + + $serno = sprintf("%010d", $sernos[$i]); + + $wfp = @fopen($bddb_cfgdir . "/$serno.cfg", "w"); + if (!$wfp) { + $cfgerrs[$i] = 'file create fail'; + $numerrs++; + continue; + } + set_file_buffer($wfp, 0); + + if (!fprintf($wfp, "serno=%d\n", $sernos[$i])) { + $cfgerrs[$i] = 'cfg wr fail (serno)'; + fclose($wfp); + $numerrs++; + continue; + } + + if (!fprintf($wfp, "date=%s\n", $date)) { + $cfgerrs[$i] = 'cfg wr fail (date)'; + fclose($wfp); + $numerrs++; + continue; + } + + if ($batch != '') { + if (!fprintf($wfp, "batch=%s\n", $batch)) { + $cfgerrs[$i] = 'cfg wr fail (batch)'; + fclose($wfp); + $numerrs++; + continue; + } + } + + $typei = enum_to_index("type", $type_vals); + if (!fprintf($wfp, "type=%d\n", $typei)) { + $cfgerrs[$i] = 'cfg wr fail (type)'; + fclose($wfp); + $numerrs++; + continue; + } + + if (!fprintf($wfp, "rev=%d\n", $rev)) { + $cfgerrs[$i] = 'cfg wr fail (rev)'; + fclose($wfp); + $numerrs++; + continue; + } + + $s = gather_enum_multi_write("sdram", 4, + $sdram_vals, $sdram_nbits); + if ($s != '') { + $b = fprintf($wfp, "sdram=%s\n", $s); + if (!$b) { + $cfgerrs[$i] = 'cfg wr fail (sdram)'; + fclose($wfp); + $numerrs++; + continue; + } + } + + $s = gather_enum_multi_write("flash", 4, + $flash_vals, $flash_nbits); + if ($s != '') { + $b = fprintf($wfp, "flash=%s\n", $s); + if (!$b) { + $cfgerrs[$i] = 'cfg wr fail (flash)'; + fclose($wfp); + $numerrs++; + continue; + } + } + + $s = gather_enum_multi_write("zbt", 16, + $zbt_vals, $zbt_nbits); + if ($s != '') { + $b = fprintf($wfp, "zbt=%s\n", $s); + if (!$b) { + $cfgerrs[$i] = 'cfg wr fail (zbt)'; + fclose($wfp); + $numerrs++; + continue; + } + } + + $s = gather_enum_multi_write("xlxtyp", 4, $xlxtyp_vals); + if ($s != '') { + $b = fprintf($wfp, "xlxtyp=%s\n", $s); + if (!$b) { + $cfgerrs[$i] = 'cfg wr fail (xlxtyp)'; + fclose($wfp); + $numerrs++; + continue; + } + } + + $s = gather_enum_multi_write("xlxspd", 4, $xlxspd_vals); + if ($s != '') { + $b = fprintf($wfp, "xlxspd=%s\n", $s); + if (!$b) { + $cfgerrs[$i] = 'cfg wr fail (xlxspd)'; + fclose($wfp); + $numerrs++; + continue; + } + } + + $s = gather_enum_multi_write("xlxtmp", 4, $xlxtmp_vals); + if ($s != '') { + $b = fprintf($wfp, "xlxtmp=%s\n", $s); + if (!$b) { + $cfgerrs[$i] = 'cfg wr fail (xlxtmp)'; + fclose($wfp); + $numerrs++; + continue; + } + } + + $s = gather_enum_multi_write("xlxgrd", 4, $xlxgrd_vals); + if ($s != '') { + $b = fprintf($wfp, "xlxgrd=%s\n", $s); + if (!$b) { + $cfgerrs[$i] = 'cfg wr fail (xlxgrd)'; + fclose($wfp); + $numerrs++; + continue; + } + } + + if ($cputyp != '') { + $cputypi = enum_to_index("cputyp",$cputyp_vals); + $cpuspdi = enum_to_index("cpuspd", $clk_vals); + $busspdi = enum_to_index("busspd", $clk_vals); + $cpmspdi = enum_to_index("cpmspd", $clk_vals); + $b = fprintf($wfp, "cputyp=%d\ncpuspd=%d\n" . + "busspd=%d\ncpmspd=%d\n", + $cputypi, $cpuspdi, $busspdi, $cpmspdi); + if (!$b) { + $cfgerrs[$i] = 'cfg wr fail (cputyp)'; + fclose($wfp); + $numerrs++; + continue; + } + } + + if ($hstype != '') { + $hstypei = enum_to_index("hstype",$hstype_vals); + $b = fprintf($wfp, "hstype=%d\n" . + "hschin=%s\nhschout=%s\n", + $hstypei, $hschin, $hschout); + if (!$b) { + $cfgerrs[$i] = 'cfg wr fail (hstype)'; + fclose($wfp); + $numerrs++; + continue; + } + } + + if (!fclose($wfp)) { + $cfgerrs[$i] = 'file cls fail'; + $numerrs++; + } + } + + return $numerrs; + } +?> diff --git a/u-boot/tools/bddb/dodelete.php b/u-boot/tools/bddb/dodelete.php new file mode 100644 index 0000000..4839e36 --- /dev/null +++ b/u-boot/tools/bddb/dodelete.php @@ -0,0 +1,65 @@ +<?php // php pages made with phpMyBuilder <http://kyber.dk/phpMyBuilder> ?> +<?php + // (C) Copyright 2001 + // Murray Jensen <Murray.Jensen@csiro.au> + // CSIRO Manufacturing Science and Technology, Preston Lab + + // dodelete page (hymod_bddb / boards) + + require("defs.php"); + + pg_head("$bddb_label - Delete Board Results"); + + if (!isset($_REQUEST['serno'])) + die("the board serial number was not specified"); + $serno=intval($_REQUEST['serno']); + + mysql_query("delete from boards where serno=$serno"); + + if(mysql_errno()) { + $errstr = mysql_error(); + echo "\t<font size=+4>\n"; + echo "\t\t<p>\n"; + echo "\t\t\tThe following error was encountered:\n"; + echo "\t\t</p>\n"; + echo "\t\t<center>\n"; + printf("\t\t\t<b>%s</b>\n", $errstr); + echo "\t\t</center>\n"; + echo "\t</font>\n"; + } + else { + echo "\t<font size=+2>\n"; + echo "\t\t<p>\n"; + echo "\t\t\tThe board with serial number <b>$serno</b> was" + . " successfully deleted\n"; + mysql_query("delete from log where serno=$serno"); + if (mysql_errno()) { + $errstr = mysql_error(); + echo "\t\t\t<font size=+4>\n"; + echo "\t\t\t\t<p>\n"; + echo "\t\t\t\t\tBut the following error occurred " . + "when deleting the log entries:\n"; + echo "\t\t\t\t</p>\n"; + echo "\t\t\t\t<center>\n"; + printf("\t\t\t\t\t<b>%s</b>\n", $errstr); + echo "\t\t\t\t</center>\n"; + echo "\t\t\t</font>\n"; + } + echo "\t\t</p>\n"; + echo "\t</font>\n"; + } +?> +<p> +<table width="100%"> +<tr> + <td align=center> + <a href="browse.php">Back to Browse</a> + </td> + <td align=center> + <a href="index.php">Back to Start</a> + </td> +</tr> +</table> +<?php + pg_foot(); +?> diff --git a/u-boot/tools/bddb/dodellog.php b/u-boot/tools/bddb/dodellog.php new file mode 100644 index 0000000..9dd78c1 --- /dev/null +++ b/u-boot/tools/bddb/dodellog.php @@ -0,0 +1,57 @@ +<?php // php pages made with phpMyBuilder <http://kyber.dk/phpMyBuilder> ?> +<?php + // (C) Copyright 2001 + // Murray Jensen <Murray.Jensen@csiro.au> + // CSIRO Manufacturing Science and Technology, Preston Lab + + // dodelete page (hymod_bddb / boards) + + require("defs.php"); + + pg_head("$bddb_label - Delete Log Entry Results"); + + if (!isset($_REQUEST['serno'])) + die("the board serial number was not specified"); + $serno=intval($_REQUEST['serno']); + + if (!isset($_REQUEST['logno']) || $_REQUEST['logno'] == 0) + die("the log entry number not specified!"); + $logno=$_REQUEST['logno']; + + mysql_query("delete from log where serno=$serno and logno=$logno"); + + if(mysql_errno()) { + $errstr = mysql_error(); + echo "\t<font size=+4>\n"; + echo "\t\t<p>\n"; + echo "\t\t\tThe following error was encountered:\n"; + echo "\t\t</p>\n"; + echo "\t\t<center>\n"; + printf("\t\t\t<b>%s</b>\n", $errstr); + echo "\t\t</center>\n"; + echo "\t</font>\n"; + } + else { + echo "\t<font size=+2>\n"; + echo "\t\t<p>\n"; + echo "\t\t\tThe log entry with log number <b>$logno</b>\n"; + echo "\t\t\tand serial number <b>$serno</b> "; + echo "was successfully deleted\n"; + echo "\t\t</p>\n"; + echo "\t</font>\n"; + } +?> +<p> +<table width="100%"> +<tr> + <td align=center> + <a href="brlog.php?serno=<?php echo "$serno"; ?>">Back to Log</a> + </td> + <td align=center> + <a href="index.php">Back to Start</a> + </td> +</tr> +</table> +<?php + pg_foot(); +?> diff --git a/u-boot/tools/bddb/doedit.php b/u-boot/tools/bddb/doedit.php new file mode 100644 index 0000000..13fbb69 --- /dev/null +++ b/u-boot/tools/bddb/doedit.php @@ -0,0 +1,186 @@ +<?php // php pages made with phpMyBuilder <http://kyber.dk/phpMyBuilder> ?> +<?php + // (C) Copyright 2001 + // Murray Jensen <Murray.Jensen@csiro.au> + // CSIRO Manufacturing Science and Technology, Preston Lab + + // doedit page (hymod_bddb / boards) + + require("defs.php"); + + pg_head("$bddb_label - Edit Board Results"); + + if (!isset($_REQUEST['serno']) || $_REQUEST['serno'] == '') + die("the board serial number was not specified"); + $serno=intval($_REQUEST['serno']); + + $query="update boards set"; + + if (isset($_REQUEST['ethaddr'])) { + $ethaddr=$_REQUEST['ethaddr']; + if (!eth_addr_is_valid($ethaddr)) + die("ethaddr is invalid ('$ethaddr')"); + $query.=" ethaddr='$ethaddr',"; + } + + if (isset($_REQUEST['date'])) { + $date=$_REQUEST['date']; + list($y, $m, $d) = split("-", $date); + if (!checkdate($m, $d, $y) || $y < 1999) + die("date is invalid (input '$date', " . + "yyyy-mm-dd '$y-$m-$d')"); + $query.=" date='$date'"; + } + + if (isset($_REQUEST['batch'])) { + $batch=$_REQUEST['batch']; + if (strlen($batch) > 32) + die("batch field too long (>32)"); + $query.=", batch='$batch'"; + } + + if (isset($_REQUEST['type'])) { + $type=$_REQUEST['type']; + if (!in_array($type, $type_vals)) + die("Invalid type ($type) specified"); + $query.=", type='$type'"; + } + + if (isset($_REQUEST['rev'])) { + $rev=$_REQUEST['rev']; + if (($rev = intval($rev)) <= 0 || $rev > 255) + die("Revision number is invalid ($rev)"); + $query.=sprintf(", rev=%d", $rev); + } + + if (isset($_REQUEST['location'])) { + $location=$_REQUEST['location']; + if (strlen($location) > 64) + die("location field too long (>64)"); + $query.=", location='$location'"; + } + + if (isset($_REQUEST['comments'])) + $comments=$_REQUEST['comments']; + $query.=", comments='" . rawurlencode($comments) . "'"; + + $query.=gather_enum_multi_query("sdram", 4); + + $query.=gather_enum_multi_query("flash", 4); + + $query.=gather_enum_multi_query("zbt", 16); + + $query.=gather_enum_multi_query("xlxtyp", 4); + $nxlx = count_enum_multi("xlxtyp", 4); + + $query.=gather_enum_multi_query("xlxspd", 4); + if (count_enum_multi("xlxspd", 4) != $nxlx) + die("number of xilinx speeds not same as number of types"); + + $query.=gather_enum_multi_query("xlxtmp", 4); + if (count_enum_multi("xlxtmp", 4) != $nxlx) + die("number of xilinx temps. not same as number of types"); + + $query.=gather_enum_multi_query("xlxgrd", 4); + if (count_enum_multi("xlxgrd", 4) != $nxlx) + die("number of xilinx grades not same as number of types"); + + if (isset($_REQUEST['cputyp'])) { + $cputyp=$_REQUEST['cputyp']; + $query.=", cputyp='$cputyp'"; + if (!isset($_REQUEST['cpuspd']) || $_REQUEST['cpuspd'] == '') + die("must specify cpu speed if cpu type is defined"); + $cpuspd=$_REQUEST['cpuspd']; + $query.=", cpuspd='$cpuspd'"; + if (!isset($_REQUEST['cpmspd']) || $_REQUEST['cpmspd'] == '') + die("must specify cpm speed if cpu type is defined"); + $cpmspd=$_REQUEST['cpmspd']; + $query.=", cpmspd='$cpmspd'"; + if (!isset($_REQUEST['busspd']) || $_REQUEST['busspd'] == '') + die("must specify bus speed if cpu type is defined"); + $busspd=$_REQUEST['busspd']; + $query.=", busspd='$busspd'"; + } + else { + if (isset($_REQUEST['cpuspd'])) + die("can't specify cpu speed if there is no cpu"); + if (isset($_REQUEST['cpmspd'])) + die("can't specify cpm speed if there is no cpu"); + if (isset($_REQUEST['busspd'])) + die("can't specify bus speed if there is no cpu"); + } + + if (isset($_REQUEST['hschin'])) { + $hschin=$_REQUEST['hschin']; + if (($hschin = intval($hschin)) < 0 || $hschin > 4) + die("Invalid number of hs input chans ($hschin)"); + } + else + $hschin = 0; + if (isset($_REQUEST['hschout'])) { + $hschout=$_REQUEST['hschout']; + if (($hschout = intval($hschout)) < 0 || $hschout > 4) + die("Invalid number of hs output chans ($hschout)"); + } + else + $hschout = 0; + if (isset($_REQUEST['hstype'])) { + $hstype=$_REQUEST['hstype']; + $query.=", hstype='$hstype'"; + } + else { + if ($_REQUEST['hschin'] != 0) + die("number of high-speed input channels must be zero" + . " if high-speed chip is not present"); + if ($_REQUEST['hschout'] != 0) + die("number of high-speed output channels must be zero" + . " if high-speed chip is not present"); + } + $query.=", hschin='$hschin'"; + $query.=", hschout='$hschout'"; + + $query.=" where serno=$serno"; + + mysql_query($query); + if(mysql_errno()) { + $errstr = mysql_error(); + echo "\t<font size=+4>\n"; + echo "\t\t<p>\n"; + echo "\t\t\tThe following error was encountered:\n"; + echo "\t\t</p>\n"; + echo "\t\t<center>\n"; + printf("\t\t\t<b>%s</b>\n", $errstr); + echo "\t\t</center>\n"; + echo "\t</font>\n"; + } + else { + $sernos = array($serno); + $nsernos = 1; + + write_eeprom_cfg_file(); + + echo "\t<font size=+2>\n"; + echo "\t\t<p>\n"; + echo "\t\t\tThe board with serial number <b>$serno</b> was" + . " successfully updated"; + if ($numerrs > 0) { + $errstr = $cfgerrs[0]; + echo "<br>\n\t\t\t"; + echo "(but the cfg file update failed: $errstr)"; + } + echo "\n"; + echo "\t\t</p>\n"; + echo "\t</font>\n"; + } + +?> +<p> +<table align=center width="100%"> +<tr> + <td align=center><a href="browse.php">Back to Browse</a></td> + <td align=center><a href="index.php">Back to Start</a></td> +</tr> +</table> +<?php + pg_foot(); +?> diff --git a/u-boot/tools/bddb/doedlog.php b/u-boot/tools/bddb/doedlog.php new file mode 100644 index 0000000..7009aa7 --- /dev/null +++ b/u-boot/tools/bddb/doedlog.php @@ -0,0 +1,76 @@ +<?php // php pages made with phpMyBuilder <http://kyber.dk/phpMyBuilder> ?> +<?php + // (C) Copyright 2001 + // Murray Jensen <Murray.Jensen@csiro.au> + // CSIRO Manufacturing Science and Technology, Preston Lab + + // doedit page (hymod_bddb / boards) + + require("defs.php"); + + pg_head("$bddb_label - Edit Log Entry Results"); + + if (!isset($_REQUEST['serno']) || $_REQUEST['serno'] == '') + die("the board serial number was not specified"); + $serno=intval($_REQUEST['serno']); + + if (!isset($_REQUEST['logno']) || $_REQUEST['logno'] == '') + die("log number not specified!"); + $logno=intval($_REQUEST['logno']); + + $query="update log set"; + + if (isset($_REQUEST['date'])) { + $date=$_REQUEST['date']; + list($y, $m, $d) = split("-", $date); + if (!checkdate($m, $d, $y) || $y < 1999) + die("date is invalid (input '$date', " . + "yyyy-mm-dd '$y-$m-$d')"); + $query.=" date='$date'"; + } + + if (isset($_REQUEST['who'])) { + $who=$_REQUEST['who']; + $query.=", who='" . $who . "'"; + } + + if (isset($_REQUEST['details'])) { + $details=$_REQUEST['details']; + $query.=", details='" . rawurlencode($details) . "'"; + } + + $query.=" where serno=$serno and logno=$logno"; + + mysql_query($query); + if(mysql_errno()) { + $errstr = mysql_error(); + echo "\t<font size=+4>\n"; + echo "\t\t<p>\n"; + echo "\t\t\tThe following error was encountered:\n"; + echo "\t\t</p>\n"; + echo "\t\t<center>\n"; + printf("\t\t\t<b>%s</b>\n", $errstr); + echo "\t\t</center>\n"; + echo "\t</font>\n"; + } + else { + echo "\t<font size=+2>\n"; + echo "\t\t<p>\n"; + echo "\t\t\tThe log entry with log number <b>$logno</b> and\n"; + echo "\t\t\tserial number <b>$serno</b> "; + echo "was successfully updated\n"; + echo "\t\t</p>\n"; + echo "\t</font>\n"; + } + +?> +<p> +<table align=center width="100%"> +<tr> + <td align=center><a href="brlog.php?serno=<?php echo "$serno"; ?>">Back to Log</a></td> + <td align=center><a href="index.php">Back to Start</a></td> +</tr> +</table> +<?php + pg_foot(); +?> diff --git a/u-boot/tools/bddb/donew.php b/u-boot/tools/bddb/donew.php new file mode 100644 index 0000000..39b2c78 --- /dev/null +++ b/u-boot/tools/bddb/donew.php @@ -0,0 +1,230 @@ +<?php // php pages made with phpMyBuilder <http://kyber.dk/phpMyBuilder> ?> +<?php + // (C) Copyright 2001 + // Murray Jensen <Murray.Jensen@csiro.au> + // CSIRO Manufacturing Science and Technology, Preston Lab + + // doedit page (hymod_bddb / boards) + + require("defs.php"); + + pg_head("$bddb_label - Board Registration Results"); + + if (isset($_REQUEST['serno'])) { + $serno=$_REQUEST['serno']; + die("serial number must not be set ($serno) when Creating!"); + } + + $query="update boards set"; + + list($y, $m, $d) = split("-", $date); + if (!checkdate($m, $d, $y) || $y < 1999) + die("date is invalid (input '$date', yyyy-mm-dd '$y-$m-$d')"); + $query.=" date='$date'"; + + if ($batch != '') { + if (strlen($batch) > 32) + die("batch field too long (>32)"); + $query.=", batch='$batch'"; + } + + if (!in_array($type, $type_vals)) + die("Invalid type ($type) specified"); + $query.=", type='$type'"; + + if (($rev = intval($rev)) <= 0 || $rev > 255) + die("Revision number is invalid ($rev)"); + $query.=sprintf(", rev=%d", $rev); + + $query.=gather_enum_multi_query("sdram", 4); + + $query.=gather_enum_multi_query("flash", 4); + + $query.=gather_enum_multi_query("zbt", 16); + + $query.=gather_enum_multi_query("xlxtyp", 4); + $nxlx = count_enum_multi("xlxtyp", 4); + + $query.=gather_enum_multi_query("xlxspd", 4); + if (count_enum_multi("xlxspd", 4) != $nxlx) + die("number of xilinx speeds not same as number of types"); + + $query.=gather_enum_multi_query("xlxtmp", 4); + if (count_enum_multi("xlxtmp", 4) != $nxlx) + die("number of xilinx temps. not same as number of types"); + + $query.=gather_enum_multi_query("xlxgrd", 4); + if (count_enum_multi("xlxgrd", 4) != $nxlx) + die("number of xilinx grades not same as number of types"); + + if ($cputyp == '') { + if ($cpuspd != '') + die("can't specify cpu speed if there is no cpu"); + if ($cpmspd != '') + die("can't specify cpm speed if there is no cpu"); + if ($busspd != '') + die("can't specify bus speed if there is no cpu"); + } + else { + $query.=", cputyp='$cputyp'"; + if ($cpuspd == '') + die("must specify cpu speed if cpu type is defined"); + $query.=", cpuspd='$cpuspd'"; + if ($cpmspd == '') + die("must specify cpm speed if cpu type is defined"); + $query.=", cpmspd='$cpmspd'"; + if ($busspd == '') + die("must specify bus speed if cpu type is defined"); + $query.=", busspd='$busspd'"; + } + + if (($hschin = intval($hschin)) < 0 || $hschin > 4) + die("Invalid number of hs input chans ($hschin)"); + if (($hschout = intval($hschout)) < 0 || $hschout > 4) + die("Invalid number of hs output chans ($hschout)"); + if ($hstype == '') { + if ($hschin != 0) + die("number of high-speed input channels must be zero" + . " if high-speed chip is not present"); + if ($hschout != 0) + die("number of high-speed output channels must be zero" + . " if high-speed chip is not present"); + } + else + $query.=", hstype='$hstype'"; + $query.=", hschin='$hschin'"; + $query.=", hschout='$hschout'"; + + // echo "final query = '$query'<br>\n"; + + $quant = intval($quant); + if ($quant <= 0) $quant = 1; + + $sernos = array(); + if ($geneths) + $ethaddrs = array(); + + $sqlerr = ''; + + while ($quant-- > 0) { + + mysql_query("insert into boards (serno) values (null)"); + if (mysql_errno()) { + $sqlerr = mysql_error(); + break; + } + + $serno = mysql_insert_id(); + if (!$serno) { + $sqlerr = "couldn't allocate new serial number"; + break; + } + + mysql_query($query . " where serno=$serno"); + if (mysql_errno()) { + $sqlerr = mysql_error(); + break; + } + + array_push($sernos, $serno); + + if ($geneths) { + + $ethaddr = gen_eth_addr($serno); + + mysql_query("update boards set ethaddr='$ethaddr'" . + " where serno=$serno"); + if (mysql_errno()) { + $sqlerr = mysql_error(); + + array_push($ethaddrs, + "<font color=#ff0000><b>" . + "db save fail" . + "</b></font>"); + break; + } + + array_push($ethaddrs, $ethaddr); + } + } + + $nsernos = count($sernos); + + if ($nsernos > 0) { + + write_eeprom_cfg_file(); + + echo "<font size=+2>\n"; + echo "\t<p>\n"; + echo "\t\tThe following board serial numbers were" + . " successfully allocated"; + if ($numerrs > 0) + echo " (but with $numerrs cfg file error" . + ($numerrs > 1 ? "s" : "") . ")"; + echo ":\n"; + echo "\t</p>\n"; + + echo "</font>\n"; + + echo "<table align=center width=\"100%\">\n"; + echo "<tr>\n"; + echo "\t<th>Serial Number</th>\n"; + if ($numerrs > 0) + echo "\t<th>Cfg File Errs</th>\n"; + if ($geneths) + echo "\t<th>Ethernet Address</th>\n"; + echo "</tr>\n"; + + for ($i = 0; $i < $nsernos; $i++) { + + $serno = sprintf("%010d", $sernos[$i]); + + echo "<tr>\n"; + + echo "\t<td align=center><font size=+2>" . + "<b>$serno</b></font></td>\n"; + + if ($numerrs > 0) { + if (($errstr = $cfgerrs[$i]) == '') + $errstr = ' '; + echo "\t<td align=center>" . + "<font size=+2 color=#ff0000><b>" . + $errstr . + "</b></font></td>\n"; + } + + if ($geneths) { + echo "\t<td align=center>" . + "<font size=+2 color=#00ff00><b>" . + $ethaddrs[$i] . + "</b></font></td>\n"; + } + + echo "</tr>\n"; + } + + echo "</table>\n"; + } + + if ($sqlerr != '') { + echo "\t<font size=+4>\n"; + echo "\t\t<p>\n"; + echo "\t\t\tThe following SQL error was encountered:\n"; + echo "\t\t</p>\n"; + echo "\t\t<center>\n"; + printf("\t\t\t<b>%s</b>\n", $sqlerr); + echo "\t\t</center>\n"; + echo "\t</font>\n"; + } + +?> +<p> +<table align=center width="100%"> +<tr> + <td align=center><a href="browse.php">Go to Browse</a></td> + <td align=center><a href="index.php">Back to Start</a></td> +</tr> +</table> +<?php + pg_foot(); +?> diff --git a/u-boot/tools/bddb/donewlog.php b/u-boot/tools/bddb/donewlog.php new file mode 100644 index 0000000..7635d29 --- /dev/null +++ b/u-boot/tools/bddb/donewlog.php @@ -0,0 +1,86 @@ +<?php // php pages made with phpMyBuilder <http://kyber.dk/phpMyBuilder> ?> +<?php + // (C) Copyright 2001 + // Murray Jensen <Murray.Jensen@csiro.au> + // CSIRO Manufacturing Science and Technology, Preston Lab + + // doedit page (hymod_bddb / boards) + + require("defs.php"); + + pg_head("$bddb_label - Add Log Entry Results"); + + if (!isset($_REQUEST['serno']) || $_REQUEST['serno'] == '') + die("serial number not specified!"); + $serno=intval($_REQUEST['serno']); + + if (isset($_REQUEST['logno'])) { + $logno=$_REQUEST['logno']; + die("log number must not be set ($logno) when Creating!"); + } + + $query="update log set serno=$serno"; + + list($y, $m, $d) = split("-", $date); + if (!checkdate($m, $d, $y) || $y < 1999) + die("date is invalid (input '$date', yyyy-mm-dd '$y-$m-$d')"); + $query.=", date='$date'"; + + if (isset($_REQUEST['who'])) { + $who=$_REQUEST['who']; + $query.=", who='" . $who . "'"; + } + + if (isset($_REQUEST['details'])) { + $details=$_REQUEST['details']; + $query.=", details='" . rawurlencode($details) . "'"; + } + + // echo "final query = '$query'<br>\n"; + + $sqlerr = ''; + + mysql_query("insert into log (logno) values (null)"); + if (mysql_errno()) + $sqlerr = mysql_error(); + else { + $logno = mysql_insert_id(); + if (!$logno) + $sqlerr = "couldn't allocate new serial number"; + else { + mysql_query($query . " where logno=$logno"); + if (mysql_errno()) + $sqlerr = mysql_error(); + } + } + + if ($sqlerr == '') { + echo "<font size=+2>\n"; + echo "\t<p>\n"; + echo "\t\tA log entry with log number '$logno' was " . + "added to the board with serial number '$serno'\n"; + echo "\t</p>\n"; + echo "</font>\n"; + } + else { + echo "\t<font size=+4>\n"; + echo "\t\t<p>\n"; + echo "\t\t\tThe following SQL error was encountered:\n"; + echo "\t\t</p>\n"; + echo "\t\t<center>\n"; + printf("\t\t\t<b>%s</b>\n", $sqlerr); + echo "\t\t</center>\n"; + echo "\t</font>\n"; + } + +?> +<p></p> +<table width="100%"> +<tr> + <td align=center><a href="brlog.php?serno=<?php echo "$serno"; ?>">Go to Browse</a></td> + <td align=center><a href="index.php">Back to Start</a></td> +</tr> +</table> +<?php + pg_foot(); +?> diff --git a/u-boot/tools/bddb/edit.php b/u-boot/tools/bddb/edit.php new file mode 100644 index 0000000..dd8c26c --- /dev/null +++ b/u-boot/tools/bddb/edit.php @@ -0,0 +1,131 @@ +<?php // php pages made with phpMyBuilder <http://kyber.dk/phpMyBuilder> ?> +<?php + // (C) Copyright 2001 + // Murray Jensen <Murray.Jensen@csiro.au> + // CSIRO Manufacturing Science and Technology, Preston Lab + + // edit page (hymod_bddb / boards) + + require("defs.php"); + + pg_head("$bddb_label - Edit Board Registration"); + + if ($serno == 0) + die("serial number not specified or invalid!"); + + $pserno = sprintf("%010d", $serno); + + echo "<center><b><font size=+2>"; + echo "Board Serial Number: $pserno"; + echo "</font></b></center>\n"; + +?> +<p> +<form action=doedit.php method=POST> +<?php + echo "<input type=hidden name=serno value=$serno>\n"; + + $r=mysql_query("select * from boards where serno=$serno"); + $row=mysql_fetch_array($r); + if(!$row) die("no record of serial number '$serno' in database"); + + begin_table(5); + + // ethaddr char(17) + print_field("ethaddr", $row, 17); + + // date date + print_field("date", $row); + + // batch char(32) + print_field("batch", $row, 32); + + // type enum('IO','CLP','DSP','INPUT','ALT-INPUT','DISPLAY') + print_enum("type", $row, $type_vals); + + // rev tinyint(3) unsigned zerofill + print_field("rev", $row, 3, 'rev_filter'); + + // location char(64) + print_field("location", $row, 64); + + // comments text + print_field_multiline("comments", $row, 60, 10, 'text_filter'); + + // sdram[0-3] enum('32M','64M','128M','256M') + print_enum_multi("sdram", $row, $sdram_vals, 4, array()); + + // flash[0-3] enum('4M','8M','16M','32M','64M') + print_enum_multi("flash", $row, $flash_vals, 4, array()); + + // zbt[0-f] enum('512K','1M','2M','4M') + print_enum_multi("zbt", $row, $zbt_vals, 16, array()); + + // xlxtyp[0-3] enum('XCV300E','XCV400E','XCV600E') + print_enum_multi("xlxtyp", $row, $xlxtyp_vals, 4, array(), 1); + + // xlxspd[0-3] enum('6','7','8') + print_enum_multi("xlxspd", $row, $xlxspd_vals, 4, array(), 1); + + // xlxtmp[0-3] enum('COM','IND') + print_enum_multi("xlxtmp", $row, $xlxtmp_vals, 4, array(), 1); + + // xlxgrd[0-3] enum('NORMAL','ENGSAMP') + print_enum_multi("xlxgrd", $row, $xlxgrd_vals, 4, array(), 1); + + // cputyp enum('MPC8260(HIP3)','MPC8260A(HIP4)','MPC8280(HIP7)') + print_enum("cputyp", $row, $cputyp_vals); + + // cpuspd enum('33MHZ','66MHZ','100MHZ','133MHZ','166MHZ','200MHZ','233MHZ','266MHZ') + print_enum_select("cpuspd", $row, $clk_vals); + + // cpmspd enum('33MHZ','66MHZ','100MHZ','133MHZ','166MHZ','200MHZ','233MHZ','266MHZ') + print_enum_select("cpmspd", $row, $clk_vals); + + // busspd enum('33MHZ','66MHZ','100MHZ','133MHZ','166MHZ','200MHZ','233MHZ','266MHZ') + print_enum_select("busspd", $row, $clk_vals); + + // hstype enum('AMCC-S2064A') + print_enum("hstype", $row, $hstype_vals); + + // hschin enum('0','1','2','3','4') + print_enum("hschin", $row, $hschin_vals); + + // hschout enum('0','1','2','3','4') + print_enum("hschout", $row, $hschout_vals); + + end_table(); + + echo "<p>\n"; + echo "<center><b>"; + echo "<font color=#ff0000>WARNING: NO UNDO ON DELETE!</font>"; + echo "<br></br>\n"; + echo "<tt>[ <a href=\"dodelete.php?serno=$serno\">delete</a> ]</tt>"; + echo "</b></center>\n"; + echo "</p>\n"; +?> +<p> +<table align=center width="100%"> +<tr> + <td align=center> + <input type=submit value=Edit> + </td> + <td> + + </td> + <td align=center> + <input type=reset value=Reset> + </td> + <td> + + </td> + <td align=center> + <a href="index.php">Back to Start</a> + </td> +</tr> +</table> +</p> +</form> +<?php + pg_foot(); +?> diff --git a/u-boot/tools/bddb/edlog.php b/u-boot/tools/bddb/edlog.php new file mode 100644 index 0000000..8befd35 --- /dev/null +++ b/u-boot/tools/bddb/edlog.php @@ -0,0 +1,86 @@ +<?php // php pages made with phpMyBuilder <http://kyber.dk/phpMyBuilder> ?> +<?php + // (C) Copyright 2001 + // Murray Jensen <Murray.Jensen@csiro.au> + // CSIRO Manufacturing Science and Technology, Preston Lab + + // edit page (hymod_bddb / boards) + + require("defs.php"); + + pg_head("$bddb_label - Edit Board Log Entry"); + + if (!isset($_REQUEST['serno']) || $_REQUEST['serno'] == '') + die("serial number not specified!"); + $serno=intval($_REQUEST['serno']); + + if (!isset($_REQUEST['logno']) || $_REQUEST['logno'] == '') + die("log number not specified!"); + $logno=intval($_REQUEST['logno']); + + $pserno = sprintf("%010d", $serno); + $plogno = sprintf("%010d", $logno); + + echo "<center><b><font size=+2>"; + echo "Board Serial Number: $pserno, Log Number: $plogno"; + echo "</font></b></center>\n"; + +?> +<p> +<form action=doedlog.php method=POST> +<?php + echo "<input type=hidden name=serno value=$serno>\n"; + echo "<input type=hidden name=logno value=$logno>\n"; + + $r=mysql_query("select * from log where serno=$serno and logno=$logno"); + $row=mysql_fetch_array($r); + if(!$row) + die("no record of log entry with serial number '$serno' " . + "and log number '$logno' in database"); + + begin_table(3); + + // date date + print_field("date", $row); + + // who char(20) + print_field("who", $row); + + // details text + print_field_multiline("details", $row, 60, 10, 'text_filter'); + + end_table(); + + echo "<p>\n"; + echo "<center><b>"; + echo "<font color=#ff0000>WARNING: NO UNDO ON DELETE!</font>"; + echo "<br></br>\n"; + echo "<tt>[ <a href=\"dodellog.php?serno=$serno&logno=$logno\">delete</a> ]</tt>"; + echo "</b></center>\n"; + echo "</p>\n"; +?> +<p> +<table align=center width="100%"> +<tr> + <td align=center> + <input type=submit value=Edit> + </td> + <td> + + </td> + <td align=center> + <input type=reset value=Reset> + </td> + <td> + + </td> + <td align=center> + <a href="index.php">Back to Start</a> + </td> +</tr> +</table> +</p> +</form> +<?php + pg_foot(); +?> diff --git a/u-boot/tools/bddb/execute.php b/u-boot/tools/bddb/execute.php new file mode 100644 index 0000000..0b62882 --- /dev/null +++ b/u-boot/tools/bddb/execute.php @@ -0,0 +1,33 @@ +<?php // php pages made with phpMyBuilder <http://kyber.dk/phpMyBuilder> ?> +<?php + // (C) Copyright 2001 + // Murray Jensen <Murray.Jensen@csiro.au> + // CSIRO Manufacturing Science and Technology, Preston Lab + + $serno=isset($_REQUEST['serno'])?$_REQUEST['serno']:''; + + $submit=isset($_REQUEST['submit'])?$_REQUEST['submit']:"[NOT SET]"; + + switch ($submit) { + + case "New": + require("new.php"); + break; + + case "Edit": + require("edit.php"); + break; + + case "Browse": + require("browse.php"); + break; + + case "Log": + require("brlog.php"); + break; + + default: + require("badsubmit.php"); + break; + } +?> diff --git a/u-boot/tools/bddb/index.php b/u-boot/tools/bddb/index.php new file mode 100644 index 0000000..842aed5 --- /dev/null +++ b/u-boot/tools/bddb/index.php @@ -0,0 +1,38 @@ +<?php // php pages made with phpMyBuilder <http://kyber.dk/phpMyBuilder> ?> +<?php + // (C) Copyright 2001 + // Murray Jensen <Murray.Jensen@csiro.au> + // CSIRO Manufacturing Science and Technology, Preston Lab + + require("defs.php"); + pg_head("$bddb_label"); +?> +<font size="+4"> + <form action=execute.php method=POST> + <table width="100%" cellspacing=10 cellpadding=10> + <tr> + <td align=center> + <input type=submit name=submit value="New"></input> + </td> + <td align=center> + <input type=submit name=submit value="Edit"></input> + </td> + <td align=center> + <input type=submit name=submit value="Browse"></input> + </td> + <td align=center> + <input type=submit name=submit value="Log"></input> + </td> + </tr> + <tr> + <td align=center colspan=4> + <b>Serial Number:</b> + <input type=text name=serno size=10 maxsize=10 value=""></input> + </td> + </tr> + </table> + </form> +</font> +<?php + pg_foot(); +?> diff --git a/u-boot/tools/bddb/new.php b/u-boot/tools/bddb/new.php new file mode 100644 index 0000000..30323ff --- /dev/null +++ b/u-boot/tools/bddb/new.php @@ -0,0 +1,120 @@ +<?php // php pages made with phpMyBuilder <http://kyber.dk/phpMyBuilder> ?> +<?php + // (C) Copyright 2001 + // Murray Jensen <Murray.Jensen@csiro.au> + // CSIRO Manufacturing Science and Technology, Preston Lab + + // edit page (hymod_bddb / boards) + + require("defs.php"); + + pg_head("$bddb_label - New Board Registration"); +?> +<form action=donew.php method=POST> +<p></p> +<?php + $serno=intval($serno); + // if a serial number was supplied, fetch the record + // and use its contents as defaults + if ($serno != 0) { + $r=mysql_query("select * from boards where serno=$serno"); + $row=mysql_fetch_array($r); + if(!$row)die("no record of serial number '$serno' in database"); + } + else + $row = array(); + + begin_table(5); + + // date date + print_field("date", array('date' => date("Y-m-d"))); + + // batch char(32) + print_field("batch", $row, 32); + + // type enum('IO','CLP','DSP','INPUT','ALT-INPUT','DISPLAY') + print_enum("type", $row, $type_vals, 0); + + // rev tinyint(3) unsigned zerofill + print_field("rev", $row, 3, 'rev_filter'); + + // sdram[0-3] enum('32M','64M','128M','256M') + print_enum_multi("sdram", $row, $sdram_vals, 4, array(2)); + + // flash[0-3] enum('4M','8M','16M','32M','64M') + print_enum_multi("flash", $row, $flash_vals, 4, array(2)); + + // zbt[0-f] enum('512K','1M','2M','4M') + print_enum_multi("zbt", $row, $zbt_vals, 16, array(2, 2)); + + // xlxtyp[0-3] enum('XCV300E','XCV400E','XCV600E') + print_enum_multi("xlxtyp", $row, $xlxtyp_vals, 4, array(1), 1); + + // xlxspd[0-3] enum('6','7','8') + print_enum_multi("xlxspd", $row, $xlxspd_vals, 4, array(1), 1); + + // xlxtmp[0-3] enum('COM','IND') + print_enum_multi("xlxtmp", $row, $xlxtmp_vals, 4, array(1), 1); + + // xlxgrd[0-3] enum('NORMAL','ENGSAMP') + print_enum_multi("xlxgrd", $row, $xlxgrd_vals, 4, array(1), 1); + + // cputyp enum('MPC8260(HIP3)','MPC8260A(HIP4)','MPC8280(HIP7)') + print_enum("cputyp", $row, $cputyp_vals, 1); + + // cpuspd enum('33MHZ','66MHZ','100MHZ','133MHZ','166MHZ','200MHZ','233MHZ','266MHZ') + print_enum_select("cpuspd", $row, $clk_vals, 4); + + // cpmspd enum('33MHZ','66MHZ','100MHZ','133MHZ','166MHZ','200MHZ','233MHZ','266MHZ') + print_enum_select("cpmspd", $row, $clk_vals, 4); + + // busspd enum('33MHZ','66MHZ','100MHZ','133MHZ','166MHZ','200MHZ','233MHZ','266MHZ') + print_enum_select("busspd", $row, $clk_vals, 2); + + // hstype enum('AMCC-S2064A') + print_enum("hstype", $row, $hstype_vals, 1); + + // hschin enum('0','1','2','3','4') + print_enum("hschin", $row, $hschin_vals, 4); + + // hschout enum('0','1','2','3','4') + print_enum("hschout", $row, $hschout_vals, 4); + + end_table(); +?> +<p></p> +<table width="100%"> +<tr> + <td align=center colspan=3> + Allocate + <input type=text name=quant size=2 maxlength=2 value=" 1"> + board serial number(s) + </td> +</tr> +<tr> + <td align=center colspan=3> + <input type=checkbox name=geneths checked> + Generate Ethernet Address(es) + </td> +</tr> +<tr> + <td colspan=3> + + </td> +</tr> +<tr> + <td align=center> + <input type=submit value="Register Board"> + </td> + <td> + + </td> + <td align=center> + <input type=reset value="Reset Form Contents"> + </td> +</tr> +</table> +</form> +<?php + pg_foot(); +?> diff --git a/u-boot/tools/bddb/newlog.php b/u-boot/tools/bddb/newlog.php new file mode 100644 index 0000000..609bb85 --- /dev/null +++ b/u-boot/tools/bddb/newlog.php @@ -0,0 +1,54 @@ +<?php // php pages made with phpMyBuilder <http://kyber.dk/phpMyBuilder> ?> +<?php + // (C) Copyright 2001 + // Murray Jensen <Murray.Jensen@csiro.au> + // CSIRO Manufacturing Science and Technology, Preston Lab + + // edit page (hymod_bddb / boards) + + require("defs.php"); + + pg_head("$bddb_label - New Log Entry"); + + if (!isset($_REQUEST['serno']) || $_REQUEST['serno'] == '') + die("serial number not specified or invalid!"); + $serno=intval($_REQUEST['serno']); + + if (isset($_REQUEST['logno'])) { + $logno=$_REQUEST['logno']; + die("log number must not be specified when adding! ($logno)"); + } +?> +<form action=donewlog.php method=POST> +<p></p> +<?php + echo "<input type=hidden name=serno value=$serno>\n"; + + begin_table(3); + + // date date + print_field("date", array('date' => date("Y-m-d"))); + + // who char(20) + print_field("who", array()); + + // details text + print_field_multiline("details", array(), 60, 10, 'text_filter'); + + end_table(); +?> +<p></p> +<table width="100%"> +<tr> + <td align=center> + <input type=submit value="Add Log Entry"> + </td> + <td align=center> + <input type=reset value="Reset Form Contents"> + </td> +</tr> +</table> +</form> +<?php + pg_foot(); +?> diff --git a/u-boot/tools/bin2header.c b/u-boot/tools/bin2header.c new file mode 100644 index 0000000..390100e --- /dev/null +++ b/u-boot/tools/bin2header.c @@ -0,0 +1,56 @@ +/* bin2header.c - program to convert binary file into a C structure + * definition to be included in a header file. + * + * (C) Copyright 2008 by Harald Welte <laforge@openmoko.org> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <stdlib.h> +#include <stdio.h> + +int main(int argc, char **argv) +{ + if (argc < 2) { + fprintf(stderr, "%s needs one argument: the structure name\n", + argv[0]); + exit(1); + } + + printf("/* bin2header output - automatically generated */\n"); + printf("unsigned char %s[] = {\n", argv[1]); + + while (1) { + int i, nread; + unsigned char buf[10]; + nread = read(0, buf, sizeof(buf)); + if (nread <= 0) + break; + + printf("\t"); + for (i = 0; i < nread - 1; i++) + printf("0x%02x, ", buf[i]); + + printf("0x%02x,\n", buf[nread-1]); + } + + printf("};\n"); + + exit(0); +} diff --git a/u-boot/tools/bmp_logo.c b/u-boot/tools/bmp_logo.c new file mode 100644 index 0000000..47228d2 --- /dev/null +++ b/u-boot/tools/bmp_logo.c @@ -0,0 +1,163 @@ +#include "compiler.h" + +typedef struct bitmap_s { /* bitmap description */ + uint16_t width; + uint16_t height; + uint8_t palette[256*3]; + uint8_t *data; +} bitmap_t; + +#define DEFAULT_CMAP_SIZE 16 /* size of default color map */ + +/* + * Neutralize little endians. + */ +uint16_t le_short(uint16_t x) +{ + uint16_t val; + uint8_t *p = (uint8_t *)(&x); + + val = (*p++ & 0xff) << 0; + val |= (*p & 0xff) << 8; + + return val; +} + +void skip_bytes (FILE *fp, int n) +{ + while (n-- > 0) + fgetc (fp); +} + +__attribute__ ((__noreturn__)) +int error (char * msg, FILE *fp) +{ + fprintf (stderr, "ERROR: %s\n", msg); + + fclose (fp); + + exit (EXIT_FAILURE); +} + +int main (int argc, char *argv[]) +{ + int i, x; + FILE *fp; + bitmap_t bmp; + bitmap_t *b = &bmp; + uint16_t data_offset, n_colors; + + if (argc < 2) { + fprintf (stderr, "Usage: %s file\n", argv[0]); + exit (EXIT_FAILURE); + } + + if ((fp = fopen (argv[1], "rb")) == NULL) { + perror (argv[1]); + exit (EXIT_FAILURE); + } + + if (fgetc (fp) != 'B' || fgetc (fp) != 'M') + error ("Input file is not a bitmap", fp); + + /* + * read width and height of the image, and the number of colors used; + * ignore the rest + */ + skip_bytes (fp, 8); + if (fread (&data_offset, sizeof (uint16_t), 1, fp) != 1) + error ("Couldn't read bitmap data offset", fp); + skip_bytes (fp, 6); + if (fread (&b->width, sizeof (uint16_t), 1, fp) != 1) + error ("Couldn't read bitmap width", fp); + skip_bytes (fp, 2); + if (fread (&b->height, sizeof (uint16_t), 1, fp) != 1) + error ("Couldn't read bitmap height", fp); + skip_bytes (fp, 22); + if (fread (&n_colors, sizeof (uint16_t), 1, fp) != 1) + error ("Couldn't read bitmap colors", fp); + skip_bytes (fp, 6); + + /* + * Repair endianess. + */ + data_offset = le_short(data_offset); + b->width = le_short(b->width); + b->height = le_short(b->height); + n_colors = le_short(n_colors); + + /* assume we are working with an 8-bit file */ + if ((n_colors == 0) || (n_colors > 256 - DEFAULT_CMAP_SIZE)) { + /* reserve DEFAULT_CMAP_SIZE color map entries for default map */ + n_colors = 256 - DEFAULT_CMAP_SIZE; + } + + printf ("/*\n" + " * Automatically generated by \"tools/bmp_logo\"\n" + " *\n" + " * DO NOT EDIT\n" + " *\n" + " */\n\n\n" + "#ifndef __BMP_LOGO_H__\n" + "#define __BMP_LOGO_H__\n\n" + "#define BMP_LOGO_WIDTH\t\t%d\n" + "#define BMP_LOGO_HEIGHT\t\t%d\n" + "#define BMP_LOGO_COLORS\t\t%d\n" + "#define BMP_LOGO_OFFSET\t\t%d\n" + "\n", + b->width, b->height, n_colors, + DEFAULT_CMAP_SIZE); + + /* allocate memory */ + if ((b->data = (uint8_t *)malloc(b->width * b->height)) == NULL) + error ("Error allocating memory for file", fp); + + /* read and print the palette information */ + printf ("unsigned short bmp_logo_palette[] = {\n"); + + for (i=0; i<n_colors; ++i) { + b->palette[(int)(i*3+2)] = fgetc(fp); + b->palette[(int)(i*3+1)] = fgetc(fp); + b->palette[(int)(i*3+0)] = fgetc(fp); + x=fgetc(fp); + + printf ("%s0x0%X%X%X,%s", + ((i%8) == 0) ? "\t" : " ", + (b->palette[(int)(i*3+0)] >> 4) & 0x0F, + (b->palette[(int)(i*3+1)] >> 4) & 0x0F, + (b->palette[(int)(i*3+2)] >> 4) & 0x0F, + ((i%8) == 7) ? "\n" : "" + ); + } + + /* seek to offset indicated by file header */ + fseek(fp, (long)data_offset, SEEK_SET); + + /* read the bitmap; leave room for default color map */ + printf ("\n"); + printf ("};\n"); + printf ("\n"); + printf ("unsigned char bmp_logo_bitmap[] = {\n"); + for (i=(b->height-1)*b->width; i>=0; i-=b->width) { + for (x = 0; x < b->width; x++) { + b->data[(uint16_t) i + x] = (uint8_t) fgetc (fp) \ + + DEFAULT_CMAP_SIZE; + } + } + fclose (fp); + + for (i=0; i<(b->height*b->width); ++i) { + if ((i%8) == 0) + putchar ('\t'); + printf ("0x%02X,%c", + b->data[i], + ((i%8) == 7) ? '\n' : ' ' + ); + } + printf ("\n" + "};\n\n" + "#endif /* __BMP_LOGO_H__ */\n" + ); + + return (0); +} diff --git a/u-boot/tools/default_image.c b/u-boot/tools/default_image.c new file mode 100644 index 0000000..f5bad47 --- /dev/null +++ b/u-boot/tools/default_image.c @@ -0,0 +1,149 @@ +/* + * (C) Copyright 2008 Semihalf + * + * (C) Copyright 2000-2004 + * DENX Software Engineering + * Wolfgang Denk, wd@denx.de + * + * Updated-by: Prafulla Wadaskar <prafulla@marvell.com> + * default_image specific code abstracted from mkimage.c + * some functions added to address abstraction + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include "mkimage.h" +#include <image.h> +#include <u-boot/crc.h> + +static image_header_t header; + +static int image_check_image_types (uint8_t type) +{ + if ((type > IH_TYPE_INVALID) && (type < IH_TYPE_FLATDT)) + return EXIT_SUCCESS; + else + return EXIT_FAILURE; +} + +static int image_check_params (struct mkimage_params *params) +{ + return ((params->dflag && (params->fflag || params->lflag)) || + (params->fflag && (params->dflag || params->lflag)) || + (params->lflag && (params->dflag || params->fflag))); +} + +static int image_verify_header (unsigned char *ptr, int image_size, + struct mkimage_params *params) +{ + uint32_t len; + const unsigned char *data; + uint32_t checksum; + image_header_t header; + image_header_t *hdr = &header; + + /* + * create copy of header so that we can blank out the + * checksum field for checking - this can't be done + * on the PROT_READ mapped data. + */ + memcpy (hdr, ptr, sizeof(image_header_t)); + + if (be32_to_cpu(hdr->ih_magic) != IH_MAGIC) { + fprintf (stderr, + "%s: Bad Magic Number: \"%s\" is no valid image\n", + params->cmdname, params->imagefile); + return -FDT_ERR_BADMAGIC; + } + + data = (const unsigned char *)hdr; + len = sizeof(image_header_t); + + checksum = be32_to_cpu(hdr->ih_hcrc); + hdr->ih_hcrc = cpu_to_be32(0); /* clear for re-calculation */ + + if (crc32 (0, data, len) != checksum) { + fprintf (stderr, + "%s: ERROR: \"%s\" has bad header checksum!\n", + params->cmdname, params->imagefile); + return -FDT_ERR_BADSTATE; + } + + data = (const unsigned char *)ptr + sizeof(image_header_t); + len = image_size - sizeof(image_header_t) ; + + checksum = be32_to_cpu(hdr->ih_dcrc); + if (crc32 (0, data, len) != checksum) { + fprintf (stderr, + "%s: ERROR: \"%s\" has corrupted data!\n", + params->cmdname, params->imagefile); + return -FDT_ERR_BADSTRUCTURE; + } + return 0; +} + +static void image_set_header (void *ptr, struct stat *sbuf, int ifd, + struct mkimage_params *params) +{ + uint32_t checksum; + + image_header_t * hdr = (image_header_t *)ptr; + + checksum = crc32 (0, + (const unsigned char *)(ptr + + sizeof(image_header_t)), + sbuf->st_size - sizeof(image_header_t)); + + /* Build new header */ + image_set_magic (hdr, IH_MAGIC); + image_set_time (hdr, sbuf->st_mtime); + image_set_size (hdr, sbuf->st_size - sizeof(image_header_t)); + image_set_load (hdr, params->addr); + image_set_ep (hdr, params->ep); + image_set_dcrc (hdr, checksum); + image_set_os (hdr, params->os); + image_set_arch (hdr, params->arch); + image_set_type (hdr, params->type); + image_set_comp (hdr, params->comp); + + image_set_name (hdr, params->imagename); + + checksum = crc32 (0, (const unsigned char *)hdr, + sizeof(image_header_t)); + + image_set_hcrc (hdr, checksum); +} + +/* + * Default image type parameters definition + */ +static struct image_type_params defimage_params = { + .name = "Default Image support", + .header_size = sizeof(image_header_t), + .hdr = (void*)&header, + .check_image_type = image_check_image_types, + .verify_header = image_verify_header, + .print_header = image_print_contents, + .set_header = image_set_header, + .check_params = image_check_params, +}; + +void init_default_image_type (void) +{ + mkimage_register (&defimage_params); +} diff --git a/u-boot/tools/easylogo/Makefile b/u-boot/tools/easylogo/Makefile new file mode 100644 index 0000000..d8e28b0 --- /dev/null +++ b/u-boot/tools/easylogo/Makefile @@ -0,0 +1,11 @@ +include $(TOPDIR)/config.mk + +all: $(obj)easylogo + +$(obj)easylogo: $(SRCTREE)/tools/easylogo/easylogo.c + $(HOSTCC) $(HOSTCFLAGS_NOPED) $(HOSTLDFLAGS) -o $@ $^ + +clean: + rm -f $(obj)easylogo + +.PHONY: all clean diff --git a/u-boot/tools/easylogo/easylogo.c b/u-boot/tools/easylogo/easylogo.c new file mode 100644 index 0000000..d9b33fa --- /dev/null +++ b/u-boot/tools/easylogo/easylogo.c @@ -0,0 +1,583 @@ +/* +** Easylogo TGA->header converter +** ============================== +** (C) 2000 by Paolo Scaffardi (arsenio@tin.it) +** AIRVENT SAM s.p.a - RIMINI(ITALY) +** (C) 2007-2008 Mike Frysinger <vapier@gentoo.org> +** +** This is still under construction! +*/ + +#include <errno.h> +#include <getopt.h> +#include <stdbool.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/stat.h> + +#pragma pack(1) + +/*#define ENABLE_ASCII_BANNERS */ + +typedef struct { + unsigned char id; + unsigned char ColorMapType; + unsigned char ImageTypeCode; + unsigned short ColorMapOrigin; + unsigned short ColorMapLenght; + unsigned char ColorMapEntrySize; + unsigned short ImageXOrigin; + unsigned short ImageYOrigin; + unsigned short ImageWidth; + unsigned short ImageHeight; + unsigned char ImagePixelSize; + unsigned char ImageDescriptorByte; +} tga_header_t; + +typedef struct { + unsigned char r, g, b; +} rgb_t; + +typedef struct { + unsigned char b, g, r; +} bgr_t; + +typedef struct { + unsigned char Cb, y1, Cr, y2; +} yuyv_t; + +typedef struct { + void *data, *palette; + int width, height, pixels, bpp, pixel_size, size, palette_size, yuyv; +} image_t; + +void *xmalloc (size_t size) +{ + void *ret = malloc (size); + if (!ret) { + fprintf (stderr, "\nerror: malloc(%zu) failed: %s", + size, strerror(errno)); + exit (1); + } + return ret; +} + +void StringUpperCase (char *str) +{ + int count = strlen (str); + char c; + + while (count--) { + c = *str; + if ((c >= 'a') && (c <= 'z')) + *str = 'A' + (c - 'a'); + str++; + } +} + +void StringLowerCase (char *str) +{ + int count = strlen (str); + char c; + + while (count--) { + c = *str; + if ((c >= 'A') && (c <= 'Z')) + *str = 'a' + (c - 'A'); + str++; + } +} +void pixel_rgb_to_yuyv (rgb_t * rgb_pixel, yuyv_t * yuyv_pixel) +{ + unsigned int pR, pG, pB; + + /* Transform (0-255) components to (0-100) */ + pR = rgb_pixel->r * 100 / 255; + pG = rgb_pixel->g * 100 / 255; + pB = rgb_pixel->b * 100 / 255; + + /* Calculate YUV values (0-255) from RGB beetween 0-100 */ + yuyv_pixel->y1 = yuyv_pixel->y2 = 209 * (pR + pG + pB) / 300 + 16; + yuyv_pixel->Cb = pB - (pR / 4) - (pG * 3 / 4) + 128; + yuyv_pixel->Cr = pR - (pG * 3 / 4) - (pB / 4) + 128; + + return; +} + +void printlogo_rgb (rgb_t * data, int w, int h) +{ + int x, y; + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++, data++) + if ((data->r < + 30) /*&&(data->g == 0)&&(data->b == 0) */ ) + printf (" "); + else + printf ("X"); + printf ("\n"); + } +} + +void printlogo_yuyv (unsigned short *data, int w, int h) +{ + int x, y; + + for (y = 0; y < h; y++) { + for (x = 0; x < w; x++, data++) + if (*data == 0x1080) /* Because of inverted on i386! */ + printf (" "); + else + printf ("X"); + printf ("\n"); + } +} + +static inline unsigned short le16_to_cpu (unsigned short val) +{ + union { + unsigned char pval[2]; + unsigned short val; + } swapped; + + swapped.val = val; + return (swapped.pval[1] << 8) + swapped.pval[0]; +} + +int image_load_tga (image_t * image, char *filename) +{ + FILE *file; + tga_header_t header; + int i; + unsigned char app; + rgb_t *p; + + if ((file = fopen (filename, "rb")) == NULL) + return -1; + + fread (&header, sizeof (header), 1, file); + + /* byte swap: tga is little endian, host is ??? */ + header.ColorMapOrigin = le16_to_cpu (header.ColorMapOrigin); + header.ColorMapLenght = le16_to_cpu (header.ColorMapLenght); + header.ImageXOrigin = le16_to_cpu (header.ImageXOrigin); + header.ImageYOrigin = le16_to_cpu (header.ImageYOrigin); + header.ImageWidth = le16_to_cpu (header.ImageWidth); + header.ImageHeight = le16_to_cpu (header.ImageHeight); + + image->width = header.ImageWidth; + image->height = header.ImageHeight; + + switch (header.ImageTypeCode) { + case 2: /* Uncompressed RGB */ + image->yuyv = 0; + image->palette_size = 0; + image->palette = NULL; + break; + + default: + printf ("Format not supported!\n"); + return -1; + } + + image->bpp = header.ImagePixelSize; + image->pixel_size = ((image->bpp - 1) / 8) + 1; + image->pixels = image->width * image->height; + image->size = image->pixels * image->pixel_size; + image->data = xmalloc (image->size); + + if (image->bpp != 24) { + printf ("Bpp not supported: %d!\n", image->bpp); + return -1; + } + + fread (image->data, image->size, 1, file); + +/* Swapping R and B values */ + + p = image->data; + for (i = 0; i < image->pixels; i++, p++) { + app = p->r; + p->r = p->b; + p->b = app; + } + +/* Swapping image */ + + if (!(header.ImageDescriptorByte & 0x20)) { + unsigned char *temp = xmalloc (image->size); + int linesize = image->pixel_size * image->width; + void *dest = image->data, + *source = temp + image->size - linesize; + + printf ("S"); + if (temp == NULL) { + printf ("Cannot alloc temp buffer!\n"); + return -1; + } + + memcpy (temp, image->data, image->size); + for (i = 0; i < image->height; + i++, dest += linesize, source -= linesize) + memcpy (dest, source, linesize); + + free (temp); + } +#ifdef ENABLE_ASCII_BANNERS + printlogo_rgb (image->data, image->width, image->height); +#endif + + fclose (file); + return 0; +} + +void image_free (image_t * image) +{ + free (image->data); + free (image->palette); +} + +int image_rgb_to_yuyv (image_t * rgb_image, image_t * yuyv_image) +{ + rgb_t *rgb_ptr = (rgb_t *) rgb_image->data; + yuyv_t yuyv; + unsigned short *dest; + int count = 0; + + yuyv_image->pixel_size = 2; + yuyv_image->bpp = 16; + yuyv_image->yuyv = 1; + yuyv_image->width = rgb_image->width; + yuyv_image->height = rgb_image->height; + yuyv_image->pixels = yuyv_image->width * yuyv_image->height; + yuyv_image->size = yuyv_image->pixels * yuyv_image->pixel_size; + dest = (unsigned short *) (yuyv_image->data = + xmalloc (yuyv_image->size)); + yuyv_image->palette = 0; + yuyv_image->palette_size = 0; + + while ((count++) < rgb_image->pixels) { + pixel_rgb_to_yuyv (rgb_ptr++, &yuyv); + + if ((count & 1) == 0) /* Was == 0 */ + memcpy (dest, ((void *) &yuyv) + 2, sizeof (short)); + else + memcpy (dest, (void *) &yuyv, sizeof (short)); + + dest++; + } + +#ifdef ENABLE_ASCII_BANNERS + printlogo_yuyv (yuyv_image->data, yuyv_image->width, + yuyv_image->height); +#endif + return 0; +} + +int image_rgb888_to_rgb565(image_t *rgb888_image, image_t *rgb565_image) +{ + rgb_t *rgb_ptr = (rgb_t *) rgb888_image->data; + unsigned short *dest; + int count = 0; + + rgb565_image->pixel_size = 2; + rgb565_image->bpp = 16; + rgb565_image->yuyv = 0; + rgb565_image->width = rgb888_image->width; + rgb565_image->height = rgb888_image->height; + rgb565_image->pixels = rgb565_image->width * rgb565_image->height; + rgb565_image->size = rgb565_image->pixels * rgb565_image->pixel_size; + dest = (unsigned short *) (rgb565_image->data = + xmalloc(rgb565_image->size)); + rgb565_image->palette = 0; + rgb565_image->palette_size = 0; + + while ((count++) < rgb888_image->pixels) { + + *dest++ = ((rgb_ptr->b & 0xF8) << 8) | + ((rgb_ptr->g & 0xFC) << 3) | + (rgb_ptr->r >> 3); + rgb_ptr++; + } + + return 0; +} + +int use_gzip = 0; + +int image_save_header (image_t * image, char *filename, char *varname) +{ + FILE *file = fopen (filename, "w"); + char app[256], str[256] = "", def_name[64]; + int count = image->size, col = 0; + unsigned char *dataptr = image->data; + + if (file == NULL) + return -1; + + /* Author information */ + fprintf (file, + "/*\n * Generated by EasyLogo, (C) 2000 by Paolo Scaffardi\n *\n"); + fprintf (file, + " * To use this, include it and call: easylogo_plot(screen,&%s, width,x,y)\n *\n", + varname); + fprintf (file, + " * Where:\t'screen'\tis the pointer to the frame buffer\n"); + fprintf (file, " *\t\t'width'\tis the screen width\n"); + fprintf (file, " *\t\t'x'\t\tis the horizontal position\n"); + fprintf (file, " *\t\t'y'\t\tis the vertical position\n */\n\n"); + + /* gzip compress */ + if (use_gzip & 0x1) { + const char *errstr = NULL; + unsigned char *compressed; + struct stat st; + FILE *gz; + char *gzfilename = xmalloc(strlen (filename) + 20); + char *gzcmd = xmalloc(strlen (filename) + 20); + + sprintf (gzfilename, "%s.gz", filename); + sprintf (gzcmd, "gzip > %s", gzfilename); + gz = popen (gzcmd, "w"); + if (!gz) { + errstr = "\nerror: popen() failed"; + goto done; + } + if (fwrite (image->data, image->size, 1, gz) != 1) { + errstr = "\nerror: writing data to gzip failed"; + goto done; + } + if (pclose (gz)) { + errstr = "\nerror: gzip process failed"; + goto done; + } + + gz = fopen (gzfilename, "r"); + if (!gz) { + errstr = "\nerror: open() on gzip data failed"; + goto done; + } + if (stat (gzfilename, &st)) { + errstr = "\nerror: stat() on gzip file failed"; + goto done; + } + compressed = xmalloc (st.st_size); + if (fread (compressed, st.st_size, 1, gz) != 1) { + errstr = "\nerror: reading gzip data failed"; + goto done; + } + fclose (gz); + + unlink (gzfilename); + + dataptr = compressed; + count = st.st_size; + fprintf (file, "#define EASYLOGO_ENABLE_GZIP %i\n\n", count); + if (use_gzip & 0x2) + fprintf (file, "static unsigned char EASYLOGO_DECOMP_BUFFER[%i];\n\n", image->size); + + done: + free (gzfilename); + free (gzcmd); + + if (errstr) { + perror (errstr); + return -1; + } + } + + /* Headers */ + fprintf (file, "#include <video_easylogo.h>\n\n"); + /* Macros */ + strcpy (def_name, varname); + StringUpperCase (def_name); + fprintf (file, "#define DEF_%s_WIDTH\t\t%d\n", def_name, + image->width); + fprintf (file, "#define DEF_%s_HEIGHT\t\t%d\n", def_name, + image->height); + fprintf (file, "#define DEF_%s_PIXELS\t\t%d\n", def_name, + image->pixels); + fprintf (file, "#define DEF_%s_BPP\t\t%d\n", def_name, image->bpp); + fprintf (file, "#define DEF_%s_PIXEL_SIZE\t%d\n", def_name, + image->pixel_size); + fprintf (file, "#define DEF_%s_SIZE\t\t%d\n\n", def_name, + image->size); + /* Declaration */ + fprintf (file, "unsigned char DEF_%s_DATA[] = {\n", + def_name); + + /* Data */ + while (count) + switch (col) { + case 0: + sprintf (str, " 0x%02x", *dataptr++); + col++; + count--; + break; + + case 16: + fprintf (file, "%s", str); + if (count > 0) + fprintf (file, ","); + fprintf (file, "\n"); + + col = 0; + break; + + default: + strcpy (app, str); + sprintf (str, "%s, 0x%02x", app, *dataptr++); + col++; + count--; + break; + } + + if (col) + fprintf (file, "%s\n", str); + + /* End of declaration */ + fprintf (file, "};\n\n"); + /* Variable */ + fprintf (file, "fastimage_t %s = {\n", varname); + fprintf (file, " DEF_%s_DATA,\n", def_name); + fprintf (file, " DEF_%s_WIDTH,\n", def_name); + fprintf (file, " DEF_%s_HEIGHT,\n", def_name); + fprintf (file, " DEF_%s_BPP,\n", def_name); + fprintf (file, " DEF_%s_PIXEL_SIZE,\n", def_name); + fprintf (file, " DEF_%s_SIZE\n};\n", def_name); + + fclose (file); + + return 0; +} + +#define DEF_FILELEN 256 + +static void usage (int exit_status) +{ + puts ( + "EasyLogo 1.0 (C) 2000 by Paolo Scaffardi\n" + "\n" + "Syntax: easylogo [options] inputfile [outputvar [outputfile]]\n" + "\n" + "Options:\n" + " -r Output RGB888 instead of YUYV\n" + " -s Output RGB565 instead of YUYV\n" + " -g Compress with gzip\n" + " -b Preallocate space in bss for decompressing image\n" + " -h Help output\n" + "\n" + "Where: 'inputfile' is the TGA image to load\n" + " 'outputvar' is the variable name to create\n" + " 'outputfile' is the output header file (default is 'inputfile.h')" + ); + exit (exit_status); +} + +int main (int argc, char *argv[]) +{ + int c; + bool use_rgb888 = false; + bool use_rgb565 = false; + char inputfile[DEF_FILELEN], + outputfile[DEF_FILELEN], varname[DEF_FILELEN]; + + image_t rgb888_logo, rgb565_logo, yuyv_logo; + + while ((c = getopt(argc, argv, "hrsgb")) > 0) { + switch (c) { + case 'h': + usage (0); + break; + case 'r': + use_rgb888 = true; + puts("Using 24-bit RGB888 Output Fromat"); + break; + case 's': + use_rgb565 = true; + puts("Using 16-bit RGB565 Output Fromat"); + break; + case 'g': + use_gzip |= 0x1; + puts ("Compressing with gzip"); + break; + case 'b': + use_gzip |= 0x2; + puts ("Preallocating bss space for decompressing image"); + break; + default: + usage (1); + break; + } + } + + c = argc - optind; + if (c > 4 || c < 1) + usage (1); + + strcpy (inputfile, argv[optind]); + + if (c > 1) + strcpy (varname, argv[optind + 1]); + else { + /* transform "input.tga" to just "input" */ + char *dot; + strcpy (varname, inputfile); + dot = strchr (varname, '.'); + if (dot) + *dot = '\0'; + } + + if (c > 2) + strcpy (outputfile, argv[optind + 2]); + else { + /* just append ".h" to input file name */ + strcpy (outputfile, inputfile); + strcat (outputfile, ".h"); + } + + /* Make sure the output is sent as soon as we printf() */ + setbuf(stdout, NULL); + + printf ("Doing '%s' (%s) from '%s'...", + outputfile, varname, inputfile); + + /* Import TGA logo */ + + printf ("L"); + if (image_load_tga(&rgb888_logo, inputfile) < 0) { + printf ("input file not found!\n"); + exit (1); + } + + /* Convert, save, and free the image */ + + if (!use_rgb888 && !use_rgb565) { + printf ("C"); + image_rgb_to_yuyv(&rgb888_logo, &yuyv_logo); + + printf("S"); + image_save_header(&yuyv_logo, outputfile, varname); + image_free(&yuyv_logo); + } else if (use_rgb565) { + printf("C"); + image_rgb888_to_rgb565(&rgb888_logo, &rgb565_logo); + + printf("S"); + image_save_header(&rgb565_logo, outputfile, varname); + image_free(&rgb565_logo); + } else { + printf("S"); + image_save_header(&rgb888_logo, outputfile, varname); + } + + /* Free original image and copy */ + + image_free(&rgb888_logo); + + printf ("\n"); + + return 0; +} diff --git a/u-boot/tools/easylogo/linux_blackfin.tga b/u-boot/tools/easylogo/linux_blackfin.tga Binary files differnew file mode 100644 index 0000000..e2bb17b --- /dev/null +++ b/u-boot/tools/easylogo/linux_blackfin.tga diff --git a/u-boot/tools/easylogo/linux_logo.tga b/u-boot/tools/easylogo/linux_logo.tga Binary files differnew file mode 100644 index 0000000..ac53def --- /dev/null +++ b/u-boot/tools/easylogo/linux_logo.tga diff --git a/u-boot/tools/easylogo/runme.sh b/u-boot/tools/easylogo/runme.sh new file mode 100644 index 0000000..625ebaa --- /dev/null +++ b/u-boot/tools/easylogo/runme.sh @@ -0,0 +1,4 @@ +#!/bin/sh +make +./easylogo linux_logo.tga u_boot_logo video_logo.h +mv video_logo.h ../../include diff --git a/u-boot/tools/env/Makefile b/u-boot/tools/env/Makefile new file mode 100644 index 0000000..2f7a59c --- /dev/null +++ b/u-boot/tools/env/Makefile @@ -0,0 +1,57 @@ +# +# (C) Copyright 2002-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# 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 +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +HOSTSRCS := $(obj)crc32.c fw_env.c fw_env_main.c +HEADERS := fw_env.h + +# Compile for a hosted environment on the target +HOSTCPPFLAGS = -idirafter $(SRCTREE)/include \ + -idirafter $(OBJTREE)/include2 \ + -idirafter $(OBJTREE)/include \ + -DUSE_HOSTCC + +ifeq ($(MTD_VERSION),old) +HOSTCPPFLAGS += -DMTD_OLD +endif + +all: $(obj)fw_printenv + +# Some files complain if compiled with -pedantic, use HOSTCFLAGS_NOPED +$(obj)fw_printenv: $(HOSTSRCS) $(HEADERS) + $(HOSTCC) $(HOSTCFLAGS_NOPED) $(HOSTLDFLAGS) -o $@ $(HOSTSRCS) + +clean: + rm -f $(obj)fw_printenv $(obj)crc32.c + +$(obj)crc32.c: + ln -s $(src)../../lib/crc32.c $(obj)crc32.c + +######################################################################### + +include $(TOPDIR)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/u-boot/tools/env/README b/u-boot/tools/env/README new file mode 100644 index 0000000..91e679a --- /dev/null +++ b/u-boot/tools/env/README @@ -0,0 +1,54 @@ + +This is a demo implementation of a Linux command line tool to access +the U-Boot's environment variables. + +For the run-time utiltity configuration uncomment the line +#define CONFIG_FILE "/etc/fw_env.config" +in fw_env.h. + +For building against older versions of the MTD headers (meaning before +v2.6.8-rc1) it is required to pass the argument "MTD_VERSION=old" to +make. + +See comments in the fw_env.config file for definitions for the +particular board. + +Configuration can also be done via #defines in the fw_env.h file. The +following lines are relevant: + +#define HAVE_REDUND /* For systems with 2 env sectors */ +#define DEVICE1_NAME "/dev/mtd1" +#define DEVICE2_NAME "/dev/mtd2" +#define DEVICE1_OFFSET 0x0000 +#define ENV1_SIZE 0x4000 +#define DEVICE1_ESIZE 0x4000 +#define DEVICE1_ENVSECTORS 2 +#define DEVICE2_OFFSET 0x0000 +#define ENV2_SIZE 0x4000 +#define DEVICE2_ESIZE 0x4000 +#define DEVICE2_ENVSECTORS 2 + +Current configuration matches the environment layout of the TRAB +board. + +Un-define HAVE_REDUND, if you want to use the utlities on a system +that does not have support for redundant environment enabled. +If HAVE_REDUND is undefined, DEVICE2_NAME is ignored, +as is ENV2_SIZE and DEVICE2_ESIZE. + +The DEVICEx_NAME constants define which MTD character devices are to +be used to access the environment. + +The DEVICEx_OFFSET constants define the environment offset within the +MTD character device. + +ENVx_SIZE defines the size in bytes taken by the environment, which +may be less then flash sector size, if the environment takes less +then 1 sector. + +DEVICEx_ESIZE defines the size of the first sector in the flash +partition where the environment resides. + +DEVICEx_ENVSECTORS defines the number of sectors that may be used for +this environment instance. On NAND this is used to limit the range +within which bad blocks are skipped, on NOR it is not used. diff --git a/u-boot/tools/env/fw_env.c b/u-boot/tools/env/fw_env.c new file mode 100644 index 0000000..8ff7052 --- /dev/null +++ b/u-boot/tools/env/fw_env.c @@ -0,0 +1,1306 @@ +/* + * (C) Copyright 2000-2010 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2008 + * Guennadi Liakhovetski, DENX Software Engineering, lg@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <string.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <unistd.h> + +#ifdef MTD_OLD +# include <stdint.h> +# include <linux/mtd/mtd.h> +#else +# define __user /* nothing */ +# include <mtd/mtd-user.h> +#endif + +#include "fw_env.h" + +#define WHITESPACE(c) ((c == '\t') || (c == ' ')) + +#define min(x, y) ({ \ + typeof(x) _min1 = (x); \ + typeof(y) _min2 = (y); \ + (void) (&_min1 == &_min2); \ + _min1 < _min2 ? _min1 : _min2; }) + +struct envdev_s { + char devname[16]; /* Device name */ + ulong devoff; /* Device offset */ + ulong env_size; /* environment size */ + ulong erase_size; /* device erase size */ + ulong env_sectors; /* number of environment sectors */ + uint8_t mtd_type; /* type of the MTD device */ +}; + +static struct envdev_s envdevices[2] = +{ + { + .mtd_type = MTD_ABSENT, + }, { + .mtd_type = MTD_ABSENT, + }, +}; +static int dev_current; + +#define DEVNAME(i) envdevices[(i)].devname +#define DEVOFFSET(i) envdevices[(i)].devoff +#define ENVSIZE(i) envdevices[(i)].env_size +#define DEVESIZE(i) envdevices[(i)].erase_size +#define ENVSECTORS(i) envdevices[(i)].env_sectors +#define DEVTYPE(i) envdevices[(i)].mtd_type + +#define CONFIG_ENV_SIZE ENVSIZE(dev_current) + +#define ENV_SIZE getenvsize() + +struct env_image_single { + uint32_t crc; /* CRC32 over data bytes */ + char data[]; +}; + +struct env_image_redundant { + uint32_t crc; /* CRC32 over data bytes */ + unsigned char flags; /* active or obsolete */ + char data[]; +}; + +enum flag_scheme { + FLAG_NONE, + FLAG_BOOLEAN, + FLAG_INCREMENTAL, +}; + +struct environment { + void *image; + uint32_t *crc; + unsigned char *flags; + char *data; + enum flag_scheme flag_scheme; +}; + +static struct environment environment = { + .flag_scheme = FLAG_NONE, +}; + +static int HaveRedundEnv = 0; + +static unsigned char active_flag = 1; +/* obsolete_flag must be 0 to efficiently set it on NOR flash without erasing */ +static unsigned char obsolete_flag = 0; + + +#define XMK_STR(x) #x +#define MK_STR(x) XMK_STR(x) + +static char default_environment[] = { +#if defined(CONFIG_BOOTARGS) + "bootargs=" CONFIG_BOOTARGS "\0" +#endif +#if defined(CONFIG_BOOTCOMMAND) + "bootcmd=" CONFIG_BOOTCOMMAND "\0" +#endif +#if defined(CONFIG_RAMBOOTCOMMAND) + "ramboot=" CONFIG_RAMBOOTCOMMAND "\0" +#endif +#if defined(CONFIG_NFSBOOTCOMMAND) + "nfsboot=" CONFIG_NFSBOOTCOMMAND "\0" +#endif +#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0) + "bootdelay=" MK_STR (CONFIG_BOOTDELAY) "\0" +#endif +#if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0) + "baudrate=" MK_STR (CONFIG_BAUDRATE) "\0" +#endif +#ifdef CONFIG_LOADS_ECHO + "loads_echo=" MK_STR (CONFIG_LOADS_ECHO) "\0" +#endif +#ifdef CONFIG_ETHADDR + "ethaddr=" MK_STR (CONFIG_ETHADDR) "\0" +#endif +#ifdef CONFIG_ETH1ADDR + "eth1addr=" MK_STR (CONFIG_ETH1ADDR) "\0" +#endif +#ifdef CONFIG_ETH2ADDR + "eth2addr=" MK_STR (CONFIG_ETH2ADDR) "\0" +#endif +#ifdef CONFIG_ETH3ADDR + "eth3addr=" MK_STR (CONFIG_ETH3ADDR) "\0" +#endif +#ifdef CONFIG_ETH4ADDR + "eth4addr=" MK_STR (CONFIG_ETH4ADDR) "\0" +#endif +#ifdef CONFIG_ETH5ADDR + "eth5addr=" MK_STR (CONFIG_ETH5ADDR) "\0" +#endif +#ifdef CONFIG_ETHPRIME + "ethprime=" CONFIG_ETHPRIME "\0" +#endif +#ifdef CONFIG_IPADDR + "ipaddr=" MK_STR (CONFIG_IPADDR) "\0" +#endif +#ifdef CONFIG_SERVERIP + "serverip=" MK_STR (CONFIG_SERVERIP) "\0" +#endif +#ifdef CONFIG_SYS_AUTOLOAD + "autoload=" CONFIG_SYS_AUTOLOAD "\0" +#endif +#ifdef CONFIG_ROOTPATH + "rootpath=" MK_STR (CONFIG_ROOTPATH) "\0" +#endif +#ifdef CONFIG_GATEWAYIP + "gatewayip=" MK_STR (CONFIG_GATEWAYIP) "\0" +#endif +#ifdef CONFIG_NETMASK + "netmask=" MK_STR (CONFIG_NETMASK) "\0" +#endif +#ifdef CONFIG_HOSTNAME + "hostname=" MK_STR (CONFIG_HOSTNAME) "\0" +#endif +#ifdef CONFIG_BOOTFILE + "bootfile=" MK_STR (CONFIG_BOOTFILE) "\0" +#endif +#ifdef CONFIG_LOADADDR + "loadaddr=" MK_STR (CONFIG_LOADADDR) "\0" +#endif +#ifdef CONFIG_PREBOOT + "preboot=" CONFIG_PREBOOT "\0" +#endif +#ifdef CONFIG_CLOCKS_IN_MHZ + "clocks_in_mhz=" "1" "\0" +#endif +#if defined(CONFIG_PCI_BOOTDELAY) && (CONFIG_PCI_BOOTDELAY > 0) + "pcidelay=" MK_STR (CONFIG_PCI_BOOTDELAY) "\0" +#endif +#ifdef CONFIG_EXTRA_ENV_SETTINGS + CONFIG_EXTRA_ENV_SETTINGS +#endif + "\0" /* Termimate struct environment data with 2 NULs */ +}; + +static int flash_io (int mode); +static char *envmatch (char * s1, char * s2); +static int parse_config (void); + +#if defined(CONFIG_FILE) +static int get_config (char *); +#endif +static inline ulong getenvsize (void) +{ + ulong rc = CONFIG_ENV_SIZE - sizeof (long); + + if (HaveRedundEnv) + rc -= sizeof (char); + return rc; +} + +static char *fw_string_blank(char *s, int noblank) +{ + int i; + int len = strlen(s); + + for (i = 0; i < len; i++, s++) { + if ((noblank && !WHITESPACE(*s)) || + (!noblank && WHITESPACE(*s))) + break; + } + if (i == len) + return NULL; + + return s; +} + +/* + * Search the environment for a variable. + * Return the value, if found, or NULL, if not found. + */ +char *fw_getenv (char *name) +{ + char *env, *nxt; + + if (fw_env_open()) + return NULL; + + for (env = environment.data; *env; env = nxt + 1) { + char *val; + + for (nxt = env; *nxt; ++nxt) { + if (nxt >= &environment.data[ENV_SIZE]) { + fprintf (stderr, "## Error: " + "environment not terminated\n"); + return NULL; + } + } + val = envmatch (name, env); + if (!val) + continue; + return val; + } + return NULL; +} + +/* + * Print the current definition of one, or more, or all + * environment variables + */ +int fw_printenv (int argc, char *argv[]) +{ + char *env, *nxt; + int i, n_flag; + int rc = 0; + + if (fw_env_open()) + return -1; + + if (argc == 1) { /* Print all env variables */ + for (env = environment.data; *env; env = nxt + 1) { + for (nxt = env; *nxt; ++nxt) { + if (nxt >= &environment.data[ENV_SIZE]) { + fprintf (stderr, "## Error: " + "environment not terminated\n"); + return -1; + } + } + + printf ("%s\n", env); + } + return 0; + } + + if (strcmp (argv[1], "-n") == 0) { + n_flag = 1; + ++argv; + --argc; + if (argc != 2) { + fprintf (stderr, "## Error: " + "`-n' option requires exactly one argument\n"); + return -1; + } + } else { + n_flag = 0; + } + + for (i = 1; i < argc; ++i) { /* print single env variables */ + char *name = argv[i]; + char *val = NULL; + + for (env = environment.data; *env; env = nxt + 1) { + + for (nxt = env; *nxt; ++nxt) { + if (nxt >= &environment.data[ENV_SIZE]) { + fprintf (stderr, "## Error: " + "environment not terminated\n"); + return -1; + } + } + val = envmatch (name, env); + if (val) { + if (!n_flag) { + fputs (name, stdout); + putc ('=', stdout); + } + puts (val); + break; + } + } + if (!val) { + fprintf (stderr, "## Error: \"%s\" not defined\n", name); + rc = -1; + } + } + + return rc; +} + +int fw_env_close(void) +{ + /* + * Update CRC + */ + *environment.crc = crc32(0, (uint8_t *) environment.data, ENV_SIZE); + + /* write environment back to flash */ + if (flash_io(O_RDWR)) { + fprintf(stderr, + "Error: can't write fw_env to flash\n"); + return -1; + } + + return 0; +} + + +/* + * Set/Clear a single variable in the environment. + * This is called in sequence to update the environment + * in RAM without updating the copy in flash after each set + */ +int fw_env_write(char *name, char *value) +{ + int len; + char *env, *nxt; + char *oldval = NULL; + + /* + * search if variable with this name already exists + */ + for (nxt = env = environment.data; *env; env = nxt + 1) { + for (nxt = env; *nxt; ++nxt) { + if (nxt >= &environment.data[ENV_SIZE]) { + fprintf(stderr, "## Error: " + "environment not terminated\n"); + errno = EINVAL; + return -1; + } + } + if ((oldval = envmatch (name, env)) != NULL) + break; + } + + /* + * Delete any existing definition + */ + if (oldval) { + /* + * Ethernet Address and serial# can be set only once + */ + if ((strcmp (name, "ethaddr") == 0) || + (strcmp (name, "serial#") == 0)) { + fprintf (stderr, "Can't overwrite \"%s\"\n", name); + errno = EROFS; + return -1; + } + + if (*++nxt == '\0') { + *env = '\0'; + } else { + for (;;) { + *env = *nxt++; + if ((*env == '\0') && (*nxt == '\0')) + break; + ++env; + } + } + *++env = '\0'; + } + + /* Delete only ? */ + if (!value || !strlen(value)) + return 0; + + /* + * Append new definition at the end + */ + for (env = environment.data; *env || *(env + 1); ++env); + if (env > environment.data) + ++env; + /* + * Overflow when: + * "name" + "=" + "val" +"\0\0" > CONFIG_ENV_SIZE - (env-environment) + */ + len = strlen (name) + 2; + /* add '=' for first arg, ' ' for all others */ + len += strlen(value) + 1; + + if (len > (&environment.data[ENV_SIZE] - env)) { + fprintf (stderr, + "Error: environment overflow, \"%s\" deleted\n", + name); + return -1; + } + + while ((*env = *name++) != '\0') + env++; + *env = '='; + while ((*++env = *value++) != '\0') + ; + + /* end is marked with double '\0' */ + *++env = '\0'; + + return 0; +} + +/* + * Deletes or sets environment variables. Returns -1 and sets errno error codes: + * 0 - OK + * EINVAL - need at least 1 argument + * EROFS - certain variables ("ethaddr", "serial#") cannot be + * modified or deleted + * + */ +int fw_setenv(int argc, char *argv[]) +{ + int i, len; + char *name; + char *value = NULL; + char *tmpval = NULL; + + if (argc < 2) { + errno = EINVAL; + return -1; + } + + if (fw_env_open()) { + fprintf(stderr, "Error: environment not initialized\n"); + return -1; + } + + name = argv[1]; + + len = strlen(name) + 2; + for (i = 2; i < argc; ++i) + len += strlen(argv[i]) + 1; + + /* Allocate enough place to the data string */ + for (i = 2; i < argc; ++i) { + char *val = argv[i]; + if (!value) { + value = (char *)malloc(len - strlen(name)); + if (!value) { + fprintf(stderr, + "Cannot malloc %u bytes: %s\n", + len - strlen(name), strerror(errno)); + return -1; + } + memset(value, 0, len - strlen(name)); + tmpval = value; + } + if (i != 2) + *tmpval++ = ' '; + while (*val != '\0') + *tmpval++ = *val++; + } + + fw_env_write(name, value); + + if (value) + free(value); + + return fw_env_close(); +} + +/* + * Parse a file and configure the u-boot variables. + * The script file has a very simple format, as follows: + * + * Each line has a couple with name, value: + * <white spaces>variable_name<white spaces>variable_value + * + * Both variable_name and variable_value are interpreted as strings. + * Any character after <white spaces> and before ending \r\n is interpreted + * as variable's value (no comment allowed on these lines !) + * + * Comments are allowed if the first character in the line is # + * + * Returns -1 and sets errno error codes: + * 0 - OK + * -1 - Error + */ +int fw_parse_script(char *fname) +{ + FILE *fp; + char dump[1024]; /* Maximum line length in the file */ + char *name; + char *val; + int lineno = 0; + int len; + int ret = 0; + + if (fw_env_open()) { + fprintf(stderr, "Error: environment not initialized\n"); + return -1; + } + + if (strcmp(fname, "-") == 0) + fp = stdin; + else { + fp = fopen(fname, "r"); + if (fp == NULL) { + fprintf(stderr, "I cannot open %s for reading\n", + fname); + return -1; + } + } + + while (fgets(dump, sizeof(dump), fp)) { + lineno++; + len = strlen(dump); + + /* + * Read a whole line from the file. If the line is too long + * or is not terminated, reports an error and exit. + */ + if (dump[len - 1] != '\n') { + fprintf(stderr, + "Line %d not corrected terminated or too long\n", + lineno); + ret = -1; + break; + } + + /* Drop ending line feed / carriage return */ + while (len > 0 && (dump[len - 1] == '\n' || + dump[len - 1] == '\r')) { + dump[len - 1] = '\0'; + len--; + } + + /* Skip comment or empty lines */ + if ((len == 0) || dump[0] == '#') + continue; + + /* + * Search for variable's name, + * remove leading whitespaces + */ + name = fw_string_blank(dump, 1); + if (!name) + continue; + + /* The first white space is the end of variable name */ + val = fw_string_blank(name, 0); + len = strlen(name); + if (val) { + *val++ = '\0'; + if ((val - name) < len) + val = fw_string_blank(val, 1); + else + val = NULL; + } + +#ifdef DEBUG + fprintf(stderr, "Setting %s : %s\n", + name, val ? val : " removed"); +#endif + + /* + * If there is an error setting a variable, + * try to save the environment and returns an error + */ + if (fw_env_write(name, val)) { + fprintf(stderr, + "fw_env_write returns with error : %s\n", + strerror(errno)); + ret = -1; + break; + } + + } + + /* Close file if not stdin */ + if (strcmp(fname, "-") != 0) + fclose(fp); + + ret |= fw_env_close(); + + return ret; + +} + +/* + * Test for bad block on NAND, just returns 0 on NOR, on NAND: + * 0 - block is good + * > 0 - block is bad + * < 0 - failed to test + */ +static int flash_bad_block (int fd, uint8_t mtd_type, loff_t *blockstart) +{ + if (mtd_type == MTD_NANDFLASH) { + int badblock = ioctl (fd, MEMGETBADBLOCK, blockstart); + + if (badblock < 0) { + perror ("Cannot read bad block mark"); + return badblock; + } + + if (badblock) { +#ifdef DEBUG + fprintf (stderr, "Bad block at 0x%llx, " + "skipping\n", *blockstart); +#endif + return badblock; + } + } + + return 0; +} + +/* + * Read data from flash at an offset into a provided buffer. On NAND it skips + * bad blocks but makes sure it stays within ENVSECTORS (dev) starting from + * the DEVOFFSET (dev) block. On NOR the loop is only run once. + */ +static int flash_read_buf (int dev, int fd, void *buf, size_t count, + off_t offset, uint8_t mtd_type) +{ + size_t blocklen; /* erase / write length - one block on NAND, + 0 on NOR */ + size_t processed = 0; /* progress counter */ + size_t readlen = count; /* current read length */ + off_t top_of_range; /* end of the last block we may use */ + off_t block_seek; /* offset inside the current block to the start + of the data */ + loff_t blockstart; /* running start of the current block - + MEMGETBADBLOCK needs 64 bits */ + int rc; + + /* + * Start of the first block to be read, relies on the fact, that + * erase sector size is always a power of 2 + */ + blockstart = offset & ~(DEVESIZE (dev) - 1); + + /* Offset inside a block */ + block_seek = offset - blockstart; + + if (mtd_type == MTD_NANDFLASH) { + /* + * NAND: calculate which blocks we are reading. We have + * to read one block at a time to skip bad blocks. + */ + blocklen = DEVESIZE (dev); + + /* + * To calculate the top of the range, we have to use the + * global DEVOFFSET (dev), which can be different from offset + */ + top_of_range = (DEVOFFSET (dev) & ~(blocklen - 1)) + + ENVSECTORS (dev) * blocklen; + + /* Limit to one block for the first read */ + if (readlen > blocklen - block_seek) + readlen = blocklen - block_seek; + } else { + blocklen = 0; + top_of_range = offset + count; + } + + /* This only runs once on NOR flash */ + while (processed < count) { + rc = flash_bad_block (fd, mtd_type, &blockstart); + if (rc < 0) /* block test failed */ + return -1; + + if (blockstart + block_seek + readlen > top_of_range) { + /* End of range is reached */ + fprintf (stderr, + "Too few good blocks within range\n"); + return -1; + } + + if (rc) { /* block is bad */ + blockstart += blocklen; + continue; + } + + /* + * If a block is bad, we retry in the next block at the same + * offset - see common/env_nand.c::writeenv() + */ + lseek (fd, blockstart + block_seek, SEEK_SET); + + rc = read (fd, buf + processed, readlen); + if (rc != readlen) { + fprintf (stderr, "Read error on %s: %s\n", + DEVNAME (dev), strerror (errno)); + return -1; + } +#ifdef DEBUG + fprintf (stderr, "Read 0x%x bytes at 0x%llx\n", + rc, blockstart + block_seek); +#endif + processed += readlen; + readlen = min (blocklen, count - processed); + block_seek = 0; + blockstart += blocklen; + } + + return processed; +} + +/* + * Write count bytes at offset, but stay within ENVSETCORS (dev) sectors of + * DEVOFFSET (dev). Similar to the read case above, on NOR we erase and write + * the whole data at once. + */ +static int flash_write_buf (int dev, int fd, void *buf, size_t count, + off_t offset, uint8_t mtd_type) +{ + void *data; + struct erase_info_user erase; + size_t blocklen; /* length of NAND block / NOR erase sector */ + size_t erase_len; /* whole area that can be erased - may include + bad blocks */ + size_t erasesize; /* erase / write length - one block on NAND, + whole area on NOR */ + size_t processed = 0; /* progress counter */ + size_t write_total; /* total size to actually write - excludinig + bad blocks */ + off_t erase_offset; /* offset to the first erase block (aligned) + below offset */ + off_t block_seek; /* offset inside the erase block to the start + of the data */ + off_t top_of_range; /* end of the last block we may use */ + loff_t blockstart; /* running start of the current block - + MEMGETBADBLOCK needs 64 bits */ + int rc; + + blocklen = DEVESIZE (dev); + + /* Erase sector size is always a power of 2 */ + top_of_range = (DEVOFFSET (dev) & ~(blocklen - 1)) + + ENVSECTORS (dev) * blocklen; + + erase_offset = offset & ~(blocklen - 1); + + /* Maximum area we may use */ + erase_len = top_of_range - erase_offset; + + blockstart = erase_offset; + /* Offset inside a block */ + block_seek = offset - erase_offset; + + /* + * Data size we actually have to write: from the start of the block + * to the start of the data, then count bytes of data, and to the + * end of the block + */ + write_total = (block_seek + count + blocklen - 1) & ~(blocklen - 1); + + /* + * Support data anywhere within erase sectors: read out the complete + * area to be erased, replace the environment image, write the whole + * block back again. + */ + if (write_total > count) { + data = malloc (erase_len); + if (!data) { + fprintf (stderr, + "Cannot malloc %u bytes: %s\n", + erase_len, strerror (errno)); + return -1; + } + + rc = flash_read_buf (dev, fd, data, write_total, erase_offset, + mtd_type); + if (write_total != rc) + return -1; + + /* Overwrite the old environment */ + memcpy (data + block_seek, buf, count); + } else { + /* + * We get here, iff offset is block-aligned and count is a + * multiple of blocklen - see write_total calculation above + */ + data = buf; + } + + if (mtd_type == MTD_NANDFLASH) { + /* + * NAND: calculate which blocks we are writing. We have + * to write one block at a time to skip bad blocks. + */ + erasesize = blocklen; + } else { + erasesize = erase_len; + } + + erase.length = erasesize; + + /* This only runs once on NOR flash */ + while (processed < write_total) { + rc = flash_bad_block (fd, mtd_type, &blockstart); + if (rc < 0) /* block test failed */ + return rc; + + if (blockstart + erasesize > top_of_range) { + fprintf (stderr, "End of range reached, aborting\n"); + return -1; + } + + if (rc) { /* block is bad */ + blockstart += blocklen; + continue; + } + + erase.start = blockstart; + ioctl (fd, MEMUNLOCK, &erase); + + if (ioctl (fd, MEMERASE, &erase) != 0) { + fprintf (stderr, "MTD erase error on %s: %s\n", + DEVNAME (dev), + strerror (errno)); + return -1; + } + + if (lseek (fd, blockstart, SEEK_SET) == -1) { + fprintf (stderr, + "Seek error on %s: %s\n", + DEVNAME (dev), strerror (errno)); + return -1; + } + +#ifdef DEBUG + printf ("Write 0x%x bytes at 0x%llx\n", erasesize, blockstart); +#endif + if (write (fd, data + processed, erasesize) != erasesize) { + fprintf (stderr, "Write error on %s: %s\n", + DEVNAME (dev), strerror (errno)); + return -1; + } + + ioctl (fd, MEMLOCK, &erase); + + processed += blocklen; + block_seek = 0; + blockstart += blocklen; + } + + if (write_total > count) + free (data); + + return processed; +} + +/* + * Set obsolete flag at offset - NOR flash only + */ +static int flash_flag_obsolete (int dev, int fd, off_t offset) +{ + int rc; + struct erase_info_user erase; + + erase.start = DEVOFFSET (dev); + erase.length = DEVESIZE (dev); + /* This relies on the fact, that obsolete_flag == 0 */ + rc = lseek (fd, offset, SEEK_SET); + if (rc < 0) { + fprintf (stderr, "Cannot seek to set the flag on %s \n", + DEVNAME (dev)); + return rc; + } + ioctl (fd, MEMUNLOCK, &erase); + rc = write (fd, &obsolete_flag, sizeof (obsolete_flag)); + ioctl (fd, MEMLOCK, &erase); + if (rc < 0) + perror ("Could not set obsolete flag"); + + return rc; +} + +static int flash_write (int fd_current, int fd_target, int dev_target) +{ + int rc; + + switch (environment.flag_scheme) { + case FLAG_NONE: + break; + case FLAG_INCREMENTAL: + (*environment.flags)++; + break; + case FLAG_BOOLEAN: + *environment.flags = active_flag; + break; + default: + fprintf (stderr, "Unimplemented flash scheme %u \n", + environment.flag_scheme); + return -1; + } + +#ifdef DEBUG + printf ("Writing new environment at 0x%lx on %s\n", + DEVOFFSET (dev_target), DEVNAME (dev_target)); +#endif + rc = flash_write_buf (dev_target, fd_target, environment.image, + CONFIG_ENV_SIZE, DEVOFFSET (dev_target), + DEVTYPE(dev_target)); + if (rc < 0) + return rc; + + if (environment.flag_scheme == FLAG_BOOLEAN) { + /* Have to set obsolete flag */ + off_t offset = DEVOFFSET (dev_current) + + offsetof (struct env_image_redundant, flags); +#ifdef DEBUG + printf ("Setting obsolete flag in environment at 0x%lx on %s\n", + DEVOFFSET (dev_current), DEVNAME (dev_current)); +#endif + flash_flag_obsolete (dev_current, fd_current, offset); + } + + return 0; +} + +static int flash_read (int fd) +{ + struct mtd_info_user mtdinfo; + int rc; + + rc = ioctl (fd, MEMGETINFO, &mtdinfo); + if (rc < 0) { + perror ("Cannot get MTD information"); + return -1; + } + + if (mtdinfo.type != MTD_NORFLASH && mtdinfo.type != MTD_NANDFLASH) { + fprintf (stderr, "Unsupported flash type %u\n", mtdinfo.type); + return -1; + } + + DEVTYPE(dev_current) = mtdinfo.type; + + rc = flash_read_buf (dev_current, fd, environment.image, CONFIG_ENV_SIZE, + DEVOFFSET (dev_current), mtdinfo.type); + + return (rc != CONFIG_ENV_SIZE) ? -1 : 0; +} + +static int flash_io (int mode) +{ + int fd_current, fd_target, rc, dev_target; + + /* dev_current: fd_current, erase_current */ + fd_current = open (DEVNAME (dev_current), mode); + if (fd_current < 0) { + fprintf (stderr, + "Can't open %s: %s\n", + DEVNAME (dev_current), strerror (errno)); + return -1; + } + + if (mode == O_RDWR) { + if (HaveRedundEnv) { + /* switch to next partition for writing */ + dev_target = !dev_current; + /* dev_target: fd_target, erase_target */ + fd_target = open (DEVNAME (dev_target), mode); + if (fd_target < 0) { + fprintf (stderr, + "Can't open %s: %s\n", + DEVNAME (dev_target), + strerror (errno)); + rc = -1; + goto exit; + } + } else { + dev_target = dev_current; + fd_target = fd_current; + } + + rc = flash_write (fd_current, fd_target, dev_target); + + if (HaveRedundEnv) { + if (close (fd_target)) { + fprintf (stderr, + "I/O error on %s: %s\n", + DEVNAME (dev_target), + strerror (errno)); + rc = -1; + } + } + } else { + rc = flash_read (fd_current); + } + +exit: + if (close (fd_current)) { + fprintf (stderr, + "I/O error on %s: %s\n", + DEVNAME (dev_current), strerror (errno)); + return -1; + } + + return rc; +} + +/* + * s1 is either a simple 'name', or a 'name=value' pair. + * s2 is a 'name=value' pair. + * If the names match, return the value of s2, else NULL. + */ + +static char *envmatch (char * s1, char * s2) +{ + + while (*s1 == *s2++) + if (*s1++ == '=') + return s2; + if (*s1 == '\0' && *(s2 - 1) == '=') + return s2; + return NULL; +} + +/* + * Prevent confusion if running from erased flash memory + */ +int fw_env_open(void) +{ + int crc0, crc0_ok; + char flag0; + void *addr0; + + int crc1, crc1_ok; + char flag1; + void *addr1; + + struct env_image_single *single; + struct env_image_redundant *redundant; + + if (parse_config ()) /* should fill envdevices */ + return -1; + + addr0 = calloc (1, CONFIG_ENV_SIZE); + if (addr0 == NULL) { + fprintf (stderr, + "Not enough memory for environment (%ld bytes)\n", + CONFIG_ENV_SIZE); + return -1; + } + + /* read environment from FLASH to local buffer */ + environment.image = addr0; + + if (HaveRedundEnv) { + redundant = addr0; + environment.crc = &redundant->crc; + environment.flags = &redundant->flags; + environment.data = redundant->data; + } else { + single = addr0; + environment.crc = &single->crc; + environment.flags = NULL; + environment.data = single->data; + } + + dev_current = 0; + if (flash_io (O_RDONLY)) + return -1; + + crc0 = crc32 (0, (uint8_t *) environment.data, ENV_SIZE); + crc0_ok = (crc0 == *environment.crc); + if (!HaveRedundEnv) { + if (!crc0_ok) { + fprintf (stderr, + "Warning: Bad CRC, using default environment\n"); + memcpy(environment.data, default_environment, sizeof default_environment); + } + } else { + flag0 = *environment.flags; + + dev_current = 1; + addr1 = calloc (1, CONFIG_ENV_SIZE); + if (addr1 == NULL) { + fprintf (stderr, + "Not enough memory for environment (%ld bytes)\n", + CONFIG_ENV_SIZE); + return -1; + } + redundant = addr1; + + /* + * have to set environment.image for flash_read(), careful - + * other pointers in environment still point inside addr0 + */ + environment.image = addr1; + if (flash_io (O_RDONLY)) + return -1; + + /* Check flag scheme compatibility */ + if (DEVTYPE(dev_current) == MTD_NORFLASH && + DEVTYPE(!dev_current) == MTD_NORFLASH) { + environment.flag_scheme = FLAG_BOOLEAN; + } else if (DEVTYPE(dev_current) == MTD_NANDFLASH && + DEVTYPE(!dev_current) == MTD_NANDFLASH) { + environment.flag_scheme = FLAG_INCREMENTAL; + } else { + fprintf (stderr, "Incompatible flash types!\n"); + return -1; + } + + crc1 = crc32 (0, (uint8_t *) redundant->data, ENV_SIZE); + crc1_ok = (crc1 == redundant->crc); + flag1 = redundant->flags; + + if (crc0_ok && !crc1_ok) { + dev_current = 0; + } else if (!crc0_ok && crc1_ok) { + dev_current = 1; + } else if (!crc0_ok && !crc1_ok) { + fprintf (stderr, + "Warning: Bad CRC, using default environment\n"); + memcpy (environment.data, default_environment, + sizeof default_environment); + dev_current = 0; + } else { + switch (environment.flag_scheme) { + case FLAG_BOOLEAN: + if (flag0 == active_flag && + flag1 == obsolete_flag) { + dev_current = 0; + } else if (flag0 == obsolete_flag && + flag1 == active_flag) { + dev_current = 1; + } else if (flag0 == flag1) { + dev_current = 0; + } else if (flag0 == 0xFF) { + dev_current = 0; + } else if (flag1 == 0xFF) { + dev_current = 1; + } else { + dev_current = 0; + } + break; + case FLAG_INCREMENTAL: + if ((flag0 == 255 && flag1 == 0) || + flag1 > flag0) + dev_current = 1; + else if ((flag1 == 255 && flag0 == 0) || + flag0 > flag1) + dev_current = 0; + else /* flags are equal - almost impossible */ + dev_current = 0; + break; + default: + fprintf (stderr, "Unknown flag scheme %u \n", + environment.flag_scheme); + return -1; + } + } + + /* + * If we are reading, we don't need the flag and the CRC any + * more, if we are writing, we will re-calculate CRC and update + * flags before writing out + */ + if (dev_current) { + environment.image = addr1; + environment.crc = &redundant->crc; + environment.flags = &redundant->flags; + environment.data = redundant->data; + free (addr0); + } else { + environment.image = addr0; + /* Other pointers are already set */ + free (addr1); + } + } + return 0; +} + + +static int parse_config () +{ + struct stat st; + +#if defined(CONFIG_FILE) + /* Fills in DEVNAME(), ENVSIZE(), DEVESIZE(). Or don't. */ + if (get_config (CONFIG_FILE)) { + fprintf (stderr, + "Cannot parse config file: %s\n", strerror (errno)); + return -1; + } +#else + strcpy (DEVNAME (0), DEVICE1_NAME); + DEVOFFSET (0) = DEVICE1_OFFSET; + ENVSIZE (0) = ENV1_SIZE; + DEVESIZE (0) = DEVICE1_ESIZE; + ENVSECTORS (0) = DEVICE1_ENVSECTORS; +#ifdef HAVE_REDUND + strcpy (DEVNAME (1), DEVICE2_NAME); + DEVOFFSET (1) = DEVICE2_OFFSET; + ENVSIZE (1) = ENV2_SIZE; + DEVESIZE (1) = DEVICE2_ESIZE; + ENVSECTORS (1) = DEVICE2_ENVSECTORS; + HaveRedundEnv = 1; +#endif +#endif + if (stat (DEVNAME (0), &st)) { + fprintf (stderr, + "Cannot access MTD device %s: %s\n", + DEVNAME (0), strerror (errno)); + return -1; + } + + if (HaveRedundEnv && stat (DEVNAME (1), &st)) { + fprintf (stderr, + "Cannot access MTD device %s: %s\n", + DEVNAME (1), strerror (errno)); + return -1; + } + return 0; +} + +#if defined(CONFIG_FILE) +static int get_config (char *fname) +{ + FILE *fp; + int i = 0; + int rc; + char dump[128]; + + fp = fopen (fname, "r"); + if (fp == NULL) + return -1; + + while (i < 2 && fgets (dump, sizeof (dump), fp)) { + /* Skip incomplete conversions and comment strings */ + if (dump[0] == '#') + continue; + + rc = sscanf (dump, "%s %lx %lx %lx %lx", + DEVNAME (i), + &DEVOFFSET (i), + &ENVSIZE (i), + &DEVESIZE (i), + &ENVSECTORS (i)); + + if (rc < 4) + continue; + + if (rc < 5) + /* Default - 1 sector */ + ENVSECTORS (i) = 1; + + i++; + } + fclose (fp); + + HaveRedundEnv = i - 1; + if (!i) { /* No valid entries found */ + errno = EINVAL; + return -1; + } else + return 0; +} +#endif diff --git a/u-boot/tools/env/fw_env.config b/u-boot/tools/env/fw_env.config new file mode 100644 index 0000000..c8f12cf --- /dev/null +++ b/u-boot/tools/env/fw_env.config @@ -0,0 +1,11 @@ +# Configuration file for fw_(printenv/saveenv) utility. +# Up to two entries are valid, in this case the redundant +# environment sector is assumed present. +# Notice, that the "Number of sectors" is ignored on NOR. + +# MTD device name Device offset Env. size Flash sector size Number of sectors +/dev/mtd1 0x0000 0x4000 0x4000 +/dev/mtd2 0x0000 0x4000 0x4000 + +# NAND example +#/dev/mtd0 0x4000 0x4000 0x20000 2 diff --git a/u-boot/tools/env/fw_env.h b/u-boot/tools/env/fw_env.h new file mode 100644 index 0000000..8130fa1 --- /dev/null +++ b/u-boot/tools/env/fw_env.h @@ -0,0 +1,58 @@ +/* + * (C) Copyright 2002-2008 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * To build the utility with the run-time configuration + * uncomment the next line. + * See included "fw_env.config" sample file (TRAB board) + * for notes on configuration. + */ +#define CONFIG_FILE "/etc/fw_env.config" + +#define HAVE_REDUND /* For systems with 2 env sectors */ +#define DEVICE1_NAME "/dev/mtd1" +#define DEVICE2_NAME "/dev/mtd2" +#define DEVICE1_OFFSET 0x0000 +#define ENV1_SIZE 0x4000 +#define DEVICE1_ESIZE 0x4000 +#define DEVICE2_OFFSET 0x0000 +#define ENV2_SIZE 0x4000 +#define DEVICE2_ESIZE 0x4000 + +#define CONFIG_BAUDRATE 115200 +#define CONFIG_BOOTDELAY 5 /* autoboot after 5 seconds */ +#define CONFIG_BOOTCOMMAND \ + "bootp; " \ + "setenv bootargs root=/dev/nfs nfsroot=${serverip}:${rootpath} " \ + "ip=${ipaddr}:${serverip}:${gatewayip}:${netmask}:${hostname}::off; " \ + "bootm" + +extern int fw_printenv(int argc, char *argv[]); +extern char *fw_getenv (char *name); +extern int fw_setenv (int argc, char *argv[]); +extern int fw_parse_script(char *fname); +extern int fw_env_open(void); +extern int fw_env_write(char *name, char *value); +extern int fw_env_close(void); + +extern unsigned long crc32 (unsigned long, const unsigned char *, unsigned); diff --git a/u-boot/tools/env/fw_env_main.c b/u-boot/tools/env/fw_env_main.c new file mode 100644 index 0000000..c654057 --- /dev/null +++ b/u-boot/tools/env/fw_env_main.c @@ -0,0 +1,141 @@ +/* + * (C) Copyright 2000-2008 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * Command line user interface to firmware (=U-Boot) environment. + * + * Implements: + * fw_printenv [[ -n name ] | [ name ... ]] + * - prints the value of a single environment variable + * "name", the ``name=value'' pairs of one or more + * environment variables "name", or the whole + * environment if no names are specified. + * fw_setenv name [ value ... ] + * - If a name without any values is given, the variable + * with this name is deleted from the environment; + * otherwise, all "value" arguments are concatenated, + * separated by single blank characters, and the + * resulting string is assigned to the environment + * variable "name" + */ + +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <getopt.h> +#include "fw_env.h" + +#define CMD_PRINTENV "fw_printenv" +#define CMD_SETENV "fw_setenv" + +static struct option long_options[] = { + {"script", required_argument, NULL, 's'}, + {"help", no_argument, NULL, 'h'}, + {NULL, 0, NULL, 0} +}; + +void usage(void) +{ + + fprintf(stderr, "fw_printenv/fw_setenv, " + "a command line interface to U-Boot environment\n\n" + "usage:\tfw_printenv [-n] [variable name]\n" + "\tfw_setenv [variable name] [variable value]\n" + "\tfw_setenv -s [ file ]\n" + "\tfw_setenv -s - < [ file ]\n\n" + "The file passed as argument contains only pairs " + "name / value\n" + "Example:\n" + "# Any line starting with # is treated as comment\n" + "\n" + "\t netdev eth0\n" + "\t kernel_addr 400000\n" + "\t var1\n" + "\t var2 The quick brown fox jumps over the " + "lazy dog\n" + "\n" + "A variable without value will be dropped. It is possible\n" + "to put any number of spaces between the fields, but any\n" + "space inside the value is treated as part of the value " + "itself.\n\n" + ); +} + +int +main(int argc, char *argv[]) +{ + char *p; + char *cmdname = *argv; + char *script_file = NULL; + int c; + + if ((p = strrchr (cmdname, '/')) != NULL) { + cmdname = p + 1; + } + + while ((c = getopt_long (argc, argv, "ns:h", + long_options, NULL)) != EOF) { + switch (c) { + case 'n': + /* handled in fw_printenv */ + break; + case 's': + script_file = optarg; + break; + case 'h': + usage(); + return EXIT_SUCCESS; + default: /* '?' */ + fprintf(stderr, "Try `%s --help' for more information." + "\n", cmdname); + return EXIT_FAILURE; + } + } + + + if (strcmp(cmdname, CMD_PRINTENV) == 0) { + + if (fw_printenv (argc, argv) != 0) + return EXIT_FAILURE; + + return EXIT_SUCCESS; + + } else if (strcmp(cmdname, CMD_SETENV) == 0) { + if (!script_file) { + if (fw_setenv(argc, argv) != 0) + return EXIT_FAILURE; + } else { + if (fw_parse_script(script_file) != 0) + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; + + } + + fprintf (stderr, + "Identity crisis - may be called as `" CMD_PRINTENV + "' or as `" CMD_SETENV "' but not as `%s'\n", + cmdname); + return EXIT_FAILURE; +} diff --git a/u-boot/tools/envcrc.c b/u-boot/tools/envcrc.c new file mode 100644 index 0000000..c8c50d7 --- /dev/null +++ b/u-boot/tools/envcrc.c @@ -0,0 +1,140 @@ +/* + * (C) Copyright 2001 + * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <errno.h> +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#ifndef __ASSEMBLY__ +#define __ASSEMBLY__ /* Dirty trick to get only #defines */ +#endif +#define __ASM_STUB_PROCESSOR_H__ /* don't include asm/processor. */ +#include <config.h> +#undef __ASSEMBLY__ + +#if defined(CONFIG_ENV_IS_IN_FLASH) +# ifndef CONFIG_ENV_ADDR +# define CONFIG_ENV_ADDR (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET) +# endif +# ifndef CONFIG_ENV_OFFSET +# define CONFIG_ENV_OFFSET (CONFIG_ENV_ADDR - CONFIG_SYS_FLASH_BASE) +# endif +# if !defined(CONFIG_ENV_ADDR_REDUND) && defined(CONFIG_ENV_OFFSET_REDUND) +# define CONFIG_ENV_ADDR_REDUND (CONFIG_SYS_FLASH_BASE + CONFIG_ENV_OFFSET_REDUND) +# endif +# ifndef CONFIG_ENV_SIZE +# define CONFIG_ENV_SIZE CONFIG_ENV_SECT_SIZE +# endif +# if defined(CONFIG_ENV_ADDR_REDUND) && !defined(CONFIG_ENV_SIZE_REDUND) +# define CONFIG_ENV_SIZE_REDUND CONFIG_ENV_SIZE +# endif +# if (CONFIG_ENV_ADDR >= CONFIG_SYS_MONITOR_BASE) && \ + ((CONFIG_ENV_ADDR + CONFIG_ENV_SIZE) <= (CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN)) +# define ENV_IS_EMBEDDED 1 +# endif +# if defined(CONFIG_ENV_ADDR_REDUND) || defined(CONFIG_ENV_OFFSET_REDUND) +# define CONFIG_SYS_REDUNDAND_ENVIRONMENT 1 +# endif +#endif /* CONFIG_ENV_IS_IN_FLASH */ + +#ifdef CONFIG_SYS_REDUNDAND_ENVIRONMENT +# define ENV_HEADER_SIZE (sizeof(uint32_t) + 1) +#else +# define ENV_HEADER_SIZE (sizeof(uint32_t)) +#endif + +#define ENV_SIZE (CONFIG_ENV_SIZE - ENV_HEADER_SIZE) + + +extern uint32_t crc32 (uint32_t, const unsigned char *, unsigned int); + +#ifdef ENV_IS_EMBEDDED +extern unsigned int env_size; +extern unsigned char environment; +#endif /* ENV_IS_EMBEDDED */ + +int main (int argc, char **argv) +{ +#ifdef ENV_IS_EMBEDDED + unsigned char pad = 0x00; + uint32_t crc; + unsigned char *envptr = &environment, + *dataptr = envptr + ENV_HEADER_SIZE; + unsigned int datasize = ENV_SIZE; + unsigned int eoe; + + if (argv[1] && !strncmp(argv[1], "--binary", 8)) { + int ipad = 0xff; + if (argv[1][8] == '=') + sscanf(argv[1] + 9, "%i", &ipad); + pad = ipad; + } + + if (pad) { + /* find the end of env */ + for (eoe = 0; eoe < datasize - 1; ++eoe) + if (!dataptr[eoe] && !dataptr[eoe+1]) { + eoe += 2; + break; + } + if (eoe < datasize - 1) + memset(dataptr + eoe, pad, datasize - eoe); + } + + crc = crc32 (0, dataptr, datasize); + + /* Check if verbose mode is activated passing a parameter to the program */ + if (argc > 1) { + if (!strncmp(argv[1], "--binary", 8)) { + int le = (argc > 2 ? !strcmp(argv[2], "le") : 1); + size_t i, start, end, step; + if (le) { + start = 0; + end = ENV_HEADER_SIZE; + step = 1; + } else { + start = ENV_HEADER_SIZE - 1; + end = -1; + step = -1; + } + for (i = start; i != end; i += step) + printf("%c", (crc & (0xFF << (i * 8))) >> (i * 8)); + if (fwrite(dataptr, 1, datasize, stdout) != datasize) + fprintf(stderr, "fwrite() failed: %s\n", strerror(errno)); + } else { + printf("CRC32 from offset %08X to %08X of environment = %08X\n", + (unsigned int) (dataptr - envptr), + (unsigned int) (dataptr - envptr) + datasize, + crc); + } + } else { + printf ("0x%08X\n", crc); + } +#else + printf ("0\n"); +#endif + return EXIT_SUCCESS; +} diff --git a/u-boot/tools/fdt_host.h b/u-boot/tools/fdt_host.h new file mode 100644 index 0000000..085013e --- /dev/null +++ b/u-boot/tools/fdt_host.h @@ -0,0 +1,28 @@ +/* + * (C) Copyright 2008 Semihalf + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef __FDT_HOST_H__ +#define __FDT_HOST_H__ + +/* Make sure to include u-boot version of libfdt include files */ +#include "../include/fdt.h" +#include "../include/libfdt.h" +#include "../include/fdt_support.h" + +#endif /* __FDT_HOST_H__ */ diff --git a/u-boot/tools/fit_image.c b/u-boot/tools/fit_image.c new file mode 100644 index 0000000..ef9ffee --- /dev/null +++ b/u-boot/tools/fit_image.c @@ -0,0 +1,180 @@ +/* + * (C) Copyright 2008 Semihalf + * + * (C) Copyright 2000-2004 + * DENX Software Engineering + * Wolfgang Denk, wd@denx.de + * + * Updated-by: Prafulla Wadaskar <prafulla@marvell.com> + * FIT image specific code abstracted from mkimage.c + * some functions added to address abstraction + * + * All rights reserved. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include "mkimage.h" +#include <image.h> +#include <u-boot/crc.h> + +static image_header_t header; + +static int fit_verify_header (unsigned char *ptr, int image_size, + struct mkimage_params *params) +{ + return fdt_check_header ((void *)ptr); +} + +static int fit_check_image_types (uint8_t type) +{ + if (type == IH_TYPE_FLATDT) + return EXIT_SUCCESS; + else + return EXIT_FAILURE; +} + +/** + * fit_handle_file - main FIT file processing function + * + * fit_handle_file() runs dtc to convert .its to .itb, includes + * binary data, updates timestamp property and calculates hashes. + * + * datafile - .its file + * imagefile - .itb file + * + * returns: + * only on success, otherwise calls exit (EXIT_FAILURE); + */ +static int fit_handle_file (struct mkimage_params *params) +{ + char tmpfile[MKIMAGE_MAX_TMPFILE_LEN]; + char cmd[MKIMAGE_MAX_DTC_CMDLINE_LEN]; + int tfd; + struct stat sbuf; + unsigned char *ptr; + + /* Flattened Image Tree (FIT) format handling */ + debug ("FIT format handling\n"); + + /* call dtc to include binary properties into the tmp file */ + if (strlen (params->imagefile) + + strlen (MKIMAGE_TMPFILE_SUFFIX) + 1 > sizeof (tmpfile)) { + fprintf (stderr, "%s: Image file name (%s) too long, " + "can't create tmpfile", + params->imagefile, params->cmdname); + return (EXIT_FAILURE); + } + sprintf (tmpfile, "%s%s", params->imagefile, MKIMAGE_TMPFILE_SUFFIX); + + /* dtc -I dts -O -p 200 datafile > tmpfile */ + sprintf (cmd, "%s %s %s > %s", + MKIMAGE_DTC, params->dtc, params->datafile, tmpfile); + debug ("Trying to execute \"%s\"\n", cmd); + if (system (cmd) == -1) { + fprintf (stderr, "%s: system(%s) failed: %s\n", + params->cmdname, cmd, strerror(errno)); + unlink (tmpfile); + return (EXIT_FAILURE); + } + + /* load FIT blob into memory */ + tfd = open (tmpfile, O_RDWR|O_BINARY); + + if (tfd < 0) { + fprintf (stderr, "%s: Can't open %s: %s\n", + params->cmdname, tmpfile, strerror(errno)); + unlink (tmpfile); + return (EXIT_FAILURE); + } + + if (fstat (tfd, &sbuf) < 0) { + fprintf (stderr, "%s: Can't stat %s: %s\n", + params->cmdname, tmpfile, strerror(errno)); + unlink (tmpfile); + return (EXIT_FAILURE); + } + + ptr = mmap (0, sbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, + tfd, 0); + if (ptr == MAP_FAILED) { + fprintf (stderr, "%s: Can't read %s: %s\n", + params->cmdname, tmpfile, strerror(errno)); + unlink (tmpfile); + return (EXIT_FAILURE); + } + + /* check if ptr has a valid blob */ + if (fdt_check_header (ptr)) { + fprintf (stderr, "%s: Invalid FIT blob\n", params->cmdname); + unlink (tmpfile); + return (EXIT_FAILURE); + } + + /* set hashes for images in the blob */ + if (fit_set_hashes (ptr)) { + fprintf (stderr, "%s Can't add hashes to FIT blob", + params->cmdname); + unlink (tmpfile); + return (EXIT_FAILURE); + } + + /* add a timestamp at offset 0 i.e., root */ + if (fit_set_timestamp (ptr, 0, sbuf.st_mtime)) { + fprintf (stderr, "%s: Can't add image timestamp\n", + params->cmdname); + unlink (tmpfile); + return (EXIT_FAILURE); + } + debug ("Added timestamp successfully\n"); + + munmap ((void *)ptr, sbuf.st_size); + close (tfd); + + if (rename (tmpfile, params->imagefile) == -1) { + fprintf (stderr, "%s: Can't rename %s to %s: %s\n", + params->cmdname, tmpfile, params->imagefile, + strerror (errno)); + unlink (tmpfile); + unlink (params->imagefile); + return (EXIT_FAILURE); + } + return (EXIT_SUCCESS); +} + +static int fit_check_params (struct mkimage_params *params) +{ + return ((params->dflag && (params->fflag || params->lflag)) || + (params->fflag && (params->dflag || params->lflag)) || + (params->lflag && (params->dflag || params->fflag))); +} + +static struct image_type_params fitimage_params = { + .name = "FIT Image support", + .header_size = sizeof(image_header_t), + .hdr = (void*)&header, + .verify_header = fit_verify_header, + .print_header = fit_print_contents, + .check_image_type = fit_check_image_types, + .fflag_handle = fit_handle_file, + .set_header = NULL, /* FIT images use DTB header */ + .check_params = fit_check_params, +}; + +void init_fit_image_type (void) +{ + mkimage_register (&fitimage_params); +} diff --git a/u-boot/tools/gdb/Makefile b/u-boot/tools/gdb/Makefile new file mode 100644 index 0000000..90037c7 --- /dev/null +++ b/u-boot/tools/gdb/Makefile @@ -0,0 +1,74 @@ +# +# (C) Copyright 2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# (C) Copyright 2000 +# Murray Jensen <Murray.Jensen@csiro.au> +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# 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 +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +BINS = gdbsend gdbcont + +COBJS = gdbsend.o gdbcont.o error.o remote.o serial.o + +HOSTOBJS := $(addprefix $(obj),$(COBJS)) +HOSTSRCS := $(COBJS:.o=.c) +BINS := $(addprefix $(obj),$(BINS)) + +# +# Use native tools and options +# +HOSTCPPFLAGS = -I$(BFD_ROOT_DIR)/include + +HOSTOS := $(shell uname -s | sed -e 's/\([Cc][Yy][Gg][Ww][Ii][Nn]\).*/cygwin/') + +ifeq ($(HOSTOS),cygwin) + +all: +$(obj).depend: + +else # ! CYGWIN + +all: $(obj).depend $(BINS) + +$(obj)gdbsend: $(obj)gdbsend.o $(obj)error.o $(obj)remote.o $(obj)serial.o + $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ + +$(obj)gdbcont: $(obj)gdbcont.o $(obj)error.o $(obj)remote.o $(obj)serial.o + $(HOSTCC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ + +clean: + rm -f $(HOSTOBJS) + +distclean: clean + rm -f $(BINS) $(obj)core $(obj)*.bak $(obj).depend + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### + +endif # cygwin diff --git a/u-boot/tools/gdb/error.c b/u-boot/tools/gdb/error.c new file mode 100644 index 0000000..276a00a --- /dev/null +++ b/u-boot/tools/gdb/error.c @@ -0,0 +1,81 @@ +/* + * (C) Copyright 2000 + * Murray Jensen <Murray.Jensen@csiro.au> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include "error.h" + +char *pname; + +void +Warning(char *fmt, ...) +{ + va_list args; + + fprintf(stderr, "%s: WARNING: ", pname); + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + + fprintf(stderr, "\n"); +} + +void +Error(char *fmt, ...) +{ + va_list args; + + fprintf(stderr, "%s: ERROR: ", pname); + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + + fprintf(stderr, "\n"); + + exit(1); +} + +void +Perror(char *fmt, ...) +{ + va_list args; + int e = errno; + char *p; + + fprintf(stderr, "%s: ERROR: ", pname); + + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); + + if ((p = strerror(e)) == NULL || *p == '\0') + fprintf(stderr, ": Unknown Error (%d)\n", e); + else + fprintf(stderr, ": %s\n", p); + + exit(1); +} diff --git a/u-boot/tools/gdb/error.h b/u-boot/tools/gdb/error.h new file mode 100644 index 0000000..0698213 --- /dev/null +++ b/u-boot/tools/gdb/error.h @@ -0,0 +1,30 @@ +/* + * (C) Copyright 2000 + * Murray Jensen <Murray.Jensen@csiro.au> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <stdarg.h> + +extern char *pname; + +extern void Warning(char *, ...); +extern void Error(char *, ...); +extern void Perror(char *, ...); diff --git a/u-boot/tools/gdb/gdbcont.c b/u-boot/tools/gdb/gdbcont.c new file mode 100644 index 0000000..300545d --- /dev/null +++ b/u-boot/tools/gdb/gdbcont.c @@ -0,0 +1,87 @@ +/* + * (C) Copyright 2000 + * Murray Jensen <Murray.Jensen@csiro.au> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include "serial.h" +#include "error.h" +#include "remote.h" + +char *serialdev = "/dev/term/b"; +speed_t speed = B230400; +int verbose = 0; + +int +main(int ac, char **av) +{ + int c, sfd; + + if ((pname = strrchr(av[0], '/')) == NULL) + pname = av[0]; + else + pname++; + + while ((c = getopt(ac, av, "b:p:v")) != EOF) + switch (c) { + + case 'b': + if ((speed = cvtspeed(optarg)) == B0) + Error("can't decode baud rate specified in -b option"); + break; + + case 'p': + serialdev = optarg; + break; + + case 'v': + verbose = 1; + break; + + default: + usage: + fprintf(stderr, "Usage: %s [-b bps] [-p dev] [-v]\n", pname); + exit(1); + } + if (optind != ac) + goto usage; + + if (verbose) + fprintf(stderr, "Opening serial port and sending continue...\n"); + + if ((sfd = serialopen(serialdev, speed)) < 0) + Perror("open of serial device '%s' failed", serialdev); + + remote_desc = sfd; + remote_reset(); + remote_continue(); + + if (serialclose(sfd) < 0) + Perror("close of serial device '%s' failed", serialdev); + + if (verbose) + fprintf(stderr, "Done.\n"); + + return (0); +} diff --git a/u-boot/tools/gdb/gdbsend.c b/u-boot/tools/gdb/gdbsend.c new file mode 100644 index 0000000..8cd8347 --- /dev/null +++ b/u-boot/tools/gdb/gdbsend.c @@ -0,0 +1,137 @@ +/* + * (C) Copyright 2000 + * Murray Jensen <Murray.Jensen@csiro.au> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include "serial.h" +#include "error.h" +#include "remote.h" + +char *serialdev = "/dev/term/b"; +speed_t speed = B230400; +int verbose = 0, docont = 0; +unsigned long addr = 0x10000UL; + +int +main(int ac, char **av) +{ + int c, sfd, ifd; + char *ifn, *image; + struct stat ist; + + if ((pname = strrchr(av[0], '/')) == NULL) + pname = av[0]; + else + pname++; + + while ((c = getopt(ac, av, "a:b:cp:v")) != EOF) + switch (c) { + + case 'a': { + char *ep; + + addr = strtol(optarg, &ep, 0); + if (ep == optarg || *ep != '\0') + Error("can't decode address specified in -a option"); + break; + } + + case 'b': + if ((speed = cvtspeed(optarg)) == B0) + Error("can't decode baud rate specified in -b option"); + break; + + case 'c': + docont = 1; + break; + + case 'p': + serialdev = optarg; + break; + + case 'v': + verbose = 1; + break; + + default: + usage: + fprintf(stderr, + "Usage: %s [-a addr] [-b bps] [-c] [-p dev] [-v] imagefile\n", + pname); + exit(1); + } + + if (optind != ac - 1) + goto usage; + ifn = av[optind++]; + + if (verbose) + fprintf(stderr, "Opening file and reading image...\n"); + + if ((ifd = open(ifn, O_RDONLY)) < 0) + Perror("can't open kernel image file '%s'", ifn); + + if (fstat(ifd, &ist) < 0) + Perror("fstat '%s' failed", ifn); + + if ((image = (char *)malloc(ist.st_size)) == NULL) + Perror("can't allocate %ld bytes for image", ist.st_size); + + if ((c = read(ifd, image, ist.st_size)) < 0) + Perror("read of %d bytes from '%s' failed", ist.st_size, ifn); + + if (c != ist.st_size) + Error("read of %ld bytes from '%s' failed (%d)", ist.st_size, ifn, c); + + if (close(ifd) < 0) + Perror("close of '%s' failed", ifn); + + if (verbose) + fprintf(stderr, "Opening serial port and sending image...\n"); + + if ((sfd = serialopen(serialdev, speed)) < 0) + Perror("open of serial device '%s' failed", serialdev); + + remote_desc = sfd; + remote_reset(); + remote_write_bytes(addr, image, ist.st_size); + + if (docont) { + if (verbose) + fprintf(stderr, "[continue]"); + remote_continue(); + } + + if (serialclose(sfd) < 0) + Perror("close of serial device '%s' failed", serialdev); + + if (verbose) + fprintf(stderr, "Done.\n"); + + return (0); +} diff --git a/u-boot/tools/gdb/remote.c b/u-boot/tools/gdb/remote.c new file mode 100644 index 0000000..c76a7ba --- /dev/null +++ b/u-boot/tools/gdb/remote.c @@ -0,0 +1,928 @@ +/* + * taken from gdb/remote.c + * + * I am only interested in the write to memory stuff - everything else + * has been ripped out + * + * all the copyright notices etc have been left in + */ + +/* enough so that it will compile */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +/*nicked from gcc..*/ + +#ifndef alloca +#ifdef __GNUC__ +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) +#include <alloca.h> +#else /* not sparc */ +#if defined (MSDOS) && !defined (__TURBOC__) +#include <malloc.h> +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +#include <malloc.h> + #pragma alloca +#else /* not MSDOS, __TURBOC__, or _AIX */ +#ifdef __hpux +#endif /* __hpux */ +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc. */ +#endif /* not GNU C. */ +#ifdef __cplusplus +extern "C" { +#endif + void* alloca(size_t); +#ifdef __cplusplus +} +#endif +#endif /* alloca not defined. */ + + +#include "serial.h" +#include "error.h" +#include "remote.h" +#define REGISTER_BYTES 0 +#define fprintf_unfiltered fprintf +#define fprintf_filtered fprintf +#define fputs_unfiltered fputs +#define fputs_filtered fputs +#define fputc_unfiltered fputc +#define fputc_filtered fputc +#define printf_unfiltered printf +#define printf_filtered printf +#define puts_unfiltered puts +#define puts_filtered puts +#define putchar_unfiltered putchar +#define putchar_filtered putchar +#define fputstr_unfiltered(a,b,c) fputs((a), (c)) +#define gdb_stdlog stderr +#define SERIAL_READCHAR(fd,timo) serialreadchar((fd), (timo)) +#define SERIAL_WRITE(fd, addr, len) serialwrite((fd), (addr), (len)) +#define error Error +#define perror_with_name Perror +#define gdb_flush fflush +#define max(a,b) (((a)>(b))?(a):(b)) +#define min(a,b) (((a)<(b))?(a):(b)) +#define target_mourn_inferior() {} +#define ULONGEST unsigned long +#define CORE_ADDR unsigned long + +static int putpkt (char *); +static int putpkt_binary(char *, int); +static void getpkt (char *, int); + +static int remote_debug = 0, remote_register_buf_size = 0, watchdog = 0; + +int remote_desc = -1, remote_timeout = 10; + +static void +fputstrn_unfiltered(char *s, int n, int x, FILE *fp) +{ + while (n-- > 0) + fputc(*s++, fp); +} + +void +remote_reset(void) +{ + SERIAL_WRITE(remote_desc, "+", 1); +} + +void +remote_continue(void) +{ + putpkt("c"); +} + +/* Remote target communications for serial-line targets in custom GDB protocol + Copyright 1988, 91, 92, 93, 94, 95, 96, 97, 98, 1999 + Free Software Foundation, Inc. + + This file is part of GDB. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + 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 + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ +/* *INDENT-OFF* */ +/* Remote communication protocol. + + A debug packet whose contents are <data> + is encapsulated for transmission in the form: + + $ <data> # CSUM1 CSUM2 + + <data> must be ASCII alphanumeric and cannot include characters + '$' or '#'. If <data> starts with two characters followed by + ':', then the existing stubs interpret this as a sequence number. + + CSUM1 and CSUM2 are ascii hex representation of an 8-bit + checksum of <data>, the most significant nibble is sent first. + the hex digits 0-9,a-f are used. + + Receiver responds with: + + + - if CSUM is correct and ready for next packet + - - if CSUM is incorrect + + <data> is as follows: + Most values are encoded in ascii hex digits. Signal numbers are according + to the numbering in target.h. + + Request Packet + + set thread Hct... Set thread for subsequent operations. + c = 'c' for thread used in step and + continue; t... can be -1 for all + threads. + c = 'g' for thread used in other + operations. If zero, pick a thread, + any thread. + reply OK for success + ENN for an error. + + read registers g + reply XX....X Each byte of register data + is described by two hex digits. + Registers are in the internal order + for GDB, and the bytes in a register + are in the same order the machine uses. + or ENN for an error. + + write regs GXX..XX Each byte of register data + is described by two hex digits. + reply OK for success + ENN for an error + + write reg Pn...=r... Write register n... with value r..., + which contains two hex digits for each + byte in the register (target byte + order). + reply OK for success + ENN for an error + (not supported by all stubs). + + read mem mAA..AA,LLLL AA..AA is address, LLLL is length. + reply XX..XX XX..XX is mem contents + Can be fewer bytes than requested + if able to read only part of the data. + or ENN NN is errno + + write mem MAA..AA,LLLL:XX..XX + AA..AA is address, + LLLL is number of bytes, + XX..XX is data + reply OK for success + ENN for an error (this includes the case + where only part of the data was + written). + + write mem XAA..AA,LLLL:XX..XX + (binary) AA..AA is address, + LLLL is number of bytes, + XX..XX is binary data + reply OK for success + ENN for an error + + continue cAA..AA AA..AA is address to resume + If AA..AA is omitted, + resume at same address. + + step sAA..AA AA..AA is address to resume + If AA..AA is omitted, + resume at same address. + + continue with Csig;AA..AA Continue with signal sig (hex signal + signal number). If ;AA..AA is omitted, + resume at same address. + + step with Ssig;AA..AA Like 'C' but step not continue. + signal + + last signal ? Reply the current reason for stopping. + This is the same reply as is generated + for step or cont : SAA where AA is the + signal number. + + detach D Reply OK. + + There is no immediate reply to step or cont. + The reply comes when the machine stops. + It is SAA AA is the signal number. + + or... TAAn...:r...;n...:r...;n...:r...; + AA = signal number + n... = register number (hex) + r... = register contents + n... = `thread' + r... = thread process ID. This is + a hex integer. + n... = other string not starting + with valid hex digit. + gdb should ignore this n,r pair + and go on to the next. This way + we can extend the protocol. + or... WAA The process exited, and AA is + the exit status. This is only + applicable for certains sorts of + targets. + or... XAA The process terminated with signal + AA. + or (obsolete) NAA;tttttttt;dddddddd;bbbbbbbb + AA = signal number + tttttttt = address of symbol "_start" + dddddddd = base of data section + bbbbbbbb = base of bss section. + Note: only used by Cisco Systems + targets. The difference between this + reply and the "qOffsets" query is that + the 'N' packet may arrive spontaneously + whereas the 'qOffsets' is a query + initiated by the host debugger. + or... OXX..XX XX..XX is hex encoding of ASCII data. This + can happen at any time while the + program is running and the debugger + should continue to wait for + 'W', 'T', etc. + + thread alive TXX Find out if the thread XX is alive. + reply OK thread is still alive + ENN thread is dead + + remote restart RXX Restart the remote server + + extended ops ! Use the extended remote protocol. + Sticky -- only needs to be set once. + + kill request k + + toggle debug d toggle debug flag (see 386 & 68k stubs) + reset r reset -- see sparc stub. + reserved <other> On other requests, the stub should + ignore the request and send an empty + response ($#<checksum>). This way + we can extend the protocol and GDB + can tell whether the stub it is + talking to uses the old or the new. + search tAA:PP,MM Search backwards starting at address + AA for a match with pattern PP and + mask MM. PP and MM are 4 bytes. + Not supported by all stubs. + + general query qXXXX Request info about XXXX. + general set QXXXX=yyyy Set value of XXXX to yyyy. + query sect offs qOffsets Get section offsets. Reply is + Text=xxx;Data=yyy;Bss=zzz + + Responses can be run-length encoded to save space. A '*' means that + the next character is an ASCII encoding giving a repeat count which + stands for that many repititions of the character preceding the '*'. + The encoding is n+29, yielding a printable character where n >=3 + (which is where rle starts to win). Don't use an n > 126. + + So + "0* " means the same as "0000". */ +/* *INDENT-ON* */ + +/* This variable (available to the user via "set remotebinarydownload") + dictates whether downloads are sent in binary (via the 'X' packet). + We assume that the stub can, and attempt to do it. This will be cleared if + the stub does not understand it. This switch is still needed, though + in cases when the packet is supported in the stub, but the connection + does not allow it (i.e., 7-bit serial connection only). */ +static int remote_binary_download = 1; + +/* Have we already checked whether binary downloads work? */ +static int remote_binary_checked; + +/* Maximum number of bytes to read/write at once. The value here + is chosen to fill up a packet (the headers account for the 32). */ +#define MAXBUFBYTES(N) (((N)-32)/2) + +/* Having this larger than 400 causes us to be incompatible with m68k-stub.c + and i386-stub.c. Normally, no one would notice because it only matters + for writing large chunks of memory (e.g. in downloads). Also, this needs + to be more than 400 if required to hold the registers (see below, where + we round it up based on REGISTER_BYTES). */ +/* Round up PBUFSIZ to hold all the registers, at least. */ +#define PBUFSIZ ((REGISTER_BYTES > MAXBUFBYTES (400)) \ + ? (REGISTER_BYTES * 2 + 32) \ + : 400) + + +/* This variable sets the number of bytes to be written to the target + in a single packet. Normally PBUFSIZ is satisfactory, but some + targets need smaller values (perhaps because the receiving end + is slow). */ + +static int remote_write_size = 0x7fffffff; + +/* This variable sets the number of bits in an address that are to be + sent in a memory ("M" or "m") packet. Normally, after stripping + leading zeros, the entire address would be sent. This variable + restricts the address to REMOTE_ADDRESS_SIZE bits. HISTORY: The + initial implementation of remote.c restricted the address sent in + memory packets to ``host::sizeof long'' bytes - (typically 32 + bits). Consequently, for 64 bit targets, the upper 32 bits of an + address was never sent. Since fixing this bug may cause a break in + some remote targets this variable is principly provided to + facilitate backward compatibility. */ + +static int remote_address_size; + +/* Convert hex digit A to a number. */ + +static int +fromhex (int a) +{ + if (a >= '0' && a <= '9') + return a - '0'; + else if (a >= 'a' && a <= 'f') + return a - 'a' + 10; + else if (a >= 'A' && a <= 'F') + return a - 'A' + 10; + else { + error ("Reply contains invalid hex digit %d", a); + return -1; + } +} + +/* Convert number NIB to a hex digit. */ + +static int +tohex (int nib) +{ + if (nib < 10) + return '0' + nib; + else + return 'a' + nib - 10; +} + +/* Return the number of hex digits in num. */ + +static int +hexnumlen (ULONGEST num) +{ + int i; + + for (i = 0; num != 0; i++) + num >>= 4; + + return max (i, 1); +} + +/* Set BUF to the hex digits representing NUM. */ + +static int +hexnumstr (char *buf, ULONGEST num) +{ + int i; + int len = hexnumlen (num); + + buf[len] = '\0'; + + for (i = len - 1; i >= 0; i--) + { + buf[i] = "0123456789abcdef"[(num & 0xf)]; + num >>= 4; + } + + return len; +} + +/* Mask all but the least significant REMOTE_ADDRESS_SIZE bits. */ + +static CORE_ADDR +remote_address_masked (CORE_ADDR addr) +{ + if (remote_address_size > 0 + && remote_address_size < (sizeof (ULONGEST) * 8)) + { + /* Only create a mask when that mask can safely be constructed + in a ULONGEST variable. */ + ULONGEST mask = 1; + mask = (mask << remote_address_size) - 1; + addr &= mask; + } + return addr; +} + +/* Determine whether the remote target supports binary downloading. + This is accomplished by sending a no-op memory write of zero length + to the target at the specified address. It does not suffice to send + the whole packet, since many stubs strip the eighth bit and subsequently + compute a wrong checksum, which causes real havoc with remote_write_bytes. + + NOTE: This can still lose if the serial line is not eight-bit clean. In + cases like this, the user should clear "remotebinarydownload". */ +static void +check_binary_download (CORE_ADDR addr) +{ + if (remote_binary_download && !remote_binary_checked) + { + char *buf = alloca (PBUFSIZ); + char *p; + remote_binary_checked = 1; + + p = buf; + *p++ = 'X'; + p += hexnumstr (p, (ULONGEST) addr); + *p++ = ','; + p += hexnumstr (p, (ULONGEST) 0); + *p++ = ':'; + *p = '\0'; + + putpkt_binary (buf, (int) (p - buf)); + getpkt (buf, 0); + + if (buf[0] == '\0') + remote_binary_download = 0; + } + + if (remote_debug) + { + if (remote_binary_download) + fprintf_unfiltered (gdb_stdlog, + "binary downloading suppported by target\n"); + else + fprintf_unfiltered (gdb_stdlog, + "binary downloading NOT suppported by target\n"); + } +} + +/* Write memory data directly to the remote machine. + This does not inform the data cache; the data cache uses this. + MEMADDR is the address in the remote memory space. + MYADDR is the address of the buffer in our space. + LEN is the number of bytes. + + Returns number of bytes transferred, or 0 for error. */ + +int +remote_write_bytes (memaddr, myaddr, len) + CORE_ADDR memaddr; + char *myaddr; + int len; +{ + unsigned char *buf = alloca (PBUFSIZ); + int max_buf_size; /* Max size of packet output buffer */ + int origlen; + extern int verbose; + + /* Verify that the target can support a binary download */ + check_binary_download (memaddr); + + /* Chop the transfer down if necessary */ + + max_buf_size = min (remote_write_size, PBUFSIZ); + if (remote_register_buf_size != 0) + max_buf_size = min (max_buf_size, remote_register_buf_size); + + /* Subtract header overhead from max payload size - $M<memaddr>,<len>:#nn */ + max_buf_size -= 2 + hexnumlen (memaddr + len - 1) + 1 + hexnumlen (len) + 4; + + origlen = len; + while (len > 0) + { + unsigned char *p, *plen; + int todo; + int i; + + /* construct "M"<memaddr>","<len>":" */ + /* sprintf (buf, "M%lx,%x:", (unsigned long) memaddr, todo); */ + memaddr = remote_address_masked (memaddr); + p = buf; + if (remote_binary_download) + { + *p++ = 'X'; + todo = min (len, max_buf_size); + } + else + { + *p++ = 'M'; + todo = min (len, max_buf_size / 2); /* num bytes that will fit */ + } + + p += hexnumstr ((char *)p, (ULONGEST) memaddr); + *p++ = ','; + + plen = p; /* remember where len field goes */ + p += hexnumstr ((char *)p, (ULONGEST) todo); + *p++ = ':'; + *p = '\0'; + + /* We send target system values byte by byte, in increasing byte + addresses, each byte encoded as two hex characters (or one + binary character). */ + if (remote_binary_download) + { + int escaped = 0; + for (i = 0; + (i < todo) && (i + escaped) < (max_buf_size - 2); + i++) + { + switch (myaddr[i] & 0xff) + { + case '$': + case '#': + case 0x7d: + /* These must be escaped */ + escaped++; + *p++ = 0x7d; + *p++ = (myaddr[i] & 0xff) ^ 0x20; + break; + default: + *p++ = myaddr[i] & 0xff; + break; + } + } + + if (i < todo) + { + /* Escape chars have filled up the buffer prematurely, + and we have actually sent fewer bytes than planned. + Fix-up the length field of the packet. */ + + /* FIXME: will fail if new len is a shorter string than + old len. */ + + plen += hexnumstr ((char *)plen, (ULONGEST) i); + *plen++ = ':'; + } + } + else + { + for (i = 0; i < todo; i++) + { + *p++ = tohex ((myaddr[i] >> 4) & 0xf); + *p++ = tohex (myaddr[i] & 0xf); + } + *p = '\0'; + } + + putpkt_binary ((char *)buf, (int) (p - buf)); + getpkt ((char *)buf, 0); + + if (buf[0] == 'E') + { + /* There is no correspondance between what the remote protocol uses + for errors and errno codes. We would like a cleaner way of + representing errors (big enough to include errno codes, bfd_error + codes, and others). But for now just return EIO. */ + errno = EIO; + return 0; + } + + /* Increment by i, not by todo, in case escape chars + caused us to send fewer bytes than we'd planned. */ + myaddr += i; + memaddr += i; + len -= i; + + if (verbose) + putc('.', stderr); + } + return origlen; +} + +/* Stuff for dealing with the packets which are part of this protocol. + See comment at top of file for details. */ + +/* Read a single character from the remote end, masking it down to 7 bits. */ + +static int +readchar (int timeout) +{ + int ch; + + ch = SERIAL_READCHAR (remote_desc, timeout); + + switch (ch) + { + case SERIAL_EOF: + error ("Remote connection closed"); + case SERIAL_ERROR: + perror_with_name ("Remote communication error"); + case SERIAL_TIMEOUT: + return ch; + default: + return ch & 0x7f; + } +} + +static int +putpkt (buf) + char *buf; +{ + return putpkt_binary (buf, strlen (buf)); +} + +/* Send a packet to the remote machine, with error checking. The data + of the packet is in BUF. The string in BUF can be at most PBUFSIZ - 5 + to account for the $, # and checksum, and for a possible /0 if we are + debugging (remote_debug) and want to print the sent packet as a string */ + +static int +putpkt_binary (buf, cnt) + char *buf; + int cnt; +{ + int i; + unsigned char csum = 0; + char *buf2 = alloca (PBUFSIZ); + char *junkbuf = alloca (PBUFSIZ); + + int ch; + int tcount = 0; + char *p; + + /* Copy the packet into buffer BUF2, encapsulating it + and giving it a checksum. */ + + if (cnt > BUFSIZ - 5) /* Prosanity check */ + abort (); + + p = buf2; + *p++ = '$'; + + for (i = 0; i < cnt; i++) + { + csum += buf[i]; + *p++ = buf[i]; + } + *p++ = '#'; + *p++ = tohex ((csum >> 4) & 0xf); + *p++ = tohex (csum & 0xf); + + /* Send it over and over until we get a positive ack. */ + + while (1) + { + int started_error_output = 0; + + if (remote_debug) + { + *p = '\0'; + fprintf_unfiltered (gdb_stdlog, "Sending packet: "); + fputstrn_unfiltered (buf2, p - buf2, 0, gdb_stdlog); + fprintf_unfiltered (gdb_stdlog, "..."); + gdb_flush (gdb_stdlog); + } + if (SERIAL_WRITE (remote_desc, buf2, p - buf2)) + perror_with_name ("putpkt: write failed"); + + /* read until either a timeout occurs (-2) or '+' is read */ + while (1) + { + ch = readchar (remote_timeout); + + if (remote_debug) + { + switch (ch) + { + case '+': + case SERIAL_TIMEOUT: + case '$': + if (started_error_output) + { + putchar_unfiltered ('\n'); + started_error_output = 0; + } + } + } + + switch (ch) + { + case '+': + if (remote_debug) + fprintf_unfiltered (gdb_stdlog, "Ack\n"); + return 1; + case SERIAL_TIMEOUT: + tcount++; + if (tcount > 3) + return 0; + break; /* Retransmit buffer */ + case '$': + { + /* It's probably an old response, and we're out of sync. + Just gobble up the packet and ignore it. */ + getpkt (junkbuf, 0); + continue; /* Now, go look for + */ + } + default: + if (remote_debug) + { + if (!started_error_output) + { + started_error_output = 1; + fprintf_unfiltered (gdb_stdlog, "putpkt: Junk: "); + } + fputc_unfiltered (ch & 0177, gdb_stdlog); + } + continue; + } + break; /* Here to retransmit */ + } + +#if 0 + /* This is wrong. If doing a long backtrace, the user should be + able to get out next time we call QUIT, without anything as + violent as interrupt_query. If we want to provide a way out of + here without getting to the next QUIT, it should be based on + hitting ^C twice as in remote_wait. */ + if (quit_flag) + { + quit_flag = 0; + interrupt_query (); + } +#endif + } +} + +/* Come here after finding the start of the frame. Collect the rest + into BUF, verifying the checksum, length, and handling run-length + compression. Returns 0 on any error, 1 on success. */ + +static int +read_frame (char *buf) +{ + unsigned char csum; + char *bp; + int c; + + csum = 0; + bp = buf; + + while (1) + { + c = readchar (remote_timeout); + + switch (c) + { + case SERIAL_TIMEOUT: + if (remote_debug) + fputs_filtered ("Timeout in mid-packet, retrying\n", gdb_stdlog); + return 0; + case '$': + if (remote_debug) + fputs_filtered ("Saw new packet start in middle of old one\n", + gdb_stdlog); + return 0; /* Start a new packet, count retries */ + case '#': + { + unsigned char pktcsum; + + *bp = '\000'; + + pktcsum = fromhex (readchar (remote_timeout)) << 4; + pktcsum |= fromhex (readchar (remote_timeout)); + + if (csum == pktcsum) + { + return 1; + } + + if (remote_debug) + { + fprintf_filtered (gdb_stdlog, + "Bad checksum, sentsum=0x%x, csum=0x%x, buf=", + pktcsum, csum); + fputs_filtered (buf, gdb_stdlog); + fputs_filtered ("\n", gdb_stdlog); + } + return 0; + } + case '*': /* Run length encoding */ + csum += c; + c = readchar (remote_timeout); + csum += c; + c = c - ' ' + 3; /* Compute repeat count */ + + if (c > 0 && c < 255 && bp + c - 1 < buf + PBUFSIZ - 1) + { + memset (bp, *(bp - 1), c); + bp += c; + continue; + } + + *bp = '\0'; + printf_filtered ("Repeat count %d too large for buffer: ", c); + puts_filtered (buf); + puts_filtered ("\n"); + return 0; + default: + if (bp < buf + PBUFSIZ - 1) + { + *bp++ = c; + csum += c; + continue; + } + + *bp = '\0'; + puts_filtered ("Remote packet too long: "); + puts_filtered (buf); + puts_filtered ("\n"); + + return 0; + } + } +} + +/* Read a packet from the remote machine, with error checking, and + store it in BUF. BUF is expected to be of size PBUFSIZ. If + FOREVER, wait forever rather than timing out; this is used while + the target is executing user code. */ + +static void +getpkt (buf, forever) + char *buf; + int forever; +{ + int c; + int tries; + int timeout; + int val; + + strcpy (buf, "timeout"); + + if (forever) + { + timeout = watchdog > 0 ? watchdog : -1; + } + + else + timeout = remote_timeout; + +#define MAX_TRIES 3 + + for (tries = 1; tries <= MAX_TRIES; tries++) + { + /* This can loop forever if the remote side sends us characters + continuously, but if it pauses, we'll get a zero from readchar + because of timeout. Then we'll count that as a retry. */ + + /* Note that we will only wait forever prior to the start of a packet. + After that, we expect characters to arrive at a brisk pace. They + should show up within remote_timeout intervals. */ + + do + { + c = readchar (timeout); + + if (c == SERIAL_TIMEOUT) + { + if (forever) /* Watchdog went off. Kill the target. */ + { + target_mourn_inferior (); + error ("Watchdog has expired. Target detached.\n"); + } + if (remote_debug) + fputs_filtered ("Timed out.\n", gdb_stdlog); + goto retry; + } + } + while (c != '$'); + + /* We've found the start of a packet, now collect the data. */ + + val = read_frame (buf); + + if (val == 1) + { + if (remote_debug) + { + fprintf_unfiltered (gdb_stdlog, "Packet received: "); + fputstr_unfiltered (buf, 0, gdb_stdlog); + fprintf_unfiltered (gdb_stdlog, "\n"); + } + SERIAL_WRITE (remote_desc, "+", 1); + return; + } + + /* Try the whole thing again. */ + retry: + SERIAL_WRITE (remote_desc, "-", 1); + } + + /* We have tried hard enough, and just can't receive the packet. Give up. */ + + printf_unfiltered ("Ignoring packet error, continuing...\n"); + SERIAL_WRITE (remote_desc, "+", 1); +} diff --git a/u-boot/tools/gdb/remote.h b/u-boot/tools/gdb/remote.h new file mode 100644 index 0000000..f14dacb --- /dev/null +++ b/u-boot/tools/gdb/remote.h @@ -0,0 +1,28 @@ +/* + * (C) Copyright 2000 + * Murray Jensen <Murray.Jensen@csiro.au> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +extern int remote_desc, remote_timeout; + +extern void remote_reset(void); +extern void remote_continue(void); +extern int remote_write_bytes(unsigned long, char *, int); diff --git a/u-boot/tools/gdb/serial.c b/u-boot/tools/gdb/serial.c new file mode 100644 index 0000000..2f2e529 --- /dev/null +++ b/u-boot/tools/gdb/serial.c @@ -0,0 +1,149 @@ +/* + * (C) Copyright 2000 + * Murray Jensen <Murray.Jensen@csiro.au> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <sys/time.h> +#include "serial.h" + +#if defined(__sun__) || \ + defined(__OpenBSD__) || \ + defined(__FreeBSD__) || \ + defined(__NetBSD__) || \ + defined(__APPLE__) +static struct termios tios = { BRKINT, 0, B115200|CS8|CREAD, 0, { 0 } }; +#else +static struct termios tios = { BRKINT, 0, B115200|CS8|CREAD, 0, 0 }; +#endif + +static struct speedmap { + char *str; + speed_t val; +} speedmap[] = { + { "50", B50 }, { "75", B75 }, { "110", B110 }, + { "134", B134 }, { "150", B150 }, { "200", B200 }, + { "300", B300 }, { "600", B600 }, { "1200", B1200 }, + { "1800", B1800 }, { "2400", B2400 }, { "4800", B4800 }, + { "9600", B9600 }, { "19200", B19200 }, { "38400", B38400 }, + { "57600", B57600 }, +#ifdef B76800 + { "76800", B76800 }, +#endif + { "115200", B115200 }, +#ifdef B153600 + { "153600", B153600 }, +#endif + { "230400", B230400 }, +#ifdef B307200 + { "307200", B307200 }, +#endif +#ifdef B460800 + { "460800", B460800 } +#endif +}; +static int nspeeds = sizeof speedmap / sizeof speedmap[0]; + +speed_t +cvtspeed(char *str) +{ + struct speedmap *smp = speedmap, *esmp = &speedmap[nspeeds]; + + while (smp < esmp) { + if (strcmp(str, smp->str) == 0) + return (smp->val); + smp++; + } + return B0; +} + +int +serialopen(char *device, speed_t speed) +{ + int fd; + + if (cfsetospeed(&tios, speed) < 0) + return -1; + + if ((fd = open(device, O_RDWR)) < 0) + return -1; + + if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) { + (void)close(fd); + return -1; + } + + return fd; +} + +int +serialreadchar(int fd, int timeout) +{ + fd_set fds; + struct timeval tv; + int n; + char ch; + + tv.tv_sec = timeout; + tv.tv_usec = 0; + + FD_ZERO(&fds); + FD_SET(fd, &fds); + + /* this is a fucking horrible quick hack - fix this */ + + if ((n = select(fd + 1, &fds, 0, 0, &tv)) < 0) + return SERIAL_ERROR; + + if (n == 0) + return SERIAL_TIMEOUT; + + if ((n = read(fd, &ch, 1)) < 0) + return SERIAL_ERROR; + + if (n == 0) + return SERIAL_EOF; + + return ch; +} + +int +serialwrite(int fd, char *buf, int len) +{ + int n; + + do { + n = write(fd, buf, len); + if (n < 0) + return 1; + len -= n; + buf += n; + } while (len > 0); + return 0; +} + +int +serialclose(int fd) +{ + return close(fd); +} diff --git a/u-boot/tools/gdb/serial.h b/u-boot/tools/gdb/serial.h new file mode 100644 index 0000000..3ed509e --- /dev/null +++ b/u-boot/tools/gdb/serial.h @@ -0,0 +1,34 @@ +/* + * (C) Copyright 2000 + * Murray Jensen <Murray.Jensen@csiro.au> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <termios.h> + +#define SERIAL_ERROR -1 /* General error, see errno for details */ +#define SERIAL_TIMEOUT -2 +#define SERIAL_EOF -3 + +extern speed_t cvtspeed(char *); +extern int serialopen(char *, speed_t); +extern int serialreadchar(int, int); +extern int serialwrite(int, char *, int); +extern int serialclose(int); diff --git a/u-boot/tools/gen_eth_addr.c b/u-boot/tools/gen_eth_addr.c new file mode 100644 index 0000000..429b20d --- /dev/null +++ b/u-boot/tools/gen_eth_addr.c @@ -0,0 +1,50 @@ +/* + * (C) Copyright 2001 + * Murray Jensen <Murray.Jensen@cmst.csiro.au> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <time.h> + +int +main(int argc, char *argv[]) +{ + unsigned long ethaddr_low, ethaddr_high; + + srand(time(0) | getpid()); + + /* + * setting the 2nd LSB in the most significant byte of + * the address makes it a locally administered ethernet + * address + */ + ethaddr_high = (rand() & 0xfeff) | 0x0200; + ethaddr_low = rand(); + + printf("%02lx:%02lx:%02lx:%02lx:%02lx:%02lx\n", + ethaddr_high >> 8, ethaddr_high & 0xff, + ethaddr_low >> 24, (ethaddr_low >> 16) & 0xff, + (ethaddr_low >> 8) & 0xff, ethaddr_low & 0xff); + + return (0); +} diff --git a/u-boot/tools/getline.c b/u-boot/tools/getline.c new file mode 100644 index 0000000..3ba52a3 --- /dev/null +++ b/u-boot/tools/getline.c @@ -0,0 +1,101 @@ +/* getline.c -- Replacement for GNU C library function getline + +Copyright (C) 1993, 1996, 2001, 2002 Free Software Foundation, Inc. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as +published by the Free Software Foundation; either version 2 of the +License, or (at your option) any later version. + +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 GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Jan Brittenson, bson@gnu.ai.mit.edu. */ + +#include <assert.h> +#include <stdio.h> + +/* Always add at least this many bytes when extending the buffer. */ +#define MIN_CHUNK 64 + +/* Read up to (and including) a TERMINATOR from STREAM into *LINEPTR + + OFFSET (and null-terminate it). *LINEPTR is a pointer returned from + malloc (or NULL), pointing to *N characters of space. It is realloc'd + as necessary. Return the number of characters read (not including the + null terminator), or -1 on error or EOF. + NOTE: There is another getstr() function declared in <curses.h>. */ +static int getstr(char **lineptr, size_t *n, FILE *stream, + char terminator, size_t offset) +{ + int nchars_avail; /* Allocated but unused chars in *LINEPTR. */ + char *read_pos; /* Where we're reading into *LINEPTR. */ + int ret; + + if (!lineptr || !n || !stream) + return -1; + + if (!*lineptr) { + *n = MIN_CHUNK; + *lineptr = malloc(*n); + if (!*lineptr) + return -1; + } + + nchars_avail = *n - offset; + read_pos = *lineptr + offset; + + for (;;) { + register int c = getc(stream); + + /* We always want at least one char left in the buffer, since we + always (unless we get an error while reading the first char) + NUL-terminate the line buffer. */ + + assert(*n - nchars_avail == read_pos - *lineptr); + if (nchars_avail < 2) { + if (*n > MIN_CHUNK) + *n *= 2; + else + *n += MIN_CHUNK; + + nchars_avail = *n + *lineptr - read_pos; + *lineptr = realloc(*lineptr, *n); + if (!*lineptr) + return -1; + read_pos = *n - nchars_avail + *lineptr; + assert(*n - nchars_avail == read_pos - *lineptr); + } + + if (c == EOF || ferror (stream)) { + /* Return partial line, if any. */ + if (read_pos == *lineptr) + return -1; + else + break; + } + + *read_pos++ = c; + nchars_avail--; + + if (c == terminator) + /* Return the line. */ + break; + } + + /* Done - NUL terminate and return the number of chars read. */ + *read_pos = '\0'; + + ret = read_pos - (*lineptr + offset); + return ret; +} + +int getline (char **lineptr, size_t *n, FILE *stream) +{ + return getstr(lineptr, n, stream, '\n', 0); +} diff --git a/u-boot/tools/getline.h b/u-boot/tools/getline.h new file mode 100644 index 0000000..a2f35b9 --- /dev/null +++ b/u-boot/tools/getline.h @@ -0,0 +1 @@ +int getline(char **lineptr, size_t *n, FILE *stream); diff --git a/u-boot/tools/img2brec.sh b/u-boot/tools/img2brec.sh new file mode 100755 index 0000000..0fcdba2 --- /dev/null +++ b/u-boot/tools/img2brec.sh @@ -0,0 +1,388 @@ +#!/bin/sh + +# This script converts binary files (u-boot.bin) into so called +# bootstrap records that are accepted by Motorola's MC9328MX1/L +# (a.k.a. DragaonBall i.MX) in "Bootstrap Mode" +# +# The code for the SynchFlash programming routines is taken from +# Bootloader\Bin\SyncFlash\programBoot_b.txt contained in +# Motorolas LINUX_BSP_0_3_8.tar.gz +# +# The script could easily extended for AMD flash routines. +# +# 2004-06-23 - steven.scholz@imc-berlin.de + +################################################################################# +# From the posting to the U-Boot-Users mailing list, 23 Jun 2004: +# =============================================================== +# I just hacked a simple script that converts u-boot.bin into a text file +# containg processor init code, SynchFlash programming code and U-Boot data in +# form of so called b-records. +# +# This can be used to programm U-Boot into (Synch)Flash using the Bootstrap +# Mode of the MC9328MX1/L +# +# 0AFE1F3410202E2E2E000000002073756363656564/ +# 0AFE1F44102E0A0000206661696C656420210A0000/ +# 0AFE100000 +# ... +# MX1ADS Sync-flash Programming Utility v0.5 2002/08/21 +# +# Source address (stored in 0x0AFE0000): 0x0A000000 +# Target address (stored in 0x0AFE0004): 0x0C000000 +# Size (stored in 0x0AFE0008): 0x0001A320 +# +# Press any key to start programming ... +# Erasing ... +# Blank checking ... +# Programming ... +# Verifying flash ... succeed. +# +# Programming finished. +# +# So no need for a BDI2000 anymore... ;-) +# +# This is working on my MX1ADS eval board. Hope this could be useful for +# someone. +################################################################################# + +if [ "$#" -lt 1 -o "$#" -gt 2 ] ; then + echo "Usage: $0 infile [outfile]" >&2 + echo " $0 u-boot.bin [u-boot.brec]" >&2 + exit 1 +fi + +if [ "$#" -ge 1 ] ; then + INFILE=$1 +fi + +if [ ! -f $INFILE ] ; then + echo "Error: file '$INFILE' does not exist." >&2 + exit 1 +fi + +FILESIZE=`filesize $INFILE` + +output_init() +{ +echo "\ +********************************************
+* Initialize I/O Pad Driving Strength *
+********************************************
+0021B80CC4000003AB
+********************************************
+* Initialize SDRAM *
+********************************************
+00221000C492120200 ; pre-charge command
+08200000E4 ; special read
+
+00221000C4A2120200 ; auto-refresh command
+08000000E4 ; 8 special read
+08000000E4 ; 8 special read
+08000000E4 ; 8 special read
+08000000E4 ; 8 special read
+08000000E4 ; 8 special read
+08000000E4 ; 8 special read
+08000000E4 ; 8 special read
+08000000E4 ; 8 special read
+
+00221000C4B2120200 ; set mode register
+08111800E4 ; special read
+
+00221000C482124200 ; set normal mode
+
" +} + +output_uboot() +{ +echo "\ +********************************************
+* U-Boot image as bootstrap records *
+* will be stored in SDRAM at 0x0A000000 *
+********************************************
+
" + +cat $INFILE | \ +hexdump -v -e "\"0A0%05.5_ax10\" 16/1 \"%02x\"\"\r\n\"" | \ +tr [:lower:] [:upper:] +} + +output_flashprog() +{ +echo "\ +********************************************
+* Address of arguments to flashProg *
+* ---------------------------------------- *
+* Source : 0x0A000000 *
+* Destination : 0x0C000000 *
" + +# get the real size of the U-Boot image +printf "* Size : 0x%08X *\r\n" $FILESIZE +printf "********************************************\r\n" +printf "0AFE0000CC0A0000000C000000%08X\r\n" $FILESIZE + +#;0AFE0000CC0A0000000C00000000006000
+ +echo "\ +********************************************
+* Flash Program *
+********************************************
+0AFE10001008D09FE5AC0000EA00F0A0E1A42DFE0A
+0AFE1010100080FE0A0DC0A0E100D82DE904B04CE2
+0AFE1020109820A0E318309FE5003093E5033082E0
+0AFE103010003093E5013003E2FF3003E20300A0E1
+0AFE10401000A81BE9A01DFE0A0DC0A0E100D82DE9
+0AFE10501004B04CE204D04DE20030A0E10D304BE5
+0AFE1060109820A0E330309FE5003093E5033082E0
+0AFE107010003093E5013903E2000053E3F7FFFF0A
+0AFE1080104020A0E310309FE5003093E5032082E0
+0AFE1090100D305BE5003082E500A81BE9A01DFE0A
+0AFE10A0100DC0A0E100D82DE904B04CE20000A0E1
+0AFE10B010D7FFFFEB0030A0E1FF3003E2000053E3
+0AFE10C010FAFFFF0A10309FE5003093E5003093E5
+0AFE10D010FF3003E20300A0E100A81BE9A01DFE0A
+0AFE10E0100DC0A0E100D82DE904B04CE204D04DE2
+0AFE10F0100030A0E10D304BE50D305BE52332A0E1
+0AFE1100100E304BE50E305BE5090053E30300009A
+0AFE1110100E305BE5373083E20E304BE5020000EA
+0AFE1120100E305BE5303083E20E304BE50E305BE5
+0AFE1130100300A0E1C3FFFFEB0D305BE50F3003E2
+0AFE1140100E304BE50E305BE5090053E30300009A
+0AFE1150100E305BE5373083E20E304BE5020000EA
+0AFE1160100E305BE5303083E20E304BE50E305BE5
+0AFE1170100300A0E1B3FFFFEB00A81BE90DC0A0E1
+0AFE11801000D82DE904B04CE21CD04DE210000BE5
+0AFE11901014100BE518200BE588009FE5E50200EB
+0AFE11A01010301BE51C300BE514301BE520300BE5
+0AFE11B0100030A0E324300BE524201BE518301BE5
+0AFE11C010030052E10000003A120000EA1C004BE2
+0AFE11D010002090E520104BE2003091E500C093E5
+0AFE11E010043083E2003081E5003092E5042082E2
+0AFE11F010002080E50C0053E10200000A0030A0E3
+0AFE12001028300BE5050000EA24301BE5043083E2
+0AFE12101024300BE5E7FFFFEA0130A0E328300BE5
+0AFE12201028001BE500A81BE9E81EFE0A0DC0A0E1
+0AFE12301000D82DE904B04CE214D04DE210000BE5
+0AFE12401014100BE56C009FE5BA0200EB10301BE5
+0AFE12501018300BE50030A0E31C300BE51C201BE5
+0AFE12601014301BE5030052E10000003A0D0000EA
+0AFE12701018304BE2002093E5001092E5042082E2
+0AFE128010002083E5010071E30200000A0030A0E3
+0AFE12901020300BE5050000EA1C301BE5043083E2
+0AFE12A0101C300BE5ECFFFFEA0130A0E320300BE5
+0AFE12B01020001BE500A81BE9001FFE0A0DC0A0E1
+0AFE12C01000D82DE904B04CE224D04DE20130A0E3
+0AFE12D01024300BE5A4229FE58139A0E3023A83E2
+0AFE12E010003082E59820A0E390329FE5003093E5
+0AFE12F010033082E0003093E5023903E2000053E3
+0AFE1300100300001A74229FE58139A0E3033A83E2
+0AFE131010003082E568029FE5860200EBAF36A0E3
+0AFE1320100E3883E2003093E510300BE554029FE5
+0AFE133010800200EB10301BE5233CA0E1FF3003E2
+0AFE1340100300A0E165FFFFEB10301BE52338A0E1
+0AFE135010FF3003E20300A0E160FFFFEB10301BE5
+0AFE1360102334A0E1FF3003E20300A0E15BFFFFEB
+0AFE13701010305BE50300A0E158FFFFEB0A00A0E3
+0AFE13801030FFFFEB0D00A0E32EFFFFEBAF36A0E3
+0AFE1390100E3883E2043083E2003093E514300BE5
+0AFE13A010E4019FE5630200EB14301BE5233CA0E1
+0AFE13B010FF3003E20300A0E148FFFFEB14301BE5
+0AFE13C0102338A0E1FF3003E20300A0E143FFFFEB
+0AFE13D01014301BE52334A0E1FF3003E20300A0E1
+0AFE13E0103EFFFFEB14305BE50300A0E13BFFFFEB
+0AFE13F0100A00A0E313FFFFEB0D00A0E311FFFFEB
+0AFE140010AF36A0E30E3883E2083083E2003093E5
+0AFE14101018300BE574019FE5460200EB18301BE5
+0AFE142010233CA0E1FF3003E20300A0E12BFFFFEB
+0AFE14301018301BE52338A0E1FF3003E20300A0E1
+0AFE14401026FFFFEB18301BE52334A0E1FF3003E2
+0AFE1450100300A0E121FFFFEB18305BE50300A0E1
+0AFE1460101EFFFFEB0A00A0E3F6FEFFEB0D00A0E3
+0AFE147010F4FEFFEBE6FEFFEB0030A0E1FF3003E2
+0AFE148010000053E30000001A020000EA03FFFFEB
+0AFE1490102D004BE5F6FFFFEAF4009FE5250200EB
+0AFE14A010FEFEFFEB2D004BE5CD0000EBC00000EB
+0AFE14B010E0009FE51F0200EB18301BE528300BE5
+0AFE14C01014301BE52C300BE52C001BE5100100EB
+0AFE14D01028301BE5013643E228300BE52C301BE5
+0AFE14E010013683E22C300BE528301BE5000053E3
+0AFE14F010F4FFFFCAAE0000EB14001BE518101BE5
+0AFE15001049FFFFEB0030A0E1FF3003E2000053E3
+0AFE151010E6FFFF0A80009FE5060200EB10001BE5
+0AFE15201014101BE518201BE5D00000EB10001BE5
+0AFE15301014101BE518201BE50FFFFFEB0030A0E1
+0AFE154010FF3003E2000053E30200000A4C009FE5
+0AFE155010F80100EB010000EA44009FE5F50100EB
+0AFE156010930000EB3C009FE5F20100EB0000A0E3
+0AFE157010A4FEFFEB0030A0E30300A0E100A81BE9
+0AFE158010A01DFE0AA41DFE0AE01DFE0A0C1EFE0A
+0AFE159010381EFE0A641EFE0A181FFE0A281FFE0A
+0AFE15A0103C1FFE0A481FFE0AB41EFE0A0DC0A0E1
+0AFE15B01000D82DE904B04CE204D04DE210000BE5
+0AFE15C01010301BE5013043E210300BE5010073E3
+0AFE15D010FAFFFF1A00A81BE90DC0A0E100D82DE9
+0AFE15E01004B04CE208D04DE210000BE510301BE5
+0AFE15F01014300BE514301BE50300A0E100A81BE9
+0AFE1600100DC0A0E100D82DE904B04CE204D04DE2
+0AFE1610102228A0E3012A82E2042082E2E134A0E3
+0AFE162010023883E2033C83E2003082E50333A0E3
+0AFE163010053983E2003093E510300BE500A81BE9
+0AFE1640100DC0A0E100D82DE904B04CE204D04DE2
+0AFE1650102228A0E3012A82E2042082E29134A0E3
+0AFE166010023883E2033C83E2003082E5C136A0E3
+0AFE167010003093E510300BE52228A0E3012A82E2
+0AFE168010042082E2E134A0E3023883E2033C83E2
+0AFE169010003082E50333A0E3073983E20020A0E3
+0AFE16A010002083E52228A0E3012A82E2042082E2
+0AFE16B0108134A0E3023883E2033C83E2003082E5
+0AFE16C0100333A0E3003093E510300BE5CBFFFFEB
+0AFE16D01010301BE50300A0E100A81BE90DC0A0E1
+0AFE16E01000D82DE904B04CE208D04DE2D3FFFFEB
+0AFE16F0100030A0E110300BE510301BE5023503E2
+0AFE170010000053E30500000A10301BE5073703E2
+0AFE171010000053E30100000A10001BE5ADFFFFEB
+0AFE17201010301BE5803003E2000053E30500000A
+0AFE17301010301BE51C3003E2000053E30100000A
+0AFE17401010001BE5A3FFFFEB10201BE50235A0E3
+0AFE175010803083E2030052E10200001A0130A0E3
+0AFE17601014300BE5010000EA0030A0E314300BE5
+0AFE17701014001BE500A81BE90DC0A0E100D82DE9
+0AFE17801004B04CE204D04DE22228A0E3012A82E2
+0AFE179010042082E29134A0E3023883E2033C83E2
+0AFE17A010003082E5C136A0E3003093E510300BE5
+0AFE17B01000A81BE90DC0A0E100D82DE904B04CE2
+0AFE17C010ECFFFFEB2228A0E3012A82E2042082E2
+0AFE17D0108134A0E3023883E2033C83E2003082E5
+0AFE17E01000A81BE90DC0A0E100D82DE904B04CE2
+0AFE17F01004D04DE22228A0E3012A82E2042082E2
+0AFE1800102238A0E3013A83E2043083E2003093E5
+0AFE181010023183E3003082E52228A0E3012A82E2
+0AFE1820102238A0E3013A83E2003093E5023183E3
+0AFE183010003082E5FA0FA0E35BFFFFEB2228A0E3
+0AFE184010012A82E2042082E2B134A0E3023883E2
+0AFE185010033C83E2003082E50333A0E3233983E2
+0AFE186010033B83E2003093E510300BE500A81BE9
+0AFE1870100DC0A0E100D82DE904B04CE21CD04DE2
+0AFE18801010000BE514100BE518200BE50030A0E3
+0AFE1890101C300BE51C201BE518301BE5030052E1
+0AFE18A0100000003A190000EAB2FFFFEB2228A0E3
+0AFE18B010012A82E2042082E2F134A0E3023883E2
+0AFE18C010033C83E2003082E514201BE51C301BE5
+0AFE18D010031082E010201BE51C301BE5033082E0
+0AFE18E010003093E5003081E57BFFFFEB0030A0E1
+0AFE18F010FF3003E2000053E3FAFFFF0AACFFFFEB
+0AFE1900101C301BE5043083E21C300BE5E0FFFFEA
+0AFE19101000A81BE90DC0A0E100D82DE904B04CE2
+0AFE1920100CD04DE210000BE52228A0E3012A82E2
+0AFE193010042082E28134A0E3023883E2033C83E2
+0AFE194010003082E510301BE5003093E514300BE5
+0AFE1950102228A0E3012A82E2042082E29134A0E3
+0AFE196010023883E2033C83E2003082E510301BE5
+0AFE197010003093E518300BE52228A0E3012A82E2
+0AFE198010042082E2E134A0E3023883E2033C83E2
+0AFE199010003082E50229A0E310301BE5032082E0
+0AFE19A0100030A0E3003082E52228A0E3012A82E2
+0AFE19B010042082E28134A0E3023883E2033C83E2
+0AFE19C010003082E510201BE50D3AA0E3D03083E2
+0AFE19D010033883E1003082E53FFFFFEB0030A0E1
+0AFE19E010FF3003E2000053E3FAFFFF0A70FFFFEB
+0AFE19F01000A81BE90DC0A0E100D82DE904B04CE2
+0AFE1A00105CFFFFEB2228A0E3012A82E2042082E2
+0AFE1A1010E134A0E3023883E2033C83E2003082E5
+0AFE1A20100333A0E3033983E20020A0E3002083E5
+0AFE1A30102228A0E3012A82E2042082E28134A0E3
+0AFE1A4010023883E2033C83E2003082E50323A0E3
+0AFE1A5010032982E20339A0E3C03083E2033883E1
+0AFE1A6010003082E500A81BE90DC0A0E100D82DE9
+0AFE1A701004B04CE23FFFFFEB2228A0E3012A82E2
+0AFE1A8010042082E2E134A0E3023883E2033C83E2
+0AFE1A9010003082E50333A0E30A3983E20020A0E3
+0AFE1AA010002083E52228A0E3012A82E2042082E2
+0AFE1AB0108134A0E3023883E2033C83E2003082E5
+0AFE1AC0100323A0E30A2982E20339A0E3C03083E2
+0AFE1AD010033883E1003082E500A81BE90DC0A0E1
+0AFE1AE01000D82DE904B04CE28729A0E3222E82E2
+0AFE1AF0108739A0E3223E83E2003093E51E3CC3E3
+0AFE1B0010003082E58729A0E38E2F82E28739A0E3
+0AFE1B10108E3F83E2003093E51E3CC3E3003082E5
+0AFE1B20108139A0E3823D83E20520A0E3002083E5
+0AFE1B30108129A0E3822D82E2042082E20139A0E3
+0AFE1B4010273083E2003082E58139A0E3823D83E2
+0AFE1B50100C3083E20120A0E3002083E58129A0E3
+0AFE1B6010822D82E2102082E22A3DA0E3013083E2
+0AFE1B7010003082E58139A0E3823D83E2243083E2
+0AFE1B80100F20A0E3002083E58139A0E3823D83E2
+0AFE1B9010283083E28A20A0E3002083E58139A0E3
+0AFE1BA010823D83E22C3083E20820A0E3002083E5
+0AFE1BB01000A81BE90DC0A0E100D82DE904B04CE2
+0AFE1BC0108139A0E3823D83E2183083E2003093E5
+0AFE1BD010013003E2FF3003E20300A0E100A81BE9
+0AFE1BE0100DC0A0E100D82DE904B04CE204D04DE2
+0AFE1BF0100030A0E10D304BE58139A0E3823D83E2
+0AFE1C0010183083E2003093E5013903E2000053E3
+0AFE1C1010F8FFFF0A8139A0E3813D83E20D205BE5
+0AFE1C2010002083E50D305BE50A0053E30A00001A
+0AFE1C30108139A0E3823D83E2183083E2003093E5
+0AFE1C4010013903E2000053E3F8FFFF0A8139A0E3
+0AFE1C5010813D83E20D20A0E3002083E500A81BE9
+0AFE1C60100DC0A0E100D82DE904B04CE20000A0E1
+0AFE1C7010CFFFFFEB0030A0E1FF3003E2000053E3
+0AFE1C8010FAFFFF0A8139A0E3023A83E2003093E5
+0AFE1C9010FF3003E20300A0E100A81BE90DC0A0E1
+0AFE1CA01000D82DE904B04CE204D04DE20030A0E1
+0AFE1CB0100D304BE50D305BE52332A0E10E304BE5
+0AFE1CC0100E305BE5090053E30300009A0E305BE5
+0AFE1CD010373083E20E304BE5020000EA0E305BE5
+0AFE1CE010303083E20E304BE50E305BE50300A0E1
+0AFE1CF010BAFFFFEB0D305BE50F3003E20E304BE5
+0AFE1D00100E305BE5090053E30300009A0E305BE5
+0AFE1D1010373083E20E304BE5020000EA0E305BE5
+0AFE1D2010303083E20E304BE50E305BE50300A0E1
+0AFE1D3010AAFFFFEB00A81BE90DC0A0E100D82DE9
+0AFE1D401004B04CE204D04DE210000BE510301BE5
+0AFE1D50100030D3E5000053E30000001A080000EA
+0AFE1D601010104BE2003091E50320A0E10020D2E5
+0AFE1D7010013083E2003081E50200A0E197FFFFEB
+0AFE1D8008F1FFFFEA00A81BE9
+0AFE1DA4100A0D4D58314144532053796E632D666C
+0AFE1DB4106173682050726F6772616D6D696E6720
+0AFE1DC4105574696C6974792076302E3520323030
+0AFE1DD410322F30382F32310A0D000000536F7572
+0AFE1DE41063652061646472657373202873746F72
+0AFE1DF410656420696E2030783041464530303030
+0AFE1E0410293A2030780000005461726765742061
+0AFE1E1410646472657373202873746F7265642069
+0AFE1E24106E2030783041464530303034293A2030
+0AFE1E34107800000053697A652020202020202020
+0AFE1E44102020202873746F72656420696E203078
+0AFE1E54103041464530303038293A203078000000
+0AFE1E6410507265737320616E79206B657920746F
+0AFE1E74102073746172742070726F6772616D6D69
+0AFE1E84106E67202E2E2E00000A0D45726173696E
+0AFE1E94106720666C617368202E2E2E000A0D5072
+0AFE1EA4106F6772616D6D696E67202E2E2E000000
+0AFE1EB4100A0D50726F6772616D6D696E67206669
+0AFE1EC4106E69736865642E0A0D50726573732027
+0AFE1ED410612720746F20636F6E74696E7565202E
+0AFE1EE4102E2E2E000A0D566572696679696E6720
+0AFE1EF410666C617368202E2E2E0000000A0D426C
+0AFE1F0410616E6B20636865636B696E67202E2E2E
+0AFE1F1410000000000A45726173696E67202E2E2E
+0AFE1F2410000000000A50726F6772616D6D696E67
+0AFE1F3410202E2E2E000000002073756363656564
+0AFE1F44102E0A0000206661696C656420210A0000
+0AFE100000
+
" +} + +######################################################### + +if [ "$#" -eq 2 ] ; then + output_init > $2 + output_uboot >> $2 + output_flashprog >> $2 +else + output_init; + output_uboot; + output_flashprog; +fi diff --git a/u-boot/tools/img2srec.c b/u-boot/tools/img2srec.c new file mode 100644 index 0000000..ec76964 --- /dev/null +++ b/u-boot/tools/img2srec.c @@ -0,0 +1,372 @@ +/************************************************************************* +| COPYRIGHT (c) 2000 BY ABATRON AG +|************************************************************************* +| +| PROJECT NAME: Linux Image to S-record Conversion Utility +| FILENAME : img2srec.c +| +| COMPILER : GCC +| +| TARGET OS : LINUX / UNIX +| TARGET HW : - +| +| PROGRAMMER : Abatron / RD +| CREATION : 07.07.00 +| +|************************************************************************* +| +| DESCRIPTION : +| +| Utility to convert a Linux Boot Image to S-record: +| ================================================== +| +| This command line utility can be used to convert a Linux boot image +| (zimage.initrd) to S-Record format used for flash programming. +| This conversion takes care of the special sections "IMAGE" and INITRD". +| +| img2srec [-o offset] image > image.srec +| +| +| Build the utility: +| ================== +| +| To build the utility use GCC as follows: +| +| gcc img2srec.c -o img2srec +| +| +|************************************************************************* +| +| +| UPDATES : +| +| DATE NAME CHANGES +| ----------------------------------------------------------- +| Latest update +| +| 07.07.00 aba Initial release +| +|*************************************************************************/ + +/************************************************************************* +| INCLUDES +|*************************************************************************/ + +#include "os_support.h" +#include <stdbool.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <elf.h> +#include <unistd.h> +#include <errno.h> + +/************************************************************************* +| FUNCTIONS +|*************************************************************************/ + +static char* ExtractHex (uint32_t* value, char* getPtr) +{ + uint32_t num; + uint32_t digit; + uint8_t c; + + while (*getPtr == ' ') getPtr++; + num = 0; + for (;;) { + c = *getPtr; + if ((c >= '0') && (c <= '9')) digit = (uint32_t)(c - '0'); + else if ((c >= 'A') && (c <= 'F')) digit = (uint32_t)(c - 'A' + 10); + else if ((c >= 'a') && (c <= 'f')) digit = (uint32_t)(c - 'a' + 10); + else break; + num <<= 4; + num += digit; + getPtr++; + } /* for */ + *value = num; + return getPtr; +} /* ExtractHex */ + +static char* ExtractDecimal (uint32_t* value, char* getPtr) +{ + uint32_t num; + uint32_t digit; + uint8_t c; + + while (*getPtr == ' ') getPtr++; + num = 0; + for (;;) { + c = *getPtr; + if ((c >= '0') && (c <= '9')) digit = (uint32_t)(c - '0'); + else break; + num *= 10; + num += digit; + getPtr++; + } /* for */ + *value = num; + return getPtr; +} /* ExtractDecimal */ + + +static void ExtractNumber (uint32_t* value, char* getPtr) +{ + bool neg = false;; + + while (*getPtr == ' ') getPtr++; + if (*getPtr == '-') { + neg = true; + getPtr++; + } /* if */ + if ((*getPtr == '0') && ((*(getPtr+1) == 'x') || (*(getPtr+1) == 'X'))) { + getPtr +=2; + (void)ExtractHex(value, getPtr); + } /* if */ + else { + (void)ExtractDecimal(value, getPtr); + } /* else */ + if (neg) *value = -(*value); +} /* ExtractNumber */ + + +static uint8_t* ExtractWord(uint16_t* value, uint8_t* buffer) +{ + uint16_t x; + x = (uint16_t)*buffer++; + x = (x<<8) + (uint16_t)*buffer++; + *value = x; + return buffer; +} /* ExtractWord */ + + +static uint8_t* ExtractLong(uint32_t* value, uint8_t* buffer) +{ + uint32_t x; + x = (uint32_t)*buffer++; + x = (x<<8) + (uint32_t)*buffer++; + x = (x<<8) + (uint32_t)*buffer++; + x = (x<<8) + (uint32_t)*buffer++; + *value = x; + return buffer; +} /* ExtractLong */ + + +static uint8_t* ExtractBlock(uint16_t count, uint8_t* data, uint8_t* buffer) +{ + while (count--) *data++ = *buffer++; + return buffer; +} /* ExtractBlock */ + + +static char* WriteHex(char* pa, uint8_t value, uint16_t* pCheckSum) +{ + uint16_t temp; + + static char ByteToHex[] = "0123456789ABCDEF"; + + *pCheckSum += value; + temp = value / 16; + *pa++ = ByteToHex[temp]; + temp = value % 16; + *pa++ = ByteToHex[temp]; + return pa; +} + + +static char* BuildSRecord(char* pa, uint16_t sType, uint32_t addr, + const uint8_t* data, int nCount) +{ + uint16_t addrLen; + uint16_t sRLen; + uint16_t checkSum; + uint16_t i; + + switch (sType) { + case 0: + case 1: + case 9: + addrLen = 2; + break; + case 2: + case 8: + addrLen = 3; + break; + case 3: + case 7: + addrLen = 4; + break; + default: + return pa; + } /* switch */ + + *pa++ = 'S'; + *pa++ = (char)(sType + '0'); + sRLen = addrLen + nCount + 1; + checkSum = 0; + pa = WriteHex(pa, (uint8_t)sRLen, &checkSum); + + /* Write address field */ + for (i = 1; i <= addrLen; i++) { + pa = WriteHex(pa, (uint8_t)(addr >> (8 * (addrLen - i))), &checkSum); + } /* for */ + + /* Write code/data fields */ + for (i = 0; i < nCount; i++) { + pa = WriteHex(pa, *data++, &checkSum); + } /* for */ + + /* Write checksum field */ + checkSum = ~checkSum; + pa = WriteHex(pa, (uint8_t)checkSum, &checkSum); + *pa++ = '\0'; + return pa; +} + + +static void ConvertELF(char* fileName, uint32_t loadOffset) +{ + FILE* file; + int i; + int rxCount; + uint8_t rxBlock[1024]; + uint32_t loadSize; + uint32_t firstAddr; + uint32_t loadAddr; + uint32_t loadDiff = 0; + Elf32_Ehdr elfHeader; + Elf32_Shdr sectHeader[32]; + uint8_t* getPtr; + char srecLine[128]; + char *hdr_name; + + + /* open file */ + if ((file = fopen(fileName,"rb")) == NULL) { + fprintf (stderr, "Can't open %s: %s\n", fileName, strerror(errno)); + return; + } /* if */ + + /* read ELF header */ + rxCount = fread(rxBlock, 1, sizeof elfHeader, file); + getPtr = ExtractBlock(sizeof elfHeader.e_ident, elfHeader.e_ident, rxBlock); + getPtr = ExtractWord(&elfHeader.e_type, getPtr); + getPtr = ExtractWord(&elfHeader.e_machine, getPtr); + getPtr = ExtractLong((uint32_t *)&elfHeader.e_version, getPtr); + getPtr = ExtractLong((uint32_t *)&elfHeader.e_entry, getPtr); + getPtr = ExtractLong((uint32_t *)&elfHeader.e_phoff, getPtr); + getPtr = ExtractLong((uint32_t *)&elfHeader.e_shoff, getPtr); + getPtr = ExtractLong((uint32_t *)&elfHeader.e_flags, getPtr); + getPtr = ExtractWord(&elfHeader.e_ehsize, getPtr); + getPtr = ExtractWord(&elfHeader.e_phentsize, getPtr); + getPtr = ExtractWord(&elfHeader.e_phnum, getPtr); + getPtr = ExtractWord(&elfHeader.e_shentsize, getPtr); + getPtr = ExtractWord(&elfHeader.e_shnum, getPtr); + getPtr = ExtractWord(&elfHeader.e_shstrndx, getPtr); + if ( (rxCount != sizeof elfHeader) + || (elfHeader.e_ident[0] != ELFMAG0) + || (elfHeader.e_ident[1] != ELFMAG1) + || (elfHeader.e_ident[2] != ELFMAG2) + || (elfHeader.e_ident[3] != ELFMAG3) + || (elfHeader.e_type != ET_EXEC) + ) { + fclose(file); + fprintf (stderr, "*** illegal file format\n"); + return; + } /* if */ + + /* read all section headers */ + fseek(file, elfHeader.e_shoff, SEEK_SET); + for (i = 0; i < elfHeader.e_shnum; i++) { + rxCount = fread(rxBlock, 1, sizeof sectHeader[0], file); + getPtr = ExtractLong((uint32_t *)§Header[i].sh_name, rxBlock); + getPtr = ExtractLong((uint32_t *)§Header[i].sh_type, getPtr); + getPtr = ExtractLong((uint32_t *)§Header[i].sh_flags, getPtr); + getPtr = ExtractLong((uint32_t *)§Header[i].sh_addr, getPtr); + getPtr = ExtractLong((uint32_t *)§Header[i].sh_offset, getPtr); + getPtr = ExtractLong((uint32_t *)§Header[i].sh_size, getPtr); + getPtr = ExtractLong((uint32_t *)§Header[i].sh_link, getPtr); + getPtr = ExtractLong((uint32_t *)§Header[i].sh_info, getPtr); + getPtr = ExtractLong((uint32_t *)§Header[i].sh_addralign, getPtr); + getPtr = ExtractLong((uint32_t *)§Header[i].sh_entsize, getPtr); + if (rxCount != sizeof sectHeader[0]) { + fclose(file); + fprintf (stderr, "*** illegal file format\n"); + return; + } /* if */ + } /* for */ + + if ((hdr_name = strrchr(fileName, '/')) == NULL) { + hdr_name = fileName; + } else { + ++hdr_name; + } + /* write start record */ + (void)BuildSRecord(srecLine, 0, 0, (uint8_t *)hdr_name, strlen(hdr_name)); + printf("%s\r\n",srecLine); + + /* write data records */ + firstAddr = ~0; + loadAddr = 0; + for (i = 0; i < elfHeader.e_shnum; i++) { + if ( (sectHeader[i].sh_type == SHT_PROGBITS) + && (sectHeader[i].sh_size != 0) + ) { + loadSize = sectHeader[i].sh_size; + if (sectHeader[i].sh_flags != 0) { + loadAddr = sectHeader[i].sh_addr; + loadDiff = loadAddr - sectHeader[i].sh_offset; + } /* if */ + else { + loadAddr = sectHeader[i].sh_offset + loadDiff; + } /* else */ + + if (loadAddr < firstAddr) + firstAddr = loadAddr; + + /* build s-records */ + loadSize = sectHeader[i].sh_size; + fseek(file, sectHeader[i].sh_offset, SEEK_SET); + while (loadSize) { + rxCount = fread(rxBlock, 1, (loadSize > 32) ? 32 : loadSize, file); + if (rxCount < 0) { + fclose(file); + fprintf (stderr, "*** illegal file format\n"); + return; + } /* if */ + (void)BuildSRecord(srecLine, 3, loadAddr + loadOffset, rxBlock, rxCount); + loadSize -= rxCount; + loadAddr += rxCount; + printf("%s\r\n",srecLine); + } /* while */ + } /* if */ + } /* for */ + + /* add end record */ + (void)BuildSRecord(srecLine, 7, firstAddr + loadOffset, 0, 0); + printf("%s\r\n",srecLine); + fclose(file); +} /* ConvertELF */ + + +/************************************************************************* +| MAIN +|*************************************************************************/ + +int main( int argc, char *argv[ ]) +{ + uint32_t offset; + + if (argc == 2) { + ConvertELF(argv[1], 0); + } /* if */ + else if ((argc == 4) && (strcmp(argv[1], "-o") == 0)) { + ExtractNumber(&offset, argv[2]); + ConvertELF(argv[3], offset); + } /* if */ + else { + fprintf (stderr, "Usage: img2srec [-o offset] <image>\n"); + } /* if */ + + return 0; +} /* main */ diff --git a/u-boot/tools/imls/Makefile b/u-boot/tools/imls/Makefile new file mode 100644 index 0000000..0caa397 --- /dev/null +++ b/u-boot/tools/imls/Makefile @@ -0,0 +1,97 @@ +# +# (C) Copyright 2009 Marco Stornelli <marco.stornelli@gmail.com> +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# 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 +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +# Generated executable files +BIN_FILES-y += imls + +# Source files which exist outside the tools/imls directory +EXT_OBJ_FILES-y += lib/crc32.o +EXT_OBJ_FILES-y += lib/md5.o +EXT_OBJ_FILES-y += lib/sha1.o +EXT_OBJ_FILES-y += common/image.o + +# Source files located in the tools/imls directory +OBJ_FILES-y += imls.o + +# Flattened device tree objects +LIBFDT_OBJ_FILES-y += fdt.o +LIBFDT_OBJ_FILES-y += fdt_ro.o +LIBFDT_OBJ_FILES-y += fdt_rw.o +LIBFDT_OBJ_FILES-y += fdt_strerror.o +LIBFDT_OBJ_FILES-y += fdt_wip.o + +# now $(obj) is defined +SRCS += $(addprefix $(SRCTREE)/,$(EXT_OBJ_FILES-y:.o=.c)) +SRCS += $(addprefix $(SRCTREE)/tools/,$(OBJ_FILES-y:.o=.c)) +SRCS += $(addprefix $(SRCTREE)/lib/libfdt/,$(LIBFDT_OBJ_FILES-y:.o=.c)) +BINS := $(addprefix $(obj),$(sort $(BIN_FILES-y))) +LIBFDT_OBJS := $(addprefix $(obj),$(LIBFDT_OBJ_FILES-y)) + +# +# Compile for a hosted environment on the target +# Define __KERNEL_STRICT_NAMES to prevent typedef overlaps +# +HOSTCPPFLAGS = -idirafter $(SRCTREE)/include \ + -idirafter $(OBJTREE)/include2 \ + -idirafter $(OBJTREE)/include \ + -I $(SRCTREE)/lib/libfdt \ + -I $(SRCTREE)/tools \ + -DUSE_HOSTCC -D__KERNEL_STRICT_NAMES + +ifeq ($(MTD_VERSION),old) +HOSTCPPFLAGS += -DMTD_OLD +endif + +all: $(BINS) + +$(obj)imls: $(obj)imls.o $(obj)crc32.o $(obj)image.o $(obj)md5.o \ + $(obj)sha1.o $(LIBFDT_OBJS) + $(CC) $(HOSTCFLAGS) $(HOSTLDFLAGS) -o $@ $^ + $(STRIP) $@ + +# Some files complain if compiled with -pedantic, use HOSTCFLAGS_NOPED +$(obj)image.o: $(SRCTREE)/common/image.c + $(CC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $< + +$(obj)imls.o: $(SRCTREE)/tools/imls/imls.c + $(CC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $< + +# Some of the tool objects need to be accessed from outside the tools/imls directory +$(obj)%.o: $(SRCTREE)/common/%.c + $(CC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $< + +$(obj)%.o: $(SRCTREE)/lib/%.c + $(CC) -g $(HOSTCFLAGS) -c -o $@ $< + +$(obj)%.o: $(SRCTREE)/lib/libfdt/%.c + $(CC) -g $(HOSTCFLAGS_NOPED) -c -o $@ $< + +clean: + rm -rf *.o imls + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/u-boot/tools/imls/README b/u-boot/tools/imls/README new file mode 100644 index 0000000..97d7e32 --- /dev/null +++ b/u-boot/tools/imls/README @@ -0,0 +1,57 @@ +# +# (C) Copyright 2009 Marco Stornelli <marco.stornelli@gmail.com> +# +# See file CREDITS for list of people who contributed to this +# project. +# +# The files in this directory are free software; you can redistribute +# them and/or modify them under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# These files are distributed in the hope that they will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# 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 +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +IMLS +------------- + +imls is an implementation of a Linux command line tool to access +to raw flash partitions and list images made with mkimage command. + +For building against older versions of the MTD headers (meaning before +v2.6.8-rc1) it is required to pass the argument "MTD_VERSION=old" to +make. + +Usage examples +-------------- + +1) Flash with sectors of 128KiB and 32 sectors: + +> imls -c 32 -s 131072 /dev/mtd0 +Searching... +Image Name: foo +Created: Fri Apr 10 18:11:30 2009 +Image Type: Intel x86 Linux Standalone Program (uncompressed) +Data Size: 10716 Bytes = 10.46 kB = 0.01 MB +Load Address: 00000000 +Entry Point: 00000000 + +2) Flash with sectors of 64KiB and 128 sectors and with a search offset of one +sector: + +> imls -o 1 -c 128 -s 65536 /dev/mtd0 +Searching... +Image Name: foo +Created: Fri Apr 10 18:11:30 2009 +Image Type: Intel x86 Linux Standalone Program (uncompressed) +Data Size: 10716 Bytes = 10.46 kB = 0.01 MB +Load Address: 00000000 +Entry Point: 00000000 diff --git a/u-boot/tools/imls/imls.c b/u-boot/tools/imls/imls.c new file mode 100644 index 0000000..b21c505 --- /dev/null +++ b/u-boot/tools/imls/imls.c @@ -0,0 +1,270 @@ +/* + * (C) Copyright 2009 Marco Stornelli + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <stddef.h> +#include <string.h> +#include <sys/types.h> +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <unistd.h> +#include <asm/page.h> + +#ifdef MTD_OLD +#include <stdint.h> +#include <linux/mtd/mtd.h> +#else +#define __user /* nothing */ +#include <mtd/mtd-user.h> +#endif + +#include <sha1.h> +#include <fdt.h> +#include <libfdt.h> +#include <fdt_support.h> +#include <image.h> + +#define MIN(a, b) (((a) < (b)) ? (a) : (b)) + +extern unsigned long crc32(unsigned long crc, const char *buf, unsigned int len); +static void usage(void); +static int image_verify_header(char *ptr, int fd); +static int flash_bad_block(int fd, uint8_t mtd_type, loff_t start); + +char *cmdname; +char *devicefile; + +unsigned int sectorcount = 0; +int sflag = 0; +unsigned int sectoroffset = 0; +unsigned int sectorsize = 0; +int cflag = 0; + +int main (int argc, char **argv) +{ + int fd = -1, err = 0, readbyte = 0, j; + struct mtd_info_user mtdinfo; + char buf[sizeof(image_header_t)]; + int found = 0; + + cmdname = *argv; + + while (--argc > 0 && **++argv == '-') { + while (*++*argv) { + switch (**argv) { + case 'c': + if (--argc <= 0) + usage (); + sectorcount = (unsigned int)atoi(*++argv); + cflag = 1; + goto NXTARG; + case 'o': + if (--argc <= 0) + usage (); + sectoroffset = (unsigned int)atoi(*++argv); + goto NXTARG; + + case 's': + if (--argc <= 0) + usage (); + sectorsize = (unsigned int)atoi(*++argv); + sflag = 1; + goto NXTARG; + default: + usage (); + } + } +NXTARG: ; + } + + if (argc != 1 || cflag == 0 || sflag == 0) + usage(); + + devicefile = *argv; + + fd = open(devicefile, O_RDONLY); + if (fd < 0) { + fprintf (stderr, "%s: Can't open %s: %s\n", + cmdname, devicefile, strerror(errno)); + exit(EXIT_FAILURE); + } + + err = ioctl(fd, MEMGETINFO, &mtdinfo); + if (err < 0) { + fprintf(stderr, "%s: Cannot get MTD information: %s\n",cmdname, + strerror(errno)); + exit(EXIT_FAILURE); + } + + if (mtdinfo.type != MTD_NORFLASH && mtdinfo.type != MTD_NANDFLASH) { + fprintf(stderr, "%s: Unsupported flash type %u\n", + cmdname, mtdinfo.type); + exit(EXIT_FAILURE); + } + + if (sectorsize * sectorcount != mtdinfo.size) { + fprintf(stderr, "%s: Partition size (%d) incompatible with " + "sector size and count\n", cmdname, mtdinfo.size); + exit(EXIT_FAILURE); + } + + if (sectorsize * sectoroffset >= mtdinfo.size) { + fprintf(stderr, "%s: Partition size (%d) incompatible with " + "sector offset given\n", cmdname, mtdinfo.size); + exit(EXIT_FAILURE); + } + + if (sectoroffset > sectorcount - 1) { + fprintf(stderr, "%s: Sector offset cannot be grater than " + "sector count minus one\n", cmdname); + exit(EXIT_FAILURE); + } + + printf("Searching....\n"); + + for (j = sectoroffset; j < sectorcount; ++j) { + + if (lseek(fd, j*sectorsize, SEEK_SET) != j*sectorsize) { + fprintf(stderr, "%s: lseek failure: %s\n", + cmdname, strerror(errno)); + exit(EXIT_FAILURE); + } + + err = flash_bad_block(fd, mtdinfo.type, j*sectorsize); + if (err < 0) + exit(EXIT_FAILURE); + if (err) + continue; /* Skip and jump to next */ + + readbyte = read(fd, buf, sizeof(image_header_t)); + if (readbyte != sizeof(image_header_t)) { + fprintf(stderr, "%s: Can't read from device: %s\n", + cmdname, strerror(errno)); + exit(EXIT_FAILURE); + } + + if (fdt_check_header(buf)) { + /* old-style image */ + if (image_verify_header(buf, fd)) { + found = 1; + image_print_contents((image_header_t *)buf); + } + } else { + /* FIT image */ + fit_print_contents(buf); + } + + } + + close(fd); + + if(!found) + printf("No images found\n"); + + exit(EXIT_SUCCESS); +} + +void usage() +{ + fprintf (stderr, "Usage:\n" + " %s [-o offset] -s size -c count device\n" + " -o ==> number of sectors to use as offset\n" + " -c ==> number of sectors\n" + " -s ==> size of sectors (byte)\n", + cmdname); + + exit(EXIT_FAILURE); +} + +static int image_verify_header(char *ptr, int fd) +{ + int len, nread; + char *data; + uint32_t checksum; + image_header_t *hdr = (image_header_t *)ptr; + char buf[PAGE_SIZE]; + + if (image_get_magic(hdr) != IH_MAGIC) + return 0; + + data = (char *)hdr; + len = image_get_header_size(); + + checksum = image_get_hcrc(hdr); + hdr->ih_hcrc = htonl(0); /* clear for re-calculation */ + + if (crc32(0, data, len) != checksum) { + fprintf(stderr, + "%s: Maybe image found but it has bad header checksum!\n", + cmdname); + return 0; + } + + len = image_get_size(hdr); + checksum = 0; + + while (len > 0) { + nread = read(fd, buf, MIN(len,PAGE_SIZE)); + if (nread != MIN(len,PAGE_SIZE)) { + fprintf(stderr, + "%s: Error while reading: %s\n", + cmdname, strerror(errno)); + exit(EXIT_FAILURE); + } + checksum = crc32(checksum, buf, nread); + len -= nread; + } + + if (checksum != image_get_dcrc(hdr)) { + fprintf (stderr, + "%s: Maybe image found but it has corrupted data!\n", + cmdname); + return 0; + } + + return 1; +} + +/* + * Test for bad block on NAND, just returns 0 on NOR, on NAND: + * 0 - block is good + * > 0 - block is bad + * < 0 - failed to test + */ +static int flash_bad_block(int fd, uint8_t mtd_type, loff_t start) +{ + if (mtd_type == MTD_NANDFLASH) { + int badblock = ioctl(fd, MEMGETBADBLOCK, &start); + + if (badblock < 0) { + fprintf(stderr,"%s: Cannot read bad block mark: %s\n", + cmdname, strerror(errno)); + return badblock; + } + + if (badblock) { + return badblock; + } + } + + return 0; +} diff --git a/u-boot/tools/imximage.c b/u-boot/tools/imximage.c new file mode 100644 index 0000000..8e81bdb --- /dev/null +++ b/u-boot/tools/imximage.c @@ -0,0 +1,574 @@ +/* + * (C) Copyright 2009 + * Stefano Babic, DENX Software Engineering, sbabic@denx.de. + * + * (C) Copyright 2008 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Prafulla Wadaskar <prafulla@marvell.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* Required to obtain the getline prototype from stdio.h */ +#define _GNU_SOURCE + +#include "mkimage.h" +#include <image.h> +#include "imximage.h" + +/* + * Supported commands for configuration file + */ +static table_entry_t imximage_cmds[] = { + {CMD_BOOT_FROM, "BOOT_FROM", "boot command", }, + {CMD_DATA, "DATA", "Reg Write Data", }, + {CMD_IMAGE_VERSION, "IMAGE_VERSION", "image version", }, + {-1, "", "", }, +}; + +/* + * Supported Boot options for configuration file + * this is needed to set the correct flash offset + */ +static table_entry_t imximage_bootops[] = { + {FLASH_OFFSET_SPI, "spi", "SPI Flash", }, + {FLASH_OFFSET_NAND, "nand", "NAND Flash", }, + {FLASH_OFFSET_SD, "sd", "SD Card", }, + {FLASH_OFFSET_ONENAND, "onenand", "OneNAND Flash",}, + {-1, "", "Invalid", }, +}; + +/* + * IMXIMAGE version definition for i.MX chips + */ +static table_entry_t imximage_versions[] = { + {IMXIMAGE_V1, "", " (i.MX25/35/51 compatible)", }, + {IMXIMAGE_V2, "", " (i.MX53 compatible)", }, + {-1, "", " (Invalid)", }, +}; + +static struct imx_header imximage_header; +static uint32_t imximage_version; + +static set_dcd_val_t set_dcd_val; +static set_dcd_rst_t set_dcd_rst; +static set_imx_hdr_t set_imx_hdr; + +static uint32_t get_cfg_value(char *token, char *name, int linenr) +{ + char *endptr; + uint32_t value; + + errno = 0; + value = strtoul(token, &endptr, 16); + if (errno || (token == endptr)) { + fprintf(stderr, "Error: %s[%d] - Invalid hex data(%s)\n", + name, linenr, token); + exit(EXIT_FAILURE); + } + return value; +} + +static uint32_t detect_imximage_version(struct imx_header *imx_hdr) +{ + imx_header_v1_t *hdr_v1 = &imx_hdr->header.hdr_v1; + imx_header_v2_t *hdr_v2 = &imx_hdr->header.hdr_v2; + flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr; + flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr; + + /* Try to detect V1 */ + if ((fhdr_v1->app_code_barker == APP_CODE_BARKER) && + (hdr_v1->dcd_table.preamble.barker == DCD_BARKER)) + return IMXIMAGE_V1; + + /* Try to detect V2 */ + if ((fhdr_v2->header.tag == IVT_HEADER_TAG) && + (hdr_v2->dcd_table.header.tag == DCD_HEADER_TAG)) + return IMXIMAGE_V2; + + return IMXIMAGE_VER_INVALID; +} + +static void err_imximage_version(int version) +{ + fprintf(stderr, + "Error: Unsupported imximage version:%d\n", version); + + exit(EXIT_FAILURE); +} + +static void set_dcd_val_v1(struct imx_header *imxhdr, char *name, int lineno, + int fld, uint32_t value, uint32_t off) +{ + dcd_v1_t *dcd_v1 = &imxhdr->header.hdr_v1.dcd_table; + + switch (fld) { + case CFG_REG_SIZE: + /* Byte, halfword, word */ + if ((value != 1) && (value != 2) && (value != 4)) { + fprintf(stderr, "Error: %s[%d] - " + "Invalid register size " "(%d)\n", + name, lineno, value); + exit(EXIT_FAILURE); + } + dcd_v1->addr_data[off].type = value; + break; + case CFG_REG_ADDRESS: + dcd_v1->addr_data[off].addr = value; + break; + case CFG_REG_VALUE: + dcd_v1->addr_data[off].value = value; + break; + default: + break; + + } +} + +static void set_dcd_val_v2(struct imx_header *imxhdr, char *name, int lineno, + int fld, uint32_t value, uint32_t off) +{ + dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.dcd_table; + + switch (fld) { + case CFG_REG_ADDRESS: + dcd_v2->addr_data[off].addr = cpu_to_be32(value); + break; + case CFG_REG_VALUE: + dcd_v2->addr_data[off].value = cpu_to_be32(value); + break; + default: + break; + + } +} + +/* + * Complete setting up the rest field of DCD of V1 + * such as barker code and DCD data length. + */ +static void set_dcd_rst_v1(struct imx_header *imxhdr, uint32_t dcd_len, + char *name, int lineno) +{ + dcd_v1_t *dcd_v1 = &imxhdr->header.hdr_v1.dcd_table; + + if (dcd_len > MAX_HW_CFG_SIZE_V1) { + fprintf(stderr, "Error: %s[%d] -" + "DCD table exceeds maximum size(%d)\n", + name, lineno, MAX_HW_CFG_SIZE_V1); + exit(EXIT_FAILURE); + } + + dcd_v1->preamble.barker = DCD_BARKER; + dcd_v1->preamble.length = dcd_len * sizeof(dcd_type_addr_data_t); +} + +/* + * Complete setting up the reset field of DCD of V2 + * such as DCD tag, version, length, etc. + */ +static void set_dcd_rst_v2(struct imx_header *imxhdr, uint32_t dcd_len, + char *name, int lineno) +{ + dcd_v2_t *dcd_v2 = &imxhdr->header.hdr_v2.dcd_table; + + if (dcd_len > MAX_HW_CFG_SIZE_V2) { + fprintf(stderr, "Error: %s[%d] -" + "DCD table exceeds maximum size(%d)\n", + name, lineno, MAX_HW_CFG_SIZE_V2); + exit(EXIT_FAILURE); + } + + dcd_v2->header.tag = DCD_HEADER_TAG; + dcd_v2->header.length = cpu_to_be16( + dcd_len * sizeof(dcd_addr_data_t) + 8); + dcd_v2->header.version = DCD_VERSION; + dcd_v2->write_dcd_command.tag = DCD_COMMAND_TAG; + dcd_v2->write_dcd_command.length = cpu_to_be16( + dcd_len * sizeof(dcd_addr_data_t) + 4); + dcd_v2->write_dcd_command.param = DCD_COMMAND_PARAM; +} + +static void set_imx_hdr_v1(struct imx_header *imxhdr, uint32_t dcd_len, + struct stat *sbuf, + struct mkimage_params *params) +{ + imx_header_v1_t *hdr_v1 = &imxhdr->header.hdr_v1; + flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr; + dcd_v1_t *dcd_v1 = &hdr_v1->dcd_table; + uint32_t base_offset; + + /* Set default offset */ + imxhdr->flash_offset = FLASH_OFFSET_STANDARD; + + /* Set magic number */ + fhdr_v1->app_code_barker = APP_CODE_BARKER; + + fhdr_v1->app_dest_ptr = params->addr; + fhdr_v1->app_dest_ptr = params->ep - imxhdr->flash_offset - + sizeof(struct imx_header); + fhdr_v1->app_code_jump_vector = params->ep; + + base_offset = fhdr_v1->app_dest_ptr + imxhdr->flash_offset ; + fhdr_v1->dcd_ptr_ptr = + (uint32_t) (offsetof(flash_header_v1_t, dcd_ptr) - + offsetof(flash_header_v1_t, app_code_jump_vector) + + base_offset); + + fhdr_v1->dcd_ptr = base_offset + + offsetof(imx_header_v1_t, dcd_table); + + /* The external flash header must be at the end of the DCD table */ + dcd_v1->addr_data[dcd_len].type = sbuf->st_size + + imxhdr->flash_offset + + sizeof(struct imx_header); + + /* Security feature are not supported */ + fhdr_v1->app_code_csf = 0; + fhdr_v1->super_root_key = 0; +} + +static void set_imx_hdr_v2(struct imx_header *imxhdr, uint32_t dcd_len, + struct stat *sbuf, + struct mkimage_params *params) +{ + imx_header_v2_t *hdr_v2 = &imxhdr->header.hdr_v2; + flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr; + + /* Set default offset */ + imxhdr->flash_offset = FLASH_OFFSET_STANDARD; + + /* Set magic number */ + fhdr_v2->header.tag = IVT_HEADER_TAG; /* 0xD1 */ + fhdr_v2->header.length = cpu_to_be16(sizeof(flash_header_v2_t)); + fhdr_v2->header.version = IVT_VERSION; /* 0x40 */ + + fhdr_v2->entry = params->ep; + fhdr_v2->reserved1 = fhdr_v2->reserved2 = 0; + fhdr_v2->self = params->ep - sizeof(struct imx_header); + + fhdr_v2->dcd_ptr = fhdr_v2->self + + offsetof(imx_header_v2_t, dcd_table); + + fhdr_v2->boot_data_ptr = fhdr_v2->self + + offsetof(imx_header_v2_t, boot_data); + + hdr_v2->boot_data.start = fhdr_v2->self - imxhdr->flash_offset; + hdr_v2->boot_data.size = sbuf->st_size + + imxhdr->flash_offset + + sizeof(struct imx_header); + + /* Security feature are not supported */ + fhdr_v2->csf = 0; +} + +static void set_hdr_func(struct imx_header *imxhdr) +{ + switch (imximage_version) { + case IMXIMAGE_V1: + set_dcd_val = set_dcd_val_v1; + set_dcd_rst = set_dcd_rst_v1; + set_imx_hdr = set_imx_hdr_v1; + break; + case IMXIMAGE_V2: + set_dcd_val = set_dcd_val_v2; + set_dcd_rst = set_dcd_rst_v2; + set_imx_hdr = set_imx_hdr_v2; + break; + default: + err_imximage_version(imximage_version); + break; + } +} + +static void print_hdr_v1(struct imx_header *imx_hdr) +{ + imx_header_v1_t *hdr_v1 = &imx_hdr->header.hdr_v1; + flash_header_v1_t *fhdr_v1 = &hdr_v1->fhdr; + dcd_v1_t *dcd_v1 = &hdr_v1->dcd_table; + uint32_t size, length, ver; + + size = dcd_v1->preamble.length; + if (size > (MAX_HW_CFG_SIZE_V1 * sizeof(dcd_type_addr_data_t))) { + fprintf(stderr, + "Error: Image corrupt DCD size %d exceed maximum %d\n", + (uint32_t)(size / sizeof(dcd_type_addr_data_t)), + MAX_HW_CFG_SIZE_V1); + exit(EXIT_FAILURE); + } + + length = dcd_v1->preamble.length / sizeof(dcd_type_addr_data_t); + ver = detect_imximage_version(imx_hdr); + + printf("Image Type: Freescale IMX Boot Image\n"); + printf("Image Ver: %x", ver); + printf("%s\n", get_table_entry_name(imximage_versions, NULL, ver)); + printf("Data Size: "); + genimg_print_size(dcd_v1->addr_data[length].type); + printf("Load Address: %08x\n", (uint32_t)fhdr_v1->app_dest_ptr); + printf("Entry Point: %08x\n", (uint32_t)fhdr_v1->app_code_jump_vector); +} + +static void print_hdr_v2(struct imx_header *imx_hdr) +{ + imx_header_v2_t *hdr_v2 = &imx_hdr->header.hdr_v2; + flash_header_v2_t *fhdr_v2 = &hdr_v2->fhdr; + dcd_v2_t *dcd_v2 = &hdr_v2->dcd_table; + uint32_t size, version; + + size = be16_to_cpu(dcd_v2->header.length) - 8; + if (size > (MAX_HW_CFG_SIZE_V2 * sizeof(dcd_addr_data_t))) { + fprintf(stderr, + "Error: Image corrupt DCD size %d exceed maximum %d\n", + (uint32_t)(size / sizeof(dcd_addr_data_t)), + MAX_HW_CFG_SIZE_V2); + exit(EXIT_FAILURE); + } + + version = detect_imximage_version(imx_hdr); + + printf("Image Type: Freescale IMX Boot Image\n"); + printf("Image Ver: %x", version); + printf("%s\n", get_table_entry_name(imximage_versions, NULL, version)); + printf("Data Size: "); + genimg_print_size(hdr_v2->boot_data.size); + printf("Load Address: %08x\n", (uint32_t)fhdr_v2->boot_data_ptr); + printf("Entry Point: %08x\n", (uint32_t)fhdr_v2->entry); +} + +static void parse_cfg_cmd(struct imx_header *imxhdr, int32_t cmd, char *token, + char *name, int lineno, int fld, int dcd_len) +{ + int value; + static int cmd_ver_first = ~0; + + switch (cmd) { + case CMD_IMAGE_VERSION: + imximage_version = get_cfg_value(token, name, lineno); + if (cmd_ver_first == 0) { + fprintf(stderr, "Error: %s[%d] - IMAGE_VERSION " + "command need be the first before other " + "valid command in the file\n", name, lineno); + exit(EXIT_FAILURE); + } + cmd_ver_first = 1; + set_hdr_func(imxhdr); + break; + case CMD_BOOT_FROM: + imxhdr->flash_offset = get_table_entry_id(imximage_bootops, + "imximage boot option", token); + if (imxhdr->flash_offset == -1) { + fprintf(stderr, "Error: %s[%d] -Invalid boot device" + "(%s)\n", name, lineno, token); + exit(EXIT_FAILURE); + } + if (unlikely(cmd_ver_first != 1)) + cmd_ver_first = 0; + break; + case CMD_DATA: + value = get_cfg_value(token, name, lineno); + (*set_dcd_val)(imxhdr, name, lineno, fld, value, dcd_len); + if (unlikely(cmd_ver_first != 1)) + cmd_ver_first = 0; + break; + } +} + +static void parse_cfg_fld(struct imx_header *imxhdr, int32_t *cmd, + char *token, char *name, int lineno, int fld, int *dcd_len) +{ + int value; + + switch (fld) { + case CFG_COMMAND: + *cmd = get_table_entry_id(imximage_cmds, + "imximage commands", token); + if (*cmd < 0) { + fprintf(stderr, "Error: %s[%d] - Invalid command" + "(%s)\n", name, lineno, token); + exit(EXIT_FAILURE); + } + break; + case CFG_REG_SIZE: + parse_cfg_cmd(imxhdr, *cmd, token, name, lineno, fld, *dcd_len); + break; + case CFG_REG_ADDRESS: + case CFG_REG_VALUE: + if (*cmd != CMD_DATA) + return; + + value = get_cfg_value(token, name, lineno); + (*set_dcd_val)(imxhdr, name, lineno, fld, value, *dcd_len); + + if (fld == CFG_REG_VALUE) + (*dcd_len)++; + break; + default: + break; + } +} +static uint32_t parse_cfg_file(struct imx_header *imxhdr, char *name) +{ + FILE *fd = NULL; + char *line = NULL; + char *token, *saveptr1, *saveptr2; + int lineno = 0; + int fld; + size_t len; + int dcd_len = 0; + int32_t cmd; + + fd = fopen(name, "r"); + if (fd == 0) { + fprintf(stderr, "Error: %s - Can't open DCD file\n", name); + exit(EXIT_FAILURE); + } + + /* Very simple parsing, line starting with # are comments + * and are dropped + */ + while ((getline(&line, &len, fd)) > 0) { + lineno++; + + token = strtok_r(line, "\r\n", &saveptr1); + if (token == NULL) + continue; + + /* Check inside the single line */ + for (fld = CFG_COMMAND, cmd = CMD_INVALID, + line = token; ; line = NULL, fld++) { + token = strtok_r(line, " \t", &saveptr2); + if (token == NULL) + break; + + /* Drop all text starting with '#' as comments */ + if (token[0] == '#') + break; + + parse_cfg_fld(imxhdr, &cmd, token, name, + lineno, fld, &dcd_len); + } + + } + + (*set_dcd_rst)(imxhdr, dcd_len, name, lineno); + fclose(fd); + + return dcd_len; +} + + +static int imximage_check_image_types(uint8_t type) +{ + if (type == IH_TYPE_IMXIMAGE) + return EXIT_SUCCESS; + else + return EXIT_FAILURE; +} + +static int imximage_verify_header(unsigned char *ptr, int image_size, + struct mkimage_params *params) +{ + struct imx_header *imx_hdr = (struct imx_header *) ptr; + + if (detect_imximage_version(imx_hdr) == IMXIMAGE_VER_INVALID) + return -FDT_ERR_BADSTRUCTURE; + + return 0; +} + +static void imximage_print_header(const void *ptr) +{ + struct imx_header *imx_hdr = (struct imx_header *) ptr; + uint32_t version = detect_imximage_version(imx_hdr); + + switch (version) { + case IMXIMAGE_V1: + print_hdr_v1(imx_hdr); + break; + case IMXIMAGE_V2: + print_hdr_v2(imx_hdr); + break; + default: + err_imximage_version(version); + break; + } +} + +static void imximage_set_header(void *ptr, struct stat *sbuf, int ifd, + struct mkimage_params *params) +{ + struct imx_header *imxhdr = (struct imx_header *)ptr; + uint32_t dcd_len; + + /* + * In order to not change the old imx cfg file + * by adding VERSION command into it, here need + * set up function ptr group to V1 by default. + */ + imximage_version = IMXIMAGE_V1; + set_hdr_func(imxhdr); + + /* Parse dcd configuration file */ + dcd_len = parse_cfg_file(imxhdr, params->imagename); + + /* Set the imx header */ + (*set_imx_hdr)(imxhdr, dcd_len, sbuf, params); +} + +int imximage_check_params(struct mkimage_params *params) +{ + if (!params) + return CFG_INVALID; + if (!strlen(params->imagename)) { + fprintf(stderr, "Error: %s - Configuration file not specified, " + "it is needed for imximage generation\n", + params->cmdname); + return CFG_INVALID; + } + /* + * Check parameters: + * XIP is not allowed and verify that incompatible + * parameters are not sent at the same time + * For example, if list is required a data image must not be provided + */ + return (params->dflag && (params->fflag || params->lflag)) || + (params->fflag && (params->dflag || params->lflag)) || + (params->lflag && (params->dflag || params->fflag)) || + (params->xflag) || !(strlen(params->imagename)); +} + +/* + * imximage parameters + */ +static struct image_type_params imximage_params = { + .name = "Freescale i.MX 5x Boot Image support", + .header_size = sizeof(struct imx_header), + .hdr = (void *)&imximage_header, + .check_image_type = imximage_check_image_types, + .verify_header = imximage_verify_header, + .print_header = imximage_print_header, + .set_header = imximage_set_header, + .check_params = imximage_check_params, +}; + +void init_imx_image_type(void) +{ + mkimage_register(&imximage_params); +} diff --git a/u-boot/tools/imximage.h b/u-boot/tools/imximage.h new file mode 100644 index 0000000..38ca6be --- /dev/null +++ b/u-boot/tools/imximage.h @@ -0,0 +1,175 @@ +/* + * (C) Copyright 2009 + * Stefano Babic, DENX Software Engineering, sbabic@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _IMXIMAGE_H_ +#define _IMXIMAGE_H_ + +#include <config.h> + +#define MAX_HW_CFG_SIZE_V2 121 /* Max number of registers imx can set for v2 */ +#define MAX_HW_CFG_SIZE_V1 60 /* Max number of registers imx can set for v1 */ +#define APP_CODE_BARKER 0xB1 +#define DCD_BARKER 0xB17219E9 + +#define HEADER_OFFSET 0x400 + +#define CMD_DATA_STR "DATA" +#define FLASH_OFFSET_STANDARD 0x400 +#define FLASH_OFFSET_NAND FLASH_OFFSET_STANDARD +#define FLASH_OFFSET_SD FLASH_OFFSET_STANDARD +#define FLASH_OFFSET_SPI FLASH_OFFSET_STANDARD +#define FLASH_OFFSET_ONENAND 0x100 + +#define IVT_HEADER_TAG 0xD1 +#define IVT_VERSION 0x40 +#define DCD_HEADER_TAG 0xD2 +#define DCD_COMMAND_TAG 0xCC +#define DCD_VERSION 0x40 +#define DCD_COMMAND_PARAM 0x4 + +enum imximage_cmd { + CMD_INVALID, + CMD_IMAGE_VERSION, + CMD_BOOT_FROM, + CMD_DATA +}; + +enum imximage_fld_types { + CFG_INVALID = -1, + CFG_COMMAND, + CFG_REG_SIZE, + CFG_REG_ADDRESS, + CFG_REG_VALUE +}; + +enum imximage_version { + IMXIMAGE_VER_INVALID = -1, + IMXIMAGE_V1 = 1, + IMXIMAGE_V2 +}; + +typedef struct { + uint32_t type; /* Type of pointer (byte, halfword, word, wait/read) */ + uint32_t addr; /* Address to write to */ + uint32_t value; /* Data to write */ +} dcd_type_addr_data_t; + +typedef struct { + uint32_t barker; /* Barker for sanity check */ + uint32_t length; /* Device configuration length (without preamble) */ +} dcd_preamble_t; + +typedef struct { + dcd_preamble_t preamble; + dcd_type_addr_data_t addr_data[MAX_HW_CFG_SIZE_V1]; +} dcd_v1_t; + +typedef struct { + uint32_t app_code_jump_vector; + uint32_t app_code_barker; + uint32_t app_code_csf; + uint32_t dcd_ptr_ptr; + uint32_t super_root_key; + uint32_t dcd_ptr; + uint32_t app_dest_ptr; +} flash_header_v1_t; + +typedef struct { + uint32_t length; /* Length of data to be read from flash */ +} flash_cfg_parms_t; + +typedef struct { + flash_header_v1_t fhdr; + dcd_v1_t dcd_table; + flash_cfg_parms_t ext_header; +} imx_header_v1_t; + +typedef struct { + uint32_t addr; + uint32_t value; +} dcd_addr_data_t; + +typedef struct { + uint8_t tag; + uint16_t length; + uint8_t version; +} __attribute__((packed)) ivt_header_t; + +typedef struct { + uint8_t tag; + uint16_t length; + uint8_t param; +} __attribute__((packed)) write_dcd_command_t; + +typedef struct { + ivt_header_t header; + write_dcd_command_t write_dcd_command; + dcd_addr_data_t addr_data[MAX_HW_CFG_SIZE_V2]; +} dcd_v2_t; + +typedef struct { + uint32_t start; + uint32_t size; + uint32_t plugin; +} boot_data_t; + +typedef struct { + ivt_header_t header; + uint32_t entry; + uint32_t reserved1; + uint32_t dcd_ptr; + uint32_t boot_data_ptr; + uint32_t self; + uint32_t csf; + uint32_t reserved2; +} flash_header_v2_t; + +typedef struct { + flash_header_v2_t fhdr; + boot_data_t boot_data; + dcd_v2_t dcd_table; +} imx_header_v2_t; + +struct imx_header { + union { + imx_header_v1_t hdr_v1; + imx_header_v2_t hdr_v2; + } header; + uint32_t flash_offset; +}; + +typedef void (*set_dcd_val_t)(struct imx_header *imxhdr, + char *name, int lineno, + int fld, uint32_t value, + uint32_t off); + +typedef void (*set_dcd_rst_t)(struct imx_header *imxhdr, + uint32_t dcd_len, + char *name, int lineno); + +typedef void (*set_imx_hdr_t)(struct imx_header *imxhdr, + uint32_t dcd_len, + struct stat *sbuf, + struct mkimage_params *params); + +#endif /* _IMXIMAGE_H_ */ diff --git a/u-boot/tools/inca-swap-bytes.c b/u-boot/tools/inca-swap-bytes.c new file mode 100644 index 0000000..3a6d82d --- /dev/null +++ b/u-boot/tools/inca-swap-bytes.c @@ -0,0 +1,38 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#ifndef BUFSIZ +# define BUFSIZ 4096 +#endif + +#undef BUFSIZ +# define BUFSIZ 64 +int main (void) +{ + short ibuff[BUFSIZ], obuff[BUFSIZ]; + int rc, i, len; + + while ((rc = read (0, ibuff, sizeof (ibuff))) > 0) { + memset (obuff, 0, sizeof (obuff)); + for (i = 0; i < (rc + 1) / 2; i++) { + obuff[i] = ibuff[i ^ 1]; + } + + len = (rc + 1) & ~1; + + if (write (1, obuff, len) != len) { + perror ("read error"); + return (EXIT_FAILURE); + } + + memset (ibuff, 0, sizeof (ibuff)); + } + + if (rc < 0) { + perror ("read error"); + return (EXIT_FAILURE); + } + return (EXIT_SUCCESS); +} diff --git a/u-boot/tools/jtagconsole b/u-boot/tools/jtagconsole new file mode 100755 index 0000000..d404fac --- /dev/null +++ b/u-boot/tools/jtagconsole @@ -0,0 +1,39 @@ +#!/bin/sh + +usage() { + ( + echo "Usage: $0 [board IP] [board port]" + echo "" + echo "If IP is not specified, 'localhost' will be used" + echo "If port is not specified, '2001' will be used" + [ -z "$*" ] && exit 0 + echo "" + echo "ERROR: $*" + exit 1 + ) 1>&2 + exit $? +} + +while [ -n "$1" ] ; do + case $1 in + -h|--help) usage;; + --) break;; + -*) usage "Invalid option $1";; + *) break;; + esac + shift +done + +ip=${1:-localhost} +port=${2:-2001} + +if [ -z "${ip}" ] || [ -n "$3" ] ; then + usage "Invalid number of arguments" +fi + +trap "stty icanon echo opost intr ^C" 0 2 3 5 10 13 15 +echo "NOTE: the interrupt signal (normally ^C) has been remapped to ^T" + +stty -icanon -echo -opost intr ^T +nc ${ip} ${port} +exit 0 diff --git a/u-boot/tools/kwbimage.c b/u-boot/tools/kwbimage.c new file mode 100644 index 0000000..964796e --- /dev/null +++ b/u-boot/tools/kwbimage.c @@ -0,0 +1,405 @@ +/* + * (C) Copyright 2008 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Prafulla Wadaskar <prafulla@marvell.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* Required to obtain the getline prototype from stdio.h */ +#define _GNU_SOURCE + +#include "mkimage.h" +#include <image.h> +#include "kwbimage.h" + +/* + * Supported commands for configuration file + */ +static table_entry_t kwbimage_cmds[] = { + {CMD_BOOT_FROM, "BOOT_FROM", "boot command", }, + {CMD_NAND_ECC_MODE, "NAND_ECC_MODE", "NAND mode", }, + {CMD_NAND_PAGE_SIZE, "NAND_PAGE_SIZE", "NAND size", }, + {CMD_SATA_PIO_MODE, "SATA_PIO_MODE", "SATA mode", }, + {CMD_DDR_INIT_DELAY, "DDR_INIT_DELAY", "DDR init dly", }, + {CMD_DATA, "DATA", "Reg Write Data", }, + {CMD_INVALID, "", "", }, +}; + +/* + * Supported Boot options for configuration file + */ +static table_entry_t kwbimage_bootops[] = { + {IBR_HDR_SPI_ID, "spi", "SPI Flash", }, + {IBR_HDR_NAND_ID, "nand", "NAND Flash", }, + {IBR_HDR_SATA_ID, "sata", "Sata port", }, + {IBR_HDR_PEX_ID, "pex", "PCIe port", }, + {IBR_HDR_UART_ID, "uart", "Serial port", }, + {-1, "", "Invalid", }, +}; + +/* + * Supported NAND ecc options configuration file + */ +static table_entry_t kwbimage_eccmodes[] = { + {IBR_HDR_ECC_DEFAULT, "default", "Default mode", }, + {IBR_HDR_ECC_FORCED_HAMMING, "hamming", "Hamming mode", }, + {IBR_HDR_ECC_FORCED_RS, "rs", "RS mode", }, + {IBR_HDR_ECC_DISABLED, "disabled", "ECC Disabled", }, + {-1, "", "", }, +}; + +static struct kwb_header kwbimage_header; +static int datacmd_cnt = 0; +static char * fname = "Unknown"; +static int lineno = -1; + +/* + * Report Error if xflag is set in addition to default + */ +static int kwbimage_check_params (struct mkimage_params *params) +{ + if (!strlen (params->imagename)) { + printf ("Error:%s - Configuration file not specified, " + "it is needed for kwbimage generation\n", + params->cmdname); + return CFG_INVALID; + } + return ((params->dflag && (params->fflag || params->lflag)) || + (params->fflag && (params->dflag || params->lflag)) || + (params->lflag && (params->dflag || params->fflag)) || + (params->xflag) || !(strlen (params->imagename))); +} + +static uint32_t check_get_hexval (char *token) +{ + uint32_t hexval; + + if (!sscanf (token, "%x", &hexval)) { + printf ("Error:%s[%d] - Invalid hex data(%s)\n", fname, + lineno, token); + exit (EXIT_FAILURE); + } + return hexval; +} + +/* + * Generates 8 bit checksum + */ +static uint8_t kwbimage_checksum8 (void *start, uint32_t len, uint8_t csum) +{ + register uint8_t sum = csum; + volatile uint8_t *p = (volatile uint8_t *)start; + + /* check len and return zero checksum if invalid */ + if (!len) + return 0; + + do { + sum += *p; + p++; + } while (--len); + return (sum); +} + +/* + * Generates 32 bit checksum + */ +static uint32_t kwbimage_checksum32 (uint32_t *start, uint32_t len, uint32_t csum) +{ + register uint32_t sum = csum; + volatile uint32_t *p = start; + + /* check len and return zero checksum if invalid */ + if (!len) + return 0; + + if (len % sizeof(uint32_t)) { + printf ("Error:%s[%d] - length is not in multiple of %zu\n", + __FUNCTION__, len, sizeof(uint32_t)); + return 0; + } + + do { + sum += *p; + p++; + len -= sizeof(uint32_t); + } while (len > 0); + return (sum); +} + +static void kwbimage_check_cfgdata (char *token, enum kwbimage_cmd cmdsw, + struct kwb_header *kwbhdr) +{ + bhr_t *mhdr = &kwbhdr->kwb_hdr; + extbhr_t *exthdr = &kwbhdr->kwb_exthdr; + int i; + + switch (cmdsw) { + case CMD_BOOT_FROM: + i = get_table_entry_id (kwbimage_bootops, + "Kwbimage boot option", token); + + if (i < 0) + goto INVL_DATA; + + mhdr->blockid = i; + printf ("Preparing kirkwood boot image to boot " + "from %s\n", token); + break; + case CMD_NAND_ECC_MODE: + i = get_table_entry_id (kwbimage_eccmodes, + "NAND ecc mode", token); + + if (i < 0) + goto INVL_DATA; + + mhdr->nandeccmode = i; + printf ("Nand ECC mode = %s\n", token); + break; + case CMD_NAND_PAGE_SIZE: + mhdr->nandpagesize = + (uint16_t) check_get_hexval (token); + printf ("Nand page size = 0x%x\n", mhdr->nandpagesize); + break; + case CMD_SATA_PIO_MODE: + mhdr->satapiomode = + (uint8_t) check_get_hexval (token); + printf ("Sata PIO mode = 0x%x\n", + mhdr->satapiomode); + break; + case CMD_DDR_INIT_DELAY: + mhdr->ddrinitdelay = + (uint16_t) check_get_hexval (token); + printf ("DDR init delay = %d msec\n", mhdr->ddrinitdelay); + break; + case CMD_DATA: + exthdr->rcfg[datacmd_cnt].raddr = + check_get_hexval (token); + + break; + case CMD_INVALID: + goto INVL_DATA; + default: + goto INVL_DATA; + } + return; + +INVL_DATA: + printf ("Error:%s[%d] - Invalid data\n", fname, lineno); + exit (EXIT_FAILURE); +} + +/* + * this function sets the kwbimage header by- + * 1. Abstracting input command line arguments data + * 2. parses the kwbimage configuration file and update extebded header data + * 3. calculates header, extended header and image checksums + */ +static void kwdimage_set_ext_header (struct kwb_header *kwbhdr, char* name) { + bhr_t *mhdr = &kwbhdr->kwb_hdr; + extbhr_t *exthdr = &kwbhdr->kwb_exthdr; + FILE *fd = NULL; + int j; + char *line = NULL; + char * token, *saveptr1, *saveptr2; + size_t len = 0; + enum kwbimage_cmd cmd; + + fname = name; + /* set dram register offset */ + exthdr->dramregsoffs = (intptr_t)&exthdr->rcfg - (intptr_t)mhdr; + + if ((fd = fopen (name, "r")) == 0) { + printf ("Error:%s - Can't open\n", fname); + exit (EXIT_FAILURE); + } + + /* Simple kwimage.cfg file parser */ + lineno=0; + while ((getline (&line, &len, fd)) > 0) { + lineno++; + token = strtok_r (line, "\r\n", &saveptr1); + /* drop all lines with zero tokens (= empty lines) */ + if (token == NULL) + continue; + + for (j = 0, cmd = CMD_INVALID, line = token; ; line = NULL) { + token = strtok_r (line, " \t", &saveptr2); + if (token == NULL) + break; + /* Drop all text starting with '#' as comments */ + if (token[0] == '#') + break; + + /* Process rest as valid config command line */ + switch (j) { + case CFG_COMMAND: + cmd = get_table_entry_id (kwbimage_cmds, + "Kwbimage command", token); + + if (cmd == CMD_INVALID) + goto INVL_CMD; + break; + + case CFG_DATA0: + kwbimage_check_cfgdata (token, cmd, kwbhdr); + break; + + case CFG_DATA1: + if (cmd != CMD_DATA) + goto INVL_CMD; + + exthdr->rcfg[datacmd_cnt].rdata = + check_get_hexval (token); + + if (datacmd_cnt > KWBIMAGE_MAX_CONFIG ) { + printf ("Error:%s[%d] - Found more " + "than max(%zd) allowed " + "data configurations\n", + fname, lineno, + KWBIMAGE_MAX_CONFIG); + exit (EXIT_FAILURE); + } else + datacmd_cnt++; + break; + + default: + goto INVL_CMD; + } + j++; + } + } + if (line) + free (line); + + fclose (fd); + return; + +/* + * Invalid Command error reporring + * + * command CMD_DATA needs three strings on a line + * whereas other commands need only two. + * + * if more than two/three (as per command type) are observed, + * then error will be reported + */ +INVL_CMD: + printf ("Error:%s[%d] - Invalid command\n", fname, lineno); + exit (EXIT_FAILURE); +} + +static void kwbimage_set_header (void *ptr, struct stat *sbuf, int ifd, + struct mkimage_params *params) +{ + struct kwb_header *hdr = (struct kwb_header *)ptr; + bhr_t *mhdr = &hdr->kwb_hdr; + extbhr_t *exthdr = &hdr->kwb_exthdr; + uint32_t checksum; + int size; + + /* Build and add image checksum header */ + checksum = kwbimage_checksum32 ((uint32_t *)ptr, sbuf->st_size, 0); + + size = write (ifd, &checksum, sizeof(uint32_t)); + if (size != sizeof(uint32_t)) { + printf ("Error:%s - Checksum write %d bytes %s\n", + params->cmdname, size, params->imagefile); + exit (EXIT_FAILURE); + } + + sbuf->st_size += sizeof(uint32_t); + + mhdr->blocksize = sbuf->st_size - sizeof(struct kwb_header); + mhdr->srcaddr = sizeof(struct kwb_header); + mhdr->destaddr= params->addr; + mhdr->execaddr =params->ep; + mhdr->ext = 0x1; /* header extension appended */ + + kwdimage_set_ext_header (hdr, params->imagename); + /* calculate checksums */ + mhdr->checkSum = kwbimage_checksum8 ((void *)mhdr, sizeof(bhr_t), 0); + exthdr->checkSum = kwbimage_checksum8 ((void *)exthdr, + sizeof(extbhr_t), 0); +} + +static int kwbimage_verify_header (unsigned char *ptr, int image_size, + struct mkimage_params *params) +{ + struct kwb_header *hdr = (struct kwb_header *)ptr; + bhr_t *mhdr = &hdr->kwb_hdr; + extbhr_t *exthdr = &hdr->kwb_exthdr; + uint8_t calc_hdrcsum; + uint8_t calc_exthdrcsum; + + calc_hdrcsum = kwbimage_checksum8 ((void *)mhdr, + sizeof(bhr_t) - sizeof(uint8_t), 0); + if (calc_hdrcsum != mhdr->checkSum) + return -FDT_ERR_BADSTRUCTURE; /* mhdr csum not matched */ + + calc_exthdrcsum = kwbimage_checksum8 ((void *)exthdr, + sizeof(extbhr_t) - sizeof(uint8_t), 0); + if (calc_hdrcsum != mhdr->checkSum) + return -FDT_ERR_BADSTRUCTURE; /* exthdr csum not matched */ + + return 0; +} + +static void kwbimage_print_header (const void *ptr) +{ + struct kwb_header *hdr = (struct kwb_header *) ptr; + bhr_t *mhdr = &hdr->kwb_hdr; + char *name = get_table_entry_name (kwbimage_bootops, + "Kwbimage boot option", + (int) mhdr->blockid); + + printf ("Image Type: Kirkwood Boot from %s Image\n", name); + printf ("Data Size: "); + genimg_print_size (mhdr->blocksize - sizeof(uint32_t)); + printf ("Load Address: %08x\n", mhdr->destaddr); + printf ("Entry Point: %08x\n", mhdr->execaddr); +} + +static int kwbimage_check_image_types (uint8_t type) +{ + if (type == IH_TYPE_KWBIMAGE) + return EXIT_SUCCESS; + else + return EXIT_FAILURE; +} + +/* + * kwbimage type parameters definition + */ +static struct image_type_params kwbimage_params = { + .name = "Kirkwood Boot Image support", + .header_size = sizeof(struct kwb_header), + .hdr = (void*)&kwbimage_header, + .check_image_type = kwbimage_check_image_types, + .verify_header = kwbimage_verify_header, + .print_header = kwbimage_print_header, + .set_header = kwbimage_set_header, + .check_params = kwbimage_check_params, +}; + +void init_kwb_image_type (void) +{ + mkimage_register (&kwbimage_params); +} diff --git a/u-boot/tools/kwbimage.h b/u-boot/tools/kwbimage.h new file mode 100644 index 0000000..3d3d5e9 --- /dev/null +++ b/u-boot/tools/kwbimage.h @@ -0,0 +1,106 @@ +/* + * (C) Copyright 2008 + * Marvell Semiconductor <www.marvell.com> + * Written-by: Prafulla Wadaskar <prafulla@marvell.com> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _KWBIMAGE_H_ +#define _KWBIMAGE_H_ + +#include <stdint.h> + +#define KWBIMAGE_MAX_CONFIG ((0x1dc - 0x20)/sizeof(struct reg_config)) +#define MAX_TEMPBUF_LEN 32 + +/* NAND ECC Mode */ +#define IBR_HDR_ECC_DEFAULT 0x00 +#define IBR_HDR_ECC_FORCED_HAMMING 0x01 +#define IBR_HDR_ECC_FORCED_RS 0x02 +#define IBR_HDR_ECC_DISABLED 0x03 + +/* Boot Type - block ID */ +#define IBR_HDR_I2C_ID 0x4D +#define IBR_HDR_SPI_ID 0x5A +#define IBR_HDR_NAND_ID 0x8B +#define IBR_HDR_SATA_ID 0x78 +#define IBR_HDR_PEX_ID 0x9C +#define IBR_HDR_UART_ID 0x69 +#define IBR_DEF_ATTRIB 0x00 + +enum kwbimage_cmd { + CMD_INVALID, + CMD_BOOT_FROM, + CMD_NAND_ECC_MODE, + CMD_NAND_PAGE_SIZE, + CMD_SATA_PIO_MODE, + CMD_DDR_INIT_DELAY, + CMD_DATA +}; + +enum kwbimage_cmd_types { + CFG_INVALID = -1, + CFG_COMMAND, + CFG_DATA0, + CFG_DATA1 +}; + +/* typedefs */ +typedef struct bhr_t { + uint8_t blockid; /*0 */ + uint8_t nandeccmode; /*1 */ + uint16_t nandpagesize; /*2-3 */ + uint32_t blocksize; /*4-7 */ + uint32_t rsvd1; /*8-11 */ + uint32_t srcaddr; /*12-15 */ + uint32_t destaddr; /*16-19 */ + uint32_t execaddr; /*20-23 */ + uint8_t satapiomode; /*24 */ + uint8_t rsvd3; /*25 */ + uint16_t ddrinitdelay; /*26-27 */ + uint16_t rsvd2; /*28-29 */ + uint8_t ext; /*30 */ + uint8_t checkSum; /*31 */ +} bhr_t, *pbhr_t; + +struct reg_config { + uint32_t raddr; + uint32_t rdata; +}; + +typedef struct extbhr_t { + uint32_t dramregsoffs; + uint8_t rsrvd1[0x20 - sizeof(uint32_t)]; + struct reg_config rcfg[KWBIMAGE_MAX_CONFIG]; + uint8_t rsrvd2[7]; + uint8_t checkSum; +} extbhr_t, *pextbhr_t; + +struct kwb_header { + bhr_t kwb_hdr; + extbhr_t kwb_exthdr; +}; + +/* + * functions + */ +void init_kwb_image_type (void); + +#endif /* _KWBIMAGE_H_ */ diff --git a/u-boot/tools/logos/atmel.bmp b/u-boot/tools/logos/atmel.bmp Binary files differnew file mode 100644 index 0000000..3c445c9 --- /dev/null +++ b/u-boot/tools/logos/atmel.bmp diff --git a/u-boot/tools/logos/denx.bmp b/u-boot/tools/logos/denx.bmp Binary files differnew file mode 100644 index 0000000..c4cde09 --- /dev/null +++ b/u-boot/tools/logos/denx.bmp diff --git a/u-boot/tools/logos/esd.bmp b/u-boot/tools/logos/esd.bmp Binary files differnew file mode 100644 index 0000000..a6b4030 --- /dev/null +++ b/u-boot/tools/logos/esd.bmp diff --git a/u-boot/tools/logos/freescale.bmp b/u-boot/tools/logos/freescale.bmp Binary files differnew file mode 100644 index 0000000..1589e80 --- /dev/null +++ b/u-boot/tools/logos/freescale.bmp diff --git a/u-boot/tools/logos/linux_logo_ttcontrol.bmp b/u-boot/tools/logos/linux_logo_ttcontrol.bmp Binary files differnew file mode 100644 index 0000000..031d3a4 --- /dev/null +++ b/u-boot/tools/logos/linux_logo_ttcontrol.bmp diff --git a/u-boot/tools/logos/linux_logo_ttcontrol_palfin.bmp b/u-boot/tools/logos/linux_logo_ttcontrol_palfin.bmp Binary files differnew file mode 100644 index 0000000..e3e38d1 --- /dev/null +++ b/u-boot/tools/logos/linux_logo_ttcontrol_palfin.bmp diff --git a/u-boot/tools/logos/ronetix.bmp b/u-boot/tools/logos/ronetix.bmp Binary files differnew file mode 100644 index 0000000..f956813 --- /dev/null +++ b/u-boot/tools/logos/ronetix.bmp diff --git a/u-boot/tools/logos/syteco.bmp b/u-boot/tools/logos/syteco.bmp Binary files differnew file mode 100644 index 0000000..9a994fe --- /dev/null +++ b/u-boot/tools/logos/syteco.bmp diff --git a/u-boot/tools/mingw_support.c b/u-boot/tools/mingw_support.c new file mode 100644 index 0000000..18b69bb --- /dev/null +++ b/u-boot/tools/mingw_support.c @@ -0,0 +1,139 @@ +/* + * Copyright 2008 Extreme Engineering Solutions, Inc. + * + * mmap/munmap implementation derived from: + * Clamav Native Windows Port : mmap win32 compatibility layer + * Copyright (c) 2005-2006 Gianluigi Tiesi <sherpya@netfarm.it> + * Parts by Kees Zeelenberg <kzlg@users.sourceforge.net> (LibGW32C) + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this software; if not, write to the + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "mingw_support.h" +#include <stdio.h> +#include <stdint.h> +#include <string.h> +#include <errno.h> +#include <assert.h> +#include <io.h> + +int fsync(int fd) +{ + return _commit(fd); +} + +void *mmap(void *addr, size_t len, int prot, int flags, int fd, int offset) +{ + void *map = NULL; + HANDLE handle = INVALID_HANDLE_VALUE; + DWORD cfm_flags = 0, mvf_flags = 0; + + switch (prot) { + case PROT_READ | PROT_WRITE: + cfm_flags = PAGE_READWRITE; + mvf_flags = FILE_MAP_ALL_ACCESS; + break; + case PROT_WRITE: + cfm_flags = PAGE_READWRITE; + mvf_flags = FILE_MAP_WRITE; + break; + case PROT_READ: + cfm_flags = PAGE_READONLY; + mvf_flags = FILE_MAP_READ; + break; + default: + return MAP_FAILED; + } + + handle = CreateFileMappingA((HANDLE) _get_osfhandle(fd), NULL, + cfm_flags, HIDWORD(len), LODWORD(len), NULL); + if (!handle) + return MAP_FAILED; + + map = MapViewOfFile(handle, mvf_flags, HIDWORD(offset), + LODWORD(offset), len); + CloseHandle(handle); + + if (!map) + return MAP_FAILED; + + return map; +} + +int munmap(void *addr, size_t len) +{ + if (!UnmapViewOfFile(addr)) + return -1; + + return 0; +} + +/* Reentrant string tokenizer. Generic version. + Copyright (C) 1991,1996-1999,2001,2004,2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + 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 + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +/* Parse S into tokens separated by characters in DELIM. + If S is NULL, the saved pointer in SAVE_PTR is used as + the next starting point. For example: + char s[] = "-abc-=-def"; + char *sp; + x = strtok_r(s, "-", &sp); // x = "abc", sp = "=-def" + x = strtok_r(NULL, "-=", &sp); // x = "def", sp = NULL + x = strtok_r(NULL, "=", &sp); // x = NULL + // s = "abc\0-def\0" +*/ +char *strtok_r(char *s, const char *delim, char **save_ptr) +{ + char *token; + + if (s == NULL) + s = *save_ptr; + + /* Scan leading delimiters. */ + s += strspn(s, delim); + if (*s == '\0') { + *save_ptr = s; + return NULL; + } + + /* Find the end of the token. */ + token = s; + s = strpbrk (token, delim); + if (s == NULL) { + /* This token finishes the string. */ + *save_ptr = memchr(token, '\0', strlen(token)); + } else { + /* Terminate the token and make *SAVE_PTR point past it. */ + *s = '\0'; + *save_ptr = s + 1; + } + return token; +} + +#include "getline.c" diff --git a/u-boot/tools/mingw_support.h b/u-boot/tools/mingw_support.h new file mode 100644 index 0000000..ee07290 --- /dev/null +++ b/u-boot/tools/mingw_support.h @@ -0,0 +1,50 @@ +/* + * Copyright 2008 Extreme Engineering Solutions, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this software; if not, write to the + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __MINGW_SUPPORT_H_ +#define __WINGW_SUPPORT_H_ 1 + +/* Defining __INSIDE_MSYS__ helps to prevent u-boot/mingw overlap */ +#define __INSIDE_MSYS__ 1 + +#include <windows.h> + +/* mmap protections */ +#define PROT_READ 0x1 /* Page can be read */ +#define PROT_WRITE 0x2 /* Page can be written */ +#define PROT_EXEC 0x4 /* Page can be executed */ +#define PROT_NONE 0x0 /* Page can not be accessed */ + +/* Sharing types (must choose one and only one of these) */ +#define MAP_SHARED 0x01 /* Share changes */ +#define MAP_PRIVATE 0x02 /* Changes are private */ + +/* Windows 64-bit access macros */ +#define LODWORD(x) ((DWORD)((DWORDLONG)(x))) +#define HIDWORD(x) ((DWORD)(((DWORDLONG)(x) >> 32) & 0xffffffff)) + +typedef UINT uint; +typedef ULONG ulong; + +int fsync(int fd); +void *mmap(void *, size_t, int, int, int, int); +int munmap(void *, size_t); +char *strtok_r(char *s, const char *delim, char **save_ptr); +#include "getline.h" + +#endif /* __MINGW_SUPPORT_H_ */ diff --git a/u-boot/tools/mkimage.c b/u-boot/tools/mkimage.c new file mode 100644 index 0000000..f5859d7 --- /dev/null +++ b/u-boot/tools/mkimage.c @@ -0,0 +1,595 @@ +/* + * (C) Copyright 2008 Semihalf + * + * (C) Copyright 2000-2009 + * DENX Software Engineering + * Wolfgang Denk, wd@denx.de + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include "mkimage.h" +#include <image.h> + +static void copy_file(int, const char *, int); +static void usage(void); + +/* image_type_params link list to maintain registered image type supports */ +struct image_type_params *mkimage_tparams = NULL; + +/* parameters initialized by core will be used by the image type code */ +struct mkimage_params params = { + .os = IH_OS_LINUX, + .arch = IH_ARCH_PPC, + .type = IH_TYPE_KERNEL, + .comp = IH_COMP_GZIP, + .dtc = MKIMAGE_DEFAULT_DTC_OPTIONS, + .imagename = "", +}; + +/* + * mkimage_register - + * + * It is used to register respective image generation/list support to the + * mkimage core + * + * the input struct image_type_params is checked and appended to the link + * list, if the input structure is already registered, error + */ +void mkimage_register (struct image_type_params *tparams) +{ + struct image_type_params **tp; + + if (!tparams) { + fprintf (stderr, "%s: %s: Null input\n", + params.cmdname, __FUNCTION__); + exit (EXIT_FAILURE); + } + + /* scan the linked list, check for registry and point the last one */ + for (tp = &mkimage_tparams; *tp != NULL; tp = &(*tp)->next) { + if (!strcmp((*tp)->name, tparams->name)) { + fprintf (stderr, "%s: %s already registered\n", + params.cmdname, tparams->name); + return; + } + } + + /* add input struct entry at the end of link list */ + *tp = tparams; + /* mark input entry as last entry in the link list */ + tparams->next = NULL; + + debug ("Registered %s\n", tparams->name); +} + +/* + * mkimage_get_type - + * + * It scans all registers image type supports + * checks the input type_id for each supported image type + * + * if successful, + * returns respective image_type_params pointer if success + * if input type_id is not supported by any of image_type_support + * returns NULL + */ +struct image_type_params *mkimage_get_type(int type) +{ + struct image_type_params *curr; + + for (curr = mkimage_tparams; curr != NULL; curr = curr->next) { + if (curr->check_image_type) { + if (!curr->check_image_type (type)) + return curr; + } + } + return NULL; +} + +/* + * mkimage_verify_print_header - + * + * It scans mkimage_tparams link list, + * verifies image_header for each supported image type + * if verification is successful, prints respective header + * + * returns negative if input image format does not match with any of + * supported image types + */ +int mkimage_verify_print_header (void *ptr, struct stat *sbuf) +{ + int retval = -1; + struct image_type_params *curr; + + for (curr = mkimage_tparams; curr != NULL; curr = curr->next ) { + if (curr->verify_header) { + retval = curr->verify_header ( + (unsigned char *)ptr, sbuf->st_size, + ¶ms); + + if (retval == 0) { + /* + * Print the image information + * if verify is successful + */ + if (curr->print_header) + curr->print_header (ptr); + else { + fprintf (stderr, + "%s: print_header undefined for %s\n", + params.cmdname, curr->name); + } + break; + } + } + } + return retval; +} + +int +main (int argc, char **argv) +{ + int ifd = -1; + struct stat sbuf; + char *ptr; + int retval = 0; + struct image_type_params *tparams = NULL; + + /* Init Kirkwood Boot image generation/list support */ + init_kwb_image_type (); + /* Init Freescale imx Boot image generation/list support */ + init_imx_image_type (); + /* Init FIT image generation/list support */ + init_fit_image_type (); + /* Init Default image generation/list support */ + init_default_image_type (); + + params.cmdname = *argv; + params.addr = params.ep = 0; + + while (--argc > 0 && **++argv == '-') { + while (*++*argv) { + switch (**argv) { + case 'l': + params.lflag = 1; + break; + case 'A': + if ((--argc <= 0) || + (params.arch = + genimg_get_arch_id (*++argv)) < 0) + usage (); + goto NXTARG; + case 'C': + if ((--argc <= 0) || + (params.comp = + genimg_get_comp_id (*++argv)) < 0) + usage (); + goto NXTARG; + case 'D': + if (--argc <= 0) + usage (); + params.dtc = *++argv; + goto NXTARG; + + case 'O': + if ((--argc <= 0) || + (params.os = + genimg_get_os_id (*++argv)) < 0) + usage (); + goto NXTARG; + case 'T': + if ((--argc <= 0) || + (params.type = + genimg_get_type_id (*++argv)) < 0) + usage (); + goto NXTARG; + + case 'a': + if (--argc <= 0) + usage (); + params.addr = strtoul (*++argv, &ptr, 16); + if (*ptr) { + fprintf (stderr, + "%s: invalid load address %s\n", + params.cmdname, *argv); + exit (EXIT_FAILURE); + } + goto NXTARG; + case 'd': + if (--argc <= 0) + usage (); + params.datafile = *++argv; + params.dflag = 1; + goto NXTARG; + case 'e': + if (--argc <= 0) + usage (); + params.ep = strtoul (*++argv, &ptr, 16); + if (*ptr) { + fprintf (stderr, + "%s: invalid entry point %s\n", + params.cmdname, *argv); + exit (EXIT_FAILURE); + } + params.eflag = 1; + goto NXTARG; + case 'f': + if (--argc <= 0) + usage (); + /* + * The flattened image tree (FIT) format + * requires a flattened device tree image type + */ + params.type = IH_TYPE_FLATDT; + params.datafile = *++argv; + params.fflag = 1; + goto NXTARG; + case 'n': + if (--argc <= 0) + usage (); + params.imagename = *++argv; + goto NXTARG; + case 'v': + params.vflag++; + break; + case 'x': + params.xflag++; + break; + default: + usage (); + } + } +NXTARG: ; + } + + if (argc != 1) + usage (); + + /* set tparams as per input type_id */ + tparams = mkimage_get_type(params.type); + if (tparams == NULL) { + fprintf (stderr, "%s: unsupported type %s\n", + params.cmdname, genimg_get_type_name(params.type)); + exit (EXIT_FAILURE); + } + + /* + * check the passed arguments parameters meets the requirements + * as per image type to be generated/listed + */ + if (tparams->check_params) + if (tparams->check_params (¶ms)) + usage (); + + if (!params.eflag) { + params.ep = params.addr; + /* If XIP, entry point must be after the U-Boot header */ + if (params.xflag) + params.ep += tparams->header_size; + } + + params.imagefile = *argv; + + if (params.fflag){ + if (tparams->fflag_handle) + /* + * in some cases, some additional processing needs + * to be done if fflag is defined + * + * For ex. fit_handle_file for Fit file support + */ + retval = tparams->fflag_handle(¶ms); + + if (retval != EXIT_SUCCESS) + exit (retval); + } + + if (params.lflag || params.fflag) { + ifd = open (params.imagefile, O_RDONLY|O_BINARY); + } else { + ifd = open (params.imagefile, + O_RDWR|O_CREAT|O_TRUNC|O_BINARY, 0666); + } + + if (ifd < 0) { + fprintf (stderr, "%s: Can't open %s: %s\n", + params.cmdname, params.imagefile, + strerror(errno)); + exit (EXIT_FAILURE); + } + + if (params.lflag || params.fflag) { + /* + * list header information of existing image + */ + if (fstat(ifd, &sbuf) < 0) { + fprintf (stderr, "%s: Can't stat %s: %s\n", + params.cmdname, params.imagefile, + strerror(errno)); + exit (EXIT_FAILURE); + } + + if ((unsigned)sbuf.st_size < tparams->header_size) { + fprintf (stderr, + "%s: Bad size: \"%s\" is not valid image\n", + params.cmdname, params.imagefile); + exit (EXIT_FAILURE); + } + + ptr = mmap(0, sbuf.st_size, PROT_READ, MAP_SHARED, ifd, 0); + if (ptr == MAP_FAILED) { + fprintf (stderr, "%s: Can't read %s: %s\n", + params.cmdname, params.imagefile, + strerror(errno)); + exit (EXIT_FAILURE); + } + + /* + * scan through mkimage registry for all supported image types + * and verify the input image file header for match + * Print the image information for matched image type + * Returns the error code if not matched + */ + retval = mkimage_verify_print_header (ptr, &sbuf); + + (void) munmap((void *)ptr, sbuf.st_size); + (void) close (ifd); + + exit (retval); + } + + /* + * Must be -w then: + * + * write dummy header, to be fixed later + */ + memset (tparams->hdr, 0, tparams->header_size); + + if (write(ifd, tparams->hdr, tparams->header_size) + != tparams->header_size) { + fprintf (stderr, "%s: Write error on %s: %s\n", + params.cmdname, params.imagefile, strerror(errno)); + exit (EXIT_FAILURE); + } + + if (params.type == IH_TYPE_MULTI || params.type == IH_TYPE_SCRIPT) { + char *file = params.datafile; + uint32_t 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", + params.cmdname, file, strerror(errno)); + exit (EXIT_FAILURE); + } + size = cpu_to_uimage (sbuf.st_size); + } else { + size = 0; + } + + if (write(ifd, (char *)&size, sizeof(size)) != sizeof(size)) { + fprintf (stderr, "%s: Write error on %s: %s\n", + params.cmdname, params.imagefile, + strerror(errno)); + exit (EXIT_FAILURE); + } + + if (!file) { + break; + } + + if (sep) { + *sep = ':'; + file = sep + 1; + } else { + file = NULL; + } + } + + file = params.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, params.datafile, 0); + } + + /* We're a bit of paranoid */ +#if defined(_POSIX_SYNCHRONIZED_IO) && \ + !defined(__sun__) && \ + !defined(__FreeBSD__) && \ + !defined(__APPLE__) + (void) fdatasync (ifd); +#else + (void) fsync (ifd); +#endif + + if (fstat(ifd, &sbuf) < 0) { + fprintf (stderr, "%s: Can't stat %s: %s\n", + params.cmdname, params.imagefile, strerror(errno)); + exit (EXIT_FAILURE); + } + + 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", + params.cmdname, params.imagefile, strerror(errno)); + exit (EXIT_FAILURE); + } + + /* Setup the image header as per input image type*/ + if (tparams->set_header) + tparams->set_header (ptr, &sbuf, ifd, ¶ms); + else { + fprintf (stderr, "%s: Can't set header for %s: %s\n", + params.cmdname, tparams->name, strerror(errno)); + exit (EXIT_FAILURE); + } + + /* Print the image information by processing image header */ + if (tparams->print_header) + tparams->print_header (ptr); + else { + fprintf (stderr, "%s: Can't print header for %s: %s\n", + params.cmdname, tparams->name, strerror(errno)); + exit (EXIT_FAILURE); + } + + (void) munmap((void *)ptr, sbuf.st_size); + + /* We're a bit of paranoid */ +#if defined(_POSIX_SYNCHRONIZED_IO) && \ + !defined(__sun__) && \ + !defined(__FreeBSD__) && \ + !defined(__APPLE__) + (void) fdatasync (ifd); +#else + (void) fsync (ifd); +#endif + + if (close(ifd)) { + fprintf (stderr, "%s: Write error on %s: %s\n", + params.cmdname, params.imagefile, strerror(errno)); + exit (EXIT_FAILURE); + } + + 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; + int offset = 0; + int size; + struct image_type_params *tparams = mkimage_get_type (params.type); + + if (params.vflag) { + fprintf (stderr, "Adding Image %s\n", datafile); + } + + if ((dfd = open(datafile, O_RDONLY|O_BINARY)) < 0) { + fprintf (stderr, "%s: Can't open %s: %s\n", + params.cmdname, datafile, strerror(errno)); + exit (EXIT_FAILURE); + } + + if (fstat(dfd, &sbuf) < 0) { + fprintf (stderr, "%s: Can't stat %s: %s\n", + params.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", + params.cmdname, datafile, strerror(errno)); + exit (EXIT_FAILURE); + } + + if (params.xflag) { + unsigned char *p = NULL; + /* + * XIP: do not append the image_header_t at the + * beginning of the file, but consume the space + * reserved for it. + */ + + if ((unsigned)sbuf.st_size < tparams->header_size) { + fprintf (stderr, + "%s: Bad size: \"%s\" is too small for XIP\n", + params.cmdname, datafile); + exit (EXIT_FAILURE); + } + + for (p = ptr; p < ptr + tparams->header_size; p++) { + if ( *p != 0xff ) { + fprintf (stderr, + "%s: Bad file: \"%s\" has invalid buffer for XIP\n", + params.cmdname, datafile); + exit (EXIT_FAILURE); + } + } + + offset = tparams->header_size; + } + + size = sbuf.st_size - offset; + if (write(ifd, ptr + offset, size) != size) { + fprintf (stderr, "%s: Write error on %s: %s\n", + params.cmdname, params.imagefile, strerror(errno)); + exit (EXIT_FAILURE); + } + + if (pad && ((tail = size % 4) != 0)) { + + if (write(ifd, (char *)&zero, 4-tail) != 4-tail) { + fprintf (stderr, "%s: Write error on %s: %s\n", + params.cmdname, params.imagefile, + strerror(errno)); + exit (EXIT_FAILURE); + } + } + + (void) munmap((void *)ptr, sbuf.st_size); + (void) close (dfd); +} + +void +usage () +{ + fprintf (stderr, "Usage: %s -l image\n" + " -l ==> list image header information\n", + params.cmdname); + fprintf (stderr, " %s [-x] -A arch -O os -T type -C comp " + "-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" + " -C ==> set compression type 'comp'\n" + " -a ==> set load address to 'addr' (hex)\n" + " -e ==> set entry point to 'ep' (hex)\n" + " -n ==> set image name to 'name'\n" + " -d ==> use image data from 'datafile'\n" + " -x ==> set XIP (execute in place)\n", + params.cmdname); + fprintf (stderr, " %s [-D dtc_options] -f fit-image.its fit-image\n", + params.cmdname); + + exit (EXIT_FAILURE); +} diff --git a/u-boot/tools/mkimage.h b/u-boot/tools/mkimage.h new file mode 100644 index 0000000..9033a7d --- /dev/null +++ b/u-boot/tools/mkimage.h @@ -0,0 +1,147 @@ +/* + * (C) Copyright 2000-2004 + * DENX Software Engineering + * Wolfgang Denk, wd@denx.de + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#ifndef _MKIIMAGE_H_ +#define _MKIIMAGE_H_ + +#include "os_support.h" +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <time.h> +#include <unistd.h> +#include <sha1.h> +#include "fdt_host.h" + +#undef MKIMAGE_DEBUG + +#ifdef MKIMAGE_DEBUG +#define debug(fmt,args...) printf (fmt ,##args) +#else +#define debug(fmt,args...) +#endif /* MKIMAGE_DEBUG */ + +#define MKIMAGE_TMPFILE_SUFFIX ".tmp" +#define MKIMAGE_MAX_TMPFILE_LEN 256 +#define MKIMAGE_DEFAULT_DTC_OPTIONS "-I dts -O dtb -p 500" +#define MKIMAGE_MAX_DTC_CMDLINE_LEN 512 +#define MKIMAGE_DTC "dtc" /* assume dtc is in $PATH */ + +/* + * This structure defines all such variables those are initialized by + * mkimage main core and need to be referred by image type specific + * functions + */ +struct mkimage_params { + int dflag; + int eflag; + int fflag; + int lflag; + int vflag; + int xflag; + int os; + int arch; + int type; + int comp; + char *dtc; + unsigned int addr; + unsigned int ep; + char *imagename; + char *datafile; + char *imagefile; + char *cmdname; +}; + +/* + * image type specific variables and callback functions + */ +struct image_type_params { + /* name is an identification tag string for added support */ + char *name; + /* + * header size is local to the specific image type to be supported, + * mkimage core treats this as number of bytes + */ + uint32_t header_size; + /* Image type header pointer */ + void *hdr; + /* + * There are several arguments that are passed on the command line + * and are registered as flags in mkimage_params structure. + * This callback function can be used to check the passed arguments + * are in-lined with the image type to be supported + * + * Returns 1 if parameter check is successful + */ + int (*check_params) (struct mkimage_params *); + /* + * This function is used by list command (i.e. mkimage -l <filename>) + * image type verification code must be put here + * + * Returns 0 if image header verification is successful + * otherwise, returns respective negative error codes + */ + int (*verify_header) (unsigned char *, int, struct mkimage_params *); + /* Prints image information abstracting from image header */ + void (*print_header) (const void *); + /* + * The header or image contents need to be set as per image type to + * be generated using this callback function. + * further output file post processing (for ex. checksum calculation, + * padding bytes etc..) can also be done in this callback function. + */ + void (*set_header) (void *, struct stat *, int, + struct mkimage_params *); + /* + * Some image generation support for ex (default image type) supports + * more than one type_ids, this callback function is used to check + * whether input (-T <image_type>) is supported by registered image + * generation/list low level code + */ + int (*check_image_type) (uint8_t); + /* This callback function will be executed if fflag is defined */ + int (*fflag_handle) (struct mkimage_params *); + /* pointer to the next registered entry in linked list */ + struct image_type_params *next; +}; + +/* + * Exported functions + */ +void mkimage_register (struct image_type_params *tparams); + +/* + * There is a c file associated with supported image type low level code + * for ex. default_image.c, fit_image.c + * init is the only function referred by mkimage core. + * to avoid a single lined header file, you can define them here + * + * Supported image types init functions + */ +void init_kwb_image_type (void); +void init_imx_image_type (void); +void init_default_image_type (void); +void init_fit_image_type (void); + +#endif /* _MKIIMAGE_H_ */ diff --git a/u-boot/tools/mpc86x_clk.c b/u-boot/tools/mpc86x_clk.c new file mode 100644 index 0000000..8dfbd4e --- /dev/null +++ b/u-boot/tools/mpc86x_clk.c @@ -0,0 +1,218 @@ +/* + * (C) Copyright 2003 Intracom S.A. + * Pantelis Antoniou <panto@intracom.gr> + * + * This little program makes an exhaustive search for the + * correct terms of pdf, mfi, mfn, mfd, s, dbrmo, in PLPRCR. + * The goal is to produce a gclk2 from a xin input, while respecting + * all the restrictions on their combination. + * + * Generaly you select the first row of the produced table. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + + +#include <stdio.h> +#include <stdlib.h> + +#define DPREF_MIN 10000000 +#define DPREF_MAX 32000000 + +#define DPGDCK_MAX 320000000 +#define DPGDCK_MIN 160000000 + +#define S_MIN 0 +#define S_MAX 2 + +#define MFI_MIN 5 +#define MFI_MAX 15 + +#define MFN_MIN 0 +#define MFN_MAX 15 + +#define MFD_MIN 0 +#define MFD_MAX 31 + +#define MF_MIN 5 +#define MF_MAX 15 + +#define PDF_MIN 0 +#define PDF_MAX 15 + +#define GCLK2_MAX 150000000 + +static int calculate (int xin, int target_clock, + int ppm, int pdf, int mfi, int mfn, int mfd, int s, + int *dprefp, int *dpgdckp, int *jdbckp, + int *gclk2p, int *dbrmop) +{ + unsigned int dpref, dpgdck, jdbck, gclk2, t1, t2, dbrmo; + + /* valid MFI? */ + if (mfi < MFI_MIN) + return -1; + + /* valid num, denum? */ + if (mfn > 0 && mfn >= mfd) + return -1; + + dpref = xin / (pdf + 1); + + /* valid dpef? */ + if (dpref < DPREF_MIN || dpref > DPREF_MAX) + return -1; + + if (mfn == 0) { + dpgdck = (2 * mfi * xin) / (pdf + 1) ; + dbrmo = 0; + } else { + /* 5 <= mfi + (mfn / mfd + 1) <= 15 */ + t1 = mfd + 1; + t2 = mfi * t1 + mfn; + if ( MF_MIN * t1 > t2 || MF_MAX * t1 < t2) + return -1; + + dpgdck = (unsigned int)(2 * (mfi * mfd + mfi + mfn) * + (unsigned int)xin) / + ((mfd + 1) * (pdf + 1)); + + dbrmo = 10 * mfn < (mfd + 1); + } + + /* valid dpgclk? */ + if (dpgdck < DPGDCK_MIN || dpgdck > DPGDCK_MAX) + return -1; + + jdbck = dpgdck >> s; + gclk2 = jdbck / 2; + + /* valid gclk2 */ + if (gclk2 > GCLK2_MAX) + return -1; + + t1 = abs(gclk2 - target_clock); + + /* XXX max 1MHz dev. in clock */ + if (t1 > 1000000) + return -1; + + /* dev within range (XXX gclk2 scaled to avoid overflow) */ + if (t1 * 1000 > (unsigned int)ppm * (gclk2 / 1000)) + return -1; + + *dprefp = dpref; + *dpgdckp = dpgdck; + *jdbckp = jdbck; + *gclk2p = gclk2; + *dbrmop = dbrmo; + + return gclk2; +} + +int conf_clock(int xin, int target_clock, int ppm) +{ + int pdf, s, mfn, mfd, mfi; + int dpref, dpgdck, jdbck, gclk2, xout, dbrmo; + int found = 0; + + /* integer multipliers */ + for (pdf = PDF_MIN; pdf <= PDF_MAX; pdf++) { + for (mfi = MFI_MIN; mfi <= MFI_MAX; mfi++) { + for (s = 0; s <= S_MAX; s++) { + xout = calculate(xin, target_clock, + ppm, pdf, mfi, 0, 0, s, + &dpref, &dpgdck, &jdbck, + &gclk2, &dbrmo); + if (xout < 0) + continue; + + if (found == 0) { + printf("pdf mfi mfn mfd s dbrmo dpref dpgdck jdbck gclk2 exact?\n"); + printf("--- --- --- --- - ----- ----- ------ ----- ----- ------\n"); + } + + printf("%3d %3d --- --- %1d %5d %9d %9d %9d %9d%s\n", + pdf, mfi, s, dbrmo, + dpref, dpgdck, jdbck, gclk2, + gclk2 == target_clock ? " YES" : ""); + + found++; + } + } + } + + /* fractional multipliers */ + for (pdf = PDF_MIN; pdf <= PDF_MAX; pdf++) { + for (mfi = MFI_MIN; mfi <= MFI_MAX; mfi++) { + for (mfn = 1; mfn <= MFN_MAX; mfn++) { + for (mfd = 1; mfd <= MFD_MAX; mfd++) { + for (s = 0; s <= S_MAX; s++) { + xout = calculate(xin, target_clock, + ppm, pdf, mfi, mfn, mfd, s, + &dpref, &dpgdck, &jdbck, + &gclk2, &dbrmo); + if (xout < 0) + continue; + + if (found == 0) { + printf("pdf mfi mfn mfd s dbrmo dpref dpgdck jdbck gclk2 exact?\n"); + printf("--- --- --- --- - ----- ----- ------ ----- ----- ------\n"); + } + + printf("%3d %3d %3d %3d %1d %5d %9d %9d %9d %9d%s\n", + pdf, mfi, mfn, mfd, s, + dbrmo, dpref, dpgdck, jdbck, gclk2, + gclk2 == target_clock ? " YES" : ""); + + found++; + } + } + } + + } + } + + return found; +} + +int main(int argc, char *argv[]) +{ + int xin, want_gclk2, found, ppm = 100; + + if (argc < 3) { + fprintf(stderr, "usage: mpc86x_clk <xin> <want_gclk2> [ppm]\n"); + fprintf(stderr, " default ppm is 100\n"); + return 10; + } + + xin = atoi(argv[1]); + want_gclk2 = atoi(argv[2]); + if (argc >= 4) + ppm = atoi(argv[3]); + + found = conf_clock(xin, want_gclk2, ppm); + if (found <= 0) { + fprintf(stderr, "cannot produce gclk2 %d from xin %d\n", + want_gclk2, xin); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} diff --git a/u-boot/tools/ncb.c b/u-boot/tools/ncb.c new file mode 100644 index 0000000..ec8d8a7 --- /dev/null +++ b/u-boot/tools/ncb.c @@ -0,0 +1,38 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/socket.h> +#include <netinet/in.h> + +int main (int argc, char *argv[]) +{ + int s, len, o, port = 6666; + char buf[512]; + struct sockaddr_in addr; + socklen_t addr_len = sizeof addr; + + if (argc > 1) + port = atoi (argv[1]); + + s = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); + + o = 1; + len = 4; + setsockopt (3, SOL_SOCKET, SO_REUSEADDR, &o, len); + + addr.sin_family = AF_INET; + addr.sin_port = htons (port); + addr.sin_addr.s_addr = INADDR_ANY; /* receive broadcasts */ + + bind (s, (struct sockaddr *) &addr, sizeof addr); + + for (;;) { + len = recvfrom (s, buf, sizeof buf, 0, (struct sockaddr *) &addr, &addr_len); + if (len < 0) + break; + if (write (1, buf, len) != len) + fprintf(stderr, "WARNING: serial characters dropped\n"); + } + + return 0; +} diff --git a/u-boot/tools/netconsole b/u-boot/tools/netconsole new file mode 100755 index 0000000..c8109bb --- /dev/null +++ b/u-boot/tools/netconsole @@ -0,0 +1,59 @@ +#!/bin/sh + +usage() { + ( + echo "Usage: $0 <board IP> [board port]" + echo "" + echo "If port is not specified, '6666' will be used" + [ -z "$*" ] && exit 0 + echo "" + echo "ERROR: $*" + exit 1 + ) 1>&2 + exit $? +} + +while [ -n "$1" ] ; do + case $1 in + -h|--help) usage;; + --) break;; + -*) usage "Invalid option $1";; + *) break;; + esac + shift +done + +ip=$1 +port=${2:-6666} + +if [ -z "${ip}" ] || [ -n "$3" ] ; then + usage "Invalid number of arguments" +fi + +for nc in netcat nc ; do + type ${nc} >/dev/null 2>&1 && break +done + +trap "stty icanon echo intr ^C" 0 2 3 5 10 13 15 +echo "NOTE: the interrupt signal (normally ^C) has been remapped to ^T" + +stty -icanon -echo intr ^T +( +if type ncb 2>/dev/null ; then + # see if ncb is in $PATH + exec ncb ${port} + +elif [ -x ${0%/*}/ncb ] ; then + # maybe it's in the same dir as the netconsole script + exec ${0%/*}/ncb ${port} + +else + # blah, just use regular netcat + while ${nc} -u -l -p ${port} < /dev/null ; do + : + done +fi +) & +pid=$! +${nc} -u ${ip} ${port} +kill ${pid} 2>/dev/null diff --git a/u-boot/tools/os_support.c b/u-boot/tools/os_support.c new file mode 100644 index 0000000..1ed89e6 --- /dev/null +++ b/u-boot/tools/os_support.c @@ -0,0 +1,28 @@ +/* + * Copyright 2009 Extreme Engineering Solutions, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this software; if not, write to the + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/* + * Include additional files required for supporting different operating systems + */ +#include "compiler.h" +#ifdef __MINGW32__ +#include "mingw_support.c" +#endif +#ifdef __APPLE__ +#include "getline.c" +#endif diff --git a/u-boot/tools/os_support.h b/u-boot/tools/os_support.h new file mode 100644 index 0000000..7dcbee4 --- /dev/null +++ b/u-boot/tools/os_support.h @@ -0,0 +1,35 @@ +/* + * Copyright 2009 Extreme Engineering Solutions, Inc. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this software; if not, write to the + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __OS_SUPPORT_H_ +#define __OS_SUPPORT_H_ + +#include "compiler.h" + +/* + * Include additional files required for supporting different operating systems + */ +#ifdef __MINGW32__ +#include "mingw_support.h" +#endif + +#ifdef __APPLE__ +#include "getline.h" +#endif + +#endif /* __OS_SUPPORT_H_ */ diff --git a/u-boot/tools/scripts/README b/u-boot/tools/scripts/README new file mode 100644 index 0000000..046c1d4 --- /dev/null +++ b/u-boot/tools/scripts/README @@ -0,0 +1,67 @@ +# +# (C) Copyright 2001 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# The files in this directory are free software; you can redistribute +# them and/or modify them under the terms of the GNU General Public +# License as published by the Free Software Foundation; either +# version 2 of the License, or (at your option) any later version. +# +# These files are distributed in the hope that they will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# 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 +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +This directory contains scripts that help to perform certain actions +that need to be done frequently when working with U-Boot. + +They are meant as EXAMPLE code, so it is very likely that you will +have to modify them before use. + + +Short description: +================== + +dot.kermrc: + + Example for "~/.kermrc" Kermit init file for use with U-Boot + + by Wolfgang Denk, 24 Jun 2001 + +flash_param: + + "kermit" script to automatically initialize the environment + variables on your target. This is most useful during + development when your environment variables are stored in an + embedded flash sector which is erased whenever you install a + new U-Boot image. + + by Swen Anderson, 10 May 2001 + +send_cmd: + + send_cmd U_BOOT_COMMAND + + "kermit" script to send a U-Boot command and print the + results. When used from a shell with history (like the bash) + this indirectly adds kind of history to U-Boot ;-) + + by Swen Anderson, 10 May 2001 + +send_image: + + send_image FILE_NAME OFFSET + + "kermit" script to automatically download a file to the + target using the "loadb" command (kermit binary protocol) + + by Swen Anderson, 10 May 2001 diff --git a/u-boot/tools/scripts/define2mk.sed b/u-boot/tools/scripts/define2mk.sed new file mode 100644 index 0000000..13e2845 --- /dev/null +++ b/u-boot/tools/scripts/define2mk.sed @@ -0,0 +1,33 @@ +# +# Sed script to parse CPP macros and generate output usable by make +# +# It is expected that this script is fed the output of 'gpp -dM' +# which preprocesses the common.h header files and outputs the final +# list of CPP macros (and whitespace is sanitized) +# + +# Only process values prefixed with #define CONFIG_ +/^#define CONFIG_[A-Za-z0-9_][A-Za-z0-9_]*/ { + # Strip the #define prefix + s/#define *//; + # Change to form CONFIG_*=VALUE + s/ */=/; + # Drop trailing spaces + s/ *$//; + # drop quotes around string values + s/="\(.*\)"$/=\1/; + # Concatenate string values + s/" *"//g; + # Assume strings as default - add quotes around values + s/=\(..*\)/="\1"/; + # but remove again from decimal numbers + s/="\([0-9][0-9]*\)"/=\1/; + # ... and from hex numbers + s/="\(0[Xx][0-9a-fA-F][0-9a-fA-F]*\)"/=\1/; + # Change '1' and empty values to "y" (not perfect, but + # supports conditional compilation in the makefiles + s/=$/=y/; + s/=1$/=y/; + # print the line + p +} diff --git a/u-boot/tools/scripts/dot.kermrc b/u-boot/tools/scripts/dot.kermrc new file mode 100644 index 0000000..0fc6c15 --- /dev/null +++ b/u-boot/tools/scripts/dot.kermrc @@ -0,0 +1,16 @@ +set line /dev/ttyS0 +set speed 115200 +set carrier-watch off +set handshake none +set flow-control none +robust +set file type bin +set file name lit +set rec pack 1000 +set send pack 1000 +set window 5 +set prompt Kermit> +define sz !sz \%1 \%2 \%3 \%4 \%5 \%6 \%7 \%8 \%9 < \v(line) > \v(line) +define rz !rz \%1 \%2 \%3 \%4 \%5 \%6 \%7 \%8 \%9 < \v(line) > \v(line) +define sx !sx \%1 \%2 \%3 \%4 \%5 \%6 \%7 \%8 \%9 < \v(line) > \v(line) +define rx !rx \%1 \%2 \%3 \%4 \%5 \%6 \%7 \%8 \%9 < \v(line) > \v(line) diff --git a/u-boot/tools/scripts/flash_param b/u-boot/tools/scripts/flash_param new file mode 100644 index 0000000..847f99e --- /dev/null +++ b/u-boot/tools/scripts/flash_param @@ -0,0 +1,60 @@ +#!/usr/bin/kermit + +# usage: ./flash_param parameters +# Parameters: IP Address ETH Address ERIC Number +# Format: xxx.xxx.xxx.xxx xx:xx:xx:xx:xx:xx xxxx + +set line /dev/ttyS0 +set speed 115200 +set serial 8N1 +set carrier-watch off +set handshake none +#set flow-control none +set flow-control xon/xoff +#robust +set file type bin +set file name lit +set rec pack 1000 +set send pack 1000 +set window 5 +set prompt Kermit> +#robust +# Milliseconds to pause between each OUTPUT character +set output pacing 1 + +out \13 +in 10 => +#first erase the environment memory within NVRAM +out mw f0000000 0 200\13 +in 10 => +out reset\13 +in 5 autoboot +out \13\13 +in 10 => +#set additional env parameter +out setenv ethaddr \%2\13 +in 10 => +out setenv serial# ERIC 1.0 \%3\13 +in 10 => +out setenv eric_id \%3\13 +in 10 => +#out setenv prec_videocard_bus unknown\13 +#in 10 => +#out setenv prec_bios_type unknown\13 +#in 10 => +out setenv eric_passwd .eRIC.\13 +in 10 => +#out setenv bootargs root=/dev/ram ramdisk_size=8192 init=/sbin/init ip=\%1:192.168.1.100:192.168.1.254:255.255.255.0\13 +#out setenv bootargs root=/dev/ram ramdisk_size=8192 init=/sbin/init ip=\%1:192.168.0.1\13 +#out setenv bootargs root=/dev/ram ramdisk_size=8192 init=/sbin/init ip=\%1\13 +out setenv bootargs console=/dev/ttyS0,115200 root=/dev/nfs nfsroot=192.168.1.26:/eric_root_devel ip=\%1:192.168.1.26\13 +in 10 => +out setenv bootcmd bootm FFC00000\13 +in 10 => +out saveenv\13 +in 10 => +out reset\13 +in 5 autoboot +out \13\13 +in 10 => +quit +exit 0 diff --git a/u-boot/tools/scripts/make-asm-offsets b/u-boot/tools/scripts/make-asm-offsets new file mode 100755 index 0000000..4c33756 --- /dev/null +++ b/u-boot/tools/scripts/make-asm-offsets @@ -0,0 +1,27 @@ +#!/bin/sh + +# Adapted from Linux kernel's "Kbuild": +# commit 1cdf25d704f7951d02a04064c97db547d6021872 +# Author: Christoph Lameter <clameter@sgi.com> + +mkdir -p $(dirname $2) + +# Default sed regexp - multiline due to syntax constraints +SED_CMD="/^->/{s:->#\(.*\):/* \1 */:; \ + s:^->\([^ ]*\) [\$#]*\([-0-9]*\) \(.*\):#define \1 (\2) /* \3 */:; \ + s:^->\([^ ]*\) [\$#]*\([^ ]*\) \(.*\):#define \1 \2 /* \3 */:; \ + s:->::; p;}" + +(set -e + echo "#ifndef __ASM_OFFSETS_H__" + echo "#define __ASM_OFFSETS_H__" + echo "/*" + echo " * DO NOT MODIFY." + echo " *" + echo " * This file was generated by $(basename $0)" + echo " *" + echo " */" + echo "" + sed -ne "${SED_CMD}" $1 + echo "" + echo "#endif" ) > $2 diff --git a/u-boot/tools/scripts/send_cmd b/u-boot/tools/scripts/send_cmd new file mode 100644 index 0000000..4131331 --- /dev/null +++ b/u-boot/tools/scripts/send_cmd @@ -0,0 +1,21 @@ +#!/usr/bin/kermit + +set line /dev/ttyS0 +set speed 115200 +set serial 8N1 +set carrier-watch off +set handshake none +set flow-control none +robust +set file type bin +set file name lit +set rec pack 1000 +set send pack 1000 +set window 5 +set prompt Kermit> + +#out \13 +#in 10 => +out \%1 \%2 \%3 \%4 \%5 \%6 \%7\13 +in 10 => +quit +exit 0 diff --git a/u-boot/tools/scripts/send_image b/u-boot/tools/scripts/send_image new file mode 100644 index 0000000..9b89d6b --- /dev/null +++ b/u-boot/tools/scripts/send_image @@ -0,0 +1,26 @@ +#!/usr/bin/kermit + +# usage: send_image FILE_NAME OFFSET +# e.g. send_image output.bin 1F00000 +set line /dev/ttyS0 +set speed 115200 +set serial 8N1 +set carrier-watch off +set handshake none +set flow-control none +robust +set file type bin +set file name lit +set rec pack 1000 +set send pack 1000 +set window 5 +set prompt Kermit> + +out \13 +in 10 => +out loadb \%2 \13 +in 10 download ... +send \%1 +out \13 +in 10 ## Start Addr +quit +exit 0 diff --git a/u-boot/tools/setlocalversion b/u-boot/tools/setlocalversion new file mode 100755 index 0000000..e11f54f --- /dev/null +++ b/u-boot/tools/setlocalversion @@ -0,0 +1,40 @@ +#!/bin/sh +# Print additional version information for non-release trees. + +usage() { + echo "Usage: $0 [srctree]" >&2 + exit 1 +} + +cd "${1:-.}" || usage + +# Check for git and a git repo. +if head=`git rev-parse --verify HEAD 2>/dev/null`; then + # Do we have an untagged version? + if git name-rev --tags HEAD | \ + grep -E '^HEAD[[:space:]]+(.*~[0-9]*|undefined)$' > /dev/null; then + (git describe || git describe --tags || git describe --all --long) \ + 2>/dev/null | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}' + fi + + # Are there uncommitted changes? + git update-index --refresh --unmerged > /dev/null + if git diff-index --name-only HEAD | grep -v "^scripts/package" \ + | read dummy; then + printf '%s' -dirty + fi + + # Is this git on svn? + if git config --get svn-remote.svn.url >/dev/null; then + printf -- '-svn%s' "`git svn find-rev $head`" + fi +fi + +# Check for svn and a svn repo. +if rev=`svn info 2>/dev/null` ; then + rev=`echo "${rev}" | grep '^Revision' | awk '{print $NF}'` + printf -- '-svn%s' $rev +fi + +# Check for any localversion-* files +printf '%s' "`cat localversion-* 2>/dev/null`" diff --git a/u-boot/tools/ubsha1.c b/u-boot/tools/ubsha1.c new file mode 100644 index 0000000..625e13f --- /dev/null +++ b/u-boot/tools/ubsha1.c @@ -0,0 +1,100 @@ +/* + * (C) Copyright 2007 + * Heiko Schocher, DENX Software Engineering, <hs@denx.de> + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include "os_support.h" +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <string.h> +#include <sys/stat.h> +#include "sha1.h" + +int main (int argc, char **argv) +{ + unsigned char output[20]; + int i, len; + + char *imagefile; + char *cmdname = *argv; + unsigned char *ptr; + unsigned char *data; + struct stat sbuf; + unsigned char *ptroff; + int ifd; + int off; + + if (argc > 1) { + imagefile = argv[1]; + ifd = open (imagefile, O_RDWR|O_BINARY); + if (ifd < 0) { + fprintf (stderr, "%s: Can't open %s: %s\n", + cmdname, imagefile, strerror(errno)); + exit (EXIT_FAILURE); + } + if (fstat (ifd, &sbuf) < 0) { + fprintf (stderr, "%s: Can't stat %s: %s\n", + cmdname, imagefile, strerror(errno)); + exit (EXIT_FAILURE); + } + len = sbuf.st_size; + ptr = (unsigned char *)mmap(0, len, + PROT_READ, MAP_SHARED, ifd, 0); + if (ptr == (unsigned char *)MAP_FAILED) { + fprintf (stderr, "%s: Can't read %s: %s\n", + cmdname, imagefile, strerror(errno)); + exit (EXIT_FAILURE); + } + + /* create a copy, so we can blank out the sha1 sum */ + data = malloc (len); + memcpy (data, ptr, len); + off = SHA1_SUM_POS; + ptroff = &data[len + off]; + for (i = 0; i < SHA1_SUM_LEN; i++) { + ptroff[i] = 0; + } + + sha1_csum ((unsigned char *) data, len, (unsigned char *)output); + + printf ("U-Boot sum:\n"); + for (i = 0; i < 20 ; i++) { + printf ("%02X ", output[i]); + } + printf ("\n"); + /* overwrite the sum in the bin file, with the actual */ + lseek (ifd, SHA1_SUM_POS, SEEK_END); + if (write (ifd, output, SHA1_SUM_LEN) != SHA1_SUM_LEN) { + fprintf (stderr, "%s: Can't write %s: %s\n", + cmdname, imagefile, strerror(errno)); + exit (EXIT_FAILURE); + } + + free (data); + (void) munmap((void *)ptr, len); + (void) close (ifd); + } + + return EXIT_SUCCESS; +} diff --git a/u-boot/tools/updater/Makefile b/u-boot/tools/updater/Makefile new file mode 100644 index 0000000..e9684cb --- /dev/null +++ b/u-boot/tools/updater/Makefile @@ -0,0 +1,105 @@ +# +# (C) Copyright 2000-2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# 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 +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +LOAD_ADDR = 0x40000 + +include $(TOPDIR)/config.mk + +PROG = $(obj)updater +IMAGE = $(obj)updater.image + +COBJS = update.o flash.o flash_hw.o utils.o cmd_flash.o string.o ctype.o dummy.o +COBJS_LINKS = stubs.o +AOBJS = ppcstring.o +AOBJS_LINKS = memio.o + +OBJS := $(addprefix $(obj),$(COBJS) $(COBJS_LINKS) $(AOBJS) $(AOBJS_LINKS)) +SRCS := $(COBJS:.o=.c) $(AOBJS:.o=.S) $(addprefix $(obj), $(COBJS_LINKS:.o:.c) $(AOBJS_LINKS:.o:.S)) + +CPPFLAGS += -I$(TOPDIR) -I$(TOPDIR)/board/MAI/AmigaOneG3SE +CFLAGS += -I$(TOPDIR)/board/MAI/AmigaOneG3SE +AFLAGS += -I$(TOPDIR)/board/MAI/AmigaOneG3SE + +DEPS = $(OBJTREE)/u-boot.bin $(OBJTREE)/tools/mkimage +ifneq ($(DEPS),$(wildcard $(DEPS))) +$(error "updater: Missing required objects, please run regular build first") +endif + +all: $(obj).depend $(PROG) $(IMAGE) + +######################################################################### + +$(obj)%.srec: %.o $(LIB) + $(LD) -g -Ttext $(LOAD_ADDR) -o $(<:.o=) -e $(<:.o=) $< $(LIB) + $(OBJCOPY) -O srec $(<:.o=) $@ + +$(obj)%.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +$(obj)%.o: %.S + $(CC) $(AFLAGS) -c -o $@ $< + +$(obj)memio.o: $(obj)memio.S + $(CC) $(AFLAGS) -c -o $@ $< + +$(obj)memio.S: + rm -f $(obj)memio.c + ln -s $(SRCTREE)/board/MAI/AmigaOneG3SE/memio.S $(obj)memio.S + +$(obj)stubs.o: $(obj)stubs.c + $(CC) $(CFLAGS) -c -o $@ $< + +$(obj)stubs.c: + rm -f $(obj)stubs.c + ln -s $(SRCTREE)/examples/stubs.c $(obj)stubs.c + +######################################################################### + +$(obj)updater: $(OBJS) + $(LD) -g -Ttext $(LOAD_ADDR) -o $(obj)updater -e _main $(OBJS) + $(OBJCOPY) -O binary $(obj)updater $(obj)updater.bin + +$(obj)updater.image: $(obj)updater $(OBJTREE)/u-boot.bin + cat >/tmp/tempimage $(obj)updater.bin junk $(OBJTREE)/u-boot.bin + $(OBJTREE)/tools/mkimage -A ppc -O u-boot -T standalone -C none -a $(LOAD_ADDR) \ + -e `$(NM) $(obj)updater | grep _main | cut --bytes=0-8` \ + -n "Firmware Updater" -d /tmp/tempimage $(obj)updater.image + rm /tmp/tempimage + cp $(obj)updater.image /tftpboot + +(obj)updater.image2: $(obj)updater $(OBJTREE)/u-boot.bin + cat >/tmp/tempimage $(obj)updater.bin junk ../../create_image/image + $(OBJTREE)/tools/mkimage -A ppc -O u-boot -T standalone -C none -a $(LOAD_ADDR) \ + -e `$(NM) $(obj)updater | grep _main | cut --bytes=0-8` \ + -n "Firmware Updater" -d /tmp/tempimage $(obj)updater.image + rm /tmp/tempimage + cp $(obj)updater.image /tftpboot + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/u-boot/tools/updater/cmd_flash.c b/u-boot/tools/updater/cmd_flash.c new file mode 100644 index 0000000..957a7c4 --- /dev/null +++ b/u-boot/tools/updater/cmd_flash.c @@ -0,0 +1,417 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * FLASH support + */ +#include <common.h> +#include <command.h> +#include <flash.h> + +#if defined(CONFIG_CMD_FLASH) + +extern flash_info_t flash_info[]; /* info for FLASH chips */ + +/* + * The user interface starts numbering for Flash banks with 1 + * for historical reasons. + */ + +/* + * this routine looks for an abbreviated flash range specification. + * the syntax is B:SF[-SL], where B is the bank number, SF is the first + * sector to erase, and SL is the last sector to erase (defaults to SF). + * bank numbers start at 1 to be consistent with other specs, sector numbers + * start at zero. + * + * returns: 1 - correct spec; *pinfo, *psf and *psl are + * set appropriately + * 0 - doesn't look like an abbreviated spec + * -1 - looks like an abbreviated spec, but got + * a parsing error, a number out of range, + * or an invalid flash bank. + */ +static int +abbrev_spec(char *str, flash_info_t **pinfo, int *psf, int *psl) +{ + flash_info_t *fp; + int bank, first, last; + char *p, *ep; + + if ((p = strchr(str, ':')) == NULL) + return 0; + *p++ = '\0'; + + bank = simple_strtoul(str, &ep, 10); + if (ep == str || *ep != '\0' || + bank < 1 || bank > CONFIG_SYS_MAX_FLASH_BANKS || + (fp = &flash_info[bank - 1])->flash_id == FLASH_UNKNOWN) + return -1; + + str = p; + if ((p = strchr(str, '-')) != NULL) + *p++ = '\0'; + + first = simple_strtoul(str, &ep, 10); + if (ep == str || *ep != '\0' || first >= fp->sector_count) + return -1; + + if (p != NULL) { + last = simple_strtoul(p, &ep, 10); + if (ep == p || *ep != '\0' || + last < first || last >= fp->sector_count) + return -1; + } + else + last = first; + + *pinfo = fp; + *psf = first; + *psl = last; + + return 1; +} +int do_flinfo (cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) +{ + ulong bank; + + if (argc == 1) { /* print info for all FLASH banks */ + for (bank=0; bank <CONFIG_SYS_MAX_FLASH_BANKS; ++bank) { + printf ("\nBank # %ld: ", bank+1); + + flash_print_info (&flash_info[bank]); + } + return 0; + } + + bank = simple_strtoul(argv[1], NULL, 16); + if ((bank < 1) || (bank > CONFIG_SYS_MAX_FLASH_BANKS)) { + printf ("Only FLASH Banks # 1 ... # %d supported\n", + CONFIG_SYS_MAX_FLASH_BANKS); + return 1; + } + printf ("\nBank # %ld: ", bank); + flash_print_info (&flash_info[bank-1]); + return 0; +} +int do_flerase(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) +{ + flash_info_t *info; + ulong bank, addr_first, addr_last; + int n, sect_first, sect_last; + int rcode = 0; + + if (argc < 2) + return cmd_usage(cmdtp); + + if (strcmp(argv[1], "all") == 0) { + for (bank=1; bank<=CONFIG_SYS_MAX_FLASH_BANKS; ++bank) { + printf ("Erase Flash Bank # %ld ", bank); + info = &flash_info[bank-1]; + rcode = flash_erase (info, 0, info->sector_count-1); + } + return rcode; + } + + if ((n = abbrev_spec(argv[1], &info, §_first, §_last)) != 0) { + if (n < 0) { + printf("Bad sector specification\n"); + return 1; + } + printf ("Erase Flash Sectors %d-%d in Bank # %d ", + sect_first, sect_last, (info-flash_info)+1); + rcode = flash_erase(info, sect_first, sect_last); + return rcode; + } + + if (argc != 3) + return cmd_usage(cmdtp); + + if (strcmp(argv[1], "bank") == 0) { + bank = simple_strtoul(argv[2], NULL, 16); + if ((bank < 1) || (bank > CONFIG_SYS_MAX_FLASH_BANKS)) { + printf ("Only FLASH Banks # 1 ... # %d supported\n", + CONFIG_SYS_MAX_FLASH_BANKS); + return 1; + } + printf ("Erase Flash Bank # %ld ", bank); + info = &flash_info[bank-1]; + rcode = flash_erase (info, 0, info->sector_count-1); + return rcode; + } + + addr_first = simple_strtoul(argv[1], NULL, 16); + addr_last = simple_strtoul(argv[2], NULL, 16); + + if (addr_first >= addr_last) + return cmd_usage(cmdtp); + + printf ("Erase Flash from 0x%08lx to 0x%08lx ", addr_first, addr_last); + rcode = flash_sect_erase(addr_first, addr_last); + return rcode; +} + +int flash_sect_erase (ulong addr_first, ulong addr_last) +{ + flash_info_t *info; + ulong bank; + int s_first, s_last; + int erased; + int rcode = 0; + + erased = 0; + + for (bank=0,info = &flash_info[0]; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank, ++info) { + ulong b_end; + int sect; + + if (info->flash_id == FLASH_UNKNOWN) { + continue; + } + + b_end = info->start[0] + info->size - 1; /* bank end addr */ + + s_first = -1; /* first sector to erase */ + s_last = -1; /* last sector to erase */ + + for (sect=0; sect < info->sector_count; ++sect) { + ulong end; /* last address in current sect */ + short s_end; + + s_end = info->sector_count - 1; + + end = (sect == s_end) ? b_end : info->start[sect + 1] - 1; + + if (addr_first > end) + continue; + if (addr_last < info->start[sect]) + continue; + + if (addr_first == info->start[sect]) { + s_first = sect; + } + if (addr_last == end) { + s_last = sect; + } + } + if (s_first>=0 && s_first<=s_last) { + erased += s_last - s_first + 1; + rcode = flash_erase (info, s_first, s_last); + } + } + if (erased) { + /* printf ("Erased %d sectors\n", erased); */ + } else { + printf ("Error: start and/or end address" + " not on sector boundary\n"); + rcode = 1; + } + return rcode; +} + + +int do_protect(cmd_tbl_t *cmdtp, bd_t *bd, int flag, int argc, char *argv[]) +{ + flash_info_t *info; + ulong bank, addr_first, addr_last; + int i, p, n, sect_first, sect_last; + int rcode = 0; + + if (argc < 3) + return cmd_usage(cmdtp); + + if (strcmp(argv[1], "off") == 0) + p = 0; + else if (strcmp(argv[1], "on") == 0) + p = 1; + else + return cmd_usage(cmdtp); + + if (strcmp(argv[2], "all") == 0) { + for (bank=1; bank<=CONFIG_SYS_MAX_FLASH_BANKS; ++bank) { + info = &flash_info[bank-1]; + if (info->flash_id == FLASH_UNKNOWN) { + continue; + } + /*printf ("%sProtect Flash Bank # %ld\n", */ + /* p ? "" : "Un-", bank); */ + + for (i=0; i<info->sector_count; ++i) { +#if defined(CONFIG_SYS_FLASH_PROTECTION) + if (flash_real_protect(info, i, p)) + rcode = 1; + putc ('.'); +#else + info->protect[i] = p; +#endif /* CONFIG_SYS_FLASH_PROTECTION */ + } + } + +#if defined(CONFIG_SYS_FLASH_PROTECTION) + if (!rcode) puts (" done\n"); +#endif /* CONFIG_SYS_FLASH_PROTECTION */ + + return rcode; + } + + if ((n = abbrev_spec(argv[2], &info, §_first, §_last)) != 0) { + if (n < 0) { + printf("Bad sector specification\n"); + return 1; + } + /*printf("%sProtect Flash Sectors %d-%d in Bank # %d\n", */ + /* p ? "" : "Un-", sect_first, sect_last, */ + /* (info-flash_info)+1); */ + for (i = sect_first; i <= sect_last; i++) { +#if defined(CONFIG_SYS_FLASH_PROTECTION) + if (flash_real_protect(info, i, p)) + rcode = 1; + putc ('.'); +#else + info->protect[i] = p; +#endif /* CONFIG_SYS_FLASH_PROTECTION */ + } + +#if defined(CONFIG_SYS_FLASH_PROTECTION) + if (!rcode) puts (" done\n"); +#endif /* CONFIG_SYS_FLASH_PROTECTION */ + + return rcode; + } + + if (argc != 4) + return cmd_usage(cmdtp); + + if (strcmp(argv[2], "bank") == 0) { + bank = simple_strtoul(argv[3], NULL, 16); + if ((bank < 1) || (bank > CONFIG_SYS_MAX_FLASH_BANKS)) { + printf ("Only FLASH Banks # 1 ... # %d supported\n", + CONFIG_SYS_MAX_FLASH_BANKS); + return 1; + } + printf ("%sProtect Flash Bank # %ld\n", + p ? "" : "Un-", bank); + info = &flash_info[bank-1]; + + if (info->flash_id == FLASH_UNKNOWN) { + printf ("missing or unknown FLASH type\n"); + return 1; + } + for (i=0; i<info->sector_count; ++i) { +#if defined(CONFIG_SYS_FLASH_PROTECTION) + if (flash_real_protect(info, i, p)) + rcode = 1; + putc ('.'); +#else + info->protect[i] = p; +#endif /* CONFIG_SYS_FLASH_PROTECTION */ + } + +#if defined(CONFIG_SYS_FLASH_PROTECTION) + if (!rcode) + puts(" done\n"); +#endif /* CONFIG_SYS_FLASH_PROTECTION */ + + return rcode; + } + + addr_first = simple_strtoul(argv[2], NULL, 16); + addr_last = simple_strtoul(argv[3], NULL, 16); + + if (addr_first >= addr_last) + return cmd_usage(cmdtp); + + return flash_sect_protect (p, addr_first, addr_last); +} +int flash_sect_protect (int p, ulong addr_first, ulong addr_last) +{ + flash_info_t *info; + ulong bank; + int s_first, s_last; + int protected, i; + int rcode = 0; + + protected = 0; + + for (bank=0,info = &flash_info[0]; bank < CONFIG_SYS_MAX_FLASH_BANKS; ++bank, ++info) { + ulong b_end; + int sect; + + if (info->flash_id == FLASH_UNKNOWN) { + continue; + } + + b_end = info->start[0] + info->size - 1; /* bank end addr */ + + s_first = -1; /* first sector to erase */ + s_last = -1; /* last sector to erase */ + + for (sect=0; sect < info->sector_count; ++sect) { + ulong end; /* last address in current sect */ + short s_end; + + s_end = info->sector_count - 1; + + end = (sect == s_end) ? b_end : info->start[sect + 1] - 1; + + if (addr_first > end) + continue; + if (addr_last < info->start[sect]) + continue; + + if (addr_first == info->start[sect]) { + s_first = sect; + } + if (addr_last == end) { + s_last = sect; + } + } + if (s_first>=0 && s_first<=s_last) { + protected += s_last - s_first + 1; + for (i=s_first; i<=s_last; ++i) { +#if defined(CONFIG_SYS_FLASH_PROTECTION) + if (flash_real_protect(info, i, p)) + rcode = 1; + putc ('.'); +#else + info->protect[i] = p; +#endif /* CONFIG_SYS_FLASH_PROTECTION */ + } + } +#if defined(CONFIG_SYS_FLASH_PROTECTION) + if (!rcode) putc ('\n'); +#endif /* CONFIG_SYS_FLASH_PROTECTION */ + + } + if (protected) { + /* printf ("%sProtected %d sectors\n", */ + /* p ? "" : "Un-", protected); */ + } else { + printf ("Error: start and/or end address" + " not on sector boundary\n"); + rcode = 1; + } + return rcode; +} + +#endif diff --git a/u-boot/tools/updater/ctype.c b/u-boot/tools/updater/ctype.c new file mode 100644 index 0000000..6ed0468 --- /dev/null +++ b/u-boot/tools/updater/ctype.c @@ -0,0 +1,56 @@ +/* + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* + * linux/lib/ctype.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +#include <linux/ctype.h> + +unsigned char _ctype[] = { +_C,_C,_C,_C,_C,_C,_C,_C, /* 0-7 */ +_C,_C|_S,_C|_S,_C|_S,_C|_S,_C|_S,_C,_C, /* 8-15 */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 16-23 */ +_C,_C,_C,_C,_C,_C,_C,_C, /* 24-31 */ +_S|_SP,_P,_P,_P,_P,_P,_P,_P, /* 32-39 */ +_P,_P,_P,_P,_P,_P,_P,_P, /* 40-47 */ +_D,_D,_D,_D,_D,_D,_D,_D, /* 48-55 */ +_D,_D,_P,_P,_P,_P,_P,_P, /* 56-63 */ +_P,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U|_X,_U, /* 64-71 */ +_U,_U,_U,_U,_U,_U,_U,_U, /* 72-79 */ +_U,_U,_U,_U,_U,_U,_U,_U, /* 80-87 */ +_U,_U,_U,_P,_P,_P,_P,_P, /* 88-95 */ +_P,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L|_X,_L, /* 96-103 */ +_L,_L,_L,_L,_L,_L,_L,_L, /* 104-111 */ +_L,_L,_L,_L,_L,_L,_L,_L, /* 112-119 */ +_L,_L,_L,_P,_P,_P,_P,_C, /* 120-127 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 128-143 */ +0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* 144-159 */ +_S|_SP,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 160-175 */ +_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P,_P, /* 176-191 */ +_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U,_U, /* 192-207 */ +_U,_U,_U,_U,_U,_U,_U,_P,_U,_U,_U,_U,_U,_U,_U,_L, /* 208-223 */ +_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L,_L, /* 224-239 */ +_L,_L,_L,_L,_L,_L,_L,_P,_L,_L,_L,_L,_L,_L,_L,_L}; /* 240-255 */ diff --git a/u-boot/tools/updater/dummy.c b/u-boot/tools/updater/dummy.c new file mode 100644 index 0000000..9fe5ac1 --- /dev/null +++ b/u-boot/tools/updater/dummy.c @@ -0,0 +1 @@ +volatile int __dummy = 0xDEADBEEF; diff --git a/u-boot/tools/updater/flash.c b/u-boot/tools/updater/flash.c new file mode 100644 index 0000000..5be5f1b --- /dev/null +++ b/u-boot/tools/updater/flash.c @@ -0,0 +1,184 @@ +/* + * (C) Copyright 2000-2006 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <flash.h> + +extern flash_info_t flash_info[]; /* info for FLASH chips */ + +/*----------------------------------------------------------------------- + * Functions + */ + +/*----------------------------------------------------------------------- + * Set protection status for monitor sectors + * + * The monitor is always located in the _first_ Flash bank. + * If necessary you have to map the second bank at lower addresses. + */ +void +flash_protect (int flag, ulong from, ulong to, flash_info_t *info) +{ + ulong b_end = info->start[0] + info->size - 1; /* bank end address */ + short s_end = info->sector_count - 1; /* index of last sector */ + int i; + + /* Do nothing if input data is bad. */ + if (info->sector_count == 0 || info->size == 0 || to < from) { + return; + } + + /* There is nothing to do if we have no data about the flash + * or the protect range and flash range don't overlap. + */ + if (info->flash_id == FLASH_UNKNOWN || + to < info->start[0] || from > b_end) { + return; + } + + for (i=0; i<info->sector_count; ++i) { + ulong end; /* last address in current sect */ + + end = (i == s_end) ? b_end : info->start[i + 1] - 1; + + /* Update protection if any part of the sector + * is in the specified range. + */ + if (from <= end && to >= info->start[i]) { + if (flag & FLAG_PROTECT_CLEAR) { +#if defined(CONFIG_SYS_FLASH_PROTECTION) + flash_real_protect(info, i, 0); +#else + info->protect[i] = 0; +#endif /* CONFIG_SYS_FLASH_PROTECTION */ + } + else if (flag & FLAG_PROTECT_SET) { +#if defined(CONFIG_SYS_FLASH_PROTECTION) + flash_real_protect(info, i, 1); +#else + info->protect[i] = 1; +#endif /* CONFIG_SYS_FLASH_PROTECTION */ + } + } + } +} + +/*----------------------------------------------------------------------- + */ + +flash_info_t * +addr2info (ulong addr) +{ +#ifndef CONFIG_SPD823TS + flash_info_t *info; + int i; + + for (i=0, info = &flash_info[0]; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i, ++info) { + if (info->flash_id != FLASH_UNKNOWN && + addr >= info->start[0] && + /* WARNING - The '- 1' is needed if the flash + * is at the end of the address space, since + * info->start[0] + info->size wraps back to 0. + * Please don't change this unless you understand this. + */ + addr <= info->start[0] + info->size - 1) { + return (info); + } + } +#endif /* CONFIG_SPD823TS */ + + return (NULL); +} + +/*----------------------------------------------------------------------- + * Copy memory to flash. + * Make sure all target addresses are within Flash bounds, + * and no protected sectors are hit. + * Returns: + * ERR_OK 0 - OK + * ERR_TIMOUT 1 - write timeout + * ERR_NOT_ERASED 2 - Flash not erased + * ERR_PROTECTED 4 - target range includes protected sectors + * ERR_INVAL 8 - target address not in Flash memory + * ERR_ALIGN 16 - target address not aligned on boundary + * (only some targets require alignment) + */ +int +flash_write (char *src, ulong addr, ulong cnt) +{ +#ifdef CONFIG_SPD823TS + return (ERR_TIMOUT); /* any other error codes are possible as well */ +#else + int i; + ulong end = addr + cnt - 1; + flash_info_t *info_first = addr2info (addr); + flash_info_t *info_last = addr2info (end ); + flash_info_t *info; + int j; + + if (cnt == 0) { + return (ERR_OK); + } + + if (!info_first || !info_last) { + return (ERR_INVAL); + } + + for (info = info_first; info <= info_last; ++info) { + ulong b_end = info->start[0] + info->size; /* bank end addr */ + short s_end = info->sector_count - 1; + for (i=0; i<info->sector_count; ++i) { + ulong e_addr = (i == s_end) ? b_end : info->start[i + 1]; + + if ((end >= info->start[i]) && (addr < e_addr) && + (info->protect[i] != 0) ) { + return (ERR_PROTECTED); + } + } + } + + printf("\rWriting "); + for (j=0; j<20; j++) putc(177); + printf("\rWriting "); + + /* finally write data to flash */ + for (info = info_first; info <= info_last && cnt>0; ++info) { + ulong len; + + len = info->start[0] + info->size - addr; + if (len > cnt) + len = cnt; + + if ((i = write_buff(info, src, addr, len)) != 0) { + return (i); + } + cnt -= len; + addr += len; + src += len; + } + return (ERR_OK); +#endif /* CONFIG_SPD823TS */ +} + +/*----------------------------------------------------------------------- + */ diff --git a/u-boot/tools/updater/flash_hw.c b/u-boot/tools/updater/flash_hw.c new file mode 100644 index 0000000..b5058b3 --- /dev/null +++ b/u-boot/tools/updater/flash_hw.c @@ -0,0 +1,659 @@ +/* + * (C) Copyright 2001 + * Josh Huber <huber@mclx.com>, Mission Critical Linux, Inc. + * + * (C) Copyright 2002 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * 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 + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <flash.h> +#include <asm/io.h> +#include <memio.h> + +/*---------------------------------------------------------------------*/ +#undef DEBUG_FLASH + +#ifdef DEBUG_FLASH +#define DEBUGF(fmt,args...) printf(fmt ,##args) +#else +#define DEBUGF(fmt,args...) +#endif +/*---------------------------------------------------------------------*/ + +flash_info_t flash_info[]; + +static ulong flash_get_size (ulong addr, flash_info_t *info); +static int flash_get_offsets (ulong base, flash_info_t *info); +static int write_word (flash_info_t *info, ulong dest, ulong data); +static void flash_reset (ulong addr); + +int flash_xd_nest; + +static void flash_to_xd(void) +{ + unsigned char x; + + flash_xd_nest ++; + + if (flash_xd_nest == 1) + { + DEBUGF("Flash on XD\n"); + x = pci_read_cfg_byte(0, 0, 0x74); + pci_write_cfg_byte(0, 0, 0x74, x|1); + } +} + +static void flash_to_mem(void) +{ + unsigned char x; + + flash_xd_nest --; + + if (flash_xd_nest == 0) + { + DEBUGF("Flash on memory bus\n"); + x = pci_read_cfg_byte(0, 0, 0x74); + pci_write_cfg_byte(0, 0, 0x74, x&0xFE); + } +} + +unsigned long flash_init_old(void) +{ + int i; + + for (i = 0; i < CONFIG_SYS_MAX_FLASH_BANKS; i++) + { + flash_info[i].flash_id = FLASH_UNKNOWN; + flash_info[i].sector_count = 0; + flash_info[i].size = 0; + } + + + return 1; +} + +unsigned long flash_init (void) +{ + unsigned int i; + unsigned long flash_size = 0; + + flash_xd_nest = 0; + + flash_to_xd(); + + /* Init: no FLASHes known */ + for (i=0; i<CONFIG_SYS_MAX_FLASH_BANKS; ++i) { + flash_info[i].flash_id = FLASH_UNKNOWN; + flash_info[i].sector_count = 0; + flash_info[i].size = 0; + } + + DEBUGF("\n## Get flash size @ 0x%08x\n", CONFIG_SYS_FLASH_BASE); + + flash_size = flash_get_size (CONFIG_SYS_FLASH_BASE, flash_info); + + DEBUGF("## Flash bank size: %08lx\n", flash_size); + + if (flash_size) { +#if CONFIG_SYS_MONITOR_BASE >= CONFIG_SYS_FLASH_BASE && \ + CONFIG_SYS_MONITOR_BASE < CONFIG_SYS_FLASH_BASE + CONFIG_SYS_FLASH_MAX_SIZE + /* monitor protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CONFIG_SYS_MONITOR_BASE, + CONFIG_SYS_MONITOR_BASE + CONFIG_SYS_MONITOR_LEN - 1, + &flash_info[0]); +#endif + +#ifdef CONFIG_ENV_IS_IN_FLASH + /* ENV protection ON by default */ + flash_protect(FLAG_PROTECT_SET, + CONFIG_ENV_ADDR, + CONFIG_ENV_ADDR + CONFIG_ENV_SECT_SIZE - 1, + &flash_info[0]); +#endif + + } else { + printf ("Warning: the BOOT Flash is not initialised !"); + } + + flash_to_mem(); + + return flash_size; +} + +/* + * The following code cannot be run from FLASH! + */ +static ulong flash_get_size (ulong addr, flash_info_t *info) +{ + short i; + uchar value; + uchar *x = (uchar *)addr; + + flash_to_xd(); + + /* Write auto select command: read Manufacturer ID */ + x[0x0555] = 0xAA; + __asm__ volatile ("sync\n eieio"); + x[0x02AA] = 0x55; + __asm__ volatile ("sync\n eieio"); + x[0x0555] = 0x90; + __asm__ volatile ("sync\n eieio"); + + value = x[0]; + __asm__ volatile ("sync\n eieio"); + + DEBUGF("Manuf. ID @ 0x%08lx: 0x%08x\n", (ulong)addr, value); + + switch (value | (value << 16)) { + case AMD_MANUFACT: + info->flash_id = FLASH_MAN_AMD; + break; + + case FUJ_MANUFACT: + info->flash_id = FLASH_MAN_FUJ; + break; + + case STM_MANUFACT: + info->flash_id = FLASH_MAN_STM; + break; + + default: + info->flash_id = FLASH_UNKNOWN; + info->sector_count = 0; + info->size = 0; + flash_reset (addr); + return 0; + } + + value = x[1]; + __asm__ volatile ("sync\n eieio"); + + DEBUGF("Device ID @ 0x%08lx: 0x%08x\n", addr+1, value); + + switch (value) { + case AMD_ID_F040B: + DEBUGF("Am29F040B\n"); + info->flash_id += FLASH_AM040; + info->sector_count = 8; + info->size = 0x00080000; + break; /* => 512 kB */ + + case AMD_ID_LV040B: + DEBUGF("Am29LV040B\n"); + info->flash_id += FLASH_AM040; + info->sector_count = 8; + info->size = 0x00080000; + break; /* => 512 kB */ + + case AMD_ID_LV400T: + DEBUGF("Am29LV400T\n"); + info->flash_id += FLASH_AM400T; + info->sector_count = 11; + info->size = 0x00100000; + break; /* => 1 MB */ + + case AMD_ID_LV400B: + DEBUGF("Am29LV400B\n"); + info->flash_id += FLASH_AM400B; + info->sector_count = 11; + info->size = 0x00100000; + break; /* => 1 MB */ + + case AMD_ID_LV800T: + DEBUGF("Am29LV800T\n"); + info->flash_id += FLASH_AM800T; + info->sector_count = 19; + info->size = 0x00200000; + break; /* => 2 MB */ + + case AMD_ID_LV800B: + DEBUGF("Am29LV400B\n"); + info->flash_id += FLASH_AM800B; + info->sector_count = 19; + info->size = 0x00200000; + break; /* => 2 MB */ + + case AMD_ID_LV160T: + DEBUGF("Am29LV160T\n"); + info->flash_id += FLASH_AM160T; + info->sector_count = 35; + info->size = 0x00400000; + break; /* => 4 MB */ + + case AMD_ID_LV160B: + DEBUGF("Am29LV160B\n"); + info->flash_id += FLASH_AM160B; + info->sector_count = 35; + info->size = 0x00400000; + break; /* => 4 MB */ + + case AMD_ID_LV320T: + DEBUGF("Am29LV320T\n"); + info->flash_id += FLASH_AM320T; + info->sector_count = 67; + info->size = 0x00800000; + break; /* => 8 MB */ + +#if 0 + /* Has the same ID as AMD_ID_LV320T, to be fixed */ + case AMD_ID_LV320B: + DEBUGF("Am29LV320B\n"); + info->flash_id += FLASH_AM320B; + info->sector_count = 67; + info->size = 0x00800000; + break; /* => 8 MB */ +#endif + + case AMD_ID_LV033C: + DEBUGF("Am29LV033C\n"); + info->flash_id += FLASH_AM033C; + info->sector_count = 64; + info->size = 0x01000000; + break; /* => 16Mb */ + + case STM_ID_F040B: + DEBUGF("M29F040B\n"); + info->flash_id += FLASH_AM040; + info->sector_count = 8; + info->size = 0x00080000; + break; /* => 512 kB */ + + default: + info->flash_id = FLASH_UNKNOWN; + flash_reset (addr); + flash_to_mem(); + return (0); /* => no or unknown flash */ + + } + + if (info->sector_count > CONFIG_SYS_MAX_FLASH_SECT) { + printf ("** ERROR: sector count %d > max (%d) **\n", + info->sector_count, CONFIG_SYS_MAX_FLASH_SECT); + info->sector_count = CONFIG_SYS_MAX_FLASH_SECT; + } + + if (! flash_get_offsets (addr, info)) { + flash_reset (addr); + flash_to_mem(); + return 0; + } + + /* check for protected sectors */ + for (i = 0; i < info->sector_count; i++) { + /* read sector protection at sector address, (A7 .. A0) = 0x02 */ + /* D0 = 1 if protected */ + value = in8(info->start[i] + 2); + iobarrier_rw(); + info->protect[i] = (value & 1) != 0; + } + + /* + * Reset bank to read mode + */ + flash_reset (addr); + + flash_to_mem(); + + return (info->size); +} + +static int flash_get_offsets (ulong base, flash_info_t *info) +{ + unsigned int i; + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_AM040: + /* set sector offsets for uniform sector type */ + for (i = 0; i < info->sector_count; i++) { + info->start[i] = base + i * info->size / + info->sector_count; + } + break; + default: + return 0; + } + + return 1; +} + +int flash_erase (flash_info_t *info, int s_first, int s_last) +{ + volatile ulong addr = info->start[0]; + int flag, prot, sect, l_sect; + ulong start, now, last; + + flash_to_xd(); + + if (s_first < 0 || s_first > s_last) { + if (info->flash_id == FLASH_UNKNOWN) { + printf ("- missing\n"); + } else { + printf ("- no sectors to erase\n"); + } + flash_to_mem(); + return 1; + } + + if (info->flash_id == FLASH_UNKNOWN) { + printf ("Can't erase unknown flash type %08lx - aborted\n", + info->flash_id); + flash_to_mem(); + return 1; + } + + prot = 0; + for (sect=s_first; sect<=s_last; ++sect) { + if (info->protect[sect]) { + prot++; + } + } + + if (prot) { + printf ("- Warning: %d protected sectors will not be erased!\n", + prot); + } else { + printf (""); + } + + l_sect = -1; + + /* Disable interrupts which might cause a timeout here */ + flag = disable_interrupts(); + + out8(addr + 0x555, 0xAA); + iobarrier_rw(); + out8(addr + 0x2AA, 0x55); + iobarrier_rw(); + out8(addr + 0x555, 0x80); + iobarrier_rw(); + out8(addr + 0x555, 0xAA); + iobarrier_rw(); + out8(addr + 0x2AA, 0x55); + iobarrier_rw(); + + /* Start erase on unprotected sectors */ + for (sect = s_first; sect<=s_last; sect++) { + if (info->protect[sect] == 0) { /* not protected */ + addr = info->start[sect]; + out8(addr, 0x30); + iobarrier_rw(); + l_sect = sect; + } + } + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* wait at least 80us - let's wait 1 ms */ + udelay (1000); + + /* + * We wait for the last triggered sector + */ + if (l_sect < 0) + goto DONE; + + start = get_timer (0); + last = start; + addr = info->start[l_sect]; + + DEBUGF ("Start erase timeout: %d\n", CONFIG_SYS_FLASH_ERASE_TOUT); + + while ((in8(addr) & 0x80) != 0x80) { + if ((now = get_timer(start)) > CONFIG_SYS_FLASH_ERASE_TOUT) { + printf ("Timeout\n"); + flash_reset (info->start[0]); + flash_to_mem(); + return 1; + } + /* show that we're waiting */ + if ((now - last) > 1000) { /* every second */ + putc ('.'); + last = now; + } + iobarrier_rw(); + } + +DONE: + /* reset to read mode */ + flash_reset (info->start[0]); + flash_to_mem(); + + printf (" done\n"); + return 0; +} + +/* + * Copy memory to flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt) +{ + ulong cp, wp, data; + int i, l, rc; + ulong out_cnt = 0; + + flash_to_xd(); + + wp = (addr & ~3); /* get lower word aligned address */ + + /* + * handle unaligned start bytes + */ + if ((l = addr - wp) != 0) { + data = 0; + for (i=0, cp=wp; i<l; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + for (; i<4 && cnt>0; ++i) { + data = (data << 8) | *src++; + --cnt; + ++cp; + } + for (; cnt==0 && i<4; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + + if ((rc = write_word(info, wp, data)) != 0) { + flash_to_mem(); + return (rc); + } + wp += 4; + } + + putc(219); + + /* + * handle word aligned part + */ + while (cnt >= 4) { + if (out_cnt>26214) + { + putc(219); + out_cnt = 0; + } + data = 0; + for (i=0; i<4; ++i) { + data = (data << 8) | *src++; + } + if ((rc = write_word(info, wp, data)) != 0) { + flash_to_mem(); + return (rc); + } + wp += 4; + cnt -= 4; + out_cnt += 4; + } + + if (cnt == 0) { + flash_to_mem(); + return (0); + } + + /* + * handle unaligned tail bytes + */ + data = 0; + for (i=0, cp=wp; i<4 && cnt>0; ++i, ++cp) { + data = (data << 8) | *src++; + --cnt; + } + for (; i<4; ++i, ++cp) { + data = (data << 8) | (*(uchar *)cp); + } + + flash_to_mem(); + return (write_word(info, wp, data)); +} + +/* + * Write a word to Flash, returns: + * 0 - OK + * 1 - write timeout + * 2 - Flash not erased + */ +static int write_word (flash_info_t *info, ulong dest, ulong data) +{ + volatile ulong addr = info->start[0]; + ulong start; + int i; + + flash_to_xd(); + + /* Check if Flash is (sufficiently) erased */ + if ((in32(dest) & data) != data) { + flash_to_mem(); + return (2); + } + + /* write each byte out */ + for (i = 0; i < 4; i++) { + char *data_ch = (char *)&data; + int flag = disable_interrupts(); + + out8(addr + 0x555, 0xAA); + iobarrier_rw(); + out8(addr + 0x2AA, 0x55); + iobarrier_rw(); + out8(addr + 0x555, 0xA0); + iobarrier_rw(); + out8(dest+i, data_ch[i]); + iobarrier_rw(); + + /* re-enable interrupts if necessary */ + if (flag) + enable_interrupts(); + + /* data polling for D7 */ + start = get_timer (0); + while ((in8(dest+i) & 0x80) != (data_ch[i] & 0x80)) { + if (get_timer(start) > CONFIG_SYS_FLASH_WRITE_TOUT) { + flash_reset (addr); + flash_to_mem(); + return (1); + } + iobarrier_rw(); + } + } + + flash_reset (addr); + flash_to_mem(); + return (0); +} + +/* + * Reset bank to read mode + */ +static void flash_reset (ulong addr) +{ + flash_to_xd(); + out8(addr, 0xF0); /* reset bank */ + iobarrier_rw(); + flash_to_mem(); +} + +void flash_print_info (flash_info_t *info) +{ + int i; + + if (info->flash_id == FLASH_UNKNOWN) { + printf ("missing or unknown FLASH type\n"); + return; + } + + switch (info->flash_id & FLASH_VENDMASK) { + case FLASH_MAN_AMD: printf ("AMD "); break; + case FLASH_MAN_FUJ: printf ("FUJITSU "); break; + case FLASH_MAN_BM: printf ("BRIGHT MICRO "); break; + case FLASH_MAN_STM: printf ("SGS THOMSON "); break; + default: printf ("Unknown Vendor "); break; + } + + switch (info->flash_id & FLASH_TYPEMASK) { + case FLASH_AM040: printf ("29F040 or 29LV040 (4 Mbit, uniform sectors)\n"); + break; + case FLASH_AM400B: printf ("AM29LV400B (4 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM400T: printf ("AM29LV400T (4 Mbit, top boot sector)\n"); + break; + case FLASH_AM800B: printf ("AM29LV800B (8 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM800T: printf ("AM29LV800T (8 Mbit, top boot sector)\n"); + break; + case FLASH_AM160B: printf ("AM29LV160B (16 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM160T: printf ("AM29LV160T (16 Mbit, top boot sector)\n"); + break; + case FLASH_AM320B: printf ("AM29LV320B (32 Mbit, bottom boot sect)\n"); + break; + case FLASH_AM320T: printf ("AM29LV320T (32 Mbit, top boot sector)\n"); + break; + default: printf ("Unknown Chip Type\n"); + break; + } + + if (info->size % 0x100000 == 0) { + printf (" Size: %ld MB in %d Sectors\n", + info->size / 0x100000, info->sector_count); + } else if (info->size % 0x400 == 0) { + printf (" Size: %ld KB in %d Sectors\n", + info->size / 0x400, info->sector_count); + } else { + printf (" Size: %ld B in %d Sectors\n", + info->size, info->sector_count); + } + + printf (" Sector Start Addresses:"); + for (i=0; i<info->sector_count; ++i) { + if ((i % 5) == 0) + printf ("\n "); + printf (" %08lX%s", + info->start[i], + info->protect[i] ? " (RO)" : " " + ); + } + printf ("\n"); +} diff --git a/u-boot/tools/updater/junk b/u-boot/tools/updater/junk new file mode 100644 index 0000000..f73285a --- /dev/null +++ b/u-boot/tools/updater/junk @@ -0,0 +1 @@ +................................................................................................................................................................................................................................................................
\ No newline at end of file diff --git a/u-boot/tools/updater/ppcstring.S b/u-boot/tools/updater/ppcstring.S new file mode 100644 index 0000000..97023a0 --- /dev/null +++ b/u-boot/tools/updater/ppcstring.S @@ -0,0 +1,216 @@ +/* + * String handling functions for PowerPC. + * + * Copyright (C) 1996 Paul Mackerras. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include <ppc_asm.tmpl> +#include <asm/errno.h> + + .globl strcpy +strcpy: + addi r5,r3,-1 + addi r4,r4,-1 +1: lbzu r0,1(r4) + cmpwi 0,r0,0 + stbu r0,1(r5) + bne 1b + blr + + .globl strncpy +strncpy: + cmpwi 0,r5,0 + beqlr + mtctr r5 + addi r6,r3,-1 + addi r4,r4,-1 +1: lbzu r0,1(r4) + cmpwi 0,r0,0 + stbu r0,1(r6) + bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */ + blr + + .globl strcat +strcat: + addi r5,r3,-1 + addi r4,r4,-1 +1: lbzu r0,1(r5) + cmpwi 0,r0,0 + bne 1b + addi r5,r5,-1 +1: lbzu r0,1(r4) + cmpwi 0,r0,0 + stbu r0,1(r5) + bne 1b + blr + + .globl strcmp +strcmp: + addi r5,r3,-1 + addi r4,r4,-1 +1: lbzu r3,1(r5) + cmpwi 1,r3,0 + lbzu r0,1(r4) + subf. r3,r0,r3 + beqlr 1 + beq 1b + blr + + .globl strlen +strlen: + addi r4,r3,-1 +1: lbzu r0,1(r4) + cmpwi 0,r0,0 + bne 1b + subf r3,r3,r4 + blr + + .globl memset +memset: + rlwimi r4,r4,8,16,23 + rlwimi r4,r4,16,0,15 + addi r6,r3,-4 + cmplwi 0,r5,4 + blt 7f + stwu r4,4(r6) + beqlr + andi. r0,r6,3 + add r5,r0,r5 + subf r6,r0,r6 + rlwinm r0,r5,32-2,2,31 + mtctr r0 + bdz 6f +1: stwu r4,4(r6) + bdnz 1b +6: andi. r5,r5,3 +7: cmpwi 0,r5,0 + beqlr + mtctr r5 + addi r6,r6,3 +8: stbu r4,1(r6) + bdnz 8b + blr + + .globl bcopy +bcopy: + mr r6,r3 + mr r3,r4 + mr r4,r6 + b memcpy + + .globl memmove +memmove: + cmplw 0,r3,r4 + bgt backwards_memcpy + /* fall through */ + + .globl memcpy +memcpy: + rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */ + addi r6,r3,-4 + addi r4,r4,-4 + beq 2f /* if less than 8 bytes to do */ + andi. r0,r6,3 /* get dest word aligned */ + mtctr r7 + bne 5f +1: lwz r7,4(r4) + lwzu r8,8(r4) + stw r7,4(r6) + stwu r8,8(r6) + bdnz 1b + andi. r5,r5,7 +2: cmplwi 0,r5,4 + blt 3f + lwzu r0,4(r4) + addi r5,r5,-4 + stwu r0,4(r6) +3: cmpwi 0,r5,0 + beqlr + mtctr r5 + addi r4,r4,3 + addi r6,r6,3 +4: lbzu r0,1(r4) + stbu r0,1(r6) + bdnz 4b + blr +5: subfic r0,r0,4 + mtctr r0 +6: lbz r7,4(r4) + addi r4,r4,1 + stb r7,4(r6) + addi r6,r6,1 + bdnz 6b + subf r5,r0,r5 + rlwinm. r7,r5,32-3,3,31 + beq 2b + mtctr r7 + b 1b + + .globl backwards_memcpy +backwards_memcpy: + rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */ + add r6,r3,r5 + add r4,r4,r5 + beq 2f + andi. r0,r6,3 + mtctr r7 + bne 5f +1: lwz r7,-4(r4) + lwzu r8,-8(r4) + stw r7,-4(r6) + stwu r8,-8(r6) + bdnz 1b + andi. r5,r5,7 +2: cmplwi 0,r5,4 + blt 3f + lwzu r0,-4(r4) + subi r5,r5,4 + stwu r0,-4(r6) +3: cmpwi 0,r5,0 + beqlr + mtctr r5 +4: lbzu r0,-1(r4) + stbu r0,-1(r6) + bdnz 4b + blr +5: mtctr r0 +6: lbzu r7,-1(r4) + stbu r7,-1(r6) + bdnz 6b + subf r5,r0,r5 + rlwinm. r7,r5,32-3,3,31 + beq 2b + mtctr r7 + b 1b + + .globl memcmp +memcmp: + cmpwi 0,r5,0 + ble- 2f + mtctr r5 + addi r6,r3,-1 + addi r4,r4,-1 +1: lbzu r3,1(r6) + lbzu r0,1(r4) + subf. r3,r0,r3 + bdnzt 2,1b + blr +2: li r3,0 + blr + + .global memchr +memchr: + cmpwi 0,r5,0 + ble- 2f + mtctr r5 + addi r3,r3,-1 +1: lbzu r0,1(r3) + cmpw 0,r0,r4 + bdnzf 2,1b + beqlr +2: li r3,0 + blr diff --git a/u-boot/tools/updater/string.c b/u-boot/tools/updater/string.c new file mode 100644 index 0000000..954fb01 --- /dev/null +++ b/u-boot/tools/updater/string.c @@ -0,0 +1,340 @@ +/* + * linux/lib/string.c + * + * Copyright (C) 1991, 1992 Linus Torvalds + */ + +/* + * stupid library routines.. The optimized versions should generally be found + * as inline code in <asm-xx/string.h> + * + * These are buggy as well.. + */ + +#include <linux/types.h> +#include <linux/string.h> +#include <malloc.h> + +#define __HAVE_ARCH_BCOPY +#define __HAVE_ARCH_MEMCMP +#define __HAVE_ARCH_MEMCPY +#define __HAVE_ARCH_MEMMOVE +#define __HAVE_ARCH_MEMSET +#define __HAVE_ARCH_STRCAT +#define __HAVE_ARCH_STRCMP +#define __HAVE_ARCH_STRCPY +#define __HAVE_ARCH_STRLEN +#define __HAVE_ARCH_STRNCPY + +char * ___strtok = NULL; + +#ifndef __HAVE_ARCH_STRCPY +char * strcpy(char * dest,const char *src) +{ + char *tmp = dest; + + while ((*dest++ = *src++) != '\0') + /* nothing */; + return tmp; +} +#endif + +#ifndef __HAVE_ARCH_STRNCPY +char * strncpy(char * dest,const char *src,size_t count) +{ + char *tmp = dest; + + while (count-- && (*dest++ = *src++) != '\0') + /* nothing */; + + return tmp; +} +#endif + +#ifndef __HAVE_ARCH_STRCAT +char * strcat(char * dest, const char * src) +{ + char *tmp = dest; + + while (*dest) + dest++; + while ((*dest++ = *src++) != '\0') + ; + + return tmp; +} +#endif + +#ifndef __HAVE_ARCH_STRNCAT +char * strncat(char *dest, const char *src, size_t count) +{ + char *tmp = dest; + + if (count) { + while (*dest) + dest++; + while ((*dest++ = *src++)) { + if (--count == 0) { + *dest = '\0'; + break; + } + } + } + + return tmp; +} +#endif + +#ifndef __HAVE_ARCH_STRCMP +int strcmp(const char * cs,const char * ct) +{ + register signed char __res; + + while (1) { + if ((__res = *cs - *ct++) != 0 || !*cs++) + break; + } + + return __res; +} +#endif + +#ifndef __HAVE_ARCH_STRNCMP +int strncmp(const char * cs,const char * ct,size_t count) +{ + register signed char __res = 0; + + while (count) { + if ((__res = *cs - *ct++) != 0 || !*cs++) + break; + count--; + } + + return __res; +} +#endif + +#ifndef __HAVE_ARCH_STRCHR +char * strchr(const char * s, int c) +{ + for(; *s != (char) c; ++s) + if (*s == '\0') + return NULL; + return (char *) s; +} +#endif + +#ifndef __HAVE_ARCH_STRRCHR +char * strrchr(const char * s, int c) +{ + const char *p = s + strlen(s); + do { + if (*p == (char)c) + return (char *)p; + } while (--p >= s); + return NULL; +} +#endif + +#ifndef __HAVE_ARCH_STRLEN +size_t strlen(const char * s) +{ + const char *sc; + + for (sc = s; *sc != '\0'; ++sc) + /* nothing */; + return sc - s; +} +#endif + +#ifndef __HAVE_ARCH_STRNLEN +size_t strnlen(const char * s, size_t count) +{ + const char *sc; + + for (sc = s; count-- && *sc != '\0'; ++sc) + /* nothing */; + return sc - s; +} +#endif + +#ifndef __HAVE_ARCH_STRDUP +char * strdup(const char *s) +{ + char *new; + + if ((s == NULL) || + ((new = malloc (strlen(s) + 1)) == NULL) ) { + return NULL; + } + + strcpy (new, s); + return new; +} +#endif + +#ifndef __HAVE_ARCH_STRSPN +size_t strspn(const char *s, const char *accept) +{ + const char *p; + const char *a; + size_t count = 0; + + for (p = s; *p != '\0'; ++p) { + for (a = accept; *a != '\0'; ++a) { + if (*p == *a) + break; + } + if (*a == '\0') + return count; + ++count; + } + + return count; +} +#endif + +#ifndef __HAVE_ARCH_STRPBRK +char * strpbrk(const char * cs,const char * ct) +{ + const char *sc1,*sc2; + + for( sc1 = cs; *sc1 != '\0'; ++sc1) { + for( sc2 = ct; *sc2 != '\0'; ++sc2) { + if (*sc1 == *sc2) + return (char *) sc1; + } + } + return NULL; +} +#endif + +#ifndef __HAVE_ARCH_STRTOK +char * strtok(char * s,const char * ct) +{ + char *sbegin, *send; + + sbegin = s ? s : ___strtok; + if (!sbegin) { + return NULL; + } + sbegin += strspn(sbegin,ct); + if (*sbegin == '\0') { + ___strtok = NULL; + return( NULL ); + } + send = strpbrk( sbegin, ct); + if (send && *send != '\0') + *send++ = '\0'; + ___strtok = send; + return (sbegin); +} +#endif + +#ifndef __HAVE_ARCH_MEMSET +void * memset(void * s,char c,size_t count) +{ + char *xs = (char *) s; + + while (count--) + *xs++ = c; + + return s; +} +#endif + +#ifndef __HAVE_ARCH_BCOPY +char * bcopy(const char * src, char * dest, int count) +{ + char *tmp = dest; + + while (count--) + *tmp++ = *src++; + + return dest; +} +#endif + +#ifndef __HAVE_ARCH_MEMCPY +void * memcpy(void * dest,const void *src,size_t count) +{ + char *tmp = (char *) dest, *s = (char *) src; + + while (count--) + *tmp++ = *s++; + + return dest; +} +#endif + +#ifndef __HAVE_ARCH_MEMMOVE +void * memmove(void * dest,const void *src,size_t count) +{ + char *tmp, *s; + + if (dest <= src) { + tmp = (char *) dest; + s = (char *) src; + while (count--) + *tmp++ = *s++; + } + else { + tmp = (char *) dest + count; + s = (char *) src + count; + while (count--) + *--tmp = *--s; + } + + return dest; +} +#endif + +#ifndef __HAVE_ARCH_MEMCMP +int memcmp(const void * cs,const void * ct,size_t count) +{ + const unsigned char *su1, *su2; + signed char res = 0; + + for( su1 = cs, su2 = ct; 0 < count; ++su1, ++su2, count--) + if ((res = *su1 - *su2) != 0) + break; + return res; +} +#endif + +/* + * find the first occurrence of byte 'c', or 1 past the area if none + */ +#ifndef __HAVE_ARCH_MEMSCAN +void * memscan(void * addr, int c, size_t size) +{ + unsigned char * p = (unsigned char *) addr; + + while (size) { + if (*p == c) + return (void *) p; + p++; + size--; + } + return (void *) p; +} +#endif + +#ifndef __HAVE_ARCH_STRSTR +char * strstr(const char * s1,const char * s2) +{ + int l1, l2; + + l2 = strlen(s2); + if (!l2) + return (char *) s1; + l1 = strlen(s1); + while (l1 >= l2) { + l1--; + if (!memcmp(s1,s2,l2)) + return (char *) s1; + s1++; + } + return NULL; +} +#endif diff --git a/u-boot/tools/updater/update.c b/u-boot/tools/updater/update.c new file mode 100644 index 0000000..18f122a --- /dev/null +++ b/u-boot/tools/updater/update.c @@ -0,0 +1,63 @@ +#include <common.h> +#include <exports.h> + +extern unsigned long __dummy; +void do_reset (void); +void do_updater(void); + +void _main(void) +{ + int i; + printf("U-Boot Firmware Updater\n\n\n"); + printf("****************************************************\n" + "* ATTENTION!! PLEASE READ THIS NOTICE CAREFULLY! *\n" + "****************************************************\n\n" + "This program will update your computer's firmware.\n" + "Do NOT remove the disk, reset the machine, or do\n" + "anything that might disrupt functionality. If this\n"); + printf("Program fails, your computer might be unusable, and\n" + "you will need to return your board for reflashing.\n" + "If you find this too risky, remove the diskette and\n" + "switch off your machine now. Otherwise press the \n" + "SPACE key now to start the process\n\n"); + do + { + char x; + while (!tstc()); + x = getc(); + if (x == ' ') break; + } while (1); + + do_updater(); + + i = 5; + + printf("\nUpdate done. Please remove diskette.\n"); + printf("The machine will automatically reset in %d seconds\n", i); + printf("You can switch off/reset now when the floppy is removed\n\n"); + + while (i) + { + printf("Resetting in %d\r", i); + udelay(1000000); + i--; + } + do_reset(); + while (1); +} + +void do_updater(void) +{ + unsigned long *addr = &__dummy + 65; + unsigned long flash_size = flash_init(); + int rc; + + flash_sect_protect(0, 0xFFF00000, 0xFFF7FFFF); + printf("Erasing "); + flash_sect_erase(0xFFF00000, 0xFFF7FFFF); + printf("Writing "); + rc = flash_write((uchar *)addr, 0xFFF00000, 0x7FFFF); + if (rc != 0) printf("\nFlashing failed due to error %d\n", rc); + else printf("\ndone\n"); + flash_sect_protect(1, 0xFFF00000, 0xFFF7FFFF); +} diff --git a/u-boot/tools/updater/utils.c b/u-boot/tools/updater/utils.c new file mode 100644 index 0000000..61a6118 --- /dev/null +++ b/u-boot/tools/updater/utils.c @@ -0,0 +1,148 @@ +#include <common.h> +#include <asm/processor.h> +#include <memio.h> +#include <linux/ctype.h> + +static __inline__ unsigned long +get_msr(void) +{ + unsigned long msr; + + asm volatile("mfmsr %0" : "=r" (msr) :); + return msr; +} + +static __inline__ void +set_msr(unsigned long msr) +{ + asm volatile("mtmsr %0" : : "r" (msr)); +} + +static __inline__ unsigned long +get_dec(void) +{ + unsigned long val; + + asm volatile("mfdec %0" : "=r" (val) :); + return val; +} + + +static __inline__ void +set_dec(unsigned long val) +{ + asm volatile("mtdec %0" : : "r" (val)); +} + + +void +enable_interrupts(void) +{ + set_msr (get_msr() | MSR_EE); +} + +/* returns flag if MSR_EE was set before */ +int +disable_interrupts(void) +{ + ulong msr; + + msr = get_msr(); + set_msr (msr & ~MSR_EE); + return ((msr & MSR_EE) != 0); +} + +u8 in8(u32 port) +{ + return in_byte(port); +} + +void out8(u32 port, u8 val) +{ + out_byte(port, val); +} + +unsigned long in32(u32 port) +{ + return in_long(port); +} + +unsigned long simple_strtoul(const char *cp,char **endp,unsigned int base) +{ + unsigned long result = 0,value; + + if (*cp == '0') { + cp++; + if ((*cp == 'x') && isxdigit(cp[1])) { + base = 16; + cp++; + } + if (!base) { + base = 8; + } + } + if (!base) { + base = 10; + } + while (isxdigit(*cp) && (value = isdigit(*cp) ? *cp-'0' : (islower(*cp) + ? toupper(*cp) : *cp)-'A'+10) < base) { + result = result*base + value; + cp++; + } + if (endp) + *endp = (char *)cp; + return result; +} + +long simple_strtol(const char *cp,char **endp,unsigned int base) +{ + if(*cp=='-') + return -simple_strtoul(cp+1,endp,base); + return simple_strtoul(cp,endp,base); +} + +static inline void +soft_restart(unsigned long addr) +{ + /* SRR0 has system reset vector, SRR1 has default MSR value */ + /* rfi restores MSR from SRR1 and sets the PC to the SRR0 value */ + + __asm__ __volatile__ ("mtspr 26, %0" :: "r" (addr)); + __asm__ __volatile__ ("li 4, (1 << 6)" ::: "r4"); + __asm__ __volatile__ ("mtspr 27, 4"); + __asm__ __volatile__ ("rfi"); + + while(1); /* not reached */ +} + +void +do_reset (void) +{ + ulong addr; + /* flush and disable I/D cache */ + __asm__ __volatile__ ("mfspr 3, 1008" ::: "r3"); + __asm__ __volatile__ ("ori 5, 5, 0xcc00" ::: "r5"); + __asm__ __volatile__ ("ori 4, 3, 0xc00" ::: "r4"); + __asm__ __volatile__ ("andc 5, 3, 5" ::: "r5"); + __asm__ __volatile__ ("sync"); + __asm__ __volatile__ ("mtspr 1008, 4"); + __asm__ __volatile__ ("isync"); + __asm__ __volatile__ ("sync"); + __asm__ __volatile__ ("mtspr 1008, 5"); + __asm__ __volatile__ ("isync"); + __asm__ __volatile__ ("sync"); + +#ifdef CONFIG_SYS_RESET_ADDRESS + addr = CONFIG_SYS_RESET_ADDRESS; +#else + /* + * note: when CONFIG_SYS_MONITOR_BASE points to a RAM address, + * CONFIG_SYS_MONITOR_BASE - sizeof (ulong) is usually a valid + * address. Better pick an address known to be invalid on your + * system and assign it to CONFIG_SYS_RESET_ADDRESS. + */ + addr = CONFIG_SYS_MONITOR_BASE - sizeof (ulong); +#endif + soft_restart(addr); + while(1); /* not reached */ +} |