Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions doc/usage.rst
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ install [OPTION…] *PACKAGE* *DEVICE*
Install a partup PACKAGE to DEVICE

-s, --skip-checksums Skip checksum verification for all input files
--dry-run Do not write to device

package [OPTION…] *PACKAGE* *FILES…*
Create a partup PACKAGE with the contents FILES
Expand Down
183 changes: 108 additions & 75 deletions src/pu-emmc.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,18 +159,103 @@ emmc_create_partition(PuEmmc *self,
return TRUE;
}

static gboolean
validate_file(PuEmmcInput *input,
gchar *prefix,
gboolean skip_checksums,
GError **error)
{
g_autofree gchar *path = NULL;

path = pu_path_from_uri(input->uri, prefix, error);
if (path == NULL) {
g_prefix_error(error, "Failed parsing input URI for partition: ");
return FALSE;
}

if (!g_file_test(path, G_FILE_TEST_IS_REGULAR)) {
g_set_error(error, PU_ERROR, PU_ERROR_FLASH_DATA,
"Input file at '%s' does not exist", path);
return FALSE;
}

if (!g_str_equal(input->md5sum, "") && !skip_checksums) {
g_debug("Checking MD5 sum of input file '%s'", path);
if (!pu_checksum_verify_file(path, input->md5sum, G_CHECKSUM_MD5, error))
return FALSE;
}

if (!g_str_equal(input->sha256sum, "") && !skip_checksums) {
g_debug("Checking SHA256 sum of input file '%s'", path);
if (!pu_checksum_verify_file(path, input->sha256sum, G_CHECKSUM_SHA256, error))
return FALSE;
}

g_free(input->uri);
input->uri = g_steal_pointer(&path);

return TRUE;
}

static gboolean
pu_emmc_validate_config(PuFlash *flash,
GError **error)
{
PuEmmc *self = PU_EMMC(flash);
g_autofree gchar *prefix = NULL;
gboolean skip_checksums = FALSE;

g_return_val_if_fail(flash != NULL, FALSE);
g_return_val_if_fail(error == NULL || *error == NULL, FALSE);

g_object_get(flash,
"prefix", &prefix,
"skip-checksums", &skip_checksums,
NULL);

for (GList *p = self->partitions; p != NULL; p = p->next) {
PuEmmcPartition *part = p->data;

for (GList *i = part->input; i != NULL; i = i->next) {
PuEmmcInput *input = i->data;
if (!validate_file(input, prefix, skip_checksums, error))
return FALSE;
}
}

for (GList *b = self->raw; b != NULL; b = b->next) {
PuEmmcBinary *bin = b->data;
PuEmmcInput *input = bin->input;
if (!validate_file(input, prefix, skip_checksums, error))
return FALSE;
}

if (self->emmc_boot_partitions) {
PuEmmcInput *input = self->emmc_boot_partitions->input;
if (!validate_file(input, prefix, skip_checksums, error))
return FALSE;
}

return TRUE;
}

