diff options
-rw-r--r-- | bootloader/gigabeat-s.c | 112 | ||||
-rw-r--r-- | firmware/target/arm/imx31/gigabeat-s/ata-imx31.c | 2 | ||||
-rw-r--r-- | 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 @@ | |||
47 | #include "avic-imx31.h" | 47 | #include "avic-imx31.h" |
48 | #include <stdarg.h> | 48 | #include <stdarg.h> |
49 | 49 | ||
50 | #define TAR_CHUNK 512 | ||
51 | #define TAR_HEADER_SIZE 157 | ||
52 | |||
50 | char version[] = APPSVERSION; | 53 | char version[] = APPSVERSION; |
51 | char buf[MAX_PATH]; | ||
52 | char basedir[] = "/Content/0b00/00/"; /* Where files sent via MTP are stored */ | 54 | char basedir[] = "/Content/0b00/00/"; /* Where files sent via MTP are stored */ |
53 | char model[5]; | ||
54 | int (*kernel_entry)(void); | 55 | int (*kernel_entry)(void); |
55 | extern void reference_system_c(void); | 56 | extern void reference_system_c(void); |
56 | 57 | ||
@@ -61,11 +62,89 @@ void reference_files(void) | |||
61 | reference_system_c(); | 62 | reference_system_c(); |
62 | } | 63 | } |
63 | 64 | ||
65 | void untar(int tar_fd) | ||
66 | { | ||
67 | char header[TAR_HEADER_SIZE]; | ||
68 | char copybuf[TAR_CHUNK]; | ||
69 | char path[102]; | ||
70 | int fd, i, size = 0, pos = 0; | ||
71 | |||
72 | while (1) | ||
73 | { | ||
74 | read(tar_fd, header, TAR_HEADER_SIZE); | ||
75 | |||
76 | if (*header == '\0') /* Check for EOF */ | ||
77 | break; | ||
78 | |||
79 | /* Parse the size field */ | ||
80 | size = 0; | ||
81 | for (i = 124 ; i < 124 + 11 ; i++) { | ||
82 | size = (8 * size) + header[i] - '0'; | ||
83 | } | ||
84 | |||
85 | /* Skip rest of header */ | ||
86 | pos = lseek(tar_fd, TAR_CHUNK - TAR_HEADER_SIZE, SEEK_CUR); | ||
87 | |||
88 | /* Make the path absolute */ | ||
89 | strcpy(path, "/"); | ||
90 | strcat(path, header); | ||
91 | |||
92 | if (header[156] == '0') /* file */ | ||
93 | { | ||
94 | int rc, wc, total = 0; | ||
95 | |||
96 | fd = creat(path); | ||
97 | if (fd < 0) | ||
98 | { | ||
99 | printf("failed to create file (%d)", fd); | ||
100 | /* Skip the file */ | ||
101 | lseek(tar_fd, (size + 511) & (~511), SEEK_CUR); | ||
102 | } | ||
103 | else | ||
104 | { | ||
105 | /* Copy the file over 512 bytes at a time */ | ||
106 | while (total < size) | ||
107 | { | ||
108 | rc = read(tar_fd, copybuf, TAR_CHUNK); | ||
109 | pos += rc; | ||
110 | |||
111 | wc = write(fd, copybuf, MIN(rc, size - total)); | ||
112 | if (wc < 0) | ||
113 | { | ||
114 | printf("write failed (%d)", wc); | ||
115 | break; | ||
116 | } | ||
117 | total += wc; | ||
118 | } | ||
119 | close(fd); | ||
120 | } | ||
121 | } | ||
122 | else if (header[156] == '5') /* directory */ | ||
123 | { | ||
124 | int ret; | ||
125 | |||
126 | /* Remove the trailing slash */ | ||
127 | if (path[strlen(path) - 1] == '/') | ||
128 | path[strlen(path) - 1] = '\0'; | ||
129 | |||
130 | /* Create the dir */ | ||
131 | ret = mkdir(path); | ||
132 | if (ret < 0 && ret != -4) | ||
133 | { | ||
134 | printf("failed to create dir (%d)", ret); | ||
135 | } | ||
136 | } | ||
137 | } | ||
138 | } | ||
139 | |||
64 | void main(void) | 140 | void main(void) |
65 | { | 141 | { |
142 | char buf[MAX_PATH]; | ||
143 | char tarstring[6]; | ||
144 | |||
66 | lcd_clear_display(); | 145 | lcd_clear_display(); |
67 | printf("Hello world!"); | 146 | printf("Hello world!"); |
68 | printf("Gigabeat S Rockbox Bootloader v.00000003"); | 147 | printf("Gigabeat S Rockbox Bootloader v.00000004"); |
69 | system_init(); | 148 | system_init(); |
70 | kernel_init(); | 149 | kernel_init(); |
71 | printf("kernel init done"); | 150 | printf("kernel init done"); |
@@ -90,7 +169,7 @@ void main(void) | |||
90 | error(EDISK,rc); | 169 | error(EDISK,rc); |
91 | } | 170 | } |
92 | 171 | ||
93 | /* Look for the first valid firmware file */ | 172 | /* Look for a tar file */ |
94 | struct dirent_uncached* entry; | 173 | struct dirent_uncached* entry; |
95 | DIR_UNCACHED* dir; | 174 | DIR_UNCACHED* dir; |
96 | int fd; | 175 | int fd; |
@@ -103,26 +182,31 @@ void main(void) | |||
103 | fd = open(buf, O_RDONLY); | 182 | fd = open(buf, O_RDONLY); |
104 | if (fd >= 0) | 183 | if (fd >= 0) |
105 | { | 184 | { |
106 | lseek(fd, 4, SEEK_SET); | 185 | lseek(fd, 257, SEEK_SET); |
107 | rc = read(fd, model, 4); | 186 | rc = read(fd, tarstring, 5); |
108 | close(fd); | 187 | if (rc == 5) |
109 | if (rc == 4) | ||
110 | { | 188 | { |
111 | model[4] = 0; | 189 | tarstring[5] = 0; |
112 | if (strcmp(model, "gigs") == 0) | 190 | if (strcmp(tarstring, "ustar") == 0) |
191 | { | ||
192 | printf("Found tar file. Unarchiving..."); | ||
193 | lseek(fd, 0, SEEK_SET); | ||
194 | untar(fd); | ||
195 | close(fd); | ||
196 | printf("Removing tar file"); | ||
197 | remove(buf); | ||
113 | break; | 198 | break; |
199 | } | ||
114 | } | 200 | } |
201 | close(fd); | ||
115 | } | 202 | } |
116 | } | 203 | } |
117 | } | 204 | } |
118 | 205 | ||
119 | printf("Firmware file: %s", buf); | ||
120 | printf("Loading firmware"); | ||
121 | |||
122 | unsigned char *loadbuffer = (unsigned char *)0x0; | 206 | unsigned char *loadbuffer = (unsigned char *)0x0; |
123 | int buffer_size = 31*1024*1024; | 207 | int buffer_size = 31*1024*1024; |
124 | 208 | ||
125 | rc = load_firmware(loadbuffer, buf, buffer_size); | 209 | rc = load_firmware(loadbuffer, "/.rockbox/rockbox.gigabeat", buffer_size); |
126 | if(rc < 0) | 210 | if(rc < 0) |
127 | error((int)buf, rc); | 211 | error((int)buf, rc); |
128 | 212 | ||
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) | |||
128 | ATA_TIME_9 = (T + 20)/T; | 128 | ATA_TIME_9 = (T + 20)/T; |
129 | } | 129 | } |
130 | 130 | ||
131 | #if 0 | ||
131 | #if !defined(BOOTLOADER) | 132 | #if !defined(BOOTLOADER) |
132 | void copy_write_sectors(const unsigned char* buf, int wordcount) | 133 | void copy_write_sectors(const unsigned char* buf, int wordcount) |
133 | { | 134 | { |
134 | (void)buf; (void)wordcount; | 135 | (void)buf; (void)wordcount; |
135 | } | 136 | } |
136 | #endif | 137 | #endif |
138 | #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 @@ | |||
22 | /* Plain C read & write loops */ | 22 | /* Plain C read & write loops */ |
23 | #define PREFER_C_READING | 23 | #define PREFER_C_READING |
24 | #define PREFER_C_WRITING | 24 | #define PREFER_C_WRITING |
25 | #if 0 | ||
25 | #if !defined(BOOTLOADER) | 26 | #if !defined(BOOTLOADER) |
26 | #define ATA_OPTIMIZED_WRITING | 27 | #define ATA_OPTIMIZED_WRITING |
27 | void copy_write_sectors(const unsigned char* buf, int wordcount); | 28 | void copy_write_sectors(const unsigned char* buf, int wordcount); |
28 | #endif | 29 | #endif |
30 | #endif | ||
29 | 31 | ||
30 | #define ATA_DATA ATA_DRIVE_DATA | 32 | #define ATA_DATA ATA_DRIVE_DATA |
31 | #define ATA_ERROR ATA_DRIVE_FEATURES | 33 | #define ATA_ERROR ATA_DRIVE_FEATURES |