diff options
author | Holger Hans Peter Freyther <zecke@selfish.org> | 2011-10-09 09:58:20 +0200 |
---|---|---|
committer | Holger Hans Peter Freyther <zecke@selfish.org> | 2011-10-09 10:01:24 +0200 |
commit | 74f53c1444dba497af1e26a2717e561db55542c9 (patch) | |
tree | 1b7e8bb4c8baa73bbb57319a613be04e20ee57b3 |
Initial commit with software from sam7utils-0.2.1-bm.tar.bz2
-rw-r--r-- | AUTHORS | 0 | ||||
-rw-r--r-- | COPYING | 340 | ||||
-rw-r--r-- | ChangeLog | 74 | ||||
-rw-r--r-- | Makefile.am | 13 | ||||
-rw-r--r-- | NEWS | 0 | ||||
-rw-r--r-- | README | 14 | ||||
-rwxr-xr-x | bootstrap | 3 | ||||
-rw-r--r-- | cmd.c | 682 | ||||
-rw-r--r-- | cmd.h | 33 | ||||
-rw-r--r-- | configure.in | 44 | ||||
-rw-r--r-- | io.h | 50 | ||||
-rw-r--r-- | io_iokit.c | 317 | ||||
-rw-r--r-- | io_libusb.c | 70 | ||||
-rw-r--r-- | io_posix.c | 149 | ||||
-rw-r--r-- | io_win32.c | 173 | ||||
-rw-r--r-- | loader128_data.h | 18 | ||||
-rw-r--r-- | loader256_data.h | 18 | ||||
-rw-r--r-- | main.c | 170 | ||||
-rw-r--r-- | samba.c | 399 | ||||
-rw-r--r-- | samba.h | 69 |
20 files changed, 2636 insertions, 0 deletions
@@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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 + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/ChangeLog b/ChangeLog new file mode 100644 index 0000000..e9e7acf --- /dev/null +++ b/ChangeLog @@ -0,0 +1,74 @@ +2006-09-15 erik gilling <konkers@konkers.net> + * version 0.2.1 + +2006-09-15 erik gilling <konkers@konkers.net> + * include io_libusb in dist + +2006-09-06 erik gilling <konkers@konkers.net> + * version 0.2.0 + +2007-02-09 erik gilling <konkers@konkers.net> + * add libusb support and make superceed posix as the default + * update README + +2007-02-04 erik gilling <konkers@konkers.net> + * add version.h include to linux driver + +2006-09-28 erik gilling <konkers@konkers.net> + * fixed -h argument (thanks Dean) + +2006-09-06 erik gilling <konkers@konkers.net> + * version 0.1.1 + +2006-09-06 erik gilling <konkers@konkers.net> + * update help on a few commands + * add linux driver fix for kernels > 2.6.14 (thanks Michael Shiloh) + * add curses check to configure.in for FC4 (thanks Russ Nelson) + +2006-07-07 erik gilling <konkers@konkers.net> + * version 0.1.0 + +2006-07-07 erik gilling <konkers@konkers.net> + * add boot_from_flash command from Liam + +2006-06-16 erik gilling <konkers@konkers.net> + * unlock_regions uses nvpsize not sramsiz + +2006-06-16 erik gilling <konkers@konkers.net> + * fix lock bit detection + +2006-06-16 erik gilling <konkers@konkers.net> + * fix configure.in to set OS options before looking for headers + * add read and read_manual commands + * add detection for number of lock bits + * fix unlock_regions for devices other than the S64 + * remove exraneous debugging info + * add --exec command line for scriptability + +2006-06-15 erik gilling <konkers@konkers.net> + * add win32 support (cygwin only for now) + +2006-06-14 erik gilling <konkers@konkers.net> + * integrate loaders into sam7 binary + +2006-06-14 erik gilling <konkers@konkers.net> + * remove endian swapping from write_half_word and write_word + +2006-06-13 erik gilling <konkers@konkers.net> + * rename samba_flash to flash + * add support for 256 byte pages using flash command + +2006-06-13 erik gilling <konkers@konkers.net> + * add loader code (tested on sam7s64) + +2006-06-09 erik gilling <konkers@konkers.net> + * correct type matching for sam7x + * first stab at endianness correction (untested) + +2006-06-08 erik gilling <konkers@konkers.net> + * read cpuid and size flash page + * print out chip info on init + +2005-12-30 erik gilling <konkers@konkers.net> + * increment version to 0.0.2 + * add manual_upload command which does not use samba.bin diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..56effdb --- /dev/null +++ b/Makefile.am @@ -0,0 +1,13 @@ +AM_CFLAGS = -Wall -Werror + +AUTOMAKE_OPTIONS = gnu + +bin_PROGRAMS = sam7 + +sam7_SOURCES = main.c io_@IOTYPE@.c samba.c cmd.c +noinst_HEADERS = io.h samba.h cmd.h loader128_data.h loader256_data.h + +EXTRA_DIST = driver/Makefile driver/at91.c \ + io_win32.c io_posix.c io_iokit.c io_libusb.c\ + loader/Makefile loader/at91.h loader/bin2c.c loader/crt0.S \ + loader/loader.c loader/loader.lds
\ No newline at end of file @@ -0,0 +1,14 @@ +> ./sam7 +response = 0d0a +it begins +sam7> set_clock +sam7> unlock_regions +unlocking page 0: done +unlocking page 1: done + + +sam7> flash test.bin +> + + + diff --git a/bootstrap b/bootstrap new file mode 100755 index 0000000..d87dafd --- /dev/null +++ b/bootstrap @@ -0,0 +1,3 @@ +#!/bin/bash + +autoreconf --install @@ -0,0 +1,682 @@ +/* + * cmd.c + * + * Copyright (C) 2005 Erik Gilling, 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, version 2. + * + */ + +#include "config.h" + +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <unistd.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#include "samba.h" +#include "cmd.h" + +#include "loader128_data.h" +#include "loader256_data.h" + +#define MANUAL_FLASH + +static int cmd_help( int argc, char *argv[] ); +static int cmd_version( int argc, char *argv[] ); +static int cmd_write_mem( int argc, char *argv[] ); +static int cmd_read_mem( int argc, char *argv[] ); +static int cmd_send_file( int argc, char *argv[] ); +static int cmd_set_clock( int argc, char *argv[] ); +static int cmd_locked_regions( int argc, char *argv[] ); +static int cmd_unlock_regions( int argc, char *argv[] ); +static int cmd_boot_from_flash( int argc, char *argv[] ); +static int cmd_flash( int argc, char *argv[] ); +static int cmd_read( int argc, char *argv[] ); +static int cmd_manual_flash( int argc, char *argv[] ); +static int cmd_manual_read( int argc, char *argv[] ); + +static cmd_t cmds[] = { + {cmd_write_mem, "wb", + "wb <addr> <byte>", "write <byte> to <addr>"}, + + {cmd_read_mem, "rb", + "rb <addr>", "read byte from <addr>"}, + + {cmd_write_mem, "ws", + "ws <addr> <short>", "write <short> to <addr>"}, + + {cmd_read_mem, "rs", + "rs <addr>", "read short from <addr>"}, + + {cmd_write_mem, "ww", + "ww <addr> <word>", "write <word> to <addr>"}, + + {cmd_read_mem, "rw", + "rw <addr>", "read word from <addr>"}, + + {cmd_send_file, "sf", + "sf <addr> <file> <offset> <len>", + "send len bytes of file starting at offset"}, + + {cmd_set_clock, "set_clock", + "set_clock", "set clock as SAM-BA does"}, + {cmd_locked_regions, "locked_regions", + "locked_regions", "display locked regions"}, + {cmd_unlock_regions, "unlock_regions", + "unlock_regions", "unlock all lock regions"}, + {cmd_boot_from_flash, "boot_from_flash", + "boot_from_flash", "set the SAM7X to boot from flash"}, + {cmd_flash, "flash", + "flash <file>", "upload <file> to flash using the loader"}, + {cmd_read, "read", + "read <file> <addr> <len>", "read <len> bytes at <addr> to <file> using R commands"}, + {cmd_manual_flash, "manual_flash", + "manual_flash <file>", "upload <file> to flash using ww commands"}, + {cmd_manual_read, "manual_read", + "manual_read <file> <addr> <len>", "write <len> bytes at <addr> to <file> using rw commands"}, + {cmd_version, "version", + "version", "get boot program version"}, + {cmd_help, "help", + "help", "display help screen"} +}; + +cmd_t *cmd_find( char *name ) +{ + int i; + for( i=0 ; i<(sizeof(cmds)/ + sizeof(*cmds)); i++ ) { + if( !strcmp( name, cmds[i].name ) ) { + return &cmds[i]; + } + } + return NULL; +} + +static int cmd_help( int argc, char *argv[] ) +{ + int i; + for( i=0 ; i<(sizeof(cmds)/ + sizeof(*cmds)); i++ ) { + printf( "%-30s%s\n", cmds[i].invo, cmds[i].help ); + } + + return 0; +} + +static int cmd_write_mem( int argc, char *argv[] ) +{ + unsigned long int addr; + unsigned long int val; + char *endp; + + if( argc != 3 ) { + return CMD_E_WRONG_NUM_ARGS; + } + + addr = strtoul( argv[1], &endp, 0 ); + if( endp == argv[1] || + *endp != '\0' ) { + return CMD_E_INVAL_ARG; + } + + val = strtoul( argv[2], &endp, 0 ); + if( endp == argv[1] || + *endp != '\0' ) { + return CMD_E_INVAL_ARG; + } + + + switch( argv[0][1] ) { + case 'b': + if( samba_write_byte( addr, (uint8_t) val ) < 0 ) { + return CMD_E_IO_FAILURE; + } + break; + case 's': + if( samba_write_half_word( addr, (uint16_t) val ) < 0 ) { + return CMD_E_IO_FAILURE; + } + break; + case 'w': + if( samba_write_word( addr, (uint32_t) val ) < 0 ) { + return CMD_E_IO_FAILURE; + } + break; + } + + return CMD_E_OK; +} + +static int cmd_read_mem( int argc, char *argv[] ) +{ + unsigned long int addr; + char *endp; + + if( argc != 2 ) { + return CMD_E_WRONG_NUM_ARGS; + } + + addr = strtoul( argv[1], &endp, 0 ); + if( endp == argv[1] || + *endp != '\0' ) { + return CMD_E_INVAL_ARG; + } + + switch( argv[0][1] ) { + case 'b': + { + uint8_t val; + if( samba_read_byte( addr, &val ) < 0 ) { + return CMD_E_IO_FAILURE; + } + printf( "%02X\n", val ); + } + break; + case 's': + { + uint16_t val; + + if( samba_read_half_word( addr, &val ) < 0 ) { + return CMD_E_IO_FAILURE; + } + printf( "%04X\n", val ); + } + break; + case 'w': + { + uint32_t val; + if( samba_read_word( addr, &val ) < 0 ) { + return CMD_E_IO_FAILURE; + } + printf( "%08X\n", (unsigned int) val ); + } + break; + } + + return CMD_E_OK; +} + +static int cmd_send_file( int argc, char *argv[] ) +{ + unsigned long int offset; + unsigned long int len; + unsigned long int addr; + char *endp; + uint8_t *data; + int fd; + + if( argc != 5 ) { + return CMD_E_WRONG_NUM_ARGS; + } + + addr = strtoul( argv[1], &endp, 0 ); + if( endp == argv[1] || + *endp != '\0' ) { + return CMD_E_INVAL_ARG; + } + + offset = strtoul( argv[3], &endp, 0 ); + if( endp == argv[1] || + *endp != '\0' ) { + return CMD_E_INVAL_ARG; + } + + len = strtoul( argv[4], &endp, 0 ); + if( endp == argv[1] || + *endp != '\0' ) { + return CMD_E_INVAL_ARG; + } + + if( (data = (uint8_t *) malloc( len )) == NULL ) { + printf( "can't allocate %d bytes\n", (int)len ); + return CMD_E_NO_MEM; + } + + if( (fd = open( argv[2], O_RDONLY )) < 0 ) { + printf( "can't open file \"%s\": %s\n", argv[2], + strerror( errno ) ); + return CMD_E_BAD_FILE; + } + + lseek( fd, offset, SEEK_SET ); + len = read( fd, data, len ); + + if( samba_send_file( 0x202000, data, len ) < 0 ) { + return CMD_E_IO_FAILURE; + } + + return CMD_E_OK; +} + +static int cmd_version( int argc, char *argv[] ) +{ + char buff[256]; + + if( samba_get_version( buff, 256 ) < 0 ) { + return CMD_E_IO_FAILURE; + } + + printf( "%s\n", buff ); + + return CMD_E_OK; +} + +static int cmd_set_clock( int argc, char *argv[] ) +{ + uint32_t val; + uint8_t val8; + + /* set clock to main clock / 2 */ + if( samba_write_word( 0xFFFFFC30, 0x5 ) < 0 ) { + return -1; + } + + do { + if( samba_read_word( 0xFFFFFC68, &val ) < 0 ) { + return -1; + } + } while( val != 0xD ); + + /* set clock to pll clock / 2 */ + if( samba_write_word( 0xFFFFFC30, 0x7 ) < 0 ) { + return -1; + } + + do { + if( samba_read_word( 0xFFFFFC68, &val ) < 0 ) { + return -1; + } + } while( val != 0xD ); + + + /* read 0x200000 two times because SAM-BA does it */ + if( samba_read_byte( 0x00200000, &val8 ) < 0 ) { + return -1; + } + if( val8 != 0x13 ) { + printf( "warning: magic read 0x00200000 != 0x13\n" ); + } + + if( samba_read_byte( 0x00200000, &val8 ) < 0 ) { + return -1; + } + if( val8 != 0x13 ) { + printf( "warning: magic read 0x00200000 != 0x13\n" ); + } + + + return 0; +} + +static int cmd_locked_regions( int argc, char *argv[] ) +{ + uint32_t val; + int i; + + if( samba_read_word( 0xffffff68, &val ) < 0 ) { + return -1; + } + + + printf( "Locked Regions:" ); + + for( i=0 ; i<16 ; i++ ) { + if( val & 0x00010000 ) { + printf( " %i", i ); + } + val >>= 1; + } + + printf( "\n" ); + + return 0; +} + +static int cmd_unlock_regions( int argc, char *argv[] ) +{ + uint32_t val; + int i; + + if( samba_read_word( 0xffffff68, &val ) < 0 ) { + return -1; + } + + + if( val & 0xffff0000 ) { + /* set up MCLKS to some odd value... hey SAM-BA does it */ + if( samba_write_word( 0xffffff60, 0x00050100 ) < 0 ) { + return -1; + } + + for( i=0 ; i<samba_chip_info.lock_bits; i++ ) { + if( val & 0x00010000 ) { + int page = (samba_chip_info.nvpsiz / samba_chip_info.page_size / + samba_chip_info.lock_bits) * i; + + printf( "unlocking region %i:", i ); + + + if( samba_write_word( 0xffffff64, + 0x5a000004 | (page << 8) ) < 0 ) { + return -1; + } + + printf( " done\n" ); + } + val >>= 1; + } + + + /* set up MCLKS back to a sane value */ + if( samba_write_word( 0xffffff60, 0x00480100 ) < 0 ) { + return -1; + } + } + printf( "\n" ); + + return 0; +} + +/* contributed by Liam Staskawicz */ +static int cmd_boot_from_flash( int argc, char *argv[] ) +{ + /* + * word: 5A is key to send any message, + * 02 is GPNVM2 to boot from Flash, + * 0B is "set this bit" + */ + uint32_t val; + + + do { + if( samba_read_word( 0xffffff68, &val ) < 0 ) { + return -1; + } + } while( !val & 0x1 ); + + if( samba_write_word( 0xFFFFFF64, 0x5A00020B ) < 0 ) { + printf( "Couldn't flip the bit to boot from Flash.\n" ); + return -1; + } + return 0; +} + +static int cmd_flash( int argc, char *argv[] ) +{ + struct stat stbuf; + size_t loader_len; + size_t file_len; + size_t i; + uint8_t *buff; + int file_fd; + int read_len; + int ps = samba_chip_info.page_size; + uint8_t *loader_data; + + if( argc != 2 ) { + return CMD_E_WRONG_NUM_ARGS; + } + + if( ps == 128 ) { + loader_data = loader128_data; + loader_len = sizeof( loader128_data ); + } else if( ps == 256 ) { + loader_data = loader256_data; + loader_len = sizeof( loader256_data ); + } else { + printf( "no loader for %d byte pages\n", ps ); + return -1; + } + + if( stat( argv[1], &stbuf ) < 0 ) { + printf( "%s not found\n", argv[1] ); + return -1; + } + + file_len = stbuf.st_size; + + if( (buff = (uint8_t *) malloc( ps ) ) == NULL ) { + printf( "can't alocate buffer of size 0x%x\n", ps ); + goto error0; + } + + if( samba_send_file( 0x00201600, loader_data, loader_len ) < 0 ) { + printf( "could not upload samba.bin\n" ); + goto error1; + } + + if( (file_fd = open( argv[1], O_RDONLY )) < 0 ) { + printf( "can't open %s\n", argv[1] ); + return -1; + } + + for( i=0 ; i<file_len ; i+=ps ) { + /* set page # */ + if( samba_write_word( 0x00201400+ps, i/ps ) < 0 ) { + printf( "could not write page %d address\n", (int) i/ps ); + goto error2; + } + + read_len = (file_len-i < ps)?file_len-i:ps; + /* XXX need to implement safe read */ + if( read( file_fd, buff, read_len ) < read_len ) { + printf( "could not read 0x%x bytes from file\n", read_len ); + goto error2; + } + + if( samba_send_file( 0x00201400, buff, ps ) < 0 ) { + printf( "could not send page %d\n", (int) i/ps ); + goto error2; + } + + if( samba_go( 0x00201600 ) < 0 ) { + printf( "could not send go command for page %d\n", (int) i/ps ); + goto error2; + } + + } + + free( buff ); + close( file_fd ); + + return 0; + + error2: + close( file_fd ); + + error1: + free( buff ); + + error0: + return -1; +} + +static int cmd_manual_flash( int argc, char *argv[] ) +{ + struct stat stbuf; + size_t file_len; + size_t i,j; + char *buff; + int file_fd; + int read_len; + uint32_t val; + int ps = samba_chip_info.page_size; + + if( argc != 2 ) { + return CMD_E_WRONG_NUM_ARGS; + } + + if( stat( argv[1], &stbuf ) < 0 ) { + printf( "%s not found\n", argv[1] ); + return -1; + } + file_len = stbuf.st_size; + + + if( (buff = (char *) malloc( ps )) == NULL ) { + printf( "can't alocate buffer of size 128\n" ); + return -1; + } + + + if( (file_fd = open( argv[1], O_RDONLY )) < 0 ) { + printf( "can't open %s\n", argv[1] ); + goto error0; + } + + for( i=0 ; i<file_len ; i+=ps ) { + /* wait for flash to become ready */ + do { + if( samba_read_word( 0xffffff68, &val ) < 0 ) { + goto error1; + } + } while( !val & 0x1 ); + + read_len = (file_len-i < ps)?file_len-i:ps; + /* XXX need to implement safe read */ + if( read( file_fd, buff, read_len ) < read_len ) { + printf( "could not read 0x%x bytes from file\n", read_len ); + goto error1; + } + + for( j=0 ; j<ps ; j+=4 ) { + if( samba_write_word( 0x00100000 + i + j, *((uint32_t*)(buff+j))) < 0 ) { + printf( "could not write byte 0x%x\n", (unsigned int)( 0x00100000 + i + j) ); + } + } + + /* send write command */ + if( samba_write_word( 0xFFFFFF64, 0x5A000001 | ((i/ps) << 8) ) < 0 ) { + printf( "could not send write command for page %d\n", (int) i/ps ); + goto error1; + } + + } + + free( buff ); + close( file_fd ); + + return 0; + + error1: + close( file_fd ); + + error0: + free( buff ); + + return -1; +} + +static int cmd_manual_read( int argc, char *argv[] ) +{ + unsigned long int addr; + unsigned long int len; + int fd; + int i; + uint32_t val; + char *endp; + + if( argc != 4 ) { + printf( "wrong number of args\n" ); + return CMD_E_WRONG_NUM_ARGS; + } + + addr = strtoul( argv[2], &endp, 0 ); + if( endp == argv[2] || + *endp != '\0' ) { + printf("%s not a vaild number\n", argv[2]); + return CMD_E_INVAL_ARG; + } + + len = strtoul( argv[3], &endp, 0 ); + if( endp == argv[3] || + *endp != '\0' ) { + printf("%s not a vaild number\n", argv[3]); + return CMD_E_INVAL_ARG; + } + + if( (fd = open( argv[1], O_RDWR | O_CREAT, 0666 )) < 0 ) { + printf( "can't open file \"%s\": %s\n", argv[1], + strerror( errno ) ); + return CMD_E_BAD_FILE; + } + + for( i=0; i<len ; i+=4 ) { + if( samba_read_word( addr + i, &val ) < 0 ) { + printf( "io error\n" ); + return CMD_E_IO_FAILURE; + } + + if( write( fd, &val, 4 ) < 4 ) { + printf("write error\n" ); + return CMD_E_IO_FAILURE; + } + } + + close( fd ); + + return CMD_E_OK; +} + +static int cmd_read( int argc, char *argv[] ) +{ + unsigned long int addr; + unsigned long int len; + int fd; + int i; + char *endp; + int read_len; + uint8_t buff[0x80]; + + if( argc != 4 ) { + printf( "wrong number of args\n"); + return CMD_E_WRONG_NUM_ARGS; + } + + addr = strtoul( argv[2], &endp, 0 ); + if( endp == argv[2] || + *endp != '\0' ) { + printf("%s not a vaild number\n", argv[2]); + return CMD_E_INVAL_ARG; + } + + len = strtoul( argv[3], &endp, 0 ); + if( endp == argv[3] || + *endp != '\0' ) { + printf("%s not a vaild number\n", argv[3]); + return CMD_E_INVAL_ARG; + } + + if( (fd = open( argv[1], O_RDWR | O_CREAT, 0666 )) < 0 ) { + printf( "can't open file \"%s\": %s\n", argv[1], + strerror( errno ) ); + return CMD_E_BAD_FILE; + } + + for( i=0; i<len ; i+=0x80 ) { + read_len = len-i < 0x80 ? len-i : 0x80; + if( samba_recv_file( addr + i, buff, read_len ) < 0 ) { + printf( "io error\n" ); + return CMD_E_IO_FAILURE; + } + + if( write( fd, buff, read_len ) < read_len ) { + printf("write error\n" ); + return CMD_E_IO_FAILURE; + } + } + + close( fd ); + + return CMD_E_OK; +} + + @@ -0,0 +1,33 @@ +/* + * cmd.h + * + * Copyright (C) 2005 Erik Gilling, 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, version 2. + * + */ + +#ifndef __cmd_h__ +#define __cmd_h__ + +typedef struct { + int (* func)( int argc, char *argv[] ); + char *name; + char *invo; + char *help; +} cmd_t; + + +#define CMD_E_OK 0 +#define CMD_E_WRONG_NUM_ARGS -1 +#define CMD_E_INVAL_ARG -2 +#define CMD_E_IO_FAILURE -3 +#define CMD_E_UNIMP -4 +#define CMD_E_BAD_FILE -5 +#define CMD_E_NO_MEM -6 + +cmd_t *cmd_find( char *name ); + +#endif /* __cmd_h__ */ diff --git a/configure.in b/configure.in new file mode 100644 index 0000000..66e6206 --- /dev/null +++ b/configure.in @@ -0,0 +1,44 @@ +AC_INIT([sam7utils], [0.2.1], [konkers@konkers.net]) + +AC_CANONICAL_BUILD +AC_CANONICAL_HOST +AC_CANONICAL_TARGET + +AM_INIT_AUTOMAKE(sam7utils,0.2.1) +AM_CONFIG_HEADER(config.h) + + +AC_PROG_CC +AC_PROG_INSTALL +AC_PROG_MAKE_SET + +case "${host}" in + *-*-darwin* ) + LIBS="$LIBS -framework IOKIT -framework CoreFoundation" + IOTYPE="iokit" + ;; + *-*-cygwin* ) + LIBS="$LIBS -lsetupapi" + IOTYPE="win32" + ;; + * ) + AC_CHECK_LIB(usb,usb_init,IOTYPE="libusb";LIBS="$LIBS -lusb",IOTYPE="posix") + + ;; +esac + + +AC_HEADER_STDC + +AC_CHECK_LIB(readline, readline,,AC_MSG_ERROR(readline not found)) +AC_CHECK_LIB(curses, tgoto,,AC_MSG_ERROR(curses not found)) +AC_CHECK_HEADERS(stdint.h,,AC_MSG_WARN(can't find stdint.h)) +AC_CHECK_HEADERS(ctype.h,,) +AC_CHECK_HEADERS(endian.h,,) + + + + +AC_SUBST(IOTYPE) + +AC_OUTPUT(Makefile) @@ -0,0 +1,50 @@ +/* + * io.h + * + * Copyright (C) 2005 Erik Gilling, 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, version 2. + * + */ + +#ifndef __io_h__ +#define __io_h__ + + +#include <string.h> // for strlen +#include <unistd.h> // for usleep + +#define USB_VID_ATMEL 0x03eb +#define USB_PID_SAMBA 0x6124 + + +int io_init( char *dev ); +int io_cleanup( void ); +int io_write( void *buff, int len ); +int io_read( void *buff, int len ); +int io_read_response( char *buff, int len ); + + +static inline int io_send_cmd( char *cmd, void *response, int response_len ) +{ + + if( io_write( cmd, strlen( cmd ) ) < 0 ) { + return -1; + } + usleep( 2000 ); + + if( response_len == 0 ) { + return 0; + } + + if( io_read( response, response_len ) < 0 ) { + return -1; + } + + usleep( 2000 ); + return 0; +} + +#endif /* __io_h__ */ diff --git a/io_iokit.c b/io_iokit.c new file mode 100644 index 0000000..89b298e --- /dev/null +++ b/io_iokit.c @@ -0,0 +1,317 @@ +/* + * io.c + * + * Copyright (C) 2005 Erik Gilling, 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, version 2. + * + */ + +#include "config.h" + +#include <stdio.h> + +#include <mach/mach.h> + +#include <CoreFoundation/CFNumber.h> + +#include <IOKit/IOKitLib.h> +#include <IOKit/IOCFPlugIn.h> +#include <IOKit/usb/IOUSBLib.h> + + +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif + +#include "io.h" +#include "samba.h" + + +static mach_port_t masterPort = 0; +static IOUSBDeviceInterface **usbDev = NULL; +static IOUSBInterfaceInterface **intf = NULL; +static UInt8 inPipeRef = 0; +static UInt8 outPipeRef = 0; + +#undef DEBUG_IO + + +int do_intf(io_service_t usbInterfaceRef) +{ + IOReturn err; + IOCFPlugInInterface **iodev; + SInt32 score; + UInt8 numPipes; + int i; + UInt8 direction, number, transferType, interval; + UInt16 maxPacketSize; + + err = IOCreatePlugInInterfaceForService(usbInterfaceRef, + kIOUSBInterfaceUserClientTypeID, + kIOCFPlugInInterfaceID, + &iodev, &score); + if( err || !iodev ) { + printf("unable to create plugin. ret = %08x, iodev = %p\n", err, iodev); + return -1; + } + + err = (*iodev)->QueryInterface(iodev, + CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), + (LPVOID)&intf); + IODestroyPlugInInterface(iodev); + + if (err || !intf) { + printf("unable to create a device interface. ret = %08x, intf = %p\n", + err, intf); + return -1; + } + + err = (*intf)->USBInterfaceOpen(intf); + if (err) { + printf("unable to open interface. ret = %08x\n", err); + return -1; + } + + err = (*intf)->GetNumEndpoints(intf, &numPipes); + if (err) { + printf("unable to get number of endpoints. ret = %08x\n", err); + return -1; + } + + if (numPipes) { + for (i=1; i <= numPipes; i++) { + + err = (*intf)->GetPipeProperties(intf, i, &direction, + &number, &transferType, + &maxPacketSize, &interval); + if (err) { + printf("unable to get pipe properties for pipe %d, err = %08x\n", + i, err); + continue; + } + + if (transferType != kUSBBulk) { + continue; + } + + if ((direction == kUSBIn) && !inPipeRef) { + inPipeRef = i; + } + if ((direction == kUSBOut) && !outPipeRef) { + outPipeRef = i; + } + } + } + + if( !inPipeRef || !outPipeRef ) { + (*intf)->USBInterfaceClose(intf); + (*intf)->Release(intf); + intf = NULL; + return -1; + } + + return 0; +} + + +static int do_dev( io_service_t usbDeviceRef ) +{ + IOReturn err; + IOCFPlugInInterface **iodev; // requires <IOKit/IOCFPlugIn.h> + SInt32 score; + UInt8 numConf; + IOUSBConfigurationDescriptorPtr confDesc; + IOUSBFindInterfaceRequest interfaceRequest; + io_iterator_t iterator; + io_service_t usbInterfaceRef; + + err = IOCreatePlugInInterfaceForService(usbDeviceRef, + kIOUSBDeviceUserClientTypeID, + kIOCFPlugInInterfaceID, &iodev, &score); + if (err || !iodev) { + printf("unable to create plugin. ret = %08x, iodev = %p\n", + err, iodev); + return -1; + } + + err = (*iodev)->QueryInterface(iodev, + CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), + (LPVOID)&usbDev); + IODestroyPlugInInterface(iodev); // done with this + + if (err || !usbDev) { + printf("unable to create a device interface. ret = %08x, dev = %p\n", + err, usbDev); + return -1; + } + + err = (*usbDev)->USBDeviceOpen(usbDev); + if (err) { + printf("unable to open device. ret = %08x\n", err); + return -1; + } + err = (*usbDev)->GetNumberOfConfigurations(usbDev, &numConf); + if (err || !numConf) { + printf("unable to obtain the number of configurations. ret = %08x\n", err); + return -1; + } + + err = (*usbDev)->GetConfigurationDescriptorPtr(usbDev, 0, &confDesc); // get the first config desc (index 0) + if (err) { + printf("unable to get config descriptor for index 0\n"); + return -1; + } + + + err = (*usbDev)->SetConfiguration(usbDev, confDesc->bConfigurationValue); + if (err) { + printf("unable to set the configuration\n"); + return -1; + } + + // requested class + interfaceRequest.bInterfaceClass = kIOUSBFindInterfaceDontCare; + // requested subclass + interfaceRequest.bInterfaceSubClass = kIOUSBFindInterfaceDontCare; + // requested protocol + interfaceRequest.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; + // requested alt setting + interfaceRequest.bAlternateSetting = kIOUSBFindInterfaceDontCare; + + err = (*usbDev)->CreateInterfaceIterator(usbDev, &interfaceRequest, &iterator); + if (err) { + printf("unable to create interface iterator\n"); + return -1; + } + + while( (usbInterfaceRef = IOIteratorNext(iterator)) ) { + if( do_intf( usbInterfaceRef ) == 0 ) { + IOObjectRelease(iterator); + iterator = 0; + return 0; + } + } + + + IOObjectRelease(iterator); + iterator = 0; + return -1; + + +} + +int io_init( char *dev __attribute__((unused)) ) +{ + + kern_return_t err; + CFMutableDictionaryRef matchingDictionary = 0; + CFNumberRef numberRef; + SInt32 idVendor = USB_VID_ATMEL; + SInt32 idProduct = USB_PID_SAMBA; + io_iterator_t iterator = 0; + io_service_t usbDeviceRef; + + + if( (err = IOMasterPort( MACH_PORT_NULL, &masterPort )) ) { + printf( "could not create master port, err = %08x\n", err ); + return -1; + } + + if( !(matchingDictionary = IOServiceMatching(kIOUSBDeviceClassName)) ) { + printf( "could not create matching dictionary\n" ); + return -1; + } + + if( !(numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, + &idVendor)) ) { + printf( "could not create CFNumberRef for vendor\n" ); + return -1; + } + CFDictionaryAddValue( matchingDictionary, CFSTR(kUSBVendorID), numberRef); + CFRelease( numberRef ); + numberRef = 0; + + if( !(numberRef = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, + &idProduct)) ) { + printf( "could not create CFNumberRef for product\n" ); + return -1; + } + CFDictionaryAddValue( matchingDictionary, CFSTR(kUSBProductID), numberRef); + CFRelease( numberRef ); + numberRef = 0; + + err = IOServiceGetMatchingServices( masterPort, matchingDictionary, &iterator ); + matchingDictionary = 0; // consumed by the above call + + + + if( (usbDeviceRef = IOIteratorNext( iterator )) ) { + printf( "found boot agent\n" ); + + do_dev( usbDeviceRef ); + } else { + printf( "can not find boot agent\n" ); + return -1; + } + + + + IOObjectRelease(usbDeviceRef); + + IOObjectRelease(iterator); + + + return samba_init(); + + + IOObjectRelease(usbDeviceRef); + + IOObjectRelease(iterator); + return -1; +} + + +int io_cleanup( void ) +{ + if( intf ) { + (*intf)->USBInterfaceClose(intf); + (*intf)->Release(intf); + intf = NULL; + } + + if( usbDev ) { + (*usbDev)->USBDeviceClose(usbDev); + (*usbDev)->Release(usbDev); + usbDev = NULL; + } + + return 0; +} + +int io_write( void *buff, int len ) +{ + if( (*intf)->WritePipe( intf, outPipeRef, buff, (UInt32) len ) != + kIOReturnSuccess ) { + printf( "write error\n"); + } + + return len; +} + +int io_read( void *buff, int len ) +{ + + UInt32 size = len; + + if( (*intf)->ReadPipe( intf, inPipeRef, buff, &size ) != + kIOReturnSuccess ) { + printf( "read error\n"); + } + + + return (int) size; +} + diff --git a/io_libusb.c b/io_libusb.c new file mode 100644 index 0000000..0c30494 --- /dev/null +++ b/io_libusb.c @@ -0,0 +1,70 @@ +#include "config.h" + +#include <usb.h> + +#include <stdio.h> +#include "io.h" +#include "samba.h" + +static usb_dev_handle *io_handle; + +int io_init( char *dev ) +{ + struct usb_bus *bus; + struct usb_device *usbdev; + + usb_init(); /* initialize the library */ + usb_find_busses(); /* find all busses */ + usb_find_devices(); /* find all connected devices */ + + for(bus = usb_get_busses(); bus; bus = bus->next) { + for(usbdev = bus->devices; usbdev; usbdev = usbdev->next) { + if(usbdev->descriptor.idVendor == USB_VID_ATMEL + && usbdev->descriptor.idProduct == USB_PID_SAMBA) { + + + if( (io_handle = usb_open(usbdev)) ) { + if( usb_set_configuration( io_handle, 1 ) < 0 ){ + usb_close(io_handle); + continue; + } + if( usb_claim_interface( io_handle, 1 ) < 0 ){ + usb_close(io_handle); + continue; + } + return samba_init(); + + } + } + + } + } + + return -1; +} + +int io_cleanup( void ) +{ + usb_release_interface(io_handle, 1); + usb_close(io_handle); + return 0; +} + + +int io_write( void *buff, int len ) +{ + int ret = usb_bulk_write(io_handle, 0x1, buff, len, 5000); + if( ret < 0 ) { + printf("error: %s\n", usb_strerror()); + } + return ret; +} + +int io_read( void *buff, int len ) +{ + int ret = usb_bulk_read(io_handle, 0x82, buff, len, 5000); + if( ret < 0 ) { + printf("error: %s\n", usb_strerror()); + } + return ret; +} diff --git a/io_posix.c b/io_posix.c new file mode 100644 index 0000000..ae98e10 --- /dev/null +++ b/io_posix.c @@ -0,0 +1,149 @@ +/* + * io.c + * + * Copyright (C) 2005 Erik Gilling, 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, version 2. + * + */ + +#include "config.h" + +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <sys/select.h> + +#include <stdio.h> +#include <string.h> +#include <errno.h> + + +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif + +#include "io.h" +#include "samba.h" + +static int io_fd; + +#define SAM7_TTY "/dev/at91_0" + +#undef DEBUG_IO + +int io_init( char *dev ) +{ + if( dev == NULL ) { + dev = SAM7_TTY; + } + // char buff[16]; + + if( (io_fd = open( dev, O_RDWR )) < 0 ) { + printf( "can't open \"%s\": %s\n", dev, strerror( errno ) ); + return -1; + } + + + + return samba_init(); +} + +int io_cleanup( void ) +{ + close( io_fd ); + + return 0; +} +int io_write( void *buff, int len ) +{ + int write_len = 0; + int ret; + +#ifdef DEBUG_IO + write( STDOUT_FILENO, ">", 1 ); + write( STDOUT_FILENO, buff, len ); + write( STDOUT_FILENO, "\n", 1 ); + +#endif + while( write_len < len ) { + if( (ret = write( io_fd, buff + write_len, len - write_len )) < 0 ) { + return -1; + } + write_len += ret; + } + + return write_len; +} + +int io_read( void *buff, int len ) +{ +#ifdef DEBUG_IO + int i; + char outbuff[16]; + len = read( io_fd, buff, len ); + write( STDOUT_FILENO, "<", 1 ); + for( i=0 ; i<len ; i++ ) { + snprintf( outbuff, 16, " %02X", ((char*)buff)[i] & 0xff ); + write( STDOUT_FILENO, outbuff, strlen(outbuff) ); + } + write( STDOUT_FILENO, "\n", 1 ); + + return len; +#else + return read( io_fd, buff, len ); +#endif +} + +#if 0 +int io_read_response( char *buff, int len ) +{ + int read_len = 0; + struct timeval tv; + fd_set fds; + int ret; + + while( read_len < len ) { + + tv.tv_sec = 1; + tv.tv_usec = 0; + + FD_ZERO( &fds ); + FD_SET( io_fd, &fds ); + + if( (ret = select( io_fd + 1, &fds, NULL, NULL, &tv )) < 0 ) { + if( errno == EINTR ) { + continue; + } + } + if( ret == 0 ) { + buff[read_len] = '\0'; + printf( "timeout '%s'\n", buff); + return -read_len; + } + + if( (ret = read( io_fd, buff + read_len, len - read_len )) < 0 ) { + return -1; + } + read_len += ret; + + if( (read_len > 0) && + buff[ read_len - 1 ] == '>' ) { + if( (read_len > 2) && + buff[ read_len - 2 ] == '\r' && + buff[ read_len - 3 ] == '\n' ) { + return buff[read_len - 3] = '\0' ; + return read_len-3 ; + } else { + return buff[read_len - 1] = '\0' ; + return read_len-1 ; + } + } + } + + return read_len; +} +#endif diff --git a/io_win32.c b/io_win32.c new file mode 100644 index 0000000..698e550 --- /dev/null +++ b/io_win32.c @@ -0,0 +1,173 @@ +/* + * io_win32.c + * + * Copyright (C) 2005 Erik Gilling, 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, version 2. + * + * + * USB device enumeration modeled from http://www.delcom-eng.com/downloads/USBPRGMNL.pdf + * + */ + +#include "config.h" + +#define WINVER 0x0500 +#define INITGUID +#include <windows.h> +#include <setupapi.h> +#include <basetyps.h> + +#include <stdio.h> + +#include "io.h" +#include "samba.h" + + +// {E6EF7DCD-1795-4a08-9FBF-AA78423C26F0} +DEFINE_GUID(USBIODS_GUID, +0xe6ef7dcd, 0x1795, 0x4a08, 0x9f, 0xbf, 0xaa, 0x78, 0x42, 0x3c, 0x26, 0xf0); + +HANDLE io_pipe_in, io_pipe_out; + +int io_init( char *dev ) +{ + char *devname; + + // char buff[16]; + + HDEVINFO hInfo = SetupDiGetClassDevs(&USBIODS_GUID, NULL, + NULL, DIGCF_PRESENT | + DIGCF_INTERFACEDEVICE); + + SP_INTERFACE_DEVICE_DATA Interface_Info; + Interface_Info.cbSize = sizeof(Interface_Info); + // Enumerate device + if( !SetupDiEnumDeviceInterfaces(hInfo, NULL, (LPGUID) + &USBIODS_GUID,0, &Interface_Info ) ) { + printf( "can't find boot agent\n"); + goto error0; + } + + DWORD needed; // get the required lenght + SetupDiGetInterfaceDeviceDetail(hInfo, &Interface_Info, + NULL, 0, &needed, NULL); + PSP_INTERFACE_DEVICE_DETAIL_DATA detail = + (PSP_INTERFACE_DEVICE_DETAIL_DATA) malloc(needed); + if( !detail ) { + printf( "can't find boot agent\n"); + goto error0; + return(-1); + } + + // fill the device details + detail->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); + + if( !SetupDiGetInterfaceDeviceDetail( hInfo, + &Interface_Info,detail, + needed,NULL, NULL )) { + printf( "can't find boot agent\n"); + goto error1; + } + + devname = (char *) malloc( strlen( detail->DevicePath ) + 7 ); + + strcpy( devname, detail->DevicePath ); + strcat( devname, "\\PIPE00" ); + printf( "%s\n", devname ); + + // open out + + io_pipe_out = CreateFile( devname, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ, NULL, OPEN_EXISTING, + 0, NULL ); + + if( io_pipe_out == INVALID_HANDLE_VALUE ) { + printf( "can't open output pipe\n" ); + goto error2; + } + + strcpy( devname, detail->DevicePath ); + strcat( devname, "\\PIPE01" ); + + // open in + + io_pipe_in = CreateFile( devname, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ, NULL, OPEN_EXISTING, + 0, NULL ); + + if( io_pipe_in == INVALID_HANDLE_VALUE ) { + printf( "can't open input pipe\n" ); + goto error3; + } + + + + + free((PVOID) detail); + free( devname ); + + + + return samba_init(); + + return 0; + // return samba_init(); + + error3: + CloseHandle( io_pipe_out ); + + error2: + free( devname ); + + error1: + free((PVOID) detail); + + error0: + SetupDiDestroyDeviceInfoList(hInfo); + return -1; +} + +int io_cleanup( void ) +{ + CloseHandle( io_pipe_out ); + CloseHandle( io_pipe_in ); + + return 0; +} +int io_write( void *buff, int len ) +{ + int write_len = 0; + DWORD bytes_written; + + while( write_len < len ) { + + if( !WriteFile( io_pipe_out, buff + write_len, + len - write_len, &bytes_written, NULL ) ) { + return -1; + } + write_len += bytes_written; + } + + return write_len; +} + +int io_read( void *buff, int len ) +{ + int read_len = 0; + DWORD bytes_read; + + while( read_len < len ) { + + if( !ReadFile( io_pipe_in, buff + read_len, + len - read_len, &bytes_read, NULL ) ) { + return -1; + } + read_len += bytes_read; + } + + return read_len; +} + diff --git a/loader128_data.h b/loader128_data.h new file mode 100644 index 0000000..143de12 --- /dev/null +++ b/loader128_data.h @@ -0,0 +1,18 @@ +uint8_t loader128_data[] = { + 0x0c, 0xd0, 0x9f, 0xe5, 0x00, 0x40, 0x2d, 0xe9, + 0x02, 0x00, 0x00, 0xeb, 0x01, 0x00, 0xbd, 0xe8, + 0x10, 0xff, 0x2f, 0xe1, 0x00, 0x1c, 0x20, 0x00, + 0x30, 0x40, 0x2d, 0xe9, 0x02, 0xe6, 0xa0, 0xe3, + 0x05, 0xeb, 0x8e, 0xe2, 0x80, 0x50, 0x9e, 0xe5, + 0x4c, 0x40, 0x9f, 0xe5, 0x85, 0x02, 0xa0, 0xe1, + 0x68, 0x30, 0x94, 0xe5, 0x01, 0x00, 0x13, 0xe3, + 0xfc, 0xff, 0xff, 0x0a, 0x00, 0x10, 0xa0, 0xe3, + 0x01, 0xc6, 0xa0, 0xe3, 0x01, 0x20, 0x80, 0xe0, + 0x01, 0x31, 0x9e, 0xe7, 0x01, 0x10, 0x81, 0xe2, + 0x1f, 0x00, 0x51, 0xe3, 0x02, 0x31, 0x8c, 0xe7, + 0xf9, 0xff, 0xff, 0xda, 0x05, 0x3b, 0xa0, 0xe1, + 0x23, 0x3b, 0xa0, 0xe1, 0x03, 0x34, 0xa0, 0xe1, + 0x5a, 0x34, 0x83, 0xe3, 0x01, 0x30, 0x83, 0xe3, + 0x00, 0x00, 0xa0, 0xe3, 0x64, 0x30, 0x84, 0xe5, + 0x30, 0x80, 0xbd, 0xe8, 0x00, 0xff, 0xff, 0xff +}; diff --git a/loader256_data.h b/loader256_data.h new file mode 100644 index 0000000..0b5ef0b --- /dev/null +++ b/loader256_data.h @@ -0,0 +1,18 @@ +uint8_t loader256_data[] = { + 0x0c, 0xd0, 0x9f, 0xe5, 0x00, 0x40, 0x2d, 0xe9, + 0x02, 0x00, 0x00, 0xeb, 0x01, 0x00, 0xbd, 0xe8, + 0x10, 0xff, 0x2f, 0xe1, 0x00, 0x1c, 0x20, 0x00, + 0x30, 0x40, 0x2d, 0xe9, 0x02, 0xe6, 0xa0, 0xe3, + 0x05, 0xeb, 0x8e, 0xe2, 0x00, 0x51, 0x9e, 0xe5, + 0x4c, 0x40, 0x9f, 0xe5, 0x05, 0x03, 0xa0, 0xe1, + 0x68, 0x30, 0x94, 0xe5, 0x01, 0x00, 0x13, 0xe3, + 0xfc, 0xff, 0xff, 0x0a, 0x00, 0x10, 0xa0, 0xe3, + 0x01, 0xc6, 0xa0, 0xe3, 0x01, 0x20, 0x80, 0xe0, + 0x01, 0x31, 0x9e, 0xe7, 0x01, 0x10, 0x81, 0xe2, + 0x3f, 0x00, 0x51, 0xe3, 0x02, 0x31, 0x8c, 0xe7, + 0xf9, 0xff, 0xff, 0xda, 0x05, 0x3b, 0xa0, 0xe1, + 0x23, 0x3b, 0xa0, 0xe1, 0x03, 0x34, 0xa0, 0xe1, + 0x5a, 0x34, 0x83, 0xe3, 0x01, 0x30, 0x83, 0xe3, + 0x00, 0x00, 0xa0, 0xe3, 0x64, 0x30, 0x84, 0xe5, + 0x30, 0x80, 0xbd, 0xe8, 0x00, 0xff, 0xff, 0xff +}; @@ -0,0 +1,170 @@ +/* + * main.c + * + * Copyright (C) 2005 Erik Gilling, 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, version 2. + * + */ + +#include "config.h" + +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#include <stdio.h> +#include <string.h> +#include <errno.h> +#ifdef HAVE_CTYPE_H +#include <ctype.h> +#endif + +#include <readline/readline.h> +#include <readline/history.h> + +#include <getopt.h> + +#include "io.h" +#include "samba.h" +#include "cmd.h" + +#define SAM7_TTY "/dev/at91_0" + + +static int sam7_parse_line( char *line, char *argv[] ); +static int sam7_handle_line( char *line ); +static void usage( void ); + +#define MAX_CMDS 32 + +int main( int argc, char *argv[] ) +{ + char *cmdline; + char *line = NULL; + char *cmds[MAX_CMDS]; + int n_cmds=0; + int c,i; + + + while( 1 ) { + int option_index; + static struct option long_options[] = { + { "line", 1, 0, 'l' }, + { "exec", 1, 0, 'e' }, + { "help", 0, 0, 'h' } + }; + + c = getopt_long( argc, argv, "l:e:h", long_options, &option_index ); + + if( c == -1 ) { + break; + } + + switch( c ) { + case 'l': + line = optarg; + break; + + case 'e': + if( n_cmds >= MAX_CMDS ) { + printf( "to many commands, increase MAX_CMDS\n" ); + return 1; + } + cmds[n_cmds] = optarg; + n_cmds++; + break; + + case 'h': + usage(); + return 0; + break; + + default: + printf( "unknown option\n" ); + usage(); + return 1; + } + } + + + if( io_init( line ) < 0 ) { + return 1; + } + + if( n_cmds > 0 ) { + for( i=0 ; i<n_cmds ; i++ ) { + sam7_handle_line( cmds[i] ); + } + + } else { + while( (cmdline = readline( "sam7> " )) ) { + add_history( cmdline ); + sam7_handle_line( cmdline ); + } + } + + io_cleanup(); + + return 0; +} + +static void usage( void ) +{ + printf( "usage: sam7 [options]\n" ); + printf( " -e|--exec <cmd> execute cmd instead of entering interactive mode.\n"); + printf( " -l|--line <line> specifies the line/tty which the boot agent resides.\n"); + printf( " only used for posix IO.\n" ); + printf( " -h|--help dislay this message and exit.\n"); +} + +static int sam7_parse_line( char *line, char *argv[] ) +{ + char *p = line; + int argc = 0; + + + while( *p ) { + // eat white space + while( *p && isspace( *p ) ) { p++; } + if( ! *p ) { + break; + } + + argv[argc++] = p; + + while( *p && !isspace( *p ) ) { p++; } + if( *p ) { + *p++ = '\0'; + } + } + + return argc; +} + +static int sam7_handle_line( char *line ) +{ + int argc; + char buff[256]; + char *argv[32]; + cmd_t *cmd; + + strncpy( buff, line, 255 ); + buff[255] = '\0'; + + argc = sam7_parse_line( buff, argv ); + + if( argc > 0 ) { + if( (cmd = cmd_find( argv[0] )) != NULL ) { + return cmd->func( argc, argv ); + } + printf( "command %s not found\n", argv[0] ); + return -1; + } + + return 0; +} + @@ -0,0 +1,399 @@ +/* + * samba.c + * + * Copyright (C) 2005,2006 Erik Gilling, 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, version 2. + * + */ + +#include "config.h" + +#include <unistd.h> + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> + +#ifdef HAVE_ENDIAN_H +#include <endian.h> +#endif + +#ifdef HAVE_LOCALENDIAN_H +#include <localendian.h> +#endif + +#include "io.h" +#include "samba.h" + + +#ifndef __BYTE_ORDER +# define __LITTLE_ENDIAN 4321 +# define __BIG_ENDIAN 1234 +# ifdef __LITTLE_ENDIAN__ +# define __BYTE_ORDER __LITTLE_ENDIAN +# endif +# ifdef __BIG_ENDIAN__ +# define __BYTE_ORDER __BIG_ENDIAN +# endif +#endif + +#if defined( __BYTE_ORDER ) +# if __BYTE_ORDER == __LITTLE_ENDIAN +# define le2hl(x) (x) +# define le2hs(x) (x) +# endif + +# if __BYTE_ORDER == __BIG_ENDIAN + +# define le2hl(x) \ + ((unsigned long int)((((unsigned long int)(x) & 0x000000ffU) << 24) | \ + (((unsigned long int)(x) & 0x0000ff00U) << 8) | \ + (((unsigned long int)(x) & 0x00ff0000U) >> 8) | \ + (((unsigned long int)(x) & 0xff000000U) >> 24))) + +# define le2hs(x) \ + ((unsigned short int)((((unsigned short int)(x) & 0x00ff) << 8) | \ + (((unsigned short int)(x) & 0xff00) >> 8))) + +# endif +#endif + +#define hl2le(x) le2hl(x) +#define hs2le(x) le2hs(x) + +static const char *eprocs[] = { + /* 000 */ "", + /* 001 */ "ARM946E-S", + /* 010 */ "ARM7TDMI", + /* 011 */ "", + /* 100 */ "ARM920T", + /* 101 */ "ARM926EJ-S", + /* 110 */ "", + /* 111 */ "" +}; + + +#define K 1024 + +static const int nvpsizs[] = { + /* 0000 */ 0, + /* 0001 */ 8 * K, + /* 0010 */ 16 * K, + /* 0011 */ 32 * K, + /* 0100 */ -1, + /* 0101 */ 64 * K, + /* 0110 */ -1, + /* 0111 */ 128 * K, + /* 1000 */ -1, + /* 1001 */ 256 * K, + /* 1010 */ 512 * K, + /* 1011 */ -1, + /* 1100 */ 1024 * K, + /* 1101 */ -1, + /* 1110 */ 2048 * K, + /* 1111 */ -1 +}; + +static const int sramsizs[] = { + /* 0000 */ -1, + /* 0001 */ 1 * K, + /* 0010 */ 2 * K, + /* 0011 */ -1, + /* 0100 */ 112 * K, + /* 0101 */ 4 * K, + /* 0110 */ 80 * K, + /* 0111 */ 160 * K, + /* 1000 */ 8 * K, + /* 1001 */ 16 * K, + /* 1010 */ 32 * K, + /* 1011 */ 64 * K, + /* 1100 */ 128 * K, + /* 1101 */ 256 * K, + /* 1110 */ 96 * K, + /* 1111 */ 512 * K +}; + +static const struct { unsigned id; const char *name; } archs[] = { + {AT91_ARCH_AT75Cxx, "AT75Cxx"}, + {AT91_ARCH_AT91x40, "AT91x40"}, + {AT91_ARCH_AT91x63, "AT91x63"}, + {AT91_ARCH_AT91x55, "AT91x55"}, + {AT91_ARCH_AT91x42, "AT91x42"}, + {AT91_ARCH_AT91x92, "AT91x92"}, + {AT91_ARCH_AT91x34, "AT91x34"}, + {AT91_ARCH_AT91SAM7Axx, "AT91SAM7Axx"}, + {AT91_ARCH_AT91SAM7Sxx, "AT91SAM7Sxx"}, + {AT91_ARCH_AT91SAM7XC, "AT91SAM7XC"}, + {AT91_ARCH_AT91SAM7SExx, "AT91SAM7SExx"}, + {AT91_ARCH_AT91SAM7Lxx, "AT91SAM7Lxx"}, + {AT91_ARCH_AT91SAM7Xxx, "AT91SAM7Xxx"}, + {AT91_ARCH_AT91SAM9xx, "AT91SAM9xx"} +}; + +const char *at91_arch_str( int id ) { + int i; + for( i=0 ; i<(sizeof(archs)/sizeof(*archs)) ; i++ ) { + if( archs[i].id == id ) { + return archs[i].name; + } + } + + return ""; +} + +at91_chip_info_t samba_chip_info; + +int samba_init( void ) +{ + uint32_t chipid; + uint16_t response; + + if( io_send_cmd( "N#", &response, sizeof( response ) ) < 0 ) { + printf( "can't init boot program: %s\n", strerror( errno ) ); + return -1; + } + + if( samba_read_word( 0xfffff240, &chipid ) < 0 ) { + return -1; + } + + samba_chip_info.version = AT91_CHIPID_VERSION( chipid ); + samba_chip_info.eproc = AT91_CHIPID_EPROC( chipid ); + samba_chip_info.nvpsiz = nvpsizs[AT91_CHIPID_NVPSIZ( chipid )]; + samba_chip_info.nvpsiz2 = nvpsizs[AT91_CHIPID_NVPSIZ2( chipid )]; + samba_chip_info.sramsiz = sramsizs[AT91_CHIPID_SRAMSIZ( chipid )]; + samba_chip_info.arch = AT91_CHIPID_ARCH( chipid ); + + if( samba_chip_info.arch == AT91_ARCH_AT91SAM7Sxx ) { + switch( samba_chip_info.nvpsiz) { + case 32*K: + samba_chip_info.page_size = 128; + samba_chip_info.lock_bits = 8; + break; + + case 64*K: + samba_chip_info.page_size = 128; + samba_chip_info.lock_bits = 16; + break; + + case 128*K: + samba_chip_info.page_size = 256; + samba_chip_info.lock_bits = 8; + break; + + case 256*K: + samba_chip_info.page_size = 256; + samba_chip_info.lock_bits = 16; + break; + + default: + printf( "unknown sam7s flash size %d\n", samba_chip_info.nvpsiz ); + return -1; + } + } else if( samba_chip_info.arch == AT91_ARCH_AT91SAM7SExx ) { + + switch( samba_chip_info.nvpsiz) { + case 32*K: + samba_chip_info.page_size = 128; + samba_chip_info.lock_bits = 8; + break; + + case 64*K: + samba_chip_info.page_size = 128; + samba_chip_info.lock_bits = 16; + break; + + case 128*K: + samba_chip_info.page_size = 256; + samba_chip_info.lock_bits = 8; + break; + + case 256*K: + samba_chip_info.page_size = 256; + samba_chip_info.lock_bits = 16; + break; + + case 512*K: + samba_chip_info.page_size = 256; + samba_chip_info.lock_bits = 32; + break; + + default: + printf( "unknown sam7se flash size %d\n", samba_chip_info.nvpsiz ); + return -1; + } + } else if( samba_chip_info.arch == AT91_ARCH_AT91SAM7Xxx ) { + + switch( samba_chip_info.nvpsiz ) { + case 128*K: + samba_chip_info.page_size = 256; + samba_chip_info.lock_bits = 8; + break; + + case 256*K: + samba_chip_info.page_size = 256; + samba_chip_info.lock_bits = 16; + break; + + default: + printf( "unknown sam7x srflashsize %d\n", samba_chip_info.nvpsiz ); + return -1; + } + } else { + printf( "Page size info of %s not known\n", + at91_arch_str( samba_chip_info.arch ) ); + return -1; + } + + printf("Chip Version: %d\n", samba_chip_info.version ); + printf("Embedded Processor: %s\n", eprocs[samba_chip_info.eproc] ); + printf("NVRAM Region 1 Size: %d K\n", samba_chip_info.nvpsiz / K ); + printf("NVRAM Region 2 Size: %d K\n", samba_chip_info.nvpsiz2 / K ); + printf("SRAM Size: %d K\n", samba_chip_info.sramsiz / K ); + printf("Series: %s\n", at91_arch_str( samba_chip_info.arch ) ); + printf("Page Size: %d bytes\n", samba_chip_info.page_size ); + printf("Lock Regions: %d\n", samba_chip_info.lock_bits ); + + return 0; +} + +int samba_write_byte( uint32_t addr, uint8_t value ) +{ + char cmd[64]; + + snprintf( cmd, 64, "O%08X,%02X#", (unsigned int) addr, + (unsigned int) value ); + + return io_send_cmd( cmd, NULL, 0 ); +} + +int samba_read_byte( uint32_t addr, uint8_t *value ) +{ + char cmd[64]; + + snprintf( cmd, 64, "o%08X,1#", (unsigned int) addr ); + + return io_send_cmd( cmd, value, 1 ); +} + +int samba_write_half_word( uint32_t addr, uint16_t value ) +{ + char cmd[64]; + + snprintf( cmd, 64, "H%08X,%04X#", (unsigned int) addr, + (unsigned int) value ); + + + return io_send_cmd( cmd, NULL, 0 ); +} + +int samba_read_half_word( uint32_t addr, uint16_t *value ) +{ + char cmd[64]; + int err; + + snprintf( cmd, 64, "h%X,2#", (unsigned int) addr ); + + err = io_send_cmd( cmd, value, 2 ); + *value = le2hs( *value ); + + return err; + +} + +int samba_write_word( uint32_t addr, uint32_t value ) +{ + char cmd[64]; + + snprintf( cmd, 64, "W%08X,%08X#", (unsigned int) addr, + (unsigned int) value ); + + return io_send_cmd( cmd, NULL, 0 ); +} + +int samba_read_word( uint32_t addr, uint32_t *value ) +{ + char cmd[64]; + int err; + + snprintf( cmd, 64, "w%08X,4#", (unsigned int) addr ); + + err = io_send_cmd( cmd, value, 4 ); + *value = le2hl( *value ); + + return err; +} + + +int samba_send_file( uint32_t addr, uint8_t *buff, int len ) +{ + char cmd[64]; + int i=0; + + snprintf( cmd, 64, "S%X,%X#", (unsigned int) addr, (unsigned int) len ); + + if( io_write( cmd, strlen( cmd ) ) < 0 ) { + return -1; + } + + usleep( 2000 ); + + for( i=0 ; i<len ; i+=64 ) { + if( io_write( buff+i, (len-i < 64)? len-i : 64 ) < 0 ){ + return -1; + } + usleep( 2000 ); + } + + return 0; +} + +int samba_recv_file( uint32_t addr, uint8_t *buff, int len ) +{ + char cmd[64]; + int i=0; + + snprintf( cmd, 64, "R%X,%X#", (unsigned int) addr, (unsigned int) len ); + + if( io_write( cmd, strlen( cmd ) ) < 0 ) { + return -1; + } + + usleep( 2000 ); + + for( i=0 ; i<len ; i+=64 ) { + if( io_read( buff+i, (len-i < 64)? len-i : 64 ) < 0 ){ + return -1; + } + } + + return 0; + +} + +int samba_go( uint32_t addr ) +{ + char cmd[64]; + snprintf( cmd, 64, "G%08X#", (unsigned int) addr ); + + return io_send_cmd( cmd, NULL, 0 ); +} + +int samba_get_version( char *version, int len ) +{ +#if 0 + if( io_send_cmd( "V#", version, len ) < 0 ) { + return -1; + } + + return 0; +#else + /* don't know the new form of V# */ + return -1; +#endif +} + @@ -0,0 +1,69 @@ +/* + * samba.h + * + * Copyright (C) 2005 Erik Gilling, 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, version 2. + * + */ + +#ifndef __samba_h__ +#define __samba_h__ + + +#ifdef HAVE_STDINT_H +#include <stdint.h> +#endif + +#define AT91_CHIPID_VERSION( chipid ) (((chipid)>>0)&0x1f) +#define AT91_CHIPID_EPROC( chipid ) (((chipid)>>5)&0x7) +#define AT91_CHIPID_NVPSIZ( chipid ) (((chipid)>>8)&0xf) +#define AT91_CHIPID_NVPSIZ2( chipid ) (((chipid)>>12)&0xf) +#define AT91_CHIPID_SRAMSIZ( chipid ) (((chipid)>>16)&0xf) +#define AT91_CHIPID_ARCH( chipid ) (((chipid)>>20)&0xff) +#define AT91_CHIPID_NVPTYP( chipid ) (((chipid)>>28)&0x7) +#define AT91_CHIPID_EXT( chipid ) (((chipid)>>31)&0x1) + +#define AT91_ARCH_AT75Cxx 0xF0 +#define AT91_ARCH_AT91x40 0x40 +#define AT91_ARCH_AT91x63 0x63 +#define AT91_ARCH_AT91x55 0x55 +#define AT91_ARCH_AT91x42 0x42 +#define AT91_ARCH_AT91x92 0x92 +#define AT91_ARCH_AT91x34 0x34 +#define AT91_ARCH_AT91SAM7Axx 0x60 +#define AT91_ARCH_AT91SAM7Sxx 0x70 +#define AT91_ARCH_AT91SAM7XC 0x71 +#define AT91_ARCH_AT91SAM7SExx 0x72 +#define AT91_ARCH_AT91SAM7Lxx 0x73 +#define AT91_ARCH_AT91SAM7Xxx 0x75 +#define AT91_ARCH_AT91SAM9xx 0x19 + +typedef struct { + int version; + int eproc; + int nvpsiz; + int nvpsiz2; + int sramsiz; + int arch; + int page_size; + int lock_bits; +} at91_chip_info_t; + +extern at91_chip_info_t samba_chip_info; + +int samba_init( void ); +int samba_write_byte( uint32_t addr, uint8_t value ); +int samba_read_byte( uint32_t addr, uint8_t *value ); +int samba_write_half_word( uint32_t addr, uint16_t value ); +int samba_read_half_word( uint32_t addr, uint16_t *value ); +int samba_write_word( uint32_t addr, uint32_t value ); +int samba_read_word( uint32_t addr, uint32_t *value ); +int samba_send_file( uint32_t addr, uint8_t *buff, int len ); +int samba_recv_file( uint32_t addr, uint8_t *buff, int len ); +int samba_go( uint32_t addr ); +int samba_get_version( char *version, int len ); + +#endif /* __samba_h__ */ |