2012-08-08 11:44:50 +02:00
/*
0xFFFF - Open Free Fiasco Firmware Flasher
Copyright (C) 2007-2011 pancake <pancake@youterm.com>
Copyright (C) 2011-2012 Pali Rohár <pali.rohar@gmail.com>
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 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
2012-07-14 10:33:15 +02:00
2012-08-07 14:53:52 +02:00
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
2012-08-09 17:50:50 +02:00
#include "global.h"
2012-08-07 14:53:52 +02:00
#include "device.h"
#include "image.h"
2012-08-07 14:01:15 +02:00
#include "fiasco2.h"
2012-08-09 17:50:50 +02:00
#define FIASCO_READ_ERROR(fiasco, format, ...) do { ERROR(errno, format, ##__VA_ARGS__); fiasco_free(fiasco); return NULL; } while (0)
#define FIASCO_WRITE_ERROR(file, fd, format, ...) do { ERROR(errno, "%s: " format, file, ##__VA_ARGS__); if ( fd >= 0 ) close(fd); return -1; } while (0)
#define READ_OR_FAIL(fiasco, buf, size) do { if ( read(fiasco->fd, buf, size) != size ) { FIASCO_READ_ERROR(fiasco, "Cannot read %d bytes", size); } } while (0)
2012-08-07 14:01:15 +02:00
#define READ_OR_RETURN(fiasco, buf, size) do { if ( read(fiasco->fd, buf, size) != size ) return fiasco; } while (0)
2012-08-09 17:50:50 +02:00
#define WRITE_OR_FAIL(file, fd, buf, size) do { if ( ! simulate ) { if ( write(fd, buf, size) != size ) { FIASCO_WRITE_ERROR(file, fd, "Cannot write %d bytes", size); } } } while (0)
2012-08-07 14:01:15 +02:00
2012-07-14 10:33:15 +02:00
struct fiasco * fiasco_alloc_empty ( void ) {
struct fiasco * fiasco = calloc ( 1 , sizeof ( struct fiasco ));
2012-08-09 17:50:50 +02:00
if ( ! fiasco )
ALLOC_ERROR_RETURN ( NULL );
2012-07-14 10:33:15 +02:00
fiasco -> fd = - 1 ;
return fiasco ;
}
struct fiasco * fiasco_alloc_from_file ( const char * file ) {
2012-08-07 14:01:15 +02:00
uint8_t byte ;
uint32_t length ;
uint32_t count ;
uint8_t length8 ;
uint8_t count8 ;
char type [ 13 ];
char device [ 17 ];
char hwrevs [ 1024 ];
char version [ 257 ];
char layout [ 257 ];
uint16_t hash ;
off_t offset ;
struct image * image ;
char hwrev [ 9 ];
unsigned char buf [ 512 ];
unsigned char * pbuf ;
2012-08-07 14:53:52 +02:00
2012-07-14 10:33:15 +02:00
struct fiasco * fiasco = fiasco_alloc_empty ();
if ( ! fiasco )
return NULL ;
fiasco -> fd = open ( file , O_RDONLY );
if ( fiasco -> fd < 0 ) {
2012-08-09 17:50:50 +02:00
ERROR ( errno , "Cannot open file" );
2012-08-07 14:01:15 +02:00
fiasco_free ( fiasco );
2012-07-14 10:33:15 +02:00
return NULL ;
}
2012-08-09 16:05:44 +02:00
fiasco -> orig_filename = strdup ( file );
2012-08-07 14:01:15 +02:00
READ_OR_FAIL ( fiasco , & byte , 1 );
if ( byte != 0xb4 )
FIASCO_READ_ERROR ( fiasco , "Invalid fiasco signature" );
READ_OR_FAIL ( fiasco , & length , 4 );
length = ntohl ( length );
READ_OR_FAIL ( fiasco , & count , 4 );
count = ntohl ( count );
2012-08-09 17:50:50 +02:00
VERBOSE ( "Number of header blocks: %d \n " , count );
2012-08-07 14:01:15 +02:00
2012-08-07 14:53:52 +02:00
while ( count > 0 ) {
2012-08-07 14:01:15 +02:00
READ_OR_FAIL ( fiasco , & byte , 1 );
READ_OR_FAIL ( fiasco , & length8 , 1 );
READ_OR_FAIL ( fiasco , buf , length8 );
if ( byte == 0xe8 ) {
2012-08-07 17:13:06 +02:00
memset ( fiasco -> name , 0 , sizeof ( fiasco -> name ));
2012-08-07 14:01:15 +02:00
strncpy ( fiasco -> name , ( char * ) buf , length8 );
2012-08-09 17:50:50 +02:00
VERBOSE ( "Fiasco name: %s \n " , fiasco -> name );
2012-08-07 14:01:15 +02:00
} else if ( byte == 0x31 ) {
2012-08-07 17:13:06 +02:00
memset ( fiasco -> swver , 0 , sizeof ( fiasco -> swver ));
2012-08-07 14:01:15 +02:00
strncpy ( fiasco -> swver , ( char * ) buf , length8 );
2012-08-09 17:50:50 +02:00
VERBOSE ( "SW version: %s \n " , fiasco -> swver );
2012-08-07 14:01:15 +02:00
} else {
2012-08-09 17:50:50 +02:00
VERBOSE ( "Unknown header %#x \n " , byte );
2012-08-07 14:01:15 +02:00
}
-- count ;
}
/* walk the tree */
while ( 1 ) {
2012-08-07 17:13:06 +02:00
/* If end of file, return fiasco image */
READ_OR_RETURN ( fiasco , buf , 7 );
/* Header of next image */
if ( ! buf [ 0 ] == 0x54 && buf [ 2 ] == 0x2E && buf [ 3 ] == 0x19 && buf [ 4 ] == 0x01 && buf [ 5 ] == 0x01 && buf [ 6 ] == 0x00 ) {
2012-08-09 17:50:50 +02:00
ERROR ( 0 , "Invalid next image header" );
2012-08-07 17:13:06 +02:00
return fiasco ;
2012-08-07 14:01:15 +02:00
}
count8 = buf [ 1 ];
if ( count8 > 0 )
-- count8 ;
READ_OR_RETURN ( fiasco , & hash , 2 );
2012-08-07 17:13:06 +02:00
hash = ntohs ( hash );
2012-08-07 14:01:15 +02:00
memset ( type , 0 , sizeof ( type ));
READ_OR_RETURN ( fiasco , type , 12 );
2012-08-07 17:13:06 +02:00
byte = type [ 0 ];
if ( byte == 0xFF )
2012-08-07 14:01:15 +02:00
return fiasco ;
2012-08-09 17:50:50 +02:00
VERBOSE ( " %s \n " , type );
2012-08-07 14:01:15 +02:00
READ_OR_RETURN ( fiasco , & length , 4 );
length = ntohl ( length );
2012-08-07 17:13:06 +02:00
/* unknown */
READ_OR_RETURN ( fiasco , buf , 4 );
2012-08-09 17:50:50 +02:00
VERBOSE ( " size: %d bytes \n " , length );
VERBOSE ( " hash: %#04x \n " , hash );
VERBOSE ( " subsections: %d \n " , count8 );
2012-08-07 14:01:15 +02:00
2012-08-07 17:13:06 +02:00
memset ( device , 0 , sizeof ( device ));
2012-08-07 14:01:15 +02:00
memset ( hwrevs , 0 , sizeof ( hwrevs ));
2012-08-07 17:13:06 +02:00
memset ( version , 0 , sizeof ( version ));
memset ( layout , 0 , sizeof ( layout ));
2012-08-07 14:01:15 +02:00
while ( count8 > 0 ) {
READ_OR_RETURN ( fiasco , & byte , 1 );
READ_OR_RETURN ( fiasco , & length8 , 1 );
READ_OR_RETURN ( fiasco , buf , length8 );
2012-08-09 17:50:50 +02:00
VERBOSE ( " subinfo \n " );
VERBOSE ( " length: %d \n " , length8 );
VERBOSE ( " type: " );
2012-07-14 10:33:15 +02:00
2012-08-07 14:01:15 +02:00
if ( byte == '1' ) {
memset ( version , 0 , sizeof ( version ));
2012-08-07 14:53:52 +02:00
strncpy ( version , ( char * ) buf , length8 );
2012-08-09 17:50:50 +02:00
VERBOSE ( "version string \n " );
VERBOSE ( " version: %s \n " , version );
2012-08-07 14:01:15 +02:00
} else if ( byte == '2' ) {
int tmp = length8 ;
if ( tmp > 16 ) tmp = 16 ;
memset ( device , 0 , sizeof ( device ));
2012-08-07 14:53:52 +02:00
strncpy ( device , ( char * ) buf , tmp );
2012-08-09 17:50:50 +02:00
VERBOSE ( "hw revision \n " );
VERBOSE ( " device: %s \n " , device );
2012-08-07 14:01:15 +02:00
pbuf = buf + strlen ( device ) + 1 ;
while ( pbuf < buf + length8 ) {
2012-08-07 17:13:06 +02:00
while ( pbuf < buf + length8 && * pbuf < 32 )
++ pbuf ;
if ( pbuf >= buf + length8 ) break ;
2012-08-07 14:01:15 +02:00
tmp = buf + length8 - pbuf ;
if ( tmp > 8 ) tmp = 8 ;
2012-08-07 14:53:52 +02:00
memset ( hwrev , 0 , sizeof ( hwrev ));
strncpy ( hwrev , ( char * ) pbuf , tmp );
2012-08-07 14:01:15 +02:00
if ( ! hwrevs [ 0 ] )
strcpy ( hwrevs , hwrev );
else {
2012-08-07 17:13:06 +02:00
/* TODO: check if hwrevs has enought size */
2012-08-07 14:01:15 +02:00
strcat ( hwrevs , "," );
strcat ( hwrevs , hwrev );
}
2012-08-09 17:50:50 +02:00
VERBOSE ( " hw revision: %s \n " , hwrev );
2012-08-07 17:13:06 +02:00
pbuf += strlen ( hwrev ) + 1 ;
2012-08-07 14:01:15 +02:00
}
} else if ( byte == '3' ) {
memset ( layout , 0 , sizeof ( layout ));
2012-08-07 14:53:52 +02:00
strncpy ( layout , ( char * ) buf , length8 );
2012-08-09 17:50:50 +02:00
VERBOSE ( "layout \n " );
2012-08-07 14:01:15 +02:00
} else {
2012-08-09 17:50:50 +02:00
VERBOSE ( "unknown ('%c':%#x) \n " , byte , byte );
2012-08-07 14:01:15 +02:00
}
-- count8 ;
}
2012-08-07 17:13:06 +02:00
/* unknown */
READ_OR_RETURN ( fiasco , buf , 1 );
2012-08-07 14:01:15 +02:00
offset = lseek ( fiasco -> fd , 0 , SEEK_CUR );
2012-08-09 17:50:50 +02:00
VERBOSE ( " version: %s \n " , version );
VERBOSE ( " device: %s \n " , device );
VERBOSE ( " hwrevs: %s \n " , hwrevs );
VERBOSE ( " data at: %#08x \n " , ( unsigned int ) offset );
2012-08-07 14:01:15 +02:00
2012-08-07 14:53:52 +02:00
image = image_alloc_from_shared_fd ( fiasco -> fd , length , offset , hash , type , device , hwrevs , version , layout );
2012-08-07 14:01:15 +02:00
if ( ! image )
FIASCO_READ_ERROR ( fiasco , "Cannot allocate image" );
fiasco_add_image ( fiasco , image );
lseek ( fiasco -> fd , offset + length , SEEK_SET );
}
return fiasco ;
2012-07-14 10:33:15 +02:00
}
void fiasco_free ( struct fiasco * fiasco ) {
struct image_list * list = fiasco -> first ;
while ( list ) {
struct image_list * next = list -> next ;
image_list_del ( list );
list = next ;
}
2012-08-09 16:05:44 +02:00
if ( fiasco -> fd >= 0 )
close ( fiasco -> fd );
free ( fiasco -> orig_filename );
2012-08-07 14:01:15 +02:00
free ( fiasco );
2012-07-14 10:33:15 +02:00
}
2012-08-07 14:53:52 +02:00
void fiasco_add_image ( struct fiasco * fiasco , struct image * image ) {
2012-07-14 10:33:15 +02:00
2012-08-07 17:13:06 +02:00
image_list_add ( & fiasco -> first , image );
2012-07-14 10:33:15 +02:00
}
int fiasco_write_to_file ( struct fiasco * fiasco , const char * file ) {
2012-08-07 14:01:15 +02:00
int fd = - 1 ;
uint32_t size ;
uint32_t length ;
2012-08-07 20:41:43 +02:00
uint16_t hash ;
2012-08-07 14:01:15 +02:00
uint8_t length8 ;
const char * str ;
const char * type ;
const char * device ;
struct image_list * image_list ;
struct image * image ;
unsigned char buf [ 4096 ];
if ( ! fiasco )
return - 1 ;
2012-08-09 17:50:50 +02:00
printf ( "Generating Fiasco image %s... \n " , file );
2012-08-07 14:01:15 +02:00
if ( ! fiasco -> first )
FIASCO_WRITE_ERROR ( file , fd , "Nothing to write" );
if ( fiasco -> name && strlen ( fiasco -> name ) + 1 > UINT8_MAX )
FIASCO_WRITE_ERROR ( file , fd , "Fiasco name string is too long" );
if ( fiasco -> swver && strlen ( fiasco -> swver ) + 1 > UINT8_MAX )
FIASCO_WRITE_ERROR ( file , fd , "SW version string is too long" );
2012-08-09 17:50:50 +02:00
if ( ! simulate ) {
fd = open ( file , O_RDWR | O_CREAT | O_TRUNC , 0644 );
if ( fd < 0 ) {
ERROR ( errno , "Cannot create file" );
return - 1 ;
}
2012-08-07 14:01:15 +02:00
}
2012-08-09 17:50:50 +02:00
printf ( "Writing Fiasco header... \n " );
2012-08-07 14:01:15 +02:00
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( file , fd , " \xb4 " , 1 ); /* signature */
2012-08-07 14:01:15 +02:00
2012-08-07 20:41:43 +02:00
if ( fiasco -> name [ 0 ] )
2012-08-07 14:01:15 +02:00
str = fiasco -> name ;
else
str = "OSSO UART+USB" ;
length = 4 + strlen ( str ) + 3 ;
2012-08-07 20:41:43 +02:00
if ( fiasco -> swver [ 0 ] )
2012-08-07 14:53:52 +02:00
length += strlen ( fiasco -> swver ) + 3 ;
2012-08-07 14:01:15 +02:00
length = htonl ( length );
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( file , fd , & length , 4 ); /* FW header length */
2012-08-07 14:01:15 +02:00
2012-08-07 20:41:43 +02:00
if ( fiasco -> swver [ 0 ] )
2012-08-07 14:01:15 +02:00
length = htonl ( 2 );
else
length = htonl ( 1 );
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( file , fd , & length , 4 ); /* FW header blocks count */
2012-08-07 14:01:15 +02:00
/* Fiasco name */
length8 = strlen ( str ) + 1 ;
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( file , fd , " \xe8 " , 1 );
WRITE_OR_FAIL ( file , fd , & length8 , 1 );
WRITE_OR_FAIL ( file , fd , str , length8 );
2012-08-07 14:01:15 +02:00
/* SW version */
2012-08-07 20:41:43 +02:00
if ( fiasco -> swver [ 0 ] ) {
2012-08-07 14:01:15 +02:00
printf ( "Writing SW version: %s \n " , fiasco -> swver );
2012-08-07 14:53:52 +02:00
length8 = strlen ( fiasco -> swver ) + 1 ;
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( file , fd , " \x31 " , 1 );
WRITE_OR_FAIL ( file , fd , & length8 , 1 );
WRITE_OR_FAIL ( file , fd , fiasco -> swver , length8 );
2012-08-07 14:01:15 +02:00
};
2012-08-09 17:50:50 +02:00
printf ( " \n " );
2012-08-07 14:01:15 +02:00
image_list = fiasco -> first ;
while ( image_list ) {
image = image_list -> image ;
if ( ! image )
FIASCO_WRITE_ERROR ( file , fd , "Empty image" );
2012-08-09 17:50:50 +02:00
printf ( "Writing image... \n " );
image_print_info ( image );
2012-08-07 14:01:15 +02:00
type = image_type_to_string ( image -> type );
device = device_to_string ( image -> device );
if ( ! type )
FIASCO_WRITE_ERROR ( file , fd , "Unknown image type" );
if ( image -> version && strlen ( image -> version ) > UINT8_MAX )
FIASCO_WRITE_ERROR ( file , fd , "Image version string is too long" );
if ( image -> layout && strlen ( image -> layout ) > UINT8_MAX )
FIASCO_WRITE_ERROR ( file , fd , "Image layout is too long" );
2012-08-09 17:50:50 +02:00
printf ( "Writing image header... \n " );
2012-08-07 14:01:15 +02:00
/* signature */
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( file , fd , "T" , 1 );
2012-08-07 14:01:15 +02:00
/* number of subsections */
length8 = 1 ;
if ( image -> version )
++ length8 ;
if ( device )
++ length8 ;
if ( image -> layout )
++ length8 ;
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( file , fd , & length8 , 1 );
2012-08-07 14:01:15 +02:00
/* unknown */
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( file , fd , " \x2e\x19\x01\x01\x00 " , 5 );
2012-08-07 14:01:15 +02:00
/* checksum */
2012-08-07 20:41:43 +02:00
hash = htons ( image -> hash );
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( file , fd , & hash , 2 );
2012-08-07 14:01:15 +02:00
/* image type name */
2012-08-07 20:41:43 +02:00
memset ( buf , 0 , 12 );
strncpy (( char * ) buf , type , 12 );
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( file , fd , buf , 12 );
2012-08-07 14:01:15 +02:00
/* image size */
2012-08-07 18:43:52 +02:00
size = htonl ( image -> size );
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( file , fd , & size , 4 );
2012-08-07 14:01:15 +02:00
/* unknown */
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( file , fd , " \x00\x00\x00\x00 " , 4 );
2012-08-07 14:01:15 +02:00
/* append version subsection */
if ( image -> version ) {
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( file , fd , "1" , 1 ); /* 1 - version */
2012-08-07 14:53:52 +02:00
length8 = strlen ( image -> version ) + 1 ;
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( file , fd , & length8 , 1 );
WRITE_OR_FAIL ( file , fd , image -> version , length8 );
2012-08-07 14:01:15 +02:00
}
/* append device & hwrevs subsection */
if ( device ) {
const char * ptr = image -> hwrevs ;
const char * oldptr = ptr ;
2012-08-07 14:53:52 +02:00
int i ;
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( file , fd , "2" , 1 ); /* 2 - device & hwrevs */
2012-08-07 14:01:15 +02:00
length8 = 16 ;
if ( image -> hwrevs ) {
i = 1 ;
while ( ( ptr = strchr ( ptr , ',' )) ) { i ++ ; ptr ++ ; }
if ( ( int ) length8 + i * 8 > 255 ) {
FIASCO_WRITE_ERROR ( file , fd , "Device string and HW revisions are too long" );
}
length8 += i * 8 ;
}
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( file , fd , & length8 , 1 );
2012-08-07 14:01:15 +02:00
length8 = strlen ( device );
if ( length8 > 15 ) length8 = 15 ;
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( file , fd , device , length8 );
2012-08-07 14:01:15 +02:00
for ( i = 0 ; i < 16 - length8 ; ++ i )
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( file , fd , " \x00 " , 1 );
2012-08-07 14:01:15 +02:00
if ( image -> hwrevs ) {
ptr = image -> hwrevs ;
oldptr = ptr ;
while ( ( ptr = strchr ( ptr , ',' )) ) {
length8 = ptr - oldptr ;
if ( length8 > 8 ) length8 = 8 ;
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( file , fd , oldptr , length8 );
2012-08-07 14:01:15 +02:00
for ( i = 0 ; i < 8 - length8 ; ++ i )
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( file , fd , " \x00 " , 1 );
2012-08-07 14:01:15 +02:00
++ ptr ;
oldptr = ptr ;
}
length8 = strlen ( oldptr );
if ( length8 > 8 ) length8 = 8 ;
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( file , fd , oldptr , length8 );
2012-08-07 14:01:15 +02:00
for ( i = 0 ; i < 8 - length8 ; ++ i )
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( file , fd , " \x00 " , 1 );
2012-08-07 14:01:15 +02:00
}
}
/* append layout subsection */
if ( image -> layout ) {
length8 = strlen ( image -> layout );
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( file , fd , "3" , 1 ); /* 3 - layout */
WRITE_OR_FAIL ( file , fd , & length8 , 1 );
WRITE_OR_FAIL ( file , fd , image -> layout , length8 );
2012-08-07 14:01:15 +02:00
}
/* dummy byte - end of all subsections */
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( file , fd , " \x00 " , 1 );
printf ( "Writing image data... \n " );
2012-08-07 14:01:15 +02:00
image_seek ( image , 0 );
while ( 1 ) {
size = image_read ( image , buf , sizeof ( buf ));
if ( size < 1 )
break ;
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( file , fd , buf , size );
2012-08-07 14:01:15 +02:00
}
image_list = image_list -> next ;
2012-08-09 17:50:50 +02:00
if ( image_list )
printf ( " \n " );
2012-08-07 14:01:15 +02:00
}
close ( fd );
2012-08-09 17:50:50 +02:00
printf ( " \n Done \n\n " );
2012-08-07 14:01:15 +02:00
return 0 ;
2012-07-14 10:33:15 +02:00
}
int fiasco_unpack ( struct fiasco * fiasco , const char * dir ) {
2012-08-07 17:31:53 +02:00
int fd ;
2012-08-07 14:01:15 +02:00
char * name ;
2012-08-07 17:13:06 +02:00
char * layout_name ;
2012-08-07 14:01:15 +02:00
struct image * image ;
struct image_list * image_list ;
2012-08-07 17:31:53 +02:00
uint32_t size ;
2012-08-07 21:18:17 +02:00
char cwd [ 256 ];
2012-08-07 17:31:53 +02:00
unsigned char buf [ 4096 ];
2012-08-07 14:01:15 +02:00
2012-08-07 21:18:17 +02:00
if ( dir ) {
memset ( cwd , 0 , sizeof ( cwd ));
if ( ! getcwd ( cwd , sizeof ( cwd )) ) {
2012-08-09 17:50:50 +02:00
ERROR ( errno , "Cannot store current directory" );
2012-08-07 21:18:17 +02:00
return - 1 ;
}
if ( chdir ( dir ) < 0 ) {
2012-08-09 17:50:50 +02:00
ERROR ( errno , "Cannot change current directory to %s" , dir );
2012-08-07 21:18:17 +02:00
return - 1 ;
}
2012-08-07 14:01:15 +02:00
}
2012-08-09 17:50:50 +02:00
fiasco_print_info ( fiasco );
2012-08-07 14:01:15 +02:00
image_list = fiasco -> first ;
while ( image_list ) {
image = image_list -> image ;
2012-08-07 17:13:06 +02:00
name = image_name_alloc_from_values ( image );
2012-08-09 17:50:50 +02:00
printf ( " \n " );
2012-08-07 17:13:06 +02:00
printf ( "Unpacking image... \n " );
2012-08-09 16:05:44 +02:00
image_print_info ( image );
2012-08-07 17:13:06 +02:00
if ( image -> layout ) {
layout_name = calloc ( 1 , strlen ( name ) + strlen ( ".layout" ) + 1 );
2012-08-09 17:50:50 +02:00
if ( ! layout_name )
ALLOC_ERROR_RETURN ( - 1 );
2012-08-07 17:13:06 +02:00
sprintf ( layout_name , "%s.layout" , name );
2012-08-09 16:05:44 +02:00
printf ( " Layout file: %s \n " , layout_name );
2012-08-07 17:13:06 +02:00
}
2012-08-09 16:05:44 +02:00
printf ( " Output file: %s \n " , name );
2012-08-07 14:01:15 +02:00
2012-08-07 17:31:53 +02:00
fd = open ( name , O_RDWR | O_CREAT | O_TRUNC , 0644 );
if ( fd < 0 ) {
2012-08-09 17:50:50 +02:00
ERROR ( errno , "Cannot create output file %s" , name );
2012-08-07 17:31:53 +02:00
return - 1 ;
}
2012-08-07 14:20:54 +02:00
2012-08-07 17:13:06 +02:00
free ( name );
2012-08-07 17:31:53 +02:00
image_seek ( image , 0 );
while ( 1 ) {
size = image_read ( image , buf , sizeof ( buf ));
if ( size < 1 )
break ;
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( name , fd , buf , size );
2012-08-07 17:31:53 +02:00
}
close ( fd );
if ( image -> layout ) {
fd = open ( layout_name , O_RDWR | O_CREAT | O_TRUNC , 0644 );
if ( fd < 0 ) {
2012-08-09 17:50:50 +02:00
ERROR ( errno , "Cannot create layout file %s" , layout_name );
2012-08-07 17:31:53 +02:00
return - 1 ;
}
free ( layout_name );
2012-08-09 17:50:50 +02:00
WRITE_OR_FAIL ( layout_name , fd , image -> layout , ( int ) strlen ( image -> layout ));
2012-08-07 17:31:53 +02:00
close ( fd );
}
2012-08-07 14:01:15 +02:00
image_list = image_list -> next ;
}
2012-08-07 21:18:17 +02:00
if ( dir ) {
if ( chdir ( cwd ) < 0 ) {
2012-08-09 17:50:50 +02:00
ERROR ( errno , "Cannot change current directory back to %s" , cwd );
2012-08-07 21:18:17 +02:00
return - 1 ;
}
}
2012-08-09 17:50:50 +02:00
printf ( " \n Done \n\n " );
2012-08-07 14:01:15 +02:00
return 0 ;
2012-07-14 10:33:15 +02:00
}
2012-08-09 16:05:44 +02:00
void fiasco_print_info ( struct fiasco * fiasco ) {
if ( fiasco -> orig_filename )
printf ( "File: %s \n " , fiasco -> orig_filename );
if ( fiasco -> name [ 0 ] )
printf ( " Fiasco Name: %s \n " , fiasco -> name );
if ( fiasco -> swver [ 0 ] )
printf ( " Fiasco Software release version: %s \n " , fiasco -> swver );
}