Commit da8dd713 authored by Bjorn Andersson's avatar Bjorn Andersson
Browse files

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: default avatarBjorn Andersson <bjorn.andersson@linaro.org>
parent b6e0ea31
......@@ -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;
......
......@@ -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")) {
fprintf(stderr, "[PROGRAM] unrecognized tag \"%s\", ignoring\n", node->name);
continue;
}
errors = 0;
errors = -EINVAL;
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 (!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);
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
......@@ -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;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment