2025-06-11 22:53:28 +02:00
|
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
2017-07-24 23:46:13 -07:00
|
|
|
/*
|
|
|
|
|
* Copyright (c) 2016-2017, Linaro Ltd.
|
|
|
|
|
* All rights reserved.
|
|
|
|
|
*/
|
2026-03-30 22:15:12 +00:00
|
|
|
#include <assert.h>
|
2016-07-08 11:26:26 -07:00
|
|
|
#include <errno.h>
|
|
|
|
|
#include <string.h>
|
2024-03-25 17:12:40 -05:00
|
|
|
#include <stdlib.h>
|
2016-07-08 11:26:26 -07:00
|
|
|
#include <libxml/parser.h>
|
|
|
|
|
#include <libxml/tree.h>
|
2024-12-17 14:01:22 -06:00
|
|
|
#include <unistd.h>
|
2016-07-08 11:26:26 -07:00
|
|
|
|
|
|
|
|
#include "patch.h"
|
2026-03-30 22:15:12 +00:00
|
|
|
#include "firehose.h"
|
2018-10-05 12:55:56 +08:00
|
|
|
#include "qdl.h"
|
2025-06-18 09:39:54 +02:00
|
|
|
|
2025-09-16 20:32:27 -05:00
|
|
|
static bool patches_loaded;
|
2016-07-08 11:26:26 -07:00
|
|
|
|
2026-04-06 22:29:05 +00:00
|
|
|
int patch_load_xml(struct list_head *ops, xmlDoc *doc, const char *patch_file)
|
2016-07-08 11:26:26 -07:00
|
|
|
{
|
2026-03-30 22:15:12 +00:00
|
|
|
struct firehose_op *patch;
|
2016-07-08 11:26:26 -07:00
|
|
|
xmlNode *node;
|
|
|
|
|
xmlNode *root;
|
|
|
|
|
int errors;
|
|
|
|
|
|
|
|
|
|
root = xmlDocGetRootElement(doc);
|
|
|
|
|
for (node = root->children; node ; node = node->next) {
|
|
|
|
|
if (node->type != XML_ELEMENT_NODE)
|
|
|
|
|
continue;
|
|
|
|
|
|
2025-06-18 09:39:54 +02:00
|
|
|
if (xmlStrcmp(node->name, (xmlChar *)"patch")) {
|
2024-12-17 13:24:30 -06:00
|
|
|
ux_err("unrecognized tag \"%s\" in patch-type file, ignoring\n", node->name);
|
2016-07-08 11:26:26 -07:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
errors = 0;
|
|
|
|
|
|
2026-03-30 22:15:12 +00:00
|
|
|
patch = firehose_alloc_op(FIREHOSE_OP_PATCH);
|
2016-07-08 11:26:26 -07:00
|
|
|
|
|
|
|
|
patch->sector_size = attr_as_unsigned(node, "SECTOR_SIZE_IN_BYTES", &errors);
|
|
|
|
|
patch->byte_offset = attr_as_unsigned(node, "byte_offset", &errors);
|
|
|
|
|
patch->filename = attr_as_string(node, "filename", &errors);
|
|
|
|
|
patch->partition = attr_as_unsigned(node, "physical_partition_number", &errors);
|
|
|
|
|
patch->size_in_bytes = attr_as_unsigned(node, "size_in_bytes", &errors);
|
2021-04-29 10:25:55 -05:00
|
|
|
patch->start_sector = attr_as_string(node, "start_sector", &errors);
|
2016-07-08 11:26:26 -07:00
|
|
|
patch->value = attr_as_string(node, "value", &errors);
|
|
|
|
|
patch->what = attr_as_string(node, "what", &errors);
|
|
|
|
|
|
|
|
|
|
if (errors) {
|
2024-12-17 13:24:30 -06:00
|
|
|
ux_err("errors while parsing patch-type file \"%s\"\n", patch_file);
|
2026-03-12 11:56:35 +01:00
|
|
|
free((void *)patch->filename);
|
|
|
|
|
free((void *)patch->start_sector);
|
|
|
|
|
free((void *)patch->value);
|
|
|
|
|
free((void *)patch->what);
|
2016-07-08 11:26:26 -07:00
|
|
|
free(patch);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-30 22:15:12 +00:00
|
|
|
list_append(ops, &patch->node);
|
2016-07-08 11:26:26 -07:00
|
|
|
}
|
|
|
|
|
|
2025-09-16 20:32:27 -05:00
|
|
|
patches_loaded = true;
|
|
|
|
|
|
2016-07-08 11:26:26 -07:00
|
|
|
return 0;
|
|
|
|
|
}
|
2026-04-06 22:29:05 +00:00
|
|
|
|
|
|
|
|
int patch_load(struct list_head *ops, const char *patch_file)
|
|
|
|
|
{
|
|
|
|
|
xmlDoc *doc;
|
|
|
|
|
int ret;
|
|
|
|
|
|
|
|
|
|
doc = xmlReadFile(patch_file, NULL, 0);
|
|
|
|
|
if (!doc) {
|
|
|
|
|
ux_err("failed to parse patch-type file \"%s\"\n", patch_file);
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ret = patch_load_xml(ops, doc, patch_file);
|
|
|
|
|
|
|
|
|
|
xmlFreeDoc(doc);
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|