From e2f5f21e5bf5b8e43f3eb130d8a282a5a8c62ac6 Mon Sep 17 00:00:00 2001 From: Nicolas Pennequin Date: Sun, 17 Feb 2008 23:17:08 +0000 Subject: Give the Gigabeat S bootloader the ability to untar a tarball. To test a build, use 'make tar' and send the tar to the unit. The bootloader will unarchive it and delete it before loading the main binary. This is a temporary hack to make testing possible until we have a better way of sending a complete build. Also enable writing to the disk by disabling the optimised write stubs. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16338 a1c6a512-1295-4272-9138-f99709370657 --- bootloader/gigabeat-s.c | 112 +++++++++++++++++++--- firmware/target/arm/imx31/gigabeat-s/ata-imx31.c | 2 + firmware/target/arm/imx31/gigabeat-s/ata-target.h | 2 + 3 files changed, 102 insertions(+), 14 deletions(-) diff --git a/bootloader/gigabeat-s.c b/bootloader/gigabeat-s.c index f3e2917131..eba3cd7342 100644 --- a/bootloader/gigabeat-s.c +++ b/bootloader/gigabeat-s.c @@ -47,10 +47,11 @@ #include "avic-imx31.h" #include +#define TAR_CHUNK 512 +#define TAR_HEADER_SIZE 157 + char version[] = APPSVERSION; -char buf[MAX_PATH]; char basedir[] = "/Content/0b00/00/"; /* Where files sent via MTP are stored */ -char model[5]; int (*kernel_entry)(void); extern void reference_system_c(void); @@ -61,11 +62,89 @@ void reference_files(void) reference_system_c(); } +void untar(int tar_fd) +{ + char header[TAR_HEADER_SIZE]; + char copybuf[TAR_CHUNK]; + char path[102]; + int fd, i, size = 0, pos = 0; + + while (1) + { + read(tar_fd, header, TAR_HEADER_SIZE); + + if (*header == '\0') /* Check for EOF */ + break; + + /* Parse the size field */ + size = 0; + for (i = 124 ; i < 124 + 11 ; i++) { + size = (8 * size) + header[i] - '0'; + } + + /* Skip rest of header */ + pos = lseek(tar_fd, TAR_CHUNK - TAR_HEADER_SIZE, SEEK_CUR); + + /* Make the path absolute */ + strcpy(path, "/"); + strcat(path, header); + + if (header[156] == '0') /* file */ + { + int rc, wc, total = 0; + + fd = creat(path); + if (fd < 0) + { + printf("failed to create file (%d)", fd); + /* Skip the file */ + lseek(tar_fd, (size + 511) & (~511), SEEK_CUR); + } + else + { + /* Copy the file over 512 bytes at a time */ + while (total < size) + { + rc = read(tar_fd, copybuf, TAR_CHUNK); + pos += rc; + + wc = write(fd, copybuf, MIN(rc, size - total)); + if (wc < 0) + { + printf("write failed (%d)", wc); + break; + } + total += wc; + } + close(fd); + } + } + else if (header[156] == '5') /* directory */ + { + int ret; + + /* Remove the trailing slash */ + if (path[strlen(path) - 1] == '/') + path[strlen(path) - 1] = '\0'; + + /* Create the dir */ + ret = mkdir(path); + if (ret < 0 && ret != -4) + { + printf("failed to create dir (%d)", ret); + } + } + } +} + void main(void) { + char buf[MAX_PATH]; + char tarstring[6]; + lcd_clear_display(); printf("Hello world!"); - printf("Gigabeat S Rockbox Bootloader v.00000003"); + printf("Gigabeat S Rockbox Bootloader v.00000004"); system_init(); kernel_init(); printf("kernel init done"); @@ -90,7 +169,7 @@ void main(void) error(EDISK,rc); } - /* Look for the first valid firmware file */ + /* Look for a tar file */ struct dirent_uncached* entry; DIR_UNCACHED* dir; int fd; @@ -103,26 +182,31 @@ void main(void) fd = open(buf, O_RDONLY); if (fd >= 0) { - lseek(fd, 4, SEEK_SET); - rc = read(fd, model, 4); - close(fd); - if (rc == 4) + lseek(fd, 257, SEEK_SET); + rc = read(fd, tarstring, 5); + if (rc == 5) { - model[4] = 0; - if (strcmp(model, "gigs") == 0) + tarstring[5] = 0; + if (strcmp(tarstring, "ustar") == 0) + { + printf("Found tar file. Unarchiving..."); + lseek(fd, 0, SEEK_SET); + untar(fd); + close(fd); + printf("Removing tar file"); + remove(buf); break; + } } + close(fd); } } } - printf("Firmware file: %s", buf); - printf("Loading firmware"); - unsigned char *loadbuffer = (unsigned char *)0x0; int buffer_size = 31*1024*1024; - rc = load_firmware(loadbuffer, buf, buffer_size); + rc = load_firmware(loadbuffer, "/.rockbox/rockbox.gigabeat", buffer_size); if(rc < 0) error((int)buf, rc); diff --git a/firmware/target/arm/imx31/gigabeat-s/ata-imx31.c b/firmware/target/arm/imx31/gigabeat-s/ata-imx31.c index 19e440724a..2272b2c929 100644 --- a/firmware/target/arm/imx31/gigabeat-s/ata-imx31.c +++ b/firmware/target/arm/imx31/gigabeat-s/ata-imx31.c @@ -128,9 +128,11 @@ void ata_device_init(void) ATA_TIME_9 = (T + 20)/T; } +#if 0 #if !defined(BOOTLOADER) void copy_write_sectors(const unsigned char* buf, int wordcount) { (void)buf; (void)wordcount; } #endif +#endif diff --git a/firmware/target/arm/imx31/gigabeat-s/ata-target.h b/firmware/target/arm/imx31/gigabeat-s/ata-target.h index 8b37c37d48..a1720644fe 100644 --- a/firmware/target/arm/imx31/gigabeat-s/ata-target.h +++ b/firmware/target/arm/imx31/gigabeat-s/ata-target.h @@ -22,10 +22,12 @@ /* Plain C read & write loops */ #define PREFER_C_READING #define PREFER_C_WRITING +#if 0 #if !defined(BOOTLOADER) #define ATA_OPTIMIZED_WRITING void copy_write_sectors(const unsigned char* buf, int wordcount); #endif +#endif #define ATA_DATA ATA_DRIVE_DATA #define ATA_ERROR ATA_DRIVE_FEATURES -- cgit v1.2.3