Added input args and optional complemented output
This commit is contained in:
parent
97e258814c
commit
450aa16a5b
1 changed files with 189 additions and 46 deletions
|
@ -1,7 +1,7 @@
|
|||
#!/usr/bin/perl
|
||||
#Generate a .c source that preinitializes a coffee file system
|
||||
#David Kopf <dak664@embarqmail.com> July 2009
|
||||
#Assumes coffee file_header structure is
|
||||
#For coffee file_header structure of
|
||||
#struct file_header {
|
||||
# coffee_page_t log_page;
|
||||
# uint16_t log_records;
|
||||
|
@ -11,40 +11,143 @@
|
|||
# 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;
|
||||
#coffee_sector_size is the number of bytes in the smallest allocated block of the coffee file system
|
||||
$coffee_sector_size=256;
|
||||
$null="0x00";if ($complement) {$null="0xff";}
|
||||
#$tab="/t"; #optional tab string
|
||||
$tab=" "; #optional tabs or spaces at beginning of line, e.g. "\t\t"
|
||||
|
||||
open(OUTPUT, "> httpd-coffeefsdata.c");
|
||||
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);
|
||||
|
||||
chdir("httpd-fs");
|
||||
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) {
|
||||
# $dirname = fileparse($file);
|
||||
if(-d $file && $file !~ /^\./) {
|
||||
print "Processing directory $file\n";
|
||||
print "Adding subdirectory $file\n";
|
||||
opendir(DIR, $file);
|
||||
@newfiles = grep { !/^\./ && !/(CVS|~)/ } readdir(DIR);
|
||||
closedir(DIR);
|
||||
printf "Adding files @newfiles\n";
|
||||
# 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 "$file: name is too long!";}
|
||||
print "Adding file $file\n";
|
||||
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 "Could not open file $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;}
|
||||
|
@ -57,18 +160,24 @@ foreach $file (@files) {if(-f $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;
|
||||
# for AVR, add PROGMEM here
|
||||
print(OUTPUT "\n__attribute__ ((section (\".coffeedata\")))\n");
|
||||
print(OUTPUT "static const char data".$fvar."[$coffee_length] PROGMEM = {\n");
|
||||
print(OUTPUT "\t/* $file */\n\t ");
|
||||
$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 "0x00, ");}
|
||||
for($j=0;$j<$coffee_page_t;$j++) {print (OUTPUT "$null, ");}
|
||||
#log_records, log_record_size
|
||||
for($j=0;$j<4;$j++) {print (OUTPUT "0x00, ");}
|
||||
for($j=0;$j<4;$j++) {print (OUTPUT "$null, ");}
|
||||
#max_pages
|
||||
if ($coffee_page_t==1) {
|
||||
printf(OUTPUT "0x%2.2x, ",$coffee_sectors);
|
||||
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);
|
||||
|
@ -77,59 +186,93 @@ foreach $file (@files) {if(-f $file) {
|
|||
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);
|
||||
} else {
|
||||
die "Unsupported coffee_page_t $coffee_page_t\n";
|
||||
}
|
||||
if ($complement) {$coffee_sectors=$coffee_sectors^0xffffffff;}
|
||||
#eof hint and flags
|
||||
print(OUTPUT "0x00, 0x03,\n\t");
|
||||
if ($complement) {
|
||||
print(OUTPUT "0xff, 0xfc,\n$tab");
|
||||
} else {
|
||||
print(OUTPUT "0x00, 0x03,\n$tab");
|
||||
}
|
||||
|
||||
#file name
|
||||
for($j = 0; $j < length($file); $j++) {
|
||||
printf(OUTPUT " %#02.2x,", unpack("C", substr($file, $j, 1)));
|
||||
$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 " 0x00,");
|
||||
}
|
||||
print(OUTPUT "\n\t");
|
||||
for(; $j < $coffee_name_length; $j++) {printf(OUTPUT " $null,");}
|
||||
print(OUTPUT "\n$tab");
|
||||
#------------------File Data---------------------------
|
||||
$coffee_length-=$coffee_header_length;
|
||||
$coffee_length-=$coffee_header_length;
|
||||
$i = 0;
|
||||
while(read(FILE, $data, 1)) {
|
||||
# printf(OUTPUT " %#2.2x,", unpack("C", $data));
|
||||
printf(OUTPUT " 0x%2.2x,", unpack("C", $data));
|
||||
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\t");
|
||||
print(OUTPUT "\n$tab");
|
||||
$i = 0;
|
||||
}
|
||||
}
|
||||
while (--$coffee_length>1) {
|
||||
print (OUTPUT " 0x00,");
|
||||
if($i++ == 9) {
|
||||
print(OUTPUT "\n\t");
|
||||
$i = 0;
|
||||
}
|
||||
print (OUTPUT " $null,");
|
||||
if($i++ == 9) {
|
||||
print(OUTPUT "\n$tab");
|
||||
$i = 0;
|
||||
}
|
||||
}
|
||||
print (OUTPUT " 0x00};\n");
|
||||
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 u16_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];
|
||||
}
|
||||
# for AVR, add PROGMEM here
|
||||
print(OUTPUT "const struct httpd_fsdata_file file".$fvar."[] PROGMEM = {{$prevfile, data$fvar, ");
|
||||
print(OUTPUT "data$fvar + ". (length($file) + 1) .", ");
|
||||
print(OUTPUT "sizeof(data$fvar) - ". (length($file) + 1) ."}};\n\n");
|
||||
}
|
||||
$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 "#define HTTPD_FS_ROOT file$fvars[$i - 1]\n\n");
|
||||
print(OUTPUT "#define HTTPD_FS_NUMFILES $i\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";
|
||||
|
|
Loading…
Reference in a new issue