static gboolean
pu_emmc_init_device(PuFlash *flash,
GError **error)
{
PuEmmc *self = PU_EMMC(flash);
PedDisk *newdisk;
gboolean dry_run = FALSE;

g_debug(G_STRFUNC);

g_return_val_if_fail(flash != NULL, FALSE);
g_return_val_if_fail(error == NULL || *error == NULL, FALSE);

g_object_get(flash,
"dry-run", &dry_run,
NULL);

newdisk = ped_disk_new_fresh(self->device, self->disktype);
if (newdisk == NULL) {
g_set_error(error, PU_ERROR, PU_ERROR_FLASH_INIT,
Expand All @@ -182,6 +267,10 @@ pu_emmc_init_device(PuFlash *flash,
ped_disk_destroy(self->disk);
}
self->disk = newdisk;

if (dry_run)
return TRUE;

ped_disk_commit(self->disk);

g_debug("%s: Finished", G_STRFUNC);
Expand All @@ -195,12 +284,17 @@ pu_emmc_setup_layout(PuFlash *flash,
{
PuEmmc *self = PU_EMMC(flash);
PedSector part_start = 0;
gboolean dry_run = FALSE;

g_debug(G_STRFUNC);

g_return_val_if_fail(flash != NULL, FALSE);
g_return_val_if_fail(error == NULL || *error == NULL, FALSE);

g_object_get(flash,
"dry-run", &dry_run,
NULL);

for (GList *p = self->partitions; p != NULL; p = p->next) {
PuEmmcPartition *part = p->data;

Expand Down Expand Up @@ -229,6 +323,9 @@ pu_emmc_setup_layout(PuFlash *flash,
part_start += part->size + part->offset;
}

if (dry_run)
return TRUE;

ped_disk_commit(self->disk);

if (!pu_wait_for_partitions(error))
Expand All @@ -244,21 +341,22 @@ pu_emmc_write_data(PuFlash *flash,
PuEmmc *self = PU_EMMC(flash);
guint i = 0;
gboolean first_logical_part = FALSE;
gboolean skip_checksums = FALSE;
gboolean dry_run = FALSE;
g_autofree gchar *part_path = NULL;
g_autofree gchar *part_mount = NULL;
g_autofree gchar *prefix = NULL;

g_debug(G_STRFUNC);

g_return_val_if_fail(flash != NULL, FALSE);
g_return_val_if_fail(error == NULL || *error == NULL, FALSE);

g_object_get(flash,
"prefix", &prefix,
"skip-checksums", &skip_checksums,
"dry-run", &dry_run,
NULL);

if (dry_run)
return TRUE;

for (GList *p = self->partitions; p != NULL; p = p->next) {
PuEmmcPartition *part = p->data;
if (part->type == PED_PARTITION_LOGICAL && first_logical_part == FALSE) {
Expand Down Expand Up @@ -297,26 +395,7 @@ pu_emmc_write_data(PuFlash *flash,

for (GList *i = part->input; i != NULL; i = i->next) {
PuEmmcInput *input = i->data;
g_autofree gchar *path = NULL;

path = pu_path_from_uri(input->uri, prefix, error);
if (path == NULL) {
g_prefix_error(error, "Failed parsing input URI for partition: ");
return FALSE;
}

if (!g_str_equal(input->md5sum, "") && !skip_checksums) {
g_debug("Checking MD5 sum of input file '%s'", path);
if (!pu_checksum_verify_file(path, input->md5sum,
G_CHECKSUM_MD5, error))
return FALSE;
}
if (!g_str_equal(input->sha256sum, "") && !skip_checksums) {
g_debug("Checking SHA256 sum of input file '%s'", path);
if (!pu_checksum_verify_file(path, input->sha256sum,
G_CHECKSUM_SHA256, error))
return FALSE;
}
gchar *path = input->uri;

if (g_regex_match_simple(".tar", path, G_REGEX_CASELESS, 0)) {
g_debug("Extracting '%s' to '%s'", path, part_mount);
Expand Down Expand Up @@ -362,31 +441,7 @@ pu_emmc_write_data(PuFlash *flash,
for (GList *b = self->raw; b != NULL; b = b->next) {
PuEmmcBinary *bin = b->data;
PuEmmcInput *input = bin->input;
g_autofree gchar *path = NULL;

path = pu_path_from_uri(input->uri, prefix, error);
if (path == NULL) {
g_prefix_error(error, "Failed parsing input URI for binary: ");
return FALSE;
}

if (g_str_equal(path, "")) {
g_warning("No input specified for binary");
continue;
}

if (!g_str_equal(input->md5sum, "") && !skip_checksums) {
g_debug("Checking MD5 sum of input file '%s'", path);
if (!pu_checksum_verify_file(path, input->md5sum,
G_CHECKSUM_MD5, error))
return FALSE;
}
if (!g_str_equal(input->sha256sum, "") && !skip_checksums) {
g_debug("Checking SHA256 sum of input file '%s'", path);
if (!pu_checksum_verify_file(path, input->sha256sum,
G_CHECKSUM_SHA256, error))
return FALSE;
}
gchar *path = input->uri;

if (!pu_write_raw(path, self->device->path, self->device,
bin->input_offset, bin->output_offset, 0, error))
Expand All @@ -395,32 +450,7 @@ pu_emmc_write_data(PuFlash *flash,

if (self->emmc_boot_partitions) {
PuEmmcInput *input = self->emmc_boot_partitions->input;
g_autofree gchar *path = NULL;

path = pu_path_from_uri(input->uri, prefix, error);
if (path == NULL) {
g_prefix_error(error, "Failed parsing input URI for eMMC boot partition: ");
return FALSE;
}

if (g_str_equal(path, "")) {
g_set_error(error, PU_ERROR, PU_ERROR_FLASH_DATA,
"No input specified for eMMC boot partition");
return FALSE;
}

if (!g_str_equal(input->md5sum, "") && !skip_checksums) {
g_debug("Checking MD5 sum of input file '%s'", path);
if (!pu_checksum_verify_file(path, input->md5sum,
G_CHECKSUM_MD5, error))
return FALSE;
}
if (!g_str_equal(input->sha256sum, "") && !skip_checksums) {
g_debug("Checking SHA256 sum of input file '%s'", path);
if (!pu_checksum_verify_file(path, input->sha256sum,
G_CHECKSUM_SHA256, error))
return FALSE;
}
gchar *path = input->uri;

if (!pu_write_raw_bootpart(path, self->device, 0,
self->emmc_boot_partitions->input_offset,
Expand Down Expand Up @@ -500,6 +530,7 @@ pu_emmc_class_init(PuEmmcClass *class)
PuFlashClass *flash_class = PU_FLASH_CLASS(class);
GObjectClass *object_class = G_OBJECT_CLASS(class);

flash_class->validate_config = pu_emmc_validate_config;
flash_class->init_device = pu_emmc_init_device;
flash_class->setup_layout = pu_emmc_setup_layout;
flash_class->write_data = pu_emmc_write_data;
Expand Down Expand Up @@ -836,6 +867,7 @@ pu_emmc_new(const gchar *device_path,
PuConfig *config,
const gchar *prefix,
gboolean skip_checksums,
gboolean dry_run,
GError **error)
{
PuEmmc *self;
Expand All @@ -852,6 +884,7 @@ pu_emmc_new(const gchar *device_path,
"config", config,
"prefix", prefix,
"skip-checksums", skip_checksums,
"dry-run", dry_run,
NULL);
root = pu_config_get_root(config);

Expand Down
1 change: 1 addition & 0 deletions src/pu-emmc.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ PuEmmc * pu_emmc_new(const gchar *device_path,
PuConfig *config,
const gchar *prefix,
gboolean skip_checksums,
gboolean dry_run,
GError **error);

#endif /* PARTUP_EMMC_H */
32 changes: 32 additions & 0 deletions src/pu-flash.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ typedef struct {
PuConfig *config;
gchar *prefix;
gboolean skip_checksums;
gboolean dry_run;
} PuFlashPrivate;

enum {
Expand All @@ -19,12 +20,23 @@ enum {
PROP_CONFIG,
PROP_PREFIX,
PROP_SKIP_CHECKSUMS,
PROP_DRY_RUN,
NUM_PROPS
};
static GParamSpec *props[NUM_PROPS] = { NULL };

G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE(PuFlash, pu_flash, G_TYPE_OBJECT)

static gboolean
pu_flash_default_validate_config(PuFlash *self,
G_GNUC_UNUSED GError **error)
{
g_critical("Flash of type '%s' does not implement PuFlash::validate_config",
G_OBJECT_TYPE_NAME(self));

return FALSE;
}

static gboolean
pu_flash_default_init_device(PuFlash *self,
G_GNUC_UNUSED GError **error)
Expand Down Expand Up @@ -79,6 +91,9 @@ pu_flash_set_property(GObject *object,
case PROP_SKIP_CHECKSUMS:
priv->skip_checksums = g_value_get_boolean(value);
break;
case PROP_DRY_RUN:
priv->dry_run = g_value_get_boolean(value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
Expand Down Expand Up @@ -107,6 +122,9 @@ pu_flash_get_property(GObject *object,
case PROP_SKIP_CHECKSUMS:
g_value_set_boolean(value, priv->skip_checksums);
break;
case PROP_DRY_RUN:
g_value_set_boolean(value, priv->dry_run);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
Expand All @@ -118,6 +136,7 @@ pu_flash_class_init(PuFlashClass *class)
{
GObjectClass *object_class = G_OBJECT_CLASS(class);

class->validate_config = pu_flash_default_validate_config;
class->init_device = pu_flash_default_init_device;
class->setup_layout = pu_flash_default_setup_layout;
class->write_data = pu_flash_default_write_data;
Expand Down Expand Up @@ -148,6 +167,12 @@ pu_flash_class_init(PuFlashClass *class)
"Modifier to skip checksum verification for all files when writing",
FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
props[PROP_DRY_RUN] =
g_param_spec_boolean("dry-run",
"Do not write to device",
"Do not write to device, only validate layout configuration and input files",
FALSE,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);

g_object_class_install_properties(object_class, NUM_PROPS, props);
}
Expand All @@ -157,6 +182,13 @@ pu_flash_init(G_GNUC_UNUSED PuFlash *self)
{
}

gboolean
pu_flash_validate_config(PuFlash *self,
GError **error)
{
return PU_FLASH_GET_CLASS(self)->validate_config(self, error);
}

gboolean
pu_flash_init_device(PuFlash *self,
GError **error)
Expand Down
Loading