summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorMichael Brandt <michael.brandt@stericsson.com>2010-07-20 15:08:22 +0200
committerMichael BRANDT <michael.brandt@stericsson.com>2010-08-30 20:03:48 +0200
commit20503b61a7f73fad8ee97219f7a1e74de3a8a2ac (patch)
treeec58c1f830639a45462fe07219304a06a16b7b54 /common
parent3a5b27b58258ff61dfae3167bc46fed0146ddffd (diff)
Read/write VFAT support from Rockbox-3.3 FAT stack
Add read/write VFAT support from Rockbox-3.3 FAT stack. It should be also applicable to the unmodified 2009.11 U-Boot release. Note that is was taken as is from Rockbox and from a older U-Boot Rockbox patch. "checkpatch" shows very many coding style errors and warnings, but it is tedious work to clean this up. To make this patch work an additional mmc_block_write() board support routine and the errno variable are needed. Furthermore following defines in the board config header file: #define CONFIG_ROCKBOX_FAT 1 #define CONFIG_U_BOOT 1 #define CONFIG_SUPPORT_VFAT 1 #define CONFIG_CMD_TREE_FAT This will be added in a follow-up patch. This patch is based on the patch from Etienne Carriere <etienne.carriere@stericsson.com> for the U671x U-Boot: This commit adds FAT write support to u-boot native read-only FAT code. Commit initially applied on u-boot-v2009.01 (SHA1: 72d15e705bc3983884105cb7755c7ba80e74a0a5) Based on FAT stack dumped from Rockbox package v3.1 (www.rockbox.org). Based on initial Rockbox FAT stack integration in u-boot by Keith Outwater (outwater@comcast.net). Current porting is aligned with Rockbox v3.3 FAT stack. Enable upon config switches: CONFIG_CMD_FAT CONFIG_ROCKBOX_FAT CONFIG_CMD_TREE_FAT (recommended) CONFIG_SUPPORT_VFAT (recommended) C code APIs (from U-boot native FAT support): int fat_register_device(block_dev_desc_t *dev_desc, int part_no); long file_fat_read(const char *path, void *buf, unsigned long maxsize); int file_fat_ls(const char *dirname); int file_fat_detectfs(void); C code APIs (added by Rockbox FAT support): long file_fat_write(const char *path, void *buf, unsigned long maxsize); int file_fat_rm(const char *path); int file_fat_rmdir(const char *path); int file_fat_mkdir(const char *path); int file_fat_cd(const char *path); int file_fat_pwd(void); int file_fat_mv(const char *oldpath, const char *newpath); unsigned int rockbox_fat_free(unsigned long size_kbyte); unsigned int rockbox_fat_size(void); Use "help fat" from u-boot console to see available commands. ST-Ericsson ID: WP264488 Change-Id: I9afc29ecb80f9152bd8534bbf11e47e54cfad796 Signed-off-by: Michael Brandt <michael.brandt@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/3009
Diffstat (limited to 'common')
-rwxr-xr-xcommon/Makefile1
-rw-r--r--common/cmd_fat.c592
-rw-r--r--common/unicode.c441
3 files changed, 1027 insertions, 7 deletions
diff --git a/common/Makefile b/common/Makefile
index de594b4a1..c82f08122 100755
--- a/common/Makefile
+++ b/common/Makefile
@@ -40,6 +40,7 @@ COBJS-y += s_record.o
COBJS-$(CONFIG_SERIAL_MULTI) += serial.o
COBJS-y += stdio.o
COBJS-y += xyzModem.o
+COBJS-y += unicode.o
# core command
COBJS-y += cmd_boot.o
diff --git a/common/cmd_fat.c b/common/cmd_fat.c
index f3089a296..4b40826ec 100644
--- a/common/cmd_fat.c
+++ b/common/cmd_fat.c
@@ -2,6 +2,10 @@
* (C) Copyright 2002
* Richard Jones, rjones@nexus-tech.net
*
+ * Keith Outwater (outwater4@comcast.net) - add additional
+ * FAT commands for use with rockbox (www.rockbox.org) FAT
+ * filesystem driver.
+ *
* See file CREDITS for list of people who contributed to this
* project.
*
@@ -45,7 +49,8 @@ int do_fat_fsload (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
char *ep;
if (argc < 5) {
- printf ("usage: fatload <interface> <dev[:part]> <addr> <filename> [bytes]\n");
+ printf ("usage: fatload <interface> <dev[:part]> <addr> "
+ "<filename> [bytes]\n");
return 1;
}
dev = (int)simple_strtoul (argv[2], &ep, 16);
@@ -62,7 +67,8 @@ int do_fat_fsload (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
part = (int)simple_strtoul(++ep, NULL, 16);
}
if (fat_register_device(dev_desc,part)!=0) {
- printf ("\n** Unable to use %s %d:%d for fatload **\n",argv[1],dev,part);
+ printf ("\n** Unable to use %s %d:%d for fatload **\n",
+ argv[1],dev,part);
return 1;
}
offset = simple_strtoul (argv[3], NULL, 16);
@@ -73,26 +79,511 @@ int do_fat_fsload (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
size = file_fat_read (argv[4], (unsigned char *) offset, count);
if(size==-1) {
- printf("\n** Unable to read \"%s\" from %s %d:%d **\n",argv[4],argv[1],dev,part);
+ printf("\n** Unable to read \"%s\" from %s %d:%d **\n",
+ argv[4],argv[1],dev,part);
return 1;
}
- printf ("\n%ld bytes read\n", size);
+ printf ("\n%ld bytes read\n", (ulong)size);
- sprintf(buf, "%lX", size);
+ sprintf(buf, "0x%lX", size);
setenv("filesize", buf);
return 0;
}
+#ifndef CONFIG_CMD_TREE_FAT
+#ifdef CONFIG_ROCKBOX_FAT
U_BOOT_CMD(
fatload, 6, 0, do_fat_fsload,
"load binary file from a dos filesystem",
- "<interface> <dev[:part]> <addr> <filename> [bytes]\n"
+ "<interface> <dev[:part]> <addr> <filename> [bytes]\n"
" - load binary file 'filename' from 'dev' on 'interface'\n"
" to address 'addr' from dos filesystem"
);
+#else
+U_BOOT_CMD(
+ fatload, 6, 0, do_fat_fsload,
+ "load binary file from a dos FAT16/32 filesystem\n",
+ "<interface> <dev[:part]> <addr> <filename> [bytes]\n"
+ " - load binary file 'filename' from 'dev' on 'interface'\n"
+ " to address 'addr' from dos FAT16/32 filesystem\n"
+);
+#endif
+#endif /* #ifndef CONFIG_CMD_TREE_FAT */
+
+#ifdef CONFIG_ROCKBOX_FAT
+int
+do_fat_fswrite (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ long size;
+ unsigned long offset;
+ unsigned long count;
+ char buf[12];
+ block_dev_desc_t *dev_desc=NULL;
+ int dev=0;
+ int part=1;
+ char *ep;
+
+ if (argc < 6) {
+ printf ("usage: fatwrite <interface> <dev[:part]> "
+ "<addr> <filename> <bytes>\n");
+ return 1;
+ }
+
+ dev = (int)simple_strtoul (argv[2], &ep, 16);
+ dev_desc=get_dev(argv[1],dev);
+ if (dev_desc==NULL) {
+ puts ("\n** Invalid device **\n");
+ return 1;
+ }
+
+ if (*ep) {
+ if (*ep != ':') {
+ puts ("\n** Invalid device, use `dev[:part]' **\n");
+ return 1;
+ }
+ part = (int)simple_strtoul(++ep, NULL, 16);
+ }
+
+ if (fat_register_device(dev_desc,part)!=0) {
+ printf ("\n** Unable to use %s %d:%d for fatwrite **\n",
+ argv[1],dev,part);
+ return 1;
+ }
+
+ offset = simple_strtoul (argv[3], NULL, 16);
+ count = simple_strtoul (argv[5], NULL, 16);
+ size = file_fat_write(argv[4], (unsigned char *)offset, count);
+
+ if (size <= 0) {
+ printf("\n** Unable to write\"%s\" to %s %d:%d **\n",
+ argv[4],argv[1],dev,part);
+ return 1;
+ }
+
+ printf ("\n%ld bytes written\n", size);
+ sprintf(buf, "0x%lX", size);
+ setenv("filesize", buf);
+ return 0;
+}
+
+#ifndef CONFIG_CMD_TREE_FAT
+U_BOOT_CMD(
+ fatwrite, 6, 0, do_fat_fswrite,
+ "store a binary file to a dos filesystem\n",
+ "<interface> <dev[:part]> <addr> <filename> <bytes>\n"
+ " - store binary file 'filename' to 'dev' on 'interface'\n"
+ " containing a dos filesystem from address 'addr'\n"
+ " with length 'bytes'\n"
+);
+#endif
+
+int
+do_fat_fsrm (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ char buf[256];
+ block_dev_desc_t *dev_desc=NULL;
+ int dev=0;
+ int part=1;
+ char *ep;
+
+ if (argc < 4) {
+ printf ("usage: fatrm <interface> <dev[:part]> <filename>\n");
+ return 1;
+ }
+
+ dev = (int)simple_strtoul (argv[2], &ep, 16);
+ dev_desc=get_dev(argv[1],dev);
+ if (dev_desc==NULL) {
+ puts ("\n** Invalid device **\n");
+ return 1;
+ }
+
+ if (*ep) {
+ if (*ep != ':') {
+ puts ("\n** Invalid device, use `dev[:part]' **\n");
+ return 1;
+ }
+ part = (int)simple_strtoul(++ep, NULL, 16);
+ }
+
+ if (fat_register_device(dev_desc,part)!=0) {
+ printf ("\n** Unable to use %s %d:%d for fatrm **\n",
+ argv[1],dev,part);
+ return 1;
+ }
+
+ if (file_fat_rm(argv[3]) < 0) {
+ printf("\n** Unable to remove \"%s\" **\n", argv[3]);
+ return 1;
+ }
+
+ strncpy(buf, argv[3], sizeof(buf));
+ setenv("rm_filename", buf);
+ return 0;
+}
+
+#ifndef CONFIG_CMD_TREE_FAT
+U_BOOT_CMD(
+ fatrm, 4, 0, do_fat_fsrm,
+ "remove a file in a FAT16/32 filesystem\n",
+ "<interface> <dev[:part]> <filename>\n"
+ " - remove 'filename' in the FAT16/32 filesytem\n"
+ " on 'dev' on 'interface'\n"
+);
+#endif
+
+int
+do_fat_fsmkdir (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ char buf[256];
+ block_dev_desc_t *dev_desc=NULL;
+ int dev=0;
+ int part=1;
+ char *ep;
+
+ if (argc < 4) {
+ printf ("usage: fatmkdir <interface> <dev[:part]> <dirname>\n");
+ return 1;
+ }
+
+ dev = (int)simple_strtoul (argv[2], &ep, 16);
+ dev_desc=get_dev(argv[1],dev);
+ if (dev_desc==NULL) {
+ puts ("\n** Invalid device **\n");
+ return 1;
+ }
+
+ if (*ep) {
+ if (*ep != ':') {
+ puts ("\n** Invalid device, use `dev[:part]' **\n");
+ return 1;
+ }
+ part = (int)simple_strtoul(++ep, NULL, 16);
+ }
+
+ if (fat_register_device(dev_desc,part)!=0) {
+ printf ("\n** Unable to use %s %d:%d for fatmkdir **\n",
+ argv[1],dev,part);
+ return 1;
+ }
+
+ if (file_fat_mkdir(argv[3]) < 0) {
+ printf("\n** Unable to make dir \"%s\" **\n", argv[3]);
+ return 1;
+ }
+
+ strncpy(buf, argv[3], sizeof(buf));
+ setenv("mkdir_dirname", buf);
+ return 0;
+}
+
+#ifndef CONFIG_CMD_TREE_FAT
+U_BOOT_CMD(
+ fatmkdir, 4, 0, do_fat_fsmkdir,
+ "make a directory in a FAT16/32 filesystem\n",
+ "<interface> <dev[:part]> <dirname>\n"
+ " - make 'dirname' in the FAT16/32 filesytem on 'dev'\n"
+ " on 'interface'\n"
+);
+#endif
+
+int
+do_fat_fsrmdir (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ char buf[256];
+ block_dev_desc_t *dev_desc=NULL;
+ int dev=0;
+ int part=1;
+ char *ep;
+
+ if (argc < 4) {
+ printf ("usage: fatrmdir <interface> <dev[:part]> <dirname>\n");
+ return 1;
+ }
+
+ dev = (int)simple_strtoul (argv[2], &ep, 16);
+ dev_desc=get_dev(argv[1],dev);
+ if (dev_desc==NULL) {
+ puts ("\n** Invalid device **\n");
+ return 1;
+ }
+
+ if (*ep) {
+ if (*ep != ':') {
+ puts ("\n** Invalid device, use `dev[:part]' **\n");
+ return 1;
+ }
+ part = (int)simple_strtoul(++ep, NULL, 16);
+ }
+
+ if (fat_register_device(dev_desc,part)!=0) {
+ printf ("\n** Unable to use %s %d:%d for fatrmdir **\n",
+ argv[1],dev,part);
+ return 1;
+ }
+
+ if (file_fat_rmdir(argv[3]) < 0) {
+ printf("\n** Unable to remove dir \"%s\" **\n", argv[3]);
+ return 1;
+ }
+
+ strncpy(buf, argv[3], sizeof(buf));
+ setenv("rm_dirname", buf);
+ return 0;
+}
+
+#ifndef CONFIG_CMD_TREE_FAT
+U_BOOT_CMD(
+ fatrmdir, 4, 0, do_fat_fsrmdir,
+ "remove an empty directory in a FAT16/32 filesystem\n",
+ "<interface> <dev[:part]> <dirname>\n"
+ " - remove 'dirname' in the FAT16/32 filesytem on 'dev'\n"
+ " on 'interface'\n"
+);
+#endif
+
+int
+do_fat_fscd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ char buf[256];
+ block_dev_desc_t *dev_desc=NULL;
+ int dev=0;
+ int part=1;
+ char *ep;
+
+ if (argc < 4) {
+ printf ("usage: fatcd <interface> <dev[:part]> <dirname>\n");
+ return 1;
+ }
+
+ dev = (int)simple_strtoul (argv[2], &ep, 16);
+ dev_desc=get_dev(argv[1],dev);
+ if (dev_desc==NULL) {
+ puts ("\n** Invalid device **\n");
+ return 1;
+ }
+
+ if (*ep) {
+ if (*ep != ':') {
+ puts ("\n** Invalid device, use `dev[:part]' **\n");
+ return 1;
+ }
+ part = (int)simple_strtoul(++ep, NULL, 16);
+ }
+
+ if (fat_register_device(dev_desc,part)!=0) {
+ printf ("\n** Unable to use %s %d:%d for fatcd **\n",
+ argv[1],dev,part);
+ return 1;
+ }
+
+ if (file_fat_cd(argv[3]) < 0) {
+ printf("\n** Unable to change to dir \"%s\" **\n", argv[3]);
+ return 1;
+ }
+
+ strncpy(buf, argv[3], sizeof(buf));
+ setenv("cwd", buf);
+ return 0;
+}
+
+#ifndef CONFIG_CMD_TREE_FAT
+U_BOOT_CMD(
+ fatcd, 4, 0, do_fat_fscd,
+ "change to the specified dir in a FAT16/32 filesystem\n",
+ "<interface> <dev[:part]> <dirname>\n"
+ " - change to 'dirname' in the FAT16/32 filesytem on 'dev'\n"
+ " on 'interface'\n"
+);
+#endif
+
+int
+do_fat_fspwd (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ block_dev_desc_t *dev_desc=NULL;
+ int dev=0;
+ int part=1;
+ char *ep;
+
+ if (argc < 3) {
+ printf ("usage: fatpwd <interface> <dev[:part]>\n");
+ return 1;
+ }
+
+ dev = (int)simple_strtoul (argv[2], &ep, 16);
+ dev_desc=get_dev(argv[1],dev);
+ if (dev_desc==NULL) {
+ puts ("\n** Invalid device **\n");
+ return 1;
+ }
+
+ if (*ep) {
+ if (*ep != ':') {
+ puts ("\n** Invalid device, use `dev[:part]' **\n");
+ return 1;
+ }
+ part = (int)simple_strtoul(++ep, NULL, 16);
+ }
+
+ if (fat_register_device(dev_desc,part)!=0) {
+ printf ("\n** Unable to use %s %d:%d for fatpwd **\n",
+ argv[1],dev,part);
+ return 1;
+ }
+
+ file_fat_pwd();
+ return 0;
+}
+
+#ifndef CONFIG_CMD_TREE_FAT
+U_BOOT_CMD(
+ fatpwd, 3, 0, do_fat_fspwd,
+ "print the current working dir in a FAT16/32 filesystem\n",
+ "<interface> <dev[:part]>\n"
+ " - print the CWD in the FAT16/32 filesytem on 'dev'\n"
+ " on 'interface'\n"
+);
+#endif
+
+int
+do_fat_fsmv (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ char buf[256];
+ block_dev_desc_t *dev_desc=NULL;
+ int dev=0;
+ int part=1;
+ char *ep;
+
+ if (argc < 5) {
+ printf ("usage: fatmv <interface> <dev[:part]> <oldname> <newname>\n");
+ return 1;
+ }
+
+ dev = (int)simple_strtoul (argv[2], &ep, 16);
+ dev_desc=get_dev(argv[1],dev);
+ if (dev_desc==NULL) {
+ puts ("\n** Invalid device **\n");
+ return 1;
+ }
+
+ if (*ep) {
+ if (*ep != ':') {
+ puts ("\n** Invalid device, use `dev[:part]' **\n");
+ return 1;
+ }
+ part = (int)simple_strtoul(++ep, NULL, 16);
+ }
+
+ if (fat_register_device(dev_desc,part)!=0) {
+ printf ("\n** Unable to use %s %d:%d for fatmv **\n",
+ argv[1],dev,part);
+ return 1;
+ }
+
+ if (file_fat_mv(argv[3], argv[4]) < 0) {
+ printf("\n** Unable to change \"%s\" to \"%s\" **\n",
+ argv[3], argv[4]);
+ return 1;
+ }
+
+ strncpy(buf, argv[3], sizeof(buf));
+ setenv("filename", buf);
+ return 0;
+}
+
+#ifndef CONFIG_CMD_TREE_FAT
+U_BOOT_CMD(
+ fatmv, 5, 0, do_fat_fsmv,
+ "move a file in a FAT16/32 filesystem\n",
+ "<interface> <dev[:part]> <oldname> <newname>\n"
+ " - change <oldname> to <newname> in the FAT16/32 filesytem\n"
+ " on 'dev' on 'interface'\n"
+);
+#endif
+
+int
+do_fat_free (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ block_dev_desc_t *dev_desc=NULL;
+ int dev=0;
+ int part=1;
+ char *ep;
+ unsigned int size;
+
+ if (argc < 3) {
+ printf ("usage: fatfree <interface> <dev[:part]> [<size>]\n");
+ return 1;
+ }
+
+ dev = (int)simple_strtoul (argv[2], &ep, 16);
+ dev_desc=get_dev(argv[1],dev);
+ if (dev_desc==NULL) {
+ puts ("\n** Invalid device **\n");
+ return 1;
+ }
+
+ if (*ep) {
+ if (*ep != ':') {
+ puts ("\n** Invalid device, use `dev[:part]' **\n");
+ return 1;
+ }
+ part = (int)simple_strtoul(++ep, NULL, 16);
+ }
+
+ if (fat_register_device(dev_desc,part)!=0) {
+ printf ("\n** Unable to use %s %d:%d for fatmv **\n",
+ argv[1],dev,part);
+ return 1;
+ }
+
+ if(argc>=4) {
+ size = simple_strtoul(argv[3], NULL, 10);
+ printf("Scanning FAT partition for ");
+ if (size>0x00100000) printf("%d.%02dMB", (int)(size>>20), (int)(size&0x000FFFFF)>>10);
+ else if (size>0x00000400) printf("%d.%02dkB", (int)(size>>10), (int)(size&0x000003FF));
+ else printf("%d Byte", (int)size);
+ printf(" of free space.\n");
+ if (rockbox_fat_free(size>>10)) {
+ printf("Enougth free space found.\n");
+ return 0;
+ } else {
+ printf("Not enougth free space found in partition.\n");
+ return 1;
+ }
+ }
+ { unsigned long size;
+ printf("Scanning full FAT partition for free clusters...\n");
+ size = rockbox_fat_size();
+ printf("FAT filesystem: total size = ");
+ if (size>=0x00100000) printf("%d.%02dGB", (int)(size>>20), (int)(size&0x000FFFFF)>>10);
+ else if (size>=0x00000400) printf("%d.%02dMB", (int)(size>>10), (int)(size&0x000003FF));
+ else printf("%dkB", (int)size);
+ printf(" / free size = ");
+ size = rockbox_fat_free(0);
+ if (size>=0x00100000) printf("%d.%02dGB", (int)(size>>20), (int)(size&0x000FFFFF)>>10);
+ else if (size>=0x00000400) printf("%d.%02dMB", (int)(size>>10), (int)(size&0x000003FF));
+ else printf("%dkB", (int)size);
+ putc('\n');
+ }
+ return 0;
+}
+
+#ifndef CONFIG_CMD_TREE_FAT
+U_BOOT_CMD(
+ fatfree, 4, 0, do_fat_free,
+ "print free space\n",
+ "<interface> <dev[:part]> [size]\n"
+ " - print free sapce available in filesystem.\n"
+ " If <size> not specified, full partition is scanned.\n"
+ " If <size> is specified, return true if enougth free space found.\n"
+);
+#endif
+
+
+#endif /* #ifdef CONFIG_ROCKBOX_FAT */
int do_fat_ls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
@@ -121,7 +612,8 @@ int do_fat_ls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
part = (int)simple_strtoul(++ep, NULL, 16);
}
if (fat_register_device(dev_desc,part)!=0) {
- printf ("\n** Unable to use %s %d:%d for fatls **\n",argv[1],dev,part);
+ printf ("\n** Unable to use %s %d:%d for fatls **\n",
+ argv[1],dev,part);
return 1;
}
if (argc == 4)
@@ -134,12 +626,14 @@ int do_fat_ls (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
return (ret);
}
+#ifndef CONFIG_CMD_TREE_FAT
U_BOOT_CMD(
fatls, 4, 1, do_fat_ls,
"list files in a directory (default /)",
"<interface> <dev[:part]> [directory]\n"
" - list files from 'dev' on 'interface' in a 'directory'"
);
+#endif
int do_fat_fsinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
{
@@ -172,12 +666,14 @@ int do_fat_fsinfo (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
return (file_fat_detectfs ());
}
+#ifndef CONFIG_CMD_TREE_FAT
U_BOOT_CMD(
fatinfo, 3, 1, do_fat_fsinfo,
"print information about filesystem",
"<interface> <dev[:part]>\n"
" - print information about filesystem from 'dev' on 'interface'"
);
+#endif
#ifdef NOT_IMPLEMENTED_YET
/* find first device whose first partition is a DOS filesystem */
@@ -318,3 +814,85 @@ void hexdump (int cnt, unsigned char *data)
}
}
#endif /* NOT_IMPLEMENTED_YET */
+
+
+#ifdef CONFIG_CMD_TREE_FAT
+/* replace all fatXXX commands with 'fat xxx' command.
+ */
+int do_fat(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
+{
+ int (*fn)(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]);
+ fn = NULL;
+ argc--;
+ argv++;
+
+ if (!strncmp(argv[0], "load", 5)) fn = do_fat_fsload;
+ else if (!strncmp(argv[0], "ls", 2)) fn = do_fat_ls;
+ else if (!strncmp(argv[0], "info", 5)) fn = do_fat_fsinfo;
+#ifdef CONFIG_ROCKBOX_FAT
+ else if (!strncmp(argv[0], "write", 6)) fn = do_fat_fswrite;
+ else if (!strncmp(argv[0], "rm", 3)) fn = do_fat_fsrm;
+ else if (!strncmp(argv[0], "mkdir", 6)) fn = do_fat_fsmkdir;
+ else if (!strncmp(argv[0], "rmdir", 6)) fn = do_fat_fsrmdir;
+ else if (!strncmp(argv[0], "cd", 3)) fn = do_fat_fscd;
+ else if (!strncmp(argv[0], "pwd", 4)) fn = do_fat_fspwd;
+ else if (!strncmp(argv[0], "mv", 3)) fn = do_fat_fsmv;
+ else if (!strncmp(argv[0], "free", 5)) fn = do_fat_free;
+#endif
+ if (fn) {
+ if(fn(cmdtp, flag, argc, argv) == 0) return 0;
+ return 1;
+ }
+ printf("unknown 'fat' command, check 'help fat'\n");
+ return 1;
+}
+
+U_BOOT_CMD(
+ fat, 7, 0, do_fat,
+ "some fat support commands\n",
+ "\n"
+ "fat load <interface> <dev[:part]> <addr> <filename> [bytes]\n"
+ " - load binary file 'filename' from 'dev' on 'interface'\n"
+ " to address 'addr' from dos filesystem\n"
+ "\n"
+ "fat ls <interface> <dev[:part]> [directory]\n"
+ " - list files from 'dev' on 'interface' in a 'directory'\n"
+ "\n"
+ "fat info <interface> <dev[:part]>\n"
+ " - print information about filesystem from 'dev' on 'interface'\n"
+ "\n"
+#ifdef CONFIG_ROCKBOX_FAT
+ "fat write <interface> <dev[:part]> <addr> <filename> <bytes>\n"
+ " - store binary file 'filename' to 'dev' on 'interface'\n"
+ " containing a dos filesystem from address 'addr'\n"
+ " with length 'bytes'\n"
+ "\n"
+ "fat rm <interface> <dev[:part]> <filename>\n"
+ " - remove 'filename' in the FAT16/32 filesytem\n"
+ " on 'dev' on 'interface'\n"
+ "\n"
+ "fat mkdir <interface> <dev[:part]> <dirname>\n"
+ " - make 'dirname' in the FAT16/32 filesytem on 'dev'\n"
+ " on 'interface'\n"
+ "\n"
+ "fat rmdir <interface> <dev[:part]> <dirname>\n"
+ " - remove 'dirname' in the FAT16/32 filesytem on 'dev'\n"
+ " on 'interface'\n"
+ "\n"
+ "fat cd <interface> <dev[:part]> <dirname>\n"
+ " - change to 'dirname' in the FAT16/32 filesytem on 'dev'\n"
+ " on 'interface'\n"
+ "\n"
+ "fat pwd <interface> <dev[:part]>\n"
+ " - print the CWD in the FAT16/32 filesytem on 'dev'\n"
+ " on 'interface'\n"
+ "\n"
+ "fat mv <interface> <dev[:part]> <oldname> <newname>\n"
+ " - change <oldname> to <newname> in the FAT16/32 filesytem\n"
+ " on 'dev' on 'interface'\n"
+ "\n"
+ "fat free <interface> <dev[:part]> \n"
+ " - print free sapce available in filesystem (full partition scan)\n"
+#endif
+);
+#endif
diff --git a/common/unicode.c b/common/unicode.c
new file mode 100644
index 000000000..90b862c5b
--- /dev/null
+++ b/common/unicode.c
@@ -0,0 +1,441 @@
+/***************************************************************************
+ * Copyright (c) 2004,2005 by Marcoen Hirschberg
+ *
+ * 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.
+ *
+ * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************
+ * Source file dumped from rockbox-3.1 distribution.
+ * $Id: unicode.c 19448 2008-12-15 23:42:19Z zagor $
+ * Copyright (c) 2004,2005 by Marcoen Hirschberg
+ ****************************************************************************
+ * See file CREDITS for list of people who contributed to the U-boot
+ * project.
+ *
+ * 09-jan-2008 etienne.carriere@stnwireless.com - port from rockbox to U-boot
+ ****************************************************************************
+ * Some conversion functions for handling UTF-8
+ *
+ * I got all the info from:
+ * http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
+ * and
+ * http://en.wikipedia.org/wiki/Unicode
+ ****************************************************************************
+ */
+#include <common.h> /* u-boot basics */
+
+/*#include <stdio.h> n.a for u-boot */
+/* #include "file.h" */
+/* #include "debug.h" */
+#include <rbunicode.h>
+/*#include "config.h" n.a for u-boot */
+
+#ifndef O_BINARY
+#define O_BINARY 0
+#endif
+
+/* U-boot port: no code page file accessible: remove code page ressources */
+#define UNICODE_NO_CP_TABLE
+#define UNICODE_NO_CP_TABLE
+
+
+
+#ifndef UNICODE_NO_CP_TABLE
+
+#define CODEPAGE_DIR ROCKBOX_DIR"/codepages"
+static int default_codepage = 0;
+static int loaded_cp_table = 0;
+
+#ifdef HAVE_LCD_BITMAP
+
+#define MAX_CP_TABLE_SIZE 32768
+#define NUM_TABLES 5
+
+static const char *filename[NUM_TABLES] =
+{
+ CODEPAGE_DIR"/iso.cp",
+ CODEPAGE_DIR"/932.cp", /* SJIS */
+ CODEPAGE_DIR"/936.cp", /* GB2312 */
+ CODEPAGE_DIR"/949.cp", /* KSX1001 */
+ CODEPAGE_DIR"/950.cp" /* BIG5 */
+};
+
+static const char cp_2_table[NUM_CODEPAGES] =
+{
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 4, 5, 0
+};
+
+static const char *name_codepages[NUM_CODEPAGES+1] =
+{
+ "ISO-8859-1",
+ "ISO-8859-7",
+ "ISO-8859-8",
+ "CP1251",
+ "ISO-8859-11",
+ "CP1256",
+ "ISO-8859-9",
+ "ISO-8859-2",
+ "CP1250",
+ "SJIS",
+ "GB-2312",
+ "KSX-1001",
+ "BIG5",
+ "UTF-8",
+ "unknown"
+};
+
+#else /* !HAVE_LCD_BITMAP, reduced support */
+
+#define MAX_CP_TABLE_SIZE 640
+#define NUM_TABLES 1
+
+static const char *filename[NUM_TABLES] = {
+ CODEPAGE_DIR"/isomini.cp"
+};
+
+static const char cp_2_table[NUM_CODEPAGES] =
+{
+ 0, 1, 1, 1, 1, 1, 0
+};
+
+static const char *name_codepages[NUM_CODEPAGES+1] =
+{
+ "ISO-8859-1",
+ "ISO-8859-7",
+ "CP1251",
+ "ISO-8859-9",
+ "ISO-8859-2",
+ "CP1250",
+ "UTF-8",
+ "unknown"
+};
+
+#endif
+
+static unsigned short codepage_table[MAX_CP_TABLE_SIZE];
+
+#endif /* #ifndef UNICODE_NO_CP_TABLE */
+
+static const unsigned char utf8comp[6] =
+{
+ 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC
+};
+
+#ifndef UNICODE_NO_CP_TABLE
+/* Load codepage file into memory */
+static int load_cp_table(int cp)
+{
+ int i=0;
+ int table = cp_2_table[cp];
+ int file, tablesize;
+ unsigned char tmp[2];
+
+ if (table == 0 || table == loaded_cp_table)
+ return 1;
+
+ file = open(filename[table-1], O_RDONLY|O_BINARY);
+
+ if (file < 0) {
+ DEBUGF("Can't open codepage file: %s.cp\n", filename[table-1]);
+ return 0;
+ }
+
+ tablesize = filesize(file) / 2;
+
+ if (tablesize > MAX_CP_TABLE_SIZE) {
+ DEBUGF("Invalid codepage file: %s.cp\n", filename[table-1]);
+ close(file);
+ return 0;
+ }
+
+ while (i < tablesize) {
+ if (!read(file, tmp, 2)) {
+ DEBUGF("Can't read from codepage file: %s.cp\n",
+ filename[table-1]);
+ loaded_cp_table = 0;
+ return 0;
+ }
+ codepage_table[i++] = (tmp[1] << 8) | tmp[0];
+ }
+
+ loaded_cp_table = table;
+ close(file);
+ return 1;
+}
+#endif /* #ifndef UNICODE_NO_CP_TABLE */
+
+/* Encode a UCS value as UTF-8 and return a pointer after this UTF-8 char. */
+unsigned char* utf8encode(unsigned long ucs, unsigned char *utf8)
+{
+ int tail = 0;
+
+ if (ucs > 0x7F)
+ while (ucs >> (5*tail + 6))
+ tail++;
+
+ *utf8++ = (ucs >> (6*tail)) | utf8comp[tail];
+ while (tail--)
+ *utf8++ = ((ucs >> (6*tail)) & (MASK ^ 0xFF)) | COMP;
+
+ return utf8;
+}
+
+#ifndef UNICODE_NO_CP_TABLE
+/* Recode an iso encoded string to UTF-8 */
+unsigned char* iso_decode(const unsigned char *iso, unsigned char *utf8,
+ int cp, int count)
+{
+ unsigned short ucs, tmp;
+
+ if (cp == -1) /* use default codepage */
+ cp = default_codepage;
+
+ if (!load_cp_table(cp)) cp = 0;
+
+ while (count--) {
+ if (*iso < 128 || cp == UTF_8) /* Already UTF-8 */
+ *utf8++ = *iso++;
+
+ else {
+
+ /* cp tells us which codepage to convert from */
+ switch (cp) {
+ case ISO_8859_7: /* Greek */
+ case WIN_1251: /* Cyrillic */
+ case ISO_8859_9: /* Turkish */
+ case ISO_8859_2: /* Latin Extended */
+ case WIN_1250: /* Central European */
+#ifdef HAVE_LCD_BITMAP
+ case ISO_8859_8: /* Hebrew */
+ case ISO_8859_11: /* Thai */
+ case WIN_1256: /* Arabic */
+#endif
+ tmp = ((cp-1)*128) + (*iso++ - 128);
+ ucs = codepage_table[tmp];
+ break;
+
+#ifdef HAVE_LCD_BITMAP
+ case SJIS: /* Japanese */
+ if (*iso > 0xA0 && *iso < 0xE0) {
+ tmp = *iso++ | (0xA100 - 0x8000);
+ ucs = codepage_table[tmp];
+ break;
+ }
+
+ case GB_2312: /* Simplified Chinese */
+ case KSX_1001: /* Korean */
+ case BIG_5: /* Traditional Chinese */
+ if (count < 1 || !iso[1]) {
+ ucs = *iso++;
+ break;
+ }
+
+ /* we assume all cjk strings are written
+ in big endian order */
+ tmp = *iso++ << 8;
+ tmp |= *iso++;
+ tmp -= 0x8000;
+ ucs = codepage_table[tmp];
+ count--;
+ break;
+#endif /* HAVE_LCD_BITMAP */
+
+ default:
+ ucs = *iso++;
+ break;
+ }
+
+ if (ucs == 0) /* unknown char, use replacement char */
+ ucs = 0xfffd;
+ utf8 = utf8encode(ucs, utf8);
+ }
+ }
+ return utf8;
+}
+#else /* #ifndef UNICODE_NO_CP_TABLE */
+/* Recode an iso encoded string to UTF-8 : Support only default code page ISO_8859_1 */
+unsigned char* iso_decode(const unsigned char *iso, unsigned char *utf8,
+ int cp, int count)
+{
+ unsigned short ucs;
+
+ if (cp == -1) cp = ISO_8859_1; /* use default codepage */
+ if (cp != ISO_8859_1) {
+ printf("ERROR: unsupported codepage ID %d (see include/rbunicode.h)\n", cp);
+ cp = ISO_8859_1;
+ }
+
+ while (count--) {
+ ucs = *iso++;
+ if (ucs == 0) ucs = 0xfffd; /* unknown char, use replacement char */
+ utf8 = utf8encode(ucs, utf8);
+ }
+ return utf8;
+}
+#endif
+
+/* Recode a UTF-16 string with little-endian byte ordering to UTF-8 */
+unsigned char* utf16LEdecode(const unsigned char *utf16, unsigned char *utf8,
+ int count)
+{
+ unsigned long ucs;
+
+ while (count > 0) {
+ /* Check for a surrogate pair */
+ if (utf16[1] >= 0xD8 && utf16[1] < 0xE0) {
+ ucs = 0x10000 + ((utf16[0] << 10) | ((utf16[1] - 0xD8) << 18)
+ | utf16[2] | ((utf16[3] - 0xDC) << 8));
+ utf16 += 4;
+ count -= 2;
+ } else {
+ ucs = (utf16[0] | (utf16[1] << 8));
+ utf16 += 2;
+ count -= 1;
+ }
+ utf8 = utf8encode(ucs, utf8);
+ }
+ return utf8;
+}
+
+/* Recode a UTF-16 string with big-endian byte ordering to UTF-8 */
+unsigned char* utf16BEdecode(const unsigned char *utf16, unsigned char *utf8,
+ int count)
+{
+ unsigned long ucs;
+
+ while (count > 0) {
+ if (*utf16 >= 0xD8 && *utf16 < 0xE0) { /* Check for a surrogate pair */
+ ucs = 0x10000 + (((utf16[0] - 0xD8) << 18) | (utf16[1] << 10)
+ | ((utf16[2] - 0xDC) << 8) | utf16[3]);
+ utf16 += 4;
+ count -= 2;
+ } else {
+ ucs = (utf16[0] << 8) | utf16[1];
+ utf16 += 2;
+ count -= 1;
+ }
+ utf8 = utf8encode(ucs, utf8);
+ }
+ return utf8;
+}
+
+#if 0 /* currently unused */
+/* Recode any UTF-16 string to UTF-8 */
+unsigned char* utf16decode(const unsigned char *utf16, unsigned char *utf8,
+ unsigned int count)
+{
+ unsigned long ucs;
+
+ ucs = *(utf16++) << 8;
+ ucs |= *(utf16++);
+
+ if (ucs == 0xFEFF) /* Check for BOM */
+ return utf16BEdecode(utf16, utf8, count-1);
+ else if (ucs == 0xFFFE)
+ return utf16LEdecode(utf16, utf8, count-1);
+ else { /* ADDME: Should default be LE or BE? */
+ utf16 -= 2;
+ return utf16BEdecode(utf16, utf8, count);
+ }
+}
+#endif
+
+/* Return the number of UTF-8 chars in a string */
+unsigned long utf8length(const unsigned char *utf8)
+{
+ unsigned long l = 0;
+
+ while (*utf8 != 0)
+ if ((*utf8++ & MASK) != COMP)
+ l++;
+
+ return l;
+}
+
+/* Decode 1 UTF-8 char and return a pointer to the next char. */
+const unsigned char* utf8decode(const unsigned char *utf8, unsigned short *ucs)
+{
+ unsigned char c = *utf8++;
+ unsigned long code;
+ int tail = 0;
+
+ if ((c <= 0x7f) || (c >= 0xc2)) {
+ /* Start of new character. */
+ if (c < 0x80) { /* U-00000000 - U-0000007F, 1 byte */
+ code = c;
+ } else if (c < 0xe0) { /* U-00000080 - U-000007FF, 2 bytes */
+ tail = 1;
+ code = c & 0x1f;
+ } else if (c < 0xf0) { /* U-00000800 - U-0000FFFF, 3 bytes */
+ tail = 2;
+ code = c & 0x0f;
+ } else if (c < 0xf5) { /* U-00010000 - U-001FFFFF, 4 bytes */
+ tail = 3;
+ code = c & 0x07;
+ } else {
+ /* Invalid size. */
+ code = 0xfffd;
+ }
+
+ while (tail-- && ((c = *utf8++) != 0)) {
+ if ((c & 0xc0) == 0x80) {
+ /* Valid continuation character. */
+ code = (code << 6) | (c & 0x3f);
+
+ } else {
+ /* Invalid continuation char */
+ code = 0xfffd;
+ utf8--;
+ break;
+ }
+ }
+ } else {
+ /* Invalid UTF-8 char */
+ code = 0xfffd;
+ }
+ /* currently we don't support chars above U-FFFF */
+ *ucs = (code < 0x10000) ? code : 0xfffd;
+ return utf8;
+}
+
+#ifndef UNICODE_NO_CP_TABLE
+void set_codepage(int cp)
+{
+ default_codepage = cp;
+ return;
+}
+#endif /* #ifndef UNICODE_NO_CP_TABLE */
+
+/* seek to a given char in a utf8 string and
+ return its start position in the string */
+int utf8seek(const unsigned char* utf8, int offset)
+{
+ int pos = 0;
+
+ while (offset--) {
+ pos++;
+ while ((utf8[pos] & MASK) == COMP)
+ pos++;
+ }
+ return pos;
+}
+
+#ifndef UNICODE_NO_CP_TABLE
+const char* get_codepage_name(int cp)
+{
+ if (cp < 0 || cp>= NUM_CODEPAGES)
+ return name_codepages[NUM_CODEPAGES];
+ return name_codepages[cp];
+}
+#endif /* #ifndef UNICODE_NO_CP_TABLE */
+