mirror of
https://github.com/linux-msm/qdl.git
synced 2026-02-25 13:12:25 -08:00
program: Introduce erase tag support
NAND based devices comes with a few minor tweaks to the program tag and an additional erase tag, split the program code and add the handling of the erase tag. Signed-off-by: Bjorn Andersson <bjorn.andersson@linaro.org>
This commit is contained in:
42
firehose.c
42
firehose.c
@@ -294,6 +294,39 @@ static int firehose_configure(struct qdl_device *qdl, bool skip_storage_init, co
|
||||
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
||||
#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
||||
|
||||
static int firehose_erase(struct qdl_device *qdl, struct program *program)
|
||||
{
|
||||
xmlNode *root;
|
||||
xmlNode *node;
|
||||
xmlDoc *doc;
|
||||
int ret;
|
||||
|
||||
doc = xmlNewDoc((xmlChar*)"1.0");
|
||||
root = xmlNewNode(NULL, (xmlChar*)"data");
|
||||
xmlDocSetRootElement(doc, root);
|
||||
|
||||
node = xmlNewChild(root, NULL, (xmlChar*)"erase", NULL);
|
||||
xml_setpropf(node, "PAGES_PER_BLOCK", "%d", program->pages_per_block);
|
||||
xml_setpropf(node, "SECTOR_SIZE_IN_BYTES", "%d", program->sector_size);
|
||||
xml_setpropf(node, "num_partition_sectors", "%d", program->num_sectors);
|
||||
xml_setpropf(node, "start_sector", "%d", program->start_sector);
|
||||
|
||||
ret = firehose_write(qdl, doc);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "[PROGRAM] failed to write program command\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = firehose_read(qdl, 30, firehose_nop_parser);
|
||||
fprintf(stderr, "[ERASE] erase 0x%x+0x%x %s\n",
|
||||
program->start_sector, program->num_sectors,
|
||||
ret ? "failed" : "succeeded");
|
||||
|
||||
out:
|
||||
xmlFreeDoc(doc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int firehose_program(struct qdl_device *qdl, struct program *program, int fd)
|
||||
{
|
||||
unsigned num_sectors;
|
||||
@@ -340,6 +373,11 @@ static int firehose_program(struct qdl_device *qdl, struct program *program, int
|
||||
if (program->filename)
|
||||
xml_setpropf(node, "filename", "%s", program->filename);
|
||||
|
||||
if (program->is_nand) {
|
||||
xml_setpropf(node, "PAGES_PER_BLOCK", "%d", program->pages_per_block);
|
||||
xml_setpropf(node, "last_sector", "%d", program->last_sector);
|
||||
}
|
||||
|
||||
ret = firehose_write(qdl, doc);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "[PROGRAM] failed to write program command\n");
|
||||
@@ -600,6 +638,10 @@ int firehose_run(struct qdl_device *qdl, const char *incdir, const char *storage
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = erase_execute(qdl, firehose_erase);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = program_execute(qdl, firehose_program, incdir);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
142
program.c
142
program.c
@@ -37,13 +37,90 @@
|
||||
|
||||
#include "program.h"
|
||||
#include "qdl.h"
|
||||
|
||||
|
||||
static struct program *programes;
|
||||
static struct program *programes_last;
|
||||
|
||||
int program_load(const char *program_file)
|
||||
static int load_erase_tag(xmlNode *node, bool is_nand)
|
||||
{
|
||||
struct program *program;
|
||||
int errors = 0;
|
||||
|
||||
if (!is_nand) {
|
||||
fprintf(stderr, "got \"erase\" tag for non-NAND storage\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
program = calloc(1, sizeof(struct program));
|
||||
|
||||
|
||||
program->is_nand = true;
|
||||
program->is_erase = true;
|
||||
|
||||
program->pages_per_block = attr_as_unsigned(node, "PAGES_PER_BLOCK", &errors);
|
||||
program->sector_size = attr_as_unsigned(node, "SECTOR_SIZE_IN_BYTES", &errors);
|
||||
program->num_sectors = attr_as_unsigned(node, "num_partition_sectors", &errors);
|
||||
program->start_sector = attr_as_unsigned(node, "start_sector", &errors);
|
||||
|
||||
if (errors) {
|
||||
fprintf(stderr, "[PROGRAM] errors while parsing erase tag\n");
|
||||
free(program);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (programes) {
|
||||
programes_last->next = program;
|
||||
programes_last = program;
|
||||
} else {
|
||||
programes = program;
|
||||
programes_last = program;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int load_program_tag(xmlNode *node, bool is_nand)
|
||||
{
|
||||
struct program *program;
|
||||
int errors = 0;
|
||||
|
||||
program = calloc(1, sizeof(struct program));
|
||||
|
||||
program->is_nand = is_nand;
|
||||
|
||||
program->sector_size = attr_as_unsigned(node, "SECTOR_SIZE_IN_BYTES", &errors);
|
||||
program->filename = attr_as_string(node, "filename", &errors);
|
||||
program->label = attr_as_string(node, "label", &errors);
|
||||
program->num_sectors = attr_as_unsigned(node, "num_partition_sectors", &errors);
|
||||
program->partition = attr_as_unsigned(node, "physical_partition_number", &errors);
|
||||
program->start_sector = attr_as_unsigned(node, "start_sector", &errors);
|
||||
|
||||
if (is_nand) {
|
||||
program->pages_per_block = attr_as_unsigned(node, "PAGES_PER_BLOCK", &errors);
|
||||
program->last_sector = attr_as_unsigned(node, "last_sector", &errors);
|
||||
} else {
|
||||
program->file_offset = attr_as_unsigned(node, "file_sector_offset", &errors);
|
||||
}
|
||||
|
||||
if (errors) {
|
||||
fprintf(stderr, "[PROGRAM] errors while parsing program\n");
|
||||
free(program);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (programes) {
|
||||
programes_last->next = program;
|
||||
programes_last = program;
|
||||
} else {
|
||||
programes = program;
|
||||
programes_last = program;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int program_load(const char *program_file, bool is_nand)
|
||||
{
|
||||
xmlNode *node;
|
||||
xmlNode *root;
|
||||
xmlDoc *doc;
|
||||
@@ -60,43 +137,24 @@ int program_load(const char *program_file)
|
||||
if (node->type != XML_ELEMENT_NODE)
|
||||
continue;
|
||||
|
||||
if (xmlStrcmp(node->name, (xmlChar*)"program")) {
|
||||
errors = -EINVAL;
|
||||
|
||||
if (!xmlStrcmp(node->name, (xmlChar *)"erase"))
|
||||
errors = load_erase_tag(node, is_nand);
|
||||
else if (!xmlStrcmp(node->name, (xmlChar *)"program"))
|
||||
errors = load_program_tag(node, is_nand);
|
||||
else
|
||||
fprintf(stderr, "[PROGRAM] unrecognized tag \"%s\", ignoring\n", node->name);
|
||||
continue;
|
||||
}
|
||||
|
||||
errors = 0;
|
||||
|
||||
program = calloc(1, sizeof(struct program));
|
||||
|
||||
program->sector_size = attr_as_unsigned(node, "SECTOR_SIZE_IN_BYTES", &errors);
|
||||
program->file_offset = attr_as_unsigned(node, "file_sector_offset", &errors);
|
||||
program->filename = attr_as_string(node, "filename", &errors);
|
||||
program->label = attr_as_string(node, "label", &errors);
|
||||
program->num_sectors = attr_as_unsigned(node, "num_partition_sectors", &errors);
|
||||
program->partition = attr_as_unsigned(node, "physical_partition_number", &errors);
|
||||
program->start_sector = attr_as_unsigned(node, "start_sector", &errors);
|
||||
|
||||
if (errors) {
|
||||
fprintf(stderr, "[PROGRAM] errors while parsing program\n");
|
||||
free(program);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (programes) {
|
||||
programes_last->next = program;
|
||||
programes_last = program;
|
||||
} else {
|
||||
programes = program;
|
||||
programes_last = program;
|
||||
}
|
||||
if (errors)
|
||||
return errors;
|
||||
}
|
||||
|
||||
xmlFreeDoc(doc);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int program_execute(struct qdl_device *qdl, int (*apply)(struct qdl_device *qdl, struct program *program, int fd),
|
||||
const char *incdir)
|
||||
{
|
||||
@@ -107,7 +165,7 @@ int program_execute(struct qdl_device *qdl, int (*apply)(struct qdl_device *qdl,
|
||||
int fd;
|
||||
|
||||
for (program = programes; program; program = program->next) {
|
||||
if (!program->filename)
|
||||
if (program->is_erase || !program->filename)
|
||||
continue;
|
||||
|
||||
filename = program->filename;
|
||||
@@ -134,6 +192,24 @@ int program_execute(struct qdl_device *qdl, int (*apply)(struct qdl_device *qdl,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int erase_execute(struct qdl_device *qdl, int (*apply)(struct qdl_device *qdl, struct program *program))
|
||||
{
|
||||
struct program *program;
|
||||
int ret;
|
||||
|
||||
|
||||
for (program = programes; program; program = program->next) {
|
||||
if (!program->is_erase)
|
||||
continue;
|
||||
|
||||
ret = apply(qdl, program);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* program_find_bootable_partition() - find one bootable partition
|
||||
*
|
||||
@@ -151,6 +227,8 @@ int program_find_bootable_partition(void)
|
||||
|
||||
for (program = programes; program; program = program->next) {
|
||||
label = program->label;
|
||||
if (!label)
|
||||
continue;
|
||||
|
||||
if (!strcmp(label, "xbl") || !strcmp(label, "xbl_a") ||
|
||||
!strcmp(label, "sbl1")) {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "qdl.h"
|
||||
|
||||
struct program {
|
||||
unsigned pages_per_block;
|
||||
unsigned sector_size;
|
||||
unsigned file_offset;
|
||||
const char *filename;
|
||||
@@ -12,13 +13,18 @@ struct program {
|
||||
unsigned num_sectors;
|
||||
unsigned partition;
|
||||
unsigned start_sector;
|
||||
unsigned last_sector;
|
||||
|
||||
bool is_nand;
|
||||
bool is_erase;
|
||||
|
||||
struct program *next;
|
||||
};
|
||||
|
||||
int program_load(const char *program_file);
|
||||
int program_load(const char *program_file, bool is_nand);
|
||||
int program_execute(struct qdl_device *qdl, int (*apply)(struct qdl_device *qdl, struct program *program, int fd),
|
||||
const char *incdir);
|
||||
int erase_execute(struct qdl_device *qdl, int (*apply)(struct qdl_device *qdl, struct program *program));
|
||||
int program_find_bootable_partition(void);
|
||||
|
||||
#endif
|
||||
|
||||
4
qdl.c
4
qdl.c
@@ -415,7 +415,7 @@ static void print_usage(void)
|
||||
{
|
||||
extern const char *__progname;
|
||||
fprintf(stderr,
|
||||
"%s [--debug] [--storage <emmc|ufs>] [--finalize-provisioning] [--include <PATH>] <prog.mbn> [<program> <patch> ...]\n",
|
||||
"%s [--debug] [--storage <emmc|nand|ufs>] [--finalize-provisioning] [--include <PATH>] <prog.mbn> [<program> <patch> ...]\n",
|
||||
__progname);
|
||||
}
|
||||
|
||||
@@ -478,7 +478,7 @@ int main(int argc, char **argv)
|
||||
errx(1, "patch_load %s failed", argv[optind]);
|
||||
break;
|
||||
case QDL_FILE_PROGRAM:
|
||||
ret = program_load(argv[optind]);
|
||||
ret = program_load(argv[optind], !strcmp(storage, "nand"));
|
||||
if (ret < 0)
|
||||
errx(1, "program_load %s failed", argv[optind]);
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user