2012-08-08 21:33:53 +02:00
|
|
|
/*
|
|
|
|
|
0xFFFF - Open Free Fiasco Firmware Flasher
|
2012-08-09 16:07:48 +02:00
|
|
|
Copyright (C) 2007, 2008 pancake <pancake@youterm.com>
|
2012-08-08 21:33:53 +02:00
|
|
|
Copyright (C) 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/>.
|
|
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <sys/stat.h>
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
2012-08-09 17:50:50 +02:00
|
|
|
#include "global.h"
|
2012-08-11 11:12:58 +02:00
|
|
|
|
2012-08-08 21:33:53 +02:00
|
|
|
#include "image.h"
|
2012-08-09 19:50:14 +02:00
|
|
|
#include "fiasco.h"
|
2012-08-09 16:13:43 +02:00
|
|
|
#include "device.h"
|
|
|
|
|
#include "usb-device.h"
|
2012-08-09 19:44:47 +02:00
|
|
|
#include "cold-flash.h"
|
2012-08-10 12:19:28 +02:00
|
|
|
#include "console.h"
|
|
|
|
|
#include "qmode.h"
|
2012-08-10 21:23:19 +02:00
|
|
|
#include "nolo.h"
|
2012-08-08 21:33:53 +02:00
|
|
|
|
|
|
|
|
static void show_title(void) {
|
|
|
|
|
printf("0xFFFF v%s // The Free Fiasco Firmware Flasher\n", VERSION);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void show_usage(void) {
|
|
|
|
|
|
|
|
|
|
int i;
|
|
|
|
|
printf (""
|
|
|
|
|
|
|
|
|
|
#if defined(WITH_USB) && ! defined(WITH_DEVICE)
|
|
|
|
|
"Over USB:\n"
|
2012-08-24 10:45:47 +02:00
|
|
|
" -b [cmdline] boot default or loaded kernel (default: no cmdline)\n"
|
|
|
|
|
" -b update boot default or loaded kernel to Update mode\n"
|
2012-08-08 21:33:53 +02:00
|
|
|
" -r reboot device\n"
|
2012-08-10 14:58:54 +02:00
|
|
|
" -l load kernel and initfs images to RAM\n"
|
2012-08-08 21:33:53 +02:00
|
|
|
" -f flash all specified images\n"
|
2012-08-10 14:58:54 +02:00
|
|
|
" -c cold flash 2nd and secondary image\n"
|
2012-08-08 21:33:53 +02:00
|
|
|
"\n"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef WITH_DEVICE
|
|
|
|
|
"On device:\n"
|
|
|
|
|
" -r reboot device\n"
|
|
|
|
|
" -f flash all specified images\n"
|
|
|
|
|
" -x /dev/mtd check for bad blocks on mtd device\n"
|
2012-08-24 10:45:47 +02:00
|
|
|
" -E file dump all device images to one fiasco image, see -t\n"
|
|
|
|
|
" -e [dir] dump all device images to directory, see -t (default: current)\n"
|
2012-08-08 21:33:53 +02:00
|
|
|
"\n"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(WITH_USB) || defined(WITH_DEVICE)
|
|
|
|
|
"Device configuration:\n"
|
|
|
|
|
" -I identify, show all information about device\n"
|
|
|
|
|
" -D 0|1|2 change root device: 0 - flash, 1 - mmc, 2 - usb\n"
|
|
|
|
|
" -U 0|1 disable/enable USB host mode\n"
|
|
|
|
|
" -R 0|1 disable/enable R&D mode\n"
|
|
|
|
|
" -F flags change R&D flags, flags are comma separated list, can be empty\n"
|
|
|
|
|
" -H rev change HW revision\n"
|
|
|
|
|
" -N ver change NOLO version string\n"
|
2012-08-10 22:09:31 +02:00
|
|
|
" -K ver change kernel version string\n"
|
2012-08-08 21:33:53 +02:00
|
|
|
" -S ver change SW release version string\n"
|
|
|
|
|
" -C ver change content eMMC version string\n"
|
|
|
|
|
"\n"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
"Input image specification:\n"
|
|
|
|
|
" -M file specify fiasco image\n"
|
|
|
|
|
" -m arg specify normal image\n"
|
|
|
|
|
" arg is [[[dev:[hw:]]ver:]type:]file[%%lay]\n"
|
|
|
|
|
" dev is device name string (default: emtpy)\n"
|
|
|
|
|
" hw are comma separated list of HW revisions (default: empty)\n"
|
|
|
|
|
" ver is image version string (default: empty)\n"
|
2012-08-24 10:45:47 +02:00
|
|
|
" type is image type (default: autodetect)\n"
|
2012-08-08 21:33:53 +02:00
|
|
|
" file is image file name\n"
|
|
|
|
|
" lay is layout file name (default: none)\n"
|
|
|
|
|
"\n"
|
|
|
|
|
|
|
|
|
|
"Image filters:\n"
|
2012-09-22 20:56:28 +02:00
|
|
|
" -t types filter images by type\n"
|
2012-08-08 21:33:53 +02:00
|
|
|
" -d dev filter images by device\n"
|
|
|
|
|
" -w hw filter images by HW revision\n"
|
|
|
|
|
"\n"
|
|
|
|
|
|
|
|
|
|
"Fiasco image:\n"
|
2012-08-24 10:45:47 +02:00
|
|
|
" -u [dir] unpack fiasco image to directory (default: current)\n"
|
|
|
|
|
" -g file[%%sw] generate fiasco image with SW rel version (default: no version)\n"
|
2012-08-08 21:33:53 +02:00
|
|
|
"\n"
|
|
|
|
|
|
|
|
|
|
"Other options:\n"
|
|
|
|
|
" -i identify images\n"
|
|
|
|
|
#if defined(WITH_USB) || defined(WITH_DEVICE)
|
|
|
|
|
" -p console prompt mode\n"
|
|
|
|
|
#endif
|
|
|
|
|
#if ( defined(WITH_USB) || defined(WITH_DEVICE) ) && defined(WITH_SQUEUES)
|
|
|
|
|
" -Q enter shared queues server mode (for gui or remote)\n"
|
|
|
|
|
#endif
|
|
|
|
|
" -s simulate, do not flash or write on disk\n"
|
|
|
|
|
" -n disable hash, checksum and image type checking\n"
|
|
|
|
|
" -v be verbose and noisy\n"
|
|
|
|
|
" -h show this help message\n"
|
|
|
|
|
"\n"
|
|
|
|
|
|
|
|
|
|
#if defined(WITH_USB) || defined(WITH_DEVICE)
|
|
|
|
|
"R&D flags:\n"
|
|
|
|
|
" no-omap-wd disable auto reboot by OMAP watchdog\n"
|
|
|
|
|
" no-ext-wd disable auto reboot by external watchdog\n"
|
|
|
|
|
" no-lifeguard-reset disable auto reboot by software lifeguard\n"
|
|
|
|
|
" serial-console enable serial console\n"
|
|
|
|
|
" no-usb-timeout disable usb timeout for flashing\n"
|
|
|
|
|
" sti-console enable sti console\n"
|
|
|
|
|
" no-charging disable battery charging\n"
|
|
|
|
|
" force-power-key force omap boot reason to power key\n"
|
|
|
|
|
"\n"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
printf( "Devices:\n");
|
|
|
|
|
for ( i = 0; i < DEVICE_COUNT; ++i )
|
|
|
|
|
if ( device_to_string(i) && device_to_long_string(i) )
|
|
|
|
|
printf(" %-14s %s\n", device_to_string(i), device_to_long_string(i));
|
|
|
|
|
printf( "\n");
|
|
|
|
|
|
|
|
|
|
printf( "Image types:\n");
|
|
|
|
|
for ( i = 0; i < IMAGE_COUNT; ++i )
|
|
|
|
|
if ( image_type_to_string(i) )
|
|
|
|
|
printf(" %s\n", image_type_to_string(i));
|
|
|
|
|
printf( "\n");
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int simulate;
|
|
|
|
|
int noverify;
|
|
|
|
|
int verbose;
|
|
|
|
|
|
|
|
|
|
/* arg = [[[dev:[hw:]]ver:]type:]file[%%lay] */
|
2012-08-09 16:07:48 +02:00
|
|
|
static void parse_image_arg(char * arg, struct image_list ** image_first) {
|
2012-08-08 21:33:53 +02:00
|
|
|
|
2012-08-11 18:16:29 +02:00
|
|
|
struct stat st;
|
2012-08-08 21:33:53 +02:00
|
|
|
struct image * image;
|
|
|
|
|
char * file;
|
|
|
|
|
char * type;
|
|
|
|
|
char * device;
|
|
|
|
|
char * hwrevs;
|
|
|
|
|
char * version;
|
|
|
|
|
char * layout;
|
|
|
|
|
char * layout_file;
|
|
|
|
|
|
2012-08-11 18:16:29 +02:00
|
|
|
/* Fisrt check if arg is file, then try to parse arg format */
|
|
|
|
|
if ( stat(arg, &st) == 0 ) {
|
|
|
|
|
image = image_alloc_from_file(arg, NULL, NULL, NULL, NULL, NULL);
|
|
|
|
|
if ( ! image ) {
|
2012-08-24 10:33:57 +02:00
|
|
|
ERROR("Cannot load image file %s", arg);
|
2012-08-11 18:16:29 +02:00
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
image_list_add(image_first, image);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-08 21:33:53 +02:00
|
|
|
layout_file = strchr(arg, '%');
|
|
|
|
|
if (layout_file)
|
|
|
|
|
*(layout_file++) = 0;
|
|
|
|
|
|
|
|
|
|
type = NULL;
|
|
|
|
|
device = NULL;
|
|
|
|
|
hwrevs = NULL;
|
|
|
|
|
version = NULL;
|
|
|
|
|
layout = NULL;
|
|
|
|
|
|
|
|
|
|
file = strrchr(arg, ':');
|
|
|
|
|
if (file) {
|
|
|
|
|
*(file++) = 0;
|
|
|
|
|
type = strrchr(arg, ':');
|
|
|
|
|
if (type) {
|
|
|
|
|
*(type++) = 0;
|
|
|
|
|
version = strrchr(arg, ':');
|
|
|
|
|
if (version) {
|
|
|
|
|
*(version++) = 0;
|
|
|
|
|
hwrevs = strchr(arg, ':');
|
|
|
|
|
if (hwrevs)
|
|
|
|
|
*(hwrevs++) = 0;
|
|
|
|
|
device = arg;
|
|
|
|
|
} else {
|
|
|
|
|
version = arg;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
type = arg;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
file = arg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( layout_file ) {
|
|
|
|
|
off_t len;
|
|
|
|
|
int fd = open(layout_file, O_RDONLY);
|
|
|
|
|
if ( fd < 0 ) {
|
2012-08-10 12:01:14 +02:00
|
|
|
ERROR_INFO("Cannot open layout file %s", layout_file);
|
2012-08-08 21:33:53 +02:00
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
len = lseek(fd, 0, SEEK_END);
|
|
|
|
|
if ( len == (off_t)-1 ) {
|
2012-08-10 12:01:14 +02:00
|
|
|
ERROR_INFO("Cannot get size of file %s", layout_file);
|
2012-08-08 21:33:53 +02:00
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
lseek(fd, 0, SEEK_SET);
|
|
|
|
|
layout = malloc(len);
|
|
|
|
|
if ( ! layout ) {
|
2012-08-09 17:50:50 +02:00
|
|
|
ALLOC_ERROR();
|
2012-08-08 21:33:53 +02:00
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
if ( read(fd, layout, len) != len ) {
|
2012-08-10 12:01:14 +02:00
|
|
|
ERROR_INFO("Cannot read %lu bytes from layout file %s", len, layout_file);
|
2012-08-08 21:33:53 +02:00
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
image = image_alloc_from_file(file, type, device, hwrevs, version, layout);
|
|
|
|
|
|
|
|
|
|
if ( layout )
|
|
|
|
|
free(layout);
|
|
|
|
|
|
|
|
|
|
if ( ! image ) {
|
2012-08-10 12:01:14 +02:00
|
|
|
ERROR("Cannot load image file %s", file);
|
2012-08-08 21:33:53 +02:00
|
|
|
exit(1);
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-09 16:07:48 +02:00
|
|
|
image_list_add(image_first, image);
|
2012-08-08 21:33:53 +02:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-11 09:54:05 +02:00
|
|
|
void filter_images_by_type(enum image_type type, struct image_list ** image_first) {
|
|
|
|
|
|
|
|
|
|
struct image_list * image_ptr = *image_first;
|
|
|
|
|
while ( image_ptr ) {
|
|
|
|
|
struct image_list * next = image_ptr->next;
|
|
|
|
|
if ( image_ptr->image->type != type ) {
|
|
|
|
|
image_list_del(image_ptr);
|
|
|
|
|
if ( image_ptr == *image_first )
|
|
|
|
|
*image_first = next;
|
|
|
|
|
}
|
|
|
|
|
image_ptr = next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void filter_images_by_device(enum device device, struct image_list ** image_first) {
|
|
|
|
|
|
|
|
|
|
struct image_list * image_ptr = *image_first;
|
|
|
|
|
while ( image_ptr ) {
|
|
|
|
|
struct image_list * next = image_ptr->next;
|
2012-09-22 19:49:48 +02:00
|
|
|
struct device_list * device_ptr = image_ptr->image->devices;
|
|
|
|
|
int match = 0;
|
|
|
|
|
while ( device_ptr ) {
|
|
|
|
|
if ( device_ptr->device == device || device_ptr->device == DEVICE_ANY ) {
|
|
|
|
|
match = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
device_ptr = device_ptr->next;
|
|
|
|
|
}
|
|
|
|
|
if ( ! match ) {
|
2012-08-11 09:54:05 +02:00
|
|
|
image_list_del(image_ptr);
|
|
|
|
|
if ( image_ptr == *image_first )
|
|
|
|
|
*image_first = next;
|
|
|
|
|
}
|
|
|
|
|
image_ptr = next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-22 21:23:56 +02:00
|
|
|
void filter_images_by_hwrev(int16_t hwrev, struct image_list ** image_first) {
|
2012-08-11 09:54:05 +02:00
|
|
|
|
|
|
|
|
struct image_list * image_ptr = *image_first;
|
|
|
|
|
while ( image_ptr ) {
|
|
|
|
|
struct image_list * next = image_ptr->next;
|
2012-09-22 21:23:56 +02:00
|
|
|
if ( ! image_hwrev_is_valid(image_ptr->image, hwrev) ) {
|
2012-08-11 09:54:05 +02:00
|
|
|
image_list_del(image_ptr);
|
|
|
|
|
if ( image_ptr == *image_first )
|
|
|
|
|
*image_first = next;
|
|
|
|
|
}
|
|
|
|
|
image_ptr = next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-08 21:33:53 +02:00
|
|
|
int main(int argc, char **argv) {
|
|
|
|
|
|
2012-08-11 11:57:20 +02:00
|
|
|
const char * optstring = ":"
|
2012-08-08 21:33:53 +02:00
|
|
|
#if defined(WITH_USB) && ! defined(WITH_DEVICE)
|
|
|
|
|
"b:rlfc"
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef WITH_DEVICE
|
|
|
|
|
"rfx:E:e:"
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(WITH_USB) || defined(WITH_DEVICE)
|
|
|
|
|
"ID:U:R:F:H:K:N:S:C:"
|
|
|
|
|
#endif
|
|
|
|
|
"M:m:"
|
|
|
|
|
"t:d:w:"
|
|
|
|
|
"u:g:"
|
|
|
|
|
"i"
|
|
|
|
|
#if defined(WITH_USB) || defined(WITH_DEVICE)
|
|
|
|
|
"p"
|
|
|
|
|
#endif
|
|
|
|
|
#if ( defined(WITH_USB) || defined(WITH_DEVICE) ) && defined(WITH_SQUEUES)
|
|
|
|
|
"Q"
|
|
|
|
|
#endif
|
2012-08-09 16:07:48 +02:00
|
|
|
"snvh"
|
2012-08-08 21:33:53 +02:00
|
|
|
"";
|
|
|
|
|
int c;
|
|
|
|
|
|
2012-08-09 16:07:48 +02:00
|
|
|
int ret = 0;
|
2012-08-11 21:37:55 +02:00
|
|
|
int do_something = 0;
|
2012-08-09 16:07:48 +02:00
|
|
|
|
2012-08-10 22:18:33 +02:00
|
|
|
#if defined(WITH_USB) && ! defined(WITH_DEVICE)
|
2012-08-08 21:33:53 +02:00
|
|
|
int dev_boot = 0;
|
|
|
|
|
char * dev_boot_arg = NULL;
|
|
|
|
|
int dev_load = 0;
|
|
|
|
|
int dev_cold_flash = 0;
|
2012-08-10 22:18:33 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#ifdef WITH_DEVICE
|
2012-08-08 21:33:53 +02:00
|
|
|
int dev_check = 0;
|
|
|
|
|
char * dev_check_arg = NULL;
|
|
|
|
|
int dev_dump_fiasco = 0;
|
|
|
|
|
char * dev_dump_fiasco_arg = NULL;
|
|
|
|
|
int dev_dump = 0;
|
|
|
|
|
char * dev_dump_arg = NULL;
|
2012-08-10 22:18:33 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(WITH_USB) || defined(WITH_DEVICE)
|
|
|
|
|
int dev_flash = 0;
|
|
|
|
|
int dev_reboot = 0;
|
2012-08-08 21:33:53 +02:00
|
|
|
int dev_ident = 0;
|
2012-08-10 22:18:33 +02:00
|
|
|
|
2012-08-08 21:33:53 +02:00
|
|
|
int set_root = 0;
|
|
|
|
|
char * set_root_arg = NULL;
|
|
|
|
|
int set_usb = 0;
|
|
|
|
|
char * set_usb_arg = NULL;
|
|
|
|
|
int set_rd = 0;
|
|
|
|
|
char * set_rd_arg = NULL;
|
|
|
|
|
int set_rd_flags = 0;
|
|
|
|
|
char * set_rd_flags_arg = NULL;
|
|
|
|
|
int set_hw = 0;
|
|
|
|
|
char * set_hw_arg = NULL;
|
|
|
|
|
int set_kernel = 0;
|
|
|
|
|
char * set_kernel_arg = NULL;
|
|
|
|
|
int set_nolo = 0;
|
|
|
|
|
char * set_nolo_arg = NULL;
|
|
|
|
|
int set_sw = 0;
|
|
|
|
|
char * set_sw_arg = NULL;
|
|
|
|
|
int set_emmc = 0;
|
|
|
|
|
char * set_emmc_arg = NULL;
|
2012-08-10 22:18:33 +02:00
|
|
|
#endif
|
|
|
|
|
|
2012-08-08 21:33:53 +02:00
|
|
|
int image_fiasco = 0;
|
|
|
|
|
char * image_fiasco_arg = NULL;
|
2012-08-10 22:18:33 +02:00
|
|
|
|
2012-08-08 21:33:53 +02:00
|
|
|
int filter_type = 0;
|
|
|
|
|
char * filter_type_arg = NULL;
|
|
|
|
|
int filter_device = 0;
|
|
|
|
|
char * filter_device_arg = NULL;
|
2012-08-09 16:07:48 +02:00
|
|
|
int filter_hwrev = 0;
|
|
|
|
|
char * filter_hwrev_arg = NULL;
|
2012-08-10 22:18:33 +02:00
|
|
|
|
2012-08-09 16:07:48 +02:00
|
|
|
int fiasco_un = 0;
|
|
|
|
|
char * fiasco_un_arg = NULL;
|
2012-08-08 21:33:53 +02:00
|
|
|
int fiasco_gen = 0;
|
|
|
|
|
char * fiasco_gen_arg = NULL;
|
2012-08-10 22:18:33 +02:00
|
|
|
|
2012-08-08 21:33:53 +02:00
|
|
|
int image_ident = 0;
|
2012-08-10 22:18:33 +02:00
|
|
|
#if defined(WITH_USB) || defined(WITH_DEVICE)
|
2012-08-08 21:33:53 +02:00
|
|
|
int console = 0;
|
2012-08-10 22:18:33 +02:00
|
|
|
#endif
|
|
|
|
|
#if ( defined(WITH_USB) || defined(WITH_DEVICE) ) && defined(WITH_SQUEUES)
|
2012-08-08 21:33:53 +02:00
|
|
|
int queue = 0;
|
2012-08-10 22:18:33 +02:00
|
|
|
#endif
|
2012-08-08 21:33:53 +02:00
|
|
|
|
2012-08-09 16:07:48 +02:00
|
|
|
int help = 0;
|
|
|
|
|
|
|
|
|
|
struct image_list * image_first = NULL;
|
|
|
|
|
struct image_list * image_ptr = NULL;
|
|
|
|
|
|
|
|
|
|
int have_2nd = 0;
|
|
|
|
|
int have_secondary = 0;
|
2012-09-22 11:33:14 +02:00
|
|
|
int have_kernel = 0;
|
|
|
|
|
int have_initfs = 0;
|
2012-08-09 16:07:48 +02:00
|
|
|
struct image * image_2nd = NULL;
|
|
|
|
|
struct image * image_secondary = NULL;
|
2012-09-22 11:33:14 +02:00
|
|
|
struct image * image_kernel = NULL;
|
|
|
|
|
struct image * image_initfs = NULL;
|
2012-08-09 16:07:48 +02:00
|
|
|
|
|
|
|
|
struct fiasco * fiasco_in = NULL;
|
|
|
|
|
struct fiasco * fiasco_out = NULL;
|
|
|
|
|
|
2012-08-09 19:44:47 +02:00
|
|
|
struct usb_device_info * usb_dev = NULL;
|
|
|
|
|
|
2012-08-10 21:23:19 +02:00
|
|
|
char buf[512];
|
|
|
|
|
|
2012-08-08 21:33:53 +02:00
|
|
|
simulate = 0;
|
|
|
|
|
noverify = 0;
|
|
|
|
|
verbose = 0;
|
|
|
|
|
|
|
|
|
|
show_title();
|
|
|
|
|
|
2012-08-11 11:57:20 +02:00
|
|
|
opterr = 0;
|
|
|
|
|
|
2012-08-08 21:33:53 +02:00
|
|
|
while ( ( c = getopt(argc, argv, optstring) ) != -1 ) {
|
|
|
|
|
|
2012-08-09 17:50:50 +02:00
|
|
|
switch (c) {
|
2012-08-11 11:57:20 +02:00
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
ERROR("Unknown option '%c'", c);
|
|
|
|
|
ret = 1;
|
|
|
|
|
goto clean;
|
|
|
|
|
|
|
|
|
|
case '?':
|
|
|
|
|
ERROR("Unknown option '%c'", optopt);
|
|
|
|
|
ret = 1;
|
|
|
|
|
goto clean;
|
|
|
|
|
|
|
|
|
|
case ':':
|
|
|
|
|
#if defined(WITH_USB) && ! defined(WITH_DEVICE)
|
|
|
|
|
if ( optopt == 'b' ) {
|
|
|
|
|
dev_boot = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef WITH_DEVICE
|
|
|
|
|
if ( optopt == 'e' ) {
|
|
|
|
|
dev_dump = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
if ( optopt == 'u' ) {
|
|
|
|
|
fiasco_un = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
ERROR("Option '%c' requires an argument", optopt);
|
|
|
|
|
ret = 1;
|
|
|
|
|
goto clean;
|
|
|
|
|
|
2012-08-10 22:18:33 +02:00
|
|
|
#if defined(WITH_USB) && ! defined(WITH_DEVICE)
|
2012-08-08 21:33:53 +02:00
|
|
|
case 'b':
|
|
|
|
|
dev_boot = 1;
|
2012-08-11 11:57:20 +02:00
|
|
|
if ( optarg[0] != '-' )
|
|
|
|
|
dev_boot_arg = optarg;
|
|
|
|
|
else
|
|
|
|
|
--optind;
|
2012-08-08 21:33:53 +02:00
|
|
|
break;
|
|
|
|
|
case 'l':
|
|
|
|
|
dev_load = 1;
|
|
|
|
|
break;
|
|
|
|
|
case 'c':
|
|
|
|
|
dev_cold_flash = 1;
|
|
|
|
|
break;
|
2012-08-10 22:18:33 +02:00
|
|
|
#endif
|
2012-08-08 21:33:53 +02:00
|
|
|
|
2012-08-10 22:18:33 +02:00
|
|
|
#ifdef WITH_DEVICE
|
2012-08-08 21:33:53 +02:00
|
|
|
case 'x':
|
|
|
|
|
dev_check = 1;
|
|
|
|
|
dev_check_arg = optarg;
|
|
|
|
|
break;
|
|
|
|
|
case 'E':
|
|
|
|
|
dev_dump_fiasco = 1;
|
|
|
|
|
dev_dump_fiasco_arg = optarg;
|
|
|
|
|
break;
|
|
|
|
|
case 'e':
|
|
|
|
|
dev_dump = 1;
|
2012-08-11 11:57:20 +02:00
|
|
|
if ( optarg[0] != '-' )
|
|
|
|
|
dev_dump_arg = optarg;
|
|
|
|
|
else
|
|
|
|
|
--optind;
|
2012-08-08 21:33:53 +02:00
|
|
|
break;
|
2012-08-10 22:18:33 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#if defined(WITH_USB) || defined(WITH_DEVICE)
|
|
|
|
|
case 'f':
|
|
|
|
|
dev_flash = 1;
|
|
|
|
|
break;
|
|
|
|
|
case 'r':
|
|
|
|
|
dev_reboot = 1;
|
|
|
|
|
break;
|
2012-08-08 21:33:53 +02:00
|
|
|
|
|
|
|
|
case 'I':
|
|
|
|
|
dev_ident = 1;
|
|
|
|
|
break;
|
|
|
|
|
case 'D':
|
|
|
|
|
set_root = 1;
|
|
|
|
|
set_root_arg = optarg;
|
|
|
|
|
break;
|
|
|
|
|
case 'U':
|
|
|
|
|
set_usb = 1;
|
|
|
|
|
set_usb_arg = optarg;
|
|
|
|
|
break;
|
|
|
|
|
case 'R':
|
|
|
|
|
set_rd = 1;
|
|
|
|
|
set_rd_arg = optarg;
|
|
|
|
|
break;
|
|
|
|
|
case 'F':
|
|
|
|
|
set_rd_flags = 1;
|
|
|
|
|
set_rd_flags_arg = optarg;
|
|
|
|
|
break;
|
|
|
|
|
case 'H':
|
|
|
|
|
set_hw = 1;
|
|
|
|
|
set_hw_arg = optarg;
|
|
|
|
|
break;
|
|
|
|
|
case 'K':
|
|
|
|
|
set_kernel = 1;
|
|
|
|
|
set_kernel_arg = optarg;
|
|
|
|
|
break;
|
|
|
|
|
case 'N':
|
|
|
|
|
set_nolo = 1;
|
|
|
|
|
set_nolo_arg = optarg;
|
|
|
|
|
break;
|
|
|
|
|
case 'S':
|
|
|
|
|
set_sw = 1;
|
|
|
|
|
set_sw_arg = optarg;
|
|
|
|
|
break;
|
|
|
|
|
case 'C':
|
|
|
|
|
set_emmc = 1;
|
|
|
|
|
set_emmc_arg = optarg;
|
|
|
|
|
break;
|
2012-08-10 22:18:33 +02:00
|
|
|
#endif
|
2012-08-08 21:33:53 +02:00
|
|
|
|
|
|
|
|
case 'M':
|
|
|
|
|
image_fiasco = 1;
|
|
|
|
|
image_fiasco_arg = optarg;
|
|
|
|
|
break;
|
|
|
|
|
case 'm':
|
2012-08-09 16:07:48 +02:00
|
|
|
parse_image_arg(optarg, &image_first);
|
2012-08-08 21:33:53 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 't':
|
|
|
|
|
filter_type = 1;
|
|
|
|
|
filter_type_arg = optarg;
|
|
|
|
|
break;
|
|
|
|
|
case 'd':
|
|
|
|
|
filter_device = 1;
|
|
|
|
|
filter_device_arg = optarg;
|
|
|
|
|
break;
|
|
|
|
|
case 'w':
|
2012-08-09 16:07:48 +02:00
|
|
|
filter_hwrev = 1;
|
|
|
|
|
filter_hwrev_arg = optarg;
|
2012-08-08 21:33:53 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'u':
|
2012-08-09 16:07:48 +02:00
|
|
|
fiasco_un = 1;
|
|
|
|
|
fiasco_un_arg = optarg;
|
2012-08-08 21:33:53 +02:00
|
|
|
break;
|
|
|
|
|
case 'g':
|
|
|
|
|
fiasco_gen = 1;
|
2012-08-11 11:57:20 +02:00
|
|
|
if ( optarg[0] != '-' )
|
|
|
|
|
fiasco_gen_arg = optarg;
|
|
|
|
|
else
|
|
|
|
|
--optind;
|
2012-08-08 21:33:53 +02:00
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'i':
|
|
|
|
|
image_ident = 1;
|
|
|
|
|
break;
|
2012-08-10 22:18:33 +02:00
|
|
|
#if defined(WITH_USB) || defined(WITH_DEVICE)
|
2012-08-08 21:33:53 +02:00
|
|
|
case 'p':
|
|
|
|
|
console = 1;
|
|
|
|
|
break;
|
2012-08-10 22:18:33 +02:00
|
|
|
#endif
|
|
|
|
|
#if ( defined(WITH_USB) || defined(WITH_DEVICE) ) && defined(WITH_SQUEUES)
|
2012-08-08 21:33:53 +02:00
|
|
|
case 'Q':
|
|
|
|
|
queue = 1;
|
|
|
|
|
break;
|
2012-08-10 22:18:33 +02:00
|
|
|
#endif
|
2012-08-08 21:33:53 +02:00
|
|
|
|
|
|
|
|
case 's':
|
|
|
|
|
simulate = 1;
|
|
|
|
|
break;
|
|
|
|
|
case 'n':
|
|
|
|
|
noverify = 1;
|
|
|
|
|
break;
|
|
|
|
|
case 'v':
|
|
|
|
|
verbose = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case 'h':
|
|
|
|
|
help = 1;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-11 11:57:20 +02:00
|
|
|
if ( optind < argc ) {
|
|
|
|
|
ERROR("Extra argument '%s'", argv[optind]);
|
|
|
|
|
ret = 1;
|
|
|
|
|
goto clean;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-11 21:37:55 +02:00
|
|
|
#if defined(WITH_USB) && ! defined(WITH_DEVICE)
|
|
|
|
|
if ( dev_boot || dev_load || dev_cold_flash )
|
|
|
|
|
do_something = 1;
|
|
|
|
|
#endif
|
|
|
|
|
#ifdef WITH_DEVICE
|
|
|
|
|
if ( dev_check || dev_dump_fiasco || dev_dump )
|
|
|
|
|
do_something = 1;
|
|
|
|
|
#endif
|
|
|
|
|
#if defined(WITH_USB) || defined(WITH_DEVICE)
|
|
|
|
|
if ( dev_flash || dev_reboot || dev_ident || set_root || set_usb || set_rd || set_rd_flags || set_hw || set_kernel || set_nolo || set_sw || set_emmc )
|
|
|
|
|
do_something = 1;
|
|
|
|
|
#endif
|
|
|
|
|
if ( fiasco_un || fiasco_gen || image_ident )
|
|
|
|
|
do_something = 1;
|
|
|
|
|
#if defined(WITH_USB) || defined(WITH_DEVICE)
|
|
|
|
|
if ( console )
|
|
|
|
|
do_something = 1;
|
|
|
|
|
#endif
|
|
|
|
|
#if ( defined(WITH_USB) || defined(WITH_DEVICE) ) && defined(WITH_SQUEUES)
|
|
|
|
|
if ( queue )
|
|
|
|
|
do_something = 1;
|
|
|
|
|
#endif
|
|
|
|
|
if ( help )
|
|
|
|
|
do_something = 1;
|
|
|
|
|
|
|
|
|
|
if ( ! do_something ) {
|
|
|
|
|
ERROR("Nothing to do");
|
|
|
|
|
ret = 1;
|
|
|
|
|
goto clean;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
printf("\n");
|
|
|
|
|
|
2012-08-09 16:07:48 +02:00
|
|
|
/* help */
|
2012-08-08 21:33:53 +02:00
|
|
|
if ( help ) {
|
|
|
|
|
show_usage();
|
2012-08-09 16:07:48 +02:00
|
|
|
ret = 0;
|
|
|
|
|
goto clean;
|
2012-08-08 21:33:53 +02:00
|
|
|
}
|
|
|
|
|
|
2012-08-10 22:18:33 +02:00
|
|
|
#if defined(WITH_USB) || defined(WITH_DEVICE)
|
2012-08-08 21:33:53 +02:00
|
|
|
/* console */
|
|
|
|
|
if ( console ) {
|
2012-08-10 12:19:28 +02:00
|
|
|
console_prompt();
|
2012-08-09 16:07:48 +02:00
|
|
|
ret = 0;
|
|
|
|
|
goto clean;
|
2012-08-08 21:33:53 +02:00
|
|
|
}
|
2012-08-10 22:18:33 +02:00
|
|
|
#endif
|
2012-08-08 21:33:53 +02:00
|
|
|
|
2012-08-10 22:18:33 +02:00
|
|
|
#if ( defined(WITH_USB) || defined(WITH_DEVICE) ) && defined(WITH_SQUEUES)
|
2012-08-08 21:33:53 +02:00
|
|
|
/* share queues */
|
|
|
|
|
if ( queue ) {
|
2012-08-10 12:19:28 +02:00
|
|
|
queue_mode();
|
2012-08-09 16:07:48 +02:00
|
|
|
ret = 0;
|
|
|
|
|
goto clean;
|
2012-08-08 21:33:53 +02:00
|
|
|
}
|
2012-08-10 22:18:33 +02:00
|
|
|
#endif
|
2012-08-08 21:33:53 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
/* load images from files */
|
|
|
|
|
if ( image_first && image_fiasco ) {
|
2012-08-10 12:01:14 +02:00
|
|
|
ERROR("Cannot specify normal and fiasco images together");
|
2012-08-09 16:07:48 +02:00
|
|
|
ret = 1;
|
|
|
|
|
goto clean;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* load fiasco image */
|
|
|
|
|
if ( image_fiasco ) {
|
|
|
|
|
fiasco_in = fiasco_alloc_from_file(image_fiasco_arg);
|
2012-09-22 20:56:28 +02:00
|
|
|
if ( ! fiasco_in ) {
|
2012-08-10 12:01:14 +02:00
|
|
|
ERROR("Cannot load fiasco image file %s", image_fiasco_arg);
|
2012-09-22 20:56:28 +02:00
|
|
|
ret = 1;
|
|
|
|
|
goto clean;
|
|
|
|
|
}
|
|
|
|
|
image_first = fiasco_in->first;
|
2012-08-09 16:07:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* filter images by type */
|
|
|
|
|
if ( filter_type ) {
|
|
|
|
|
enum image_type type = image_type_from_string(filter_type_arg);
|
2012-09-22 20:56:28 +02:00
|
|
|
if ( ! type ) {
|
2012-08-10 12:01:14 +02:00
|
|
|
ERROR("Specified unknown image type for filtering: %s", filter_type_arg);
|
2012-09-22 20:56:28 +02:00
|
|
|
ret = 1;
|
|
|
|
|
goto clean;
|
|
|
|
|
}
|
|
|
|
|
filter_images_by_type(type, &image_first);
|
2012-08-09 16:07:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* filter images by device */
|
|
|
|
|
if ( filter_device ) {
|
|
|
|
|
enum device device = device_from_string(filter_device_arg);
|
2012-09-22 20:56:28 +02:00
|
|
|
if ( ! device ) {
|
2012-08-10 12:01:14 +02:00
|
|
|
ERROR("Specified unknown device for filtering: %s", filter_device_arg);
|
2012-09-22 20:56:28 +02:00
|
|
|
ret = 1;
|
|
|
|
|
goto clean;
|
|
|
|
|
}
|
|
|
|
|
filter_images_by_device(device, &image_first);
|
2012-08-09 16:07:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* filter images by hwrev */
|
2012-08-11 09:54:05 +02:00
|
|
|
if ( filter_hwrev )
|
2012-09-22 21:23:56 +02:00
|
|
|
filter_images_by_hwrev(atoi(filter_hwrev_arg), &image_first);
|
2012-08-08 21:33:53 +02:00
|
|
|
|
2012-08-09 16:07:48 +02:00
|
|
|
/* reorder images for flashing (first x-loader, second secondary) */
|
|
|
|
|
/* set 2nd and secondary images for cold-flashing */
|
|
|
|
|
if ( dev_flash || dev_cold_flash ) {
|
|
|
|
|
|
|
|
|
|
struct image_list * image_unorder_first;
|
|
|
|
|
|
|
|
|
|
image_unorder_first = image_first;
|
|
|
|
|
image_first = NULL;
|
|
|
|
|
|
|
|
|
|
image_ptr = image_unorder_first;
|
|
|
|
|
while ( image_ptr ) {
|
|
|
|
|
struct image_list * next = image_ptr->next;
|
|
|
|
|
if ( image_ptr->image->type == IMAGE_XLOADER ) {
|
|
|
|
|
image_list_add(&image_first, image_ptr->image);
|
|
|
|
|
image_list_unlink(image_ptr);
|
|
|
|
|
free(image_ptr);
|
|
|
|
|
if ( image_ptr == image_unorder_first )
|
2012-09-22 11:32:41 +02:00
|
|
|
image_unorder_first = next;
|
2012-08-09 16:07:48 +02:00
|
|
|
}
|
|
|
|
|
image_ptr = next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
image_ptr = image_unorder_first;
|
|
|
|
|
while ( image_ptr ) {
|
|
|
|
|
struct image_list * next = image_ptr->next;
|
|
|
|
|
if ( image_ptr->image->type == IMAGE_SECONDARY ) {
|
|
|
|
|
if ( have_secondary == 0 ) {
|
|
|
|
|
image_secondary = image_ptr->image;
|
|
|
|
|
have_secondary = 1;
|
|
|
|
|
} else if ( have_secondary == 1 ) {
|
|
|
|
|
image_secondary = NULL;
|
|
|
|
|
have_secondary = 2;
|
|
|
|
|
}
|
|
|
|
|
image_list_add(&image_first, image_ptr->image);
|
|
|
|
|
image_list_unlink(image_ptr);
|
|
|
|
|
free(image_ptr);
|
|
|
|
|
if ( image_ptr == image_unorder_first )
|
2012-09-22 11:32:41 +02:00
|
|
|
image_unorder_first = next;
|
2012-08-09 16:07:48 +02:00
|
|
|
}
|
|
|
|
|
image_ptr = next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
image_ptr = image_unorder_first;
|
|
|
|
|
while ( image_ptr ) {
|
|
|
|
|
struct image_list * next = image_ptr->next;
|
|
|
|
|
if ( image_ptr->image->type == IMAGE_2ND ) {
|
|
|
|
|
if ( have_2nd == 0 ) {
|
|
|
|
|
image_2nd = image_ptr->image;
|
|
|
|
|
have_2nd = 1;
|
|
|
|
|
} else if ( have_2nd == 1 ) {
|
|
|
|
|
image_2nd = NULL;
|
|
|
|
|
have_2nd = 2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
image_list_add(&image_first, image_ptr->image);
|
|
|
|
|
image_list_unlink(image_ptr);
|
|
|
|
|
free(image_ptr);
|
|
|
|
|
if ( image_ptr == image_unorder_first )
|
2012-09-22 11:32:41 +02:00
|
|
|
image_unorder_first = next;
|
2012-08-09 16:07:48 +02:00
|
|
|
image_ptr = next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* make sure that fiasco_in has valid images*/
|
|
|
|
|
if ( fiasco_in )
|
|
|
|
|
fiasco_in->first = image_first;
|
2012-08-08 21:33:53 +02:00
|
|
|
|
|
|
|
|
/* identificate images */
|
|
|
|
|
if ( image_ident ) {
|
2012-08-09 16:07:48 +02:00
|
|
|
if ( fiasco_in ) {
|
|
|
|
|
fiasco_print_info(fiasco_in);
|
|
|
|
|
printf("\n");
|
2012-08-09 19:44:47 +02:00
|
|
|
} else if ( ! image_first ) {
|
2012-08-10 12:01:14 +02:00
|
|
|
ERROR("No image specified");
|
2012-08-09 19:44:47 +02:00
|
|
|
ret = 1;
|
|
|
|
|
goto clean;
|
2012-08-09 16:07:48 +02:00
|
|
|
}
|
|
|
|
|
for ( image_ptr = image_first; image_ptr; image_ptr = image_ptr->next ) {
|
|
|
|
|
image_print_info(image_ptr->image);
|
|
|
|
|
printf("\n");
|
|
|
|
|
}
|
|
|
|
|
ret = 0;
|
|
|
|
|
goto clean;
|
2012-08-08 21:33:53 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* unpack fiasco */
|
2012-08-11 11:57:20 +02:00
|
|
|
if ( fiasco_un ) {
|
|
|
|
|
if ( ! fiasco_in ) {
|
|
|
|
|
ERROR("No fiasco image specified");
|
|
|
|
|
ret = 1;
|
|
|
|
|
goto clean;
|
|
|
|
|
}
|
2012-08-09 16:07:48 +02:00
|
|
|
fiasco_unpack(fiasco_in, fiasco_un_arg);
|
2012-08-11 11:57:20 +02:00
|
|
|
}
|
2012-08-09 16:07:48 +02:00
|
|
|
|
|
|
|
|
/* remove unknown images */
|
|
|
|
|
image_ptr = image_first;
|
|
|
|
|
while ( image_ptr ) {
|
|
|
|
|
struct image_list * next = image_ptr->next;
|
2012-09-22 19:49:48 +02:00
|
|
|
if ( image_ptr->image->type == IMAGE_UNKNOWN ) {
|
2012-08-09 17:50:50 +02:00
|
|
|
WARNING("Removing unknown image (specified by %s %s)", image_ptr->image->orig_filename ? "file" : "fiasco", image_ptr->image->orig_filename ? image_ptr->image->orig_filename : "image");
|
2012-08-09 16:07:48 +02:00
|
|
|
image_list_unlink(image_ptr);
|
|
|
|
|
free(image_ptr);
|
|
|
|
|
if ( image_ptr == image_first )
|
|
|
|
|
image_first = next;
|
|
|
|
|
}
|
|
|
|
|
image_ptr = next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* make sure that fiasco_in has valid images */
|
|
|
|
|
if ( fiasco_in )
|
|
|
|
|
fiasco_in->first = image_first;
|
2012-08-08 21:33:53 +02:00
|
|
|
|
|
|
|
|
/* generate fiasco */
|
2012-08-09 16:07:48 +02:00
|
|
|
if ( fiasco_gen ) {
|
2012-08-09 17:50:50 +02:00
|
|
|
char * swver = strchr(fiasco_gen_arg, '%');
|
|
|
|
|
if ( swver )
|
|
|
|
|
*(swver++) = 0;
|
2012-08-09 16:07:48 +02:00
|
|
|
fiasco_out = fiasco_alloc_empty();
|
|
|
|
|
if ( ! fiasco_out ) {
|
2012-08-10 12:01:14 +02:00
|
|
|
ERROR("Cannot write images to fiasco file %s", fiasco_gen_arg);
|
2012-08-09 16:07:48 +02:00
|
|
|
} else {
|
2012-08-09 17:50:50 +02:00
|
|
|
if ( swver )
|
|
|
|
|
strcpy(fiasco_out->swver, swver);
|
2012-08-09 16:07:48 +02:00
|
|
|
fiasco_out->first = image_first;
|
|
|
|
|
fiasco_write_to_file(fiasco_out, fiasco_gen_arg);
|
|
|
|
|
fiasco_out->first = NULL;
|
|
|
|
|
fiasco_free(fiasco_out);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2012-08-09 19:44:47 +02:00
|
|
|
#if defined(WITH_USB) && ! defined(WITH_DEVICE)
|
2012-08-09 16:07:48 +02:00
|
|
|
|
|
|
|
|
/* over usb */
|
2012-08-08 21:33:53 +02:00
|
|
|
|
2012-08-09 19:44:47 +02:00
|
|
|
if ( dev_cold_flash ) {
|
|
|
|
|
if ( have_2nd == 0 ) {
|
2012-08-10 12:01:14 +02:00
|
|
|
ERROR("2nd image for Cold Flashing was not specified");
|
2012-08-09 19:44:47 +02:00
|
|
|
ret = 1;
|
|
|
|
|
goto clean;
|
|
|
|
|
} else if ( have_2nd == 2 ) {
|
2012-08-10 12:01:14 +02:00
|
|
|
ERROR("More 2nd images for Cold Flashing was specified");
|
2012-08-09 19:44:47 +02:00
|
|
|
ret = 1;
|
|
|
|
|
goto clean;
|
|
|
|
|
}
|
2012-08-08 21:33:53 +02:00
|
|
|
|
2012-08-09 19:44:47 +02:00
|
|
|
if ( have_secondary == 0 ) {
|
2012-08-10 12:01:14 +02:00
|
|
|
ERROR("Secondary image for Cold Flashing was not specified");
|
2012-08-09 19:44:47 +02:00
|
|
|
ret = 1;
|
|
|
|
|
goto clean;
|
|
|
|
|
} else if ( have_secondary == 2 ) {
|
2012-08-10 12:01:14 +02:00
|
|
|
ERROR("More Secondary images for Cold Flashing was specified");
|
2012-08-09 19:44:47 +02:00
|
|
|
ret = 1;
|
|
|
|
|
goto clean;
|
|
|
|
|
}
|
|
|
|
|
}
|
2012-08-08 21:33:53 +02:00
|
|
|
|
2012-08-11 09:54:05 +02:00
|
|
|
if ( dev_load && dev_flash ) {
|
|
|
|
|
ERROR("Options load and flash cannot de used together");
|
|
|
|
|
ret = 1;
|
|
|
|
|
goto clean;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-22 11:33:14 +02:00
|
|
|
if ( dev_load && ! image_first ) {
|
|
|
|
|
ERROR("No image specified for loading");
|
|
|
|
|
ret = 1;
|
|
|
|
|
goto clean;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( dev_flash && ! image_first ) {
|
|
|
|
|
ERROR("No image specified for flashing");
|
|
|
|
|
ret = 1;
|
|
|
|
|
goto clean;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-10 17:19:03 +02:00
|
|
|
if ( dev_boot || dev_reboot || dev_load || dev_flash || dev_cold_flash || dev_ident || set_root || set_usb || set_rd || set_rd_flags || set_hw || set_kernel || set_nolo || set_sw || set_emmc ) {
|
2012-08-08 21:33:53 +02:00
|
|
|
|
2012-08-11 15:25:28 +02:00
|
|
|
int again = 1;
|
|
|
|
|
|
|
|
|
|
while ( again ) {
|
|
|
|
|
|
|
|
|
|
again = 0;
|
2012-08-08 21:33:53 +02:00
|
|
|
|
2012-08-10 17:19:03 +02:00
|
|
|
usb_dev = usb_open_and_wait_for_device();
|
2012-08-08 21:33:53 +02:00
|
|
|
|
2012-08-10 17:19:03 +02:00
|
|
|
/* cold flash */
|
|
|
|
|
if ( dev_cold_flash ) {
|
2012-08-09 19:44:47 +02:00
|
|
|
|
2012-08-10 17:19:03 +02:00
|
|
|
ret = cold_flash(usb_dev, image_2nd, image_secondary);
|
|
|
|
|
usb_close_device(usb_dev);
|
|
|
|
|
usb_dev = NULL;
|
2012-08-10 14:56:38 +02:00
|
|
|
|
2012-09-22 11:32:41 +02:00
|
|
|
if ( ret == -EAGAIN ) {
|
2012-08-11 15:25:28 +02:00
|
|
|
again = 1;
|
2012-08-10 17:19:03 +02:00
|
|
|
continue;
|
2012-08-11 15:25:28 +02:00
|
|
|
}
|
2012-08-09 19:44:47 +02:00
|
|
|
|
2012-08-11 10:39:52 +02:00
|
|
|
if ( ret != 0 )
|
|
|
|
|
goto clean;
|
|
|
|
|
|
2012-08-10 17:19:03 +02:00
|
|
|
if ( dev_flash ) {
|
|
|
|
|
dev_cold_flash = 0;
|
2012-08-11 15:25:28 +02:00
|
|
|
again = 1;
|
2012-08-10 17:19:03 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
2012-08-09 19:44:47 +02:00
|
|
|
|
2012-08-10 17:19:03 +02:00
|
|
|
break;
|
2012-08-09 19:44:47 +02:00
|
|
|
|
2012-08-10 17:19:03 +02:00
|
|
|
}
|
|
|
|
|
|
2012-08-11 15:25:28 +02:00
|
|
|
if ( usb_dev->flash_device->protocol == FLASH_COLD ) {
|
|
|
|
|
leave_cold_flash(usb_dev);
|
|
|
|
|
usb_close_device(usb_dev);
|
|
|
|
|
usb_dev = NULL;
|
|
|
|
|
again = 1;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-10 21:27:18 +02:00
|
|
|
if ( usb_dev->flash_device->protocol != FLASH_NOLO ) {
|
|
|
|
|
printf("Only NOLO protocol is supported now\n");
|
|
|
|
|
usb_close_device(usb_dev);
|
|
|
|
|
usb_dev = NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-10 21:23:19 +02:00
|
|
|
if ( nolo_init(usb_dev) < 0 ) {
|
|
|
|
|
printf("Cannot initialize NOLO\n");
|
|
|
|
|
usb_close_device(usb_dev);
|
|
|
|
|
usb_dev = NULL;
|
2012-08-11 15:25:28 +02:00
|
|
|
again = 1;
|
2012-08-10 21:23:19 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
usb_dev->detected_device = nolo_get_device(usb_dev);
|
2012-08-11 09:54:05 +02:00
|
|
|
if ( ! usb_dev->detected_device )
|
|
|
|
|
printf("Device: (not detected)\n");
|
|
|
|
|
else
|
|
|
|
|
printf("Device: %s\n", device_to_string(usb_dev->detected_device));
|
2012-08-10 21:23:19 +02:00
|
|
|
|
2012-08-11 09:54:05 +02:00
|
|
|
buf[0] = 0;
|
|
|
|
|
nolo_get_hwrev(usb_dev, buf, sizeof(buf));
|
|
|
|
|
printf("HW revision: %s\n", buf[0] ? buf : "(not detected)");
|
2012-08-10 21:23:19 +02:00
|
|
|
|
2012-08-11 09:54:05 +02:00
|
|
|
if ( buf[0] )
|
2012-09-22 21:23:56 +02:00
|
|
|
usb_dev->detected_hwrev = atoi(buf);
|
2012-08-10 21:23:19 +02:00
|
|
|
|
2012-08-10 21:27:18 +02:00
|
|
|
buf[0] = 0;
|
|
|
|
|
nolo_get_nolo_ver(usb_dev, buf, sizeof(buf));
|
|
|
|
|
printf("NOLO version: %s\n", buf[0] ? buf : "(not detected)");
|
|
|
|
|
|
2012-08-10 21:54:37 +02:00
|
|
|
buf[0] = 0;
|
|
|
|
|
nolo_get_kernel_ver(usb_dev, buf, sizeof(buf));
|
|
|
|
|
printf("Kernel version: %s\n", buf[0] ? buf : "(not detected)");
|
|
|
|
|
|
2012-08-10 21:23:19 +02:00
|
|
|
buf[0] = 0;
|
|
|
|
|
nolo_get_sw_ver(usb_dev, buf, sizeof(buf));
|
|
|
|
|
printf("Software release version: %s\n", buf[0] ? buf : "(not detected)");
|
2012-08-09 19:44:47 +02:00
|
|
|
|
2012-08-10 21:54:37 +02:00
|
|
|
buf[0] = 0;
|
|
|
|
|
nolo_get_content_ver(usb_dev, buf, sizeof(buf));
|
|
|
|
|
printf("Content eMMC version: %s\n", buf[0] ? buf : "(not detected)");
|
|
|
|
|
|
|
|
|
|
ret = nolo_get_root_device(usb_dev);
|
|
|
|
|
printf("Root device: ");
|
|
|
|
|
if ( ret == 0 )
|
|
|
|
|
printf("flash");
|
|
|
|
|
else if ( ret == 1 )
|
|
|
|
|
printf("mmc");
|
|
|
|
|
else if ( ret == 2 )
|
|
|
|
|
printf("usb");
|
|
|
|
|
else
|
|
|
|
|
printf("(not detected)");
|
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
|
|
ret = nolo_get_usb_host_mode(usb_dev);
|
|
|
|
|
printf("USB host mode: ");
|
|
|
|
|
if ( ret == 0 )
|
|
|
|
|
printf("disabled");
|
|
|
|
|
else if ( ret == 1 )
|
|
|
|
|
printf("enabled");
|
|
|
|
|
else
|
|
|
|
|
printf("(not detected)");
|
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
|
|
ret = nolo_get_rd_mode(usb_dev);
|
|
|
|
|
printf("R&D mode: ");
|
|
|
|
|
if ( ret == 0 )
|
|
|
|
|
printf("disabled");
|
|
|
|
|
else if ( ret == 1 )
|
|
|
|
|
printf("enabled");
|
|
|
|
|
else
|
|
|
|
|
printf("(not detected)");
|
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
|
|
if ( ret == 1 ) {
|
|
|
|
|
ret = nolo_get_rd_flags(usb_dev, buf, sizeof(buf));
|
|
|
|
|
printf("R&D flags: ");
|
|
|
|
|
if ( ret < 0 )
|
|
|
|
|
printf("(not detected)");
|
|
|
|
|
else
|
|
|
|
|
printf("%s", buf);
|
|
|
|
|
printf("\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* device identify */
|
|
|
|
|
if ( dev_ident ) {
|
|
|
|
|
usb_close_device(usb_dev);
|
|
|
|
|
usb_dev = NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-10 22:18:33 +02:00
|
|
|
printf("\n");
|
|
|
|
|
|
2012-08-11 09:54:05 +02:00
|
|
|
/* filter images by device & hwrev */
|
|
|
|
|
if ( usb_dev->detected_device )
|
|
|
|
|
filter_images_by_device(usb_dev->detected_device, &image_first);
|
|
|
|
|
if ( usb_dev->detected_hwrev )
|
|
|
|
|
filter_images_by_hwrev(usb_dev->detected_hwrev, &image_first);
|
|
|
|
|
|
2012-09-22 11:33:14 +02:00
|
|
|
/* set kernel and initfs images for loading */
|
|
|
|
|
if ( dev_load ) {
|
|
|
|
|
image_ptr = image_first;
|
|
|
|
|
while ( image_ptr ) {
|
|
|
|
|
struct image_list * next = image_ptr->next;
|
|
|
|
|
if ( image_ptr->image->type == IMAGE_KERNEL ) {
|
|
|
|
|
if ( have_kernel == 0 ) {
|
|
|
|
|
image_kernel = image_ptr->image;
|
|
|
|
|
have_kernel = 1;
|
|
|
|
|
} else if ( have_kernel == 1 ) {
|
|
|
|
|
image_kernel = NULL;
|
|
|
|
|
have_kernel = 2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
image_ptr = next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
image_ptr = image_first;
|
|
|
|
|
while ( image_ptr ) {
|
|
|
|
|
struct image_list * next = image_ptr->next;
|
|
|
|
|
if ( image_ptr->image->type == IMAGE_INITFS ) {
|
|
|
|
|
if ( have_initfs == 0 ) {
|
|
|
|
|
image_initfs = image_ptr->image;
|
|
|
|
|
have_initfs = 1;
|
|
|
|
|
} else if ( have_initfs == 1 ) {
|
|
|
|
|
image_initfs = NULL;
|
|
|
|
|
have_initfs = 2;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
image_ptr = next;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( have_kernel == 2 ) {
|
|
|
|
|
ERROR("More Kernel images for loading was specified");
|
|
|
|
|
ret = 1;
|
|
|
|
|
goto clean;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( have_initfs == 2 ) {
|
|
|
|
|
ERROR("More Initfs images for loading was specified");
|
|
|
|
|
ret = 1;
|
|
|
|
|
goto clean;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( have_kernel == 0 && have_initfs == 0 ) {
|
|
|
|
|
ERROR("Kernel image or Initfs image for loading was not specified");
|
|
|
|
|
ret = 1;
|
|
|
|
|
goto clean;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-10 22:09:31 +02:00
|
|
|
/* load */
|
2012-08-11 09:54:05 +02:00
|
|
|
if ( dev_load ) {
|
2012-09-22 11:33:14 +02:00
|
|
|
if ( image_kernel )
|
|
|
|
|
nolo_load_image(usb_dev, image_kernel);
|
|
|
|
|
if ( image_initfs )
|
|
|
|
|
nolo_load_image(usb_dev, image_initfs);
|
2012-08-11 09:54:05 +02:00
|
|
|
}
|
2012-08-10 22:09:31 +02:00
|
|
|
|
2012-08-10 17:19:03 +02:00
|
|
|
/* flash */
|
2012-09-22 11:33:14 +02:00
|
|
|
if ( dev_flash ) {
|
|
|
|
|
image_ptr = image_first;
|
|
|
|
|
while ( image_ptr ) {
|
|
|
|
|
struct image_list * next = image_ptr->next;
|
|
|
|
|
nolo_flash_image(usb_dev, image_ptr->image);
|
|
|
|
|
image_ptr = next;
|
|
|
|
|
}
|
2012-08-11 09:54:05 +02:00
|
|
|
}
|
2012-08-09 19:44:47 +02:00
|
|
|
|
2012-08-10 17:19:03 +02:00
|
|
|
/* configuration */
|
2012-08-10 22:09:31 +02:00
|
|
|
if ( set_rd_flags ) {
|
|
|
|
|
set_rd = 1;
|
|
|
|
|
set_rd_arg = "1";
|
|
|
|
|
}
|
|
|
|
|
if ( set_root )
|
|
|
|
|
nolo_set_root_device(usb_dev, atoi(set_root_arg));
|
|
|
|
|
if ( set_usb )
|
|
|
|
|
nolo_set_usb_host_mode(usb_dev, atoi(set_usb_arg));
|
|
|
|
|
if ( set_rd )
|
|
|
|
|
nolo_set_rd_mode(usb_dev, atoi(set_rd_arg));
|
|
|
|
|
if ( set_rd_flags )
|
|
|
|
|
nolo_set_rd_flags(usb_dev, set_rd_flags_arg);
|
|
|
|
|
if ( set_hw )
|
|
|
|
|
nolo_set_hwrev(usb_dev, set_hw_arg);
|
|
|
|
|
if ( set_nolo )
|
|
|
|
|
nolo_set_nolo_ver(usb_dev, set_nolo_arg);
|
|
|
|
|
if ( set_kernel )
|
|
|
|
|
nolo_set_kernel_ver(usb_dev, set_kernel_arg);
|
|
|
|
|
if ( set_sw )
|
|
|
|
|
nolo_set_sw_ver(usb_dev, set_sw_arg);
|
|
|
|
|
if ( set_emmc )
|
|
|
|
|
nolo_set_content_ver(usb_dev, set_emmc_arg);
|
2012-08-09 19:44:47 +02:00
|
|
|
|
2012-08-10 17:19:03 +02:00
|
|
|
/* boot */
|
2012-08-10 21:23:19 +02:00
|
|
|
if ( dev_boot ) {
|
2012-08-11 15:24:16 +02:00
|
|
|
nolo_boot_device(usb_dev, dev_boot_arg);
|
2012-08-10 21:23:19 +02:00
|
|
|
usb_close_device(usb_dev);
|
|
|
|
|
usb_dev = NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-08-09 19:44:47 +02:00
|
|
|
|
2012-08-10 17:19:03 +02:00
|
|
|
/* reboot */
|
2012-08-10 21:23:19 +02:00
|
|
|
if ( dev_reboot ) {
|
|
|
|
|
nolo_reboot_device(usb_dev);
|
|
|
|
|
usb_close_device(usb_dev);
|
|
|
|
|
usb_dev = NULL;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2012-08-10 17:19:03 +02:00
|
|
|
|
2012-08-11 15:25:28 +02:00
|
|
|
}
|
2012-08-09 19:44:47 +02:00
|
|
|
|
|
|
|
|
}
|
2012-08-08 21:33:53 +02:00
|
|
|
|
|
|
|
|
|
2012-08-09 16:07:48 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifdef WITH_DEVICE
|
|
|
|
|
|
|
|
|
|
/* on device */
|
2012-08-08 21:33:53 +02:00
|
|
|
|
2012-08-09 19:44:47 +02:00
|
|
|
/* device identify */
|
|
|
|
|
|
2012-08-08 21:33:53 +02:00
|
|
|
/* check */
|
|
|
|
|
|
|
|
|
|
/* dump */
|
|
|
|
|
|
2012-08-09 16:07:48 +02:00
|
|
|
/* flash */
|
|
|
|
|
|
2012-08-09 19:44:47 +02:00
|
|
|
/* configuration */
|
|
|
|
|
|
2012-08-09 16:07:48 +02:00
|
|
|
/* reboot */
|
|
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
2012-08-10 21:54:37 +02:00
|
|
|
ret = 0;
|
2012-08-09 16:07:48 +02:00
|
|
|
|
|
|
|
|
/* clean */
|
|
|
|
|
clean:
|
|
|
|
|
|
|
|
|
|
if ( ! image_fiasco ) {
|
|
|
|
|
image_ptr = image_first;
|
|
|
|
|
while ( image_ptr ) {
|
|
|
|
|
struct image_list * next = image_ptr->next;
|
|
|
|
|
image_list_del(image_ptr);
|
|
|
|
|
image_ptr = next;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( fiasco_in )
|
|
|
|
|
fiasco_free(fiasco_in);
|
|
|
|
|
|
2012-08-09 19:44:47 +02:00
|
|
|
if ( usb_dev )
|
|
|
|
|
usb_close_device(usb_dev);
|
|
|
|
|
|
2012-08-09 16:07:48 +02:00
|
|
|
return ret;
|
2012-08-08 21:33:53 +02:00
|
|
|
}
|