1
0
mirror of git://projects.qi-hardware.com/xburst-tools.git synced 2024-11-01 16:25:20 +02:00

[flash-tool] complete inflash stage1

The stage1 file can be uploaded but the following bootstrap is not successful. Once this bug is found adding stage2 is no problem.
This commit is contained in:
lindnermarek 2009-04-26 10:37:31 +00:00
parent 08a770af52
commit 8979988877
5 changed files with 356 additions and 117 deletions

View File

@ -34,8 +34,8 @@ CFLAGS += -pedantic -Wall -W -O1 -g3 -std=gnu99
LDFLAGS += -lusb
BINARY_NAME = inflash
SRC_C= main.c
SRC_H= main.h
SRC_C= main.c usb.c
SRC_H= main.h usb.h
SRC_O= $(SRC_C:.c=.o)
$(BINARY_NAME): $(SRC_O) $(SRC_H) Makefile

View File

@ -22,144 +22,96 @@
#include "main.h"
#include "usb.h"
#include <usb.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
static int get_ingenic_device(struct ingenic_dev *ingenic_dev)
int load_file(struct ingenic_dev *ingenic_dev, const char *file_path)
{
struct usb_bus *usb_busses, *usb_bus;
struct usb_device *usb_dev;
int count = 0;
struct stat fstat;
int fd, status, res = -1;
usb_busses = usb_get_busses();
if (ingenic_dev->file_buff)
free(ingenic_dev->file_buff);
for (usb_bus = usb_busses; usb_bus != NULL; usb_bus = usb_bus->next) {
for (usb_dev = usb_bus->devices; usb_dev != NULL; usb_dev = usb_dev->next) {
ingenic_dev->file_buff = NULL;
if ((usb_dev->descriptor.idVendor == VENDOR_ID) &&
(usb_dev->descriptor.idProduct == PRODUCT_ID)) {
ingenic_dev->usb_dev = usb_dev;
count++;
}
status = stat(file_path, &fstat);
}
if (status < 0) {
fprintf(stderr, "Error - can't get file size from '%s': %s\n", file_path, strerror(errno));
goto out;
}
return count;
}
ingenic_dev->file_len = fstat.st_size;
ingenic_dev->file_buff = malloc(ingenic_dev->file_len);
static int get_ingenic_interface(struct ingenic_dev *ingenic_dev)
{
struct usb_config_descriptor *usb_config_desc;
struct usb_interface_descriptor *usb_if_desc;
struct usb_interface *usb_if;
int config_index, if_index, alt_index;
for (config_index = 0; config_index < ingenic_dev->usb_dev->descriptor.bNumConfigurations; config_index++) {
usb_config_desc = &ingenic_dev->usb_dev->config[config_index];
if (!usb_config_desc)
return 0;
for (if_index = 0; if_index < usb_config_desc->bNumInterfaces; if_index++) {
usb_if = &usb_config_desc->interface[if_index];
if (!usb_if)
return 0;
for (alt_index = 0; alt_index < usb_if->num_altsetting; alt_index++) {
usb_if_desc = &usb_if->altsetting[alt_index];
if (!usb_if_desc)
return 0;
if ((usb_if_desc->bInterfaceClass == 0xff) &&
(usb_if_desc->bInterfaceSubClass == 0)) {
ingenic_dev->interface = usb_if_desc->bInterfaceNumber;
return 1;
}
}
}
if (!ingenic_dev->file_buff) {
fprintf(stderr, "Error - can't allocate memory to read file '%s': %s\n", file_path, strerror(errno));
return -1;
}
return 0;
fd = open(file_path, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "Error - can't open file '%s': %s\n", file_path, strerror(errno));
goto out;
}
status = read(fd, ingenic_dev->file_buff, ingenic_dev->file_len);
if (status < ingenic_dev->file_len) {
fprintf(stderr, "Error - can't read file '%s': %s\n", file_path, strerror(errno));
goto close;
}
res = 1;
close:
close(fd);
out:
return res;
}
int main(int argc, char **argv)
{
int num_ingenic, status;
int res = EXIT_FAILURE;
char cpu_buff[8];
struct ingenic_dev ingenic_dev;
int res = EXIT_FAILURE;
if ((getuid()) || (getgid())) {
fprintf(stderr, "Error - you must be root to run '%s'\n", argv[0]);
exit(EXIT_FAILURE);
goto out;
}
memset(&ingenic_dev, 0, sizeof(struct ingenic_dev));
memset(cpu_buff, 0, sizeof(cpu_buff));
usb_init();
// usb_set_debug(255);
usb_find_busses();
usb_find_devices();
if (usb_ingenic_init(&ingenic_dev) < 1)
goto out;
num_ingenic = get_ingenic_device(&ingenic_dev);
if (usb_get_ingenic_cpu(&ingenic_dev) < 1)
goto out;
if (num_ingenic == 0) {
fprintf(stderr, "Error - no Ingenic device found\n");
goto exit;
}
if (load_file(&ingenic_dev, STAGE1_FILE_PATH) < 1)
goto out;
if (num_ingenic > 1) {
fprintf(stderr, "Error - too many Ingenic devices found: %i\n", num_ingenic);
goto exit;
}
if (usb_ingenic_upload(&ingenic_dev, 1) < 1)
goto cleanup;
ingenic_dev.usb_handle = usb_open(ingenic_dev.usb_dev);
if (!ingenic_dev.usb_handle) {
fprintf(stderr, "Error - can't open Ingenic device: %s\n", usb_strerror());
goto exit;
}
res = EXIT_SUCCESS;
if (get_ingenic_interface(&ingenic_dev) < 1) {
fprintf(stderr, "Error - can't find Ingenic interface\n");
goto close_handle;
}
if (usb_claim_interface(ingenic_dev.usb_handle, ingenic_dev.interface) < 0) {
fprintf(stderr, "Error - can't claim Ingenic interface: %s\n", usb_strerror());
goto close_handle;
}
status = usb_control_msg(ingenic_dev.usb_handle,
/* bmRequestType */ INGENIC_REQUEST_TYPE,
/* bRequest */ VR_GET_CPU_INFO,
/* wValue */ 0,
/* wIndex */ 0,
/* Data */ cpu_buff,
/* wLength */ 8,
USB_TIMEOUT);
if (status != sizeof(cpu_buff)) {
fprintf(stderr, "Error - can't retrieve Ingenic CPU type: %i\n", status);
goto release_if;
}
printf("Found cpu: %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x\n",
cpu_buff[0], cpu_buff[1], cpu_buff[2], cpu_buff[3],
cpu_buff[4], cpu_buff[5], cpu_buff[6], cpu_buff[7]);
release_if:
usb_release_interface(ingenic_dev.usb_handle, ingenic_dev.interface);
close_handle:
usb_close(ingenic_dev.usb_handle);
exit:
exit(res);
cleanup:
if (ingenic_dev.file_buff)
free(ingenic_dev.file_buff);
out:
usb_ingenic_cleanup(&ingenic_dev);
return res;
}

View File

@ -27,19 +27,14 @@
#define VENDOR_ID 0x601a
#define PRODUCT_ID 0x4740
#define INGENIC_REQUEST_TYPE 0x40
#define VR_GET_CPU_INFO 0x00
#define VR_SET_DATA_ADDRESS 0x01
#define VR_SET_DATA_LENGTH 0x02
#define VR_FLUSH_CACHES 0x03
#define VR_PROGRAM_START1 0x04
#define VR_PROGRAM_START2 0x05
#define USB_TIMEOUT 5000
#define STAGE1_FILE_PATH "fw.bin"
struct ingenic_dev {
struct usb_device *usb_dev;
struct usb_dev_handle *usb_handle;
uint8_t interface;
char cpu_info_buff[8];
char *file_buff;
int file_len;
};

247
flash-tool/usb.c Normal file
View File

@ -0,0 +1,247 @@
/*
* "Ingenic flash tool" - flash the Ingenic CPU via USB
*
* (C) Copyright 2009
* Author: Marek Lindner <lindner_marek@yahoo.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA
*/
#include "main.h"
#include "usb.h"
#include <usb.h>
#include <stdio.h>
static int get_ingenic_device(struct ingenic_dev *ingenic_dev)
{
struct usb_bus *usb_busses, *usb_bus;
struct usb_device *usb_dev;
int count = 0;
usb_busses = usb_get_busses();
for (usb_bus = usb_busses; usb_bus != NULL; usb_bus = usb_bus->next) {
for (usb_dev = usb_bus->devices; usb_dev != NULL; usb_dev = usb_dev->next) {
if ((usb_dev->descriptor.idVendor == VENDOR_ID) &&
(usb_dev->descriptor.idProduct == PRODUCT_ID)) {
ingenic_dev->usb_dev = usb_dev;
count++;
}
}
}
return count;
}
static int get_ingenic_interface(struct ingenic_dev *ingenic_dev)
{
struct usb_config_descriptor *usb_config_desc;
struct usb_interface_descriptor *usb_if_desc;
struct usb_interface *usb_if;
int config_index, if_index, alt_index;
for (config_index = 0; config_index < ingenic_dev->usb_dev->descriptor.bNumConfigurations; config_index++) {
usb_config_desc = &ingenic_dev->usb_dev->config[config_index];
if (!usb_config_desc)
return 0;
for (if_index = 0; if_index < usb_config_desc->bNumInterfaces; if_index++) {
usb_if = &usb_config_desc->interface[if_index];
if (!usb_if)
return 0;
for (alt_index = 0; alt_index < usb_if->num_altsetting; alt_index++) {
usb_if_desc = &usb_if->altsetting[alt_index];
if (!usb_if_desc)
return 0;
if ((usb_if_desc->bInterfaceClass == 0xff) &&
(usb_if_desc->bInterfaceSubClass == 0)) {
ingenic_dev->interface = usb_if_desc->bInterfaceNumber;
return 1;
}
}
}
}
return 0;
}
int usb_ingenic_init(struct ingenic_dev *ingenic_dev)
{
int num_ingenic, status = -1;
usb_init();
// usb_set_debug(255);
usb_find_busses();
usb_find_devices();
num_ingenic = get_ingenic_device(ingenic_dev);
if (num_ingenic == 0) {
fprintf(stderr, "Error - no Ingenic device found\n");
goto out;
}
if (num_ingenic > 1) {
fprintf(stderr, "Error - too many Ingenic devices found: %i\n", num_ingenic);
goto out;
}
ingenic_dev->usb_handle = usb_open(ingenic_dev->usb_dev);
if (!ingenic_dev->usb_handle) {
fprintf(stderr, "Error - can't open Ingenic device: %s\n", usb_strerror());
goto out;
}
if (get_ingenic_interface(ingenic_dev) < 1) {
fprintf(stderr, "Error - can't find Ingenic interface\n");
goto out;
}
if (usb_claim_interface(ingenic_dev->usb_handle, ingenic_dev->interface) < 0) {
fprintf(stderr, "Error - can't claim Ingenic interface: %s\n", usb_strerror());
goto out;
}
status = 1;
out:
return status;
}
int usb_get_ingenic_cpu(struct ingenic_dev *ingenic_dev)
{
int status;
status = usb_control_msg(ingenic_dev->usb_handle,
/* bmRequestType */ USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
/* bRequest */ VR_GET_CPU_INFO,
/* wValue */ 0,
/* wIndex */ 0,
/* Data */ ingenic_dev->cpu_info_buff,
/* wLength */ 8,
USB_TIMEOUT);
if (status != sizeof(ingenic_dev->cpu_info_buff)) {
fprintf(stderr, "Error - can't retrieve Ingenic CPU information: %i\n", status);
goto out;
}
printf("CPU data: %02x, %02x, %02x, %02x, %02x, %02x, %02x, %02x\n",
ingenic_dev->cpu_info_buff[0], ingenic_dev->cpu_info_buff[1],
ingenic_dev->cpu_info_buff[2], ingenic_dev->cpu_info_buff[3],
ingenic_dev->cpu_info_buff[4], ingenic_dev->cpu_info_buff[5],
ingenic_dev->cpu_info_buff[6], ingenic_dev->cpu_info_buff[7]);
status = 1;
out:
return status;
}
int usb_send_bulk_to_ingenic(struct ingenic_dev *ingenic_dev)
{
int status;
status = usb_bulk_write(ingenic_dev->usb_handle,
/* endpoint */ INGENIC_ENDPOINT,
/* bulk data */ ingenic_dev->file_buff, // + i,
/* bulk data length */ ingenic_dev->file_len,
USB_TIMEOUT);
if (status < ingenic_dev->file_len) {
fprintf(stderr, "Error - can't send bulk data to Ingenic CPU: %i\n", status);
return -1;
}
return 1;
}
int usb_ingenic_upload(struct ingenic_dev *ingenic_dev, int stage)
{
int status;
/* tell the device the RAM address to store the file */
status = usb_control_msg(ingenic_dev->usb_handle,
/* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
/* bRequest */ VR_SET_DATA_ADDRESS,
/* wValue */ (stage == 1 ? STAGE1_ADDR_MSB : STAGE2_ADDR_MSB),
/* wIndex */ (stage == 1 ? STAGE1_ADDR_LSB : STAGE2_ADDR_LSB),
/* Data */ 0,
/* wLength */ 0,
USB_TIMEOUT);
if (status != 0) {
fprintf(stderr, "Error - can't set the address on Ingenic device: %i\n", status);
goto out;
}
// not needed ? the windows driver does not send the length
// /* tell the device the length of the file to be uploaded */
// status = usb_control_msg(ingenic_dev->usb_handle,
// /* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
// /* bRequest */ VR_SET_DATA_LENGTH,
// /* wValue */ htons(ingenic_dev->file_len),
// /* wIndex */ ingenic_dev->file_len,
// /* Data */ 0,
// /* wLength */ 0,
// USB_TIMEOUT);
//
// if (status != 0)
// fprintf(stderr, "Error - can't set the address on Ingenic device: %i\n", status);
status = usb_send_bulk_to_ingenic(ingenic_dev);
if (status < 1)
return status;
/* tell the device to start the uploaded device */
status = usb_control_msg(ingenic_dev->usb_handle,
/* bmRequestType */ USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
/* bRequest */ (stage == 1 ? VR_PROGRAM_START1 : VR_PROGRAM_START2),
/* wValue */ (stage == 1 ? STAGE1_ADDR_MSB : STAGE2_ADDR_MSB),
/* wIndex */ (stage == 1 ? STAGE1_ADDR_LSB : STAGE2_ADDR_LSB),
/* Data */ 0,
/* wLength */ 0,
USB_TIMEOUT);
if (status != 0) {
fprintf(stderr, "Error - can't start the uploaded binary on the Ingenic device: %i\n", status);
goto out;
}
status = 1;
out:
return status;
}
void usb_ingenic_cleanup(struct ingenic_dev *ingenic_dev)
{
if ((ingenic_dev->usb_handle) && (ingenic_dev->interface))
usb_release_interface(ingenic_dev->usb_handle, ingenic_dev->interface);
if (ingenic_dev->usb_handle)
usb_close(ingenic_dev->usb_handle);
}

45
flash-tool/usb.h Normal file
View File

@ -0,0 +1,45 @@
/*
* "Ingenic flash tool" - flash the Ingenic CPU via USB
*
* (C) Copyright 2009
* Author: Marek Lindner <lindner_marek@yahoo.de>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* version 3 as published by the Free Software Foundation.
*
* 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, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA
*/
#define INGENIC_ENDPOINT 0x01
#define VR_GET_CPU_INFO 0x00
#define VR_SET_DATA_ADDRESS 0x01
#define VR_SET_DATA_LENGTH 0x02
#define VR_FLUSH_CACHES 0x03
#define VR_PROGRAM_START1 0x04
#define VR_PROGRAM_START2 0x05
#define STAGE1_ADDR_MSB 0x8000
#define STAGE1_ADDR_LSB 0x0000
#define STAGE2_ADDR_MSB 0x8000
#define STAGE2_ADDR_LSB 0x0000
#define USB_PACKET_SIZE 512
#define USB_TIMEOUT 5000
int usb_ingenic_init(struct ingenic_dev *ingenic_dev);
int usb_get_ingenic_cpu(struct ingenic_dev *ingenic_dev);
int usb_ingenic_upload(struct ingenic_dev *ingenic_dev, int stage);
void usb_ingenic_cleanup(struct ingenic_dev *ingenic_dev);