forked from contiki-os/contiki
-
Notifications
You must be signed in to change notification settings - Fork 0
/
avr-makecoffeedata
278 lines (259 loc) · 10.2 KB
/
avr-makecoffeedata
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
#!/usr/bin/perl
#Generate a .c source that preinitializes a coffee file system
#David Kopf <[email protected]> July 2009
#For coffee file_header structure of
#struct file_header {
# coffee_page_t log_page;
# uint16_t log_records;
# uint16_t log_record_size;
# coffee_page_t max_pages;
# uint8_t deprecated_eof_hint;
# uint8_t flags;
# char name[COFFEE_NAME_LENGTH];
# } __attribute__((packed));
goto DEFAULTS;
START:$version="1.0 dak";
#Process options
for($n=0;$n<=$#ARGV;$n++) {
$arg=$ARGV[$n];
if ($arg eq "-p") {
$n++;$coffee_page_length=$ARGV[$n];
} elsif ($arg eq "-s") {
$n++;$coffee_sector_size=$ARGV[$n];
} elsif ($arg eq "-t") {
$n++;$coffee_page_t =$ARGV[$n];
} elsif ($arg eq "-f") {
$n++;$coffee_name_length=$ARGV[$n];
} elsif ($arg eq "-S") {
$n++;$sectionname=$ARGV[$n];
} elsif ($arg eq "-c") {
$complement=1;
} elsif ($arg eq "-l") {
$linkedlist=1;
} elsif ($arg eq "-v") {
print "avr-makecoffeedata Version $version\n";
} elsif ($arg eq "-d") {
$n++;$directory=$ARGV[$n];
} elsif ($arg eq "-o") {
$n++;$outputfile=$ARGV[$n];
} else {
DEFAULTS:
#Set up defaults
$coffee_page_length=256;
$coffee_sector_size=256;
$coffee_page_t=1;
$coffee_name_length=16;
$complement=0;
$directory="";
$outputfile="httpd-fsdata.c";
$linkedlist=0;
$sectionname=".coffeefiles";
if (!$version) {goto START;}
print "\n";
print "Usage: avr-makecoffeedata <option(s)> <-d input_directory> <-o output_file>\n";
print " Generates c source file to make a pre-initialized coffee file system\n";
print " The default output file is $outputfile\n";
print " The input directory structure is copied. If input_directory is specified\n";
print " it becomes the root \"/\". If no input_directory is specified the first\n";
print " subdirectory found in the current directory is used as the root.\n";
print " WARNING : If the output file exists it will be overwritten without confirmation\n\n";
print " Options are:\n";
print " -p pagesize Page size in bytes (default $coffee_page_length)\n";
print " -s sectorsize Sector size in bytes (default $coffee_sector_size)\n";
print " -t page_t Number of bytes in coffee_page_t (1,2,or 4, default $coffee_page_t)\n";
print " -f namesize File name field size in bytes (default $coffee_name_length)\n";
print " -S section Section name (default $sectionname)\n";
print " -c Complement the data, useful when flash is all 1s after erase\n";
print " -l Append a linked list of the file starting addresses\n";
print " -v Display the version number\n";
exit;
}
}
#printf "coffee_page_length=$coffee_page_length\n";
#printf "coffee_page_t=$coffee_page_t\n";
#printf "coffee_name_length=$coffee_name_length\n";
#printf "complement=$complement\n";
#printf "directory=$directory\n";
#printf "outputfile=$outputfile\n";
#printf "sectionname=$sectionname;
if ($coffee_page_t==1) {
$coffeemax=0xff;
} elsif ($coffee_page_t==2) {
$coffeemax=0xffff;
} elsif ($coffee_page_t==4) {
$coffeemax=0xffffffff;
} else {
die "Unsupported coffee_page_t $coffee_page_t\n";
}
$coffee_header_length=2*$coffee_page_t+$coffee_name_length+6;
$null="0x00";if ($complement) {$null="0xff";}
#$tab="/t"; #optional tab string
$tab=" "; #optional tabs or spaces at beginning of line, e.g. "\t\t"
if (!open(OUTPUT, "> $outputfile")) {die "Aborted: Could not create output file $outputfile";}
#awkward but could not figure out how to compare paths later unless the file exists -- dak
print(OUTPUT "\n");
close($outputfile);
use Cwd qw(abs_path);
if (!open(OUTPUT, "> $outputfile")) {die "Aborted: Could not create output file $outputfile";}
$outputfile=abs_path($outputfile);
if ($directory eq "") {
opendir(DIR, ".");
@files = grep { !/^\./ && !/(CVS|~)/ } readdir(DIR);
closedir(DIR);
foreach $file (@files) {
if(-d $file && $file !~ /^\./) {
$directory=$file;
break;
}
}
}
if ($directory eq "") {die "Aborted: No subdirectory in current directory";}
if (!chdir("$directory")) {die "Aborted: Directory \"$directory\" does not exist!";}
print "Processing directory $directory as root of coffee file system\n";
opendir(DIR, ".");
@files = grep { !/^\./ && !/(CVS|~)/ } readdir(DIR);
closedir(DIR);
foreach $file (@files) {
if(-d $file && $file !~ /^\./) {
print "Adding subdirectory $file\n";
opendir(DIR, $file);
@newfiles = grep { !/^\./ && !/(CVS|~)/ } readdir(DIR);
closedir(DIR);
# printf "Adding files @newfiles\n";
@files = (@files, map { $_ = "$file/$_" } @newfiles);
next;
}
}
print "Writing to $outputfile\n";
print(OUTPUT "/**************Generated by /tools/avr-makecoffeedata*****************/\n");
print(OUTPUT "/*For coffee filesystem of sector size $coffee_sector_size and header length $coffee_header_length bytes*/\n");
$n=0;$coffeesize=0;$coffeesectors=0;
foreach $file (@files) {if(-f $file) {
if (length($file)>($coffee_name_length-1)) {die "Aborted: File name $file is too long";}
if (abs_path("$file") eq abs_path("$outputfile")) {
print "Skipping $outputfile for recursive input\n";
next;
}
print "Adding $file\n";
open(FILE, $file) || die "Aborted: Could not open file $file\n";
if (grep /.png/,$file) {binmode FILE;}
if (grep /.jpg/,$file) {binmode FILE;}
if (grep /.gif/,$file) {binmode FILE;}
$file =~ s-^-/-;
$fvar = $file;
$fvar =~ s-/-_-g;
$fvar =~ s-\.-_-g;
$file_length= -s FILE;
$coffee_sectors=int(($coffee_header_length+$file_length+$coffee_sector_size-1)/$coffee_sector_size);
# $coffee_sectors=sprintf("%.0f",($coffee_header_length+$file_length+$coffee_sector_size-1)/$coffee_sector_size)-1;
$coffee_length=$coffee_sectors*$coffee_sector_size;
$flen[$n]=$file_length;
$clen[$n]=$coffee_length;
$n++;$coffeesectors+=$coffee_sectors;$coffeesize+=$coffee_length;
if ($coffeesectors>$coffeemax) {
print "Warning: sector number $coffeesectors overflows allocated sector size in coffee header\n";
}
print(OUTPUT "\n__attribute__ ((section (\"$sectionname\")))\n");
print(OUTPUT "volatile const char data".$fvar."[$coffee_length] = {\n");
print(OUTPUT "$tab/* $file */\n$tab ");
#--------------------Header-----------------------------
#log_page
for($j=0;$j<$coffee_page_t;$j++) {print (OUTPUT "$null, ");}
#log_records, log_record_size
for($j=0;$j<4;$j++) {print (OUTPUT "$null, ");}
#max_pages
if ($complement) {$coffee_sectors=$coffee_sectors^0xffffffff;}
if ($coffee_page_t==1) {
printf(OUTPUT "0x%2.2x, ",($coffee_sectors )&0xff);
} elsif ($coffee_page_t==2) {
printf(OUTPUT "0x%2.2x, ",($coffee_sectors>> 8)&0xff);
printf(OUTPUT "0x%2.2x, ",($coffee_sectors )&0xff);
} elsif ($coffee_page_t==4) {
printf(OUTPUT "0x%2.2x, ",($coffee_sectors>>24)&0xff);
printf(OUTPUT "0x%2.2x, ",($coffee_sectors>>16)&0xff);
printf(OUTPUT "0x%2.2x, ",($coffee_sectors>> 8)&0xff);
printf(OUTPUT "0x%2.2x, ",($coffee_sectors )&0xff);
}
if ($complement) {$coffee_sectors=$coffee_sectors^0xffffffff;}
#eof hint and flags
if ($complement) {
print(OUTPUT "0xff, 0xfc,\n$tab");
} else {
print(OUTPUT "0x00, 0x03,\n$tab");
}
#file name
for($j = 0; $j < length($file); $j++) {
$temp=unpack("C", substr($file, $j, 1));
if ($complement) {$temp=$temp^0xff;}
printf(OUTPUT " %#02.2x,", $temp);
}
for(; $j < $coffee_name_length; $j++) {printf(OUTPUT " $null,");}
print(OUTPUT "\n$tab");
#------------------File Data---------------------------
$coffee_length-=$coffee_header_length;
$i = 0;
while(read(FILE, $data, 1)) {
$temp=unpack("C", $data);
if ($complement) {$temp=$temp^0xff;}
printf(OUTPUT " 0x%2.2x,", $temp);
$i++;$coffee_length--;
if($i == 10) {
print(OUTPUT "\n$tab");
$i = 0;
}
}
while (--$coffee_length>1) {
print (OUTPUT " $null,");
if($i++ == 9) {
print(OUTPUT "\n$tab");
$i = 0;
}
}
print (OUTPUT " $null};\n");
close(FILE);
push(@fvars, $fvar);
push(@pfiles, $file);
}}
if ($linkedlist) {
#-------------------httpd_fsdata_file links-------------------
#The non-coffee PROGMEM flash file system for the Raven webserver uses a linked flash list as follows:
print(OUTPUT "\n\n/* Structure of linked list (all offsets relative to start of section):\n");
print(OUTPUT "struct httpd_fsdata_file {\n");
print(OUTPUT "$tab const struct httpd_fsdata_file *next; //actual flash address of next link\n");
print(OUTPUT "$tab const char *name; //offset to coffee file name\n");
print(OUTPUT "$tab const char *data; //offset to coffee file data\n");
print(OUTPUT "$tab const int len; //length of file data\n");
print(OUTPUT "#if HTTPD_FS_STATISTICS == 1 //not enabled since list is in PROGMEM\n");
print(OUTPUT "$tab uint16_t count; //storage for file statistics\n");
print(OUTPUT "#endif\n");
print(OUTPUT "}\n*/\n");
# Note flash addresses above 0xffff require 32 bit pointers using pgm_read_byte_far,
# and the coffee file system is above that. So the addresses start from 0 which
# allows a 64K file system. The flash starting address is added in the read routine.
print(OUTPUT "\n#define HTTPD_FS_ROOT file$fvars[$i - 1]\n\n");
for($i = 0; $i < @fvars; $i++) {
$file = $pfiles[$i];
$fvar = $fvars[$i];
if($i == 0) {
$prevfile = "NULL";
$data_offset=0;
} else {
$data_offset=$data_offset+$clen[$i-1];
$prevfile = "file" . $fvars[$i - 1];
}
$filename_offset=$data_offset+6+2*$coffee_page_t;
$coffee_offset=$data_offset+$coffee_header_length;
if ($coffee_offset>0xffff) {print "Warning : Linked list offset field overflow\n";}
print(OUTPUT "const struct httpd_fsdata_file");
for ($t=length($file);$t<16;$t++) {print(OUTPUT " ")};
# for AVR, add PROGMEM here
print(OUTPUT " file".$fvar."[] PROGMEM={{");
for ($t=length($prevfile);$t<20;$t++) {print(OUTPUT " ")};
print(OUTPUT "$prevfile, ");
printf(OUTPUT "(const char *)0x%4.4x, ",$filename_offset);
printf(OUTPUT "(const char *)0x%4.4x, ",$coffee_offset);
printf(OUTPUT "%5u}};\n",$flen[$i]);
}
print(OUTPUT "\n#define HTTPD_FS_NUMFILES $i\n");
}
print "All done, preallocated coffee files occupy $coffeesize bytes\n";