Message ID | 20220616124055.2163867-2-philippe.reynes@softathome.com |
---|---|
State | Changes Requested |
Headers | show |
Series | [v2,1/2] handlers: diskpart_handler.c: add handler for script gptswap | expand |
On 16.06.22 14:40, Philippe Reynes wrote: > Add a handler to write in a GPT partition. > With the handler raw, the device of the parition ^-- partition is provided > to the raw handler. This handler use a device on the disk that > contains the GPT partition and the name of the GPT partition > to found the device of the partition to write. > > For example: > images: ( > { > filename = "u-boot.bin"; > type = "gptpart"; > device = "/dev/vdb"; > volume = "u-boot-1"; > }, > { > filename = "kernel.bin"; > type = "gptpart"; > device = "/dev/vdb"; > volume = "kernel-1"; > }, > ); > > Signed-off-by: Philippe Reynes <philippe.reynes@softathome.com> > --- > IMO I think this can be reached better if you chain the handlers. This handler is in fact a frontend for the "raw" handler. It finds which is the device and, when this is found, it is convenient to call the raw handler. I am thinking to some use cases that are drop by this implementation, for example if there is an offset: { filename = "u-boot.bin"; type = "gptpart"; device = "/dev/vdb"; volume = "u-boot-1"; offset = "1024"; }, This can be reached easy if you: /* Find device + partition */ partno = fdisk_partition_get_partno(pa); snprintf(node, sizeof(node), "%s%zu", img->device, partno + 1); /* set device for next handler */ strlcpy(img->device, node, sizeof(img->device)); strcpy(img->type, "raw"); // well, we are then not limited to raw hnd = find_handler(img); if (hnd) ==> hnd->installer(img,..); What do you think ? Best regards, Stefano > Changelog: > v2: > - rebase on master > - add a constructor to register the handler install_gpt_partition_image > > doc/source/handlers.rst | 24 ++++++++ > handlers/diskpart_handler.c | 115 ++++++++++++++++++++++++++++++++++++ > 2 files changed, 139 insertions(+) > > diff --git a/doc/source/handlers.rst b/doc/source/handlers.rst > index 01ec221..029a70c 100644 > --- a/doc/source/handlers.rst > +++ b/doc/source/handlers.rst > @@ -963,6 +963,30 @@ if the partition table is DOS. It reports an error if the table is GPT. > } > } > > +gpt partition installer > +....................... > + > +There is a handler gptpart that allows writing an image into a gpt partition selected by > +the name. This handler do not modify the gpt partition (type, size, ...), it just writes > +the image in the GPT partition. > + > +:: > + > + images: ( > + { > + filename = "u-boot.bin"; > + type = "gptpart"; > + device = "/dev/vdb"; > + volume = "u-boot-1"; > + }, > + { > + filename = "kernel.bin"; > + type = "gptpart"; > + device = "/dev/vdb"; > + volume = "kernel-1"; > + }, > + ); > + > gpt partition swap > .................. > > diff --git a/handlers/diskpart_handler.c b/handlers/diskpart_handler.c > index 925976b..7408ee6 100644 > --- a/handlers/diskpart_handler.c > +++ b/handlers/diskpart_handler.c > @@ -907,6 +907,114 @@ static int diskpart_reread_partition(char *device) > return ret; > } > > +static int install_gpt_partition_image(struct img_type *img, > + void __attribute__ ((__unused__)) *data) > +{ > + struct fdisk_context *cxt = NULL; > + struct diskpart_table *tb = NULL; > + int ret = 0; > + unsigned long hybrid = 0; > + struct hnd_priv priv = { > + .labeltype = FDISK_DISKLABEL_DOS, > + }; > + struct create_table *createtable = NULL; > + struct fdisk_partition *pa; > + size_t partno; > + char node[64]; > + int fdout; > + > + LIST_INIT(&priv.listparts); > + if (!strlen(img->device)) { > + ERROR("Partition handler without setting the device"); > + return -EINVAL; > + } > + > + createtable = calloc(1, sizeof(*createtable)); > + if (!createtable) { > + ERROR("OOM allocating createtable !"); > + return -ENOMEM; > + } > + > + /* > + * Reads flags: nolock and noinuse > + */ > + priv.nolock = strtobool(dict_get_value(&img->properties, "nolock")); > + priv.noinuse = strtobool(dict_get_value(&img->properties, "noinuse")); > + > + /* > + * Create context > + */ > + ret = diskpart_assign_context(&cxt, img, priv, hybrid, createtable); > + if (ret == -EACCES) > + goto handler_release; > + else if (ret) > + goto handler_exit; > + > + tb = calloc(1, sizeof(*tb)); > + if (!tb) { > + ERROR("OOM loading partitions !"); > + ret = -ENOMEM; > + goto handler_exit; > + } > + > + /* > + * Fill the in-memory partition table from the disk. > + */ > + ret = diskpart_get_partitions(cxt, tb, createtable); > + if (ret) > + goto handler_exit; > + > + /* > + * Search partition to update > + */ > + pa = diskpart_get_partition_by_name(tb, img->volname); > + if (!pa) { > + ERROR("Can't find partition %s", img->volname); > + ret = -1; > + goto handler_exit; > + } > + > + /* > + * Open the node of the partition > + */ > + partno = fdisk_partition_get_partno(pa); > + snprintf(node, sizeof(node), "%s%zu", img->device, partno + 1); > + fdout = open(node, O_RDWR); > + if (fdout < 0) { > + ERROR("Node %s cannot be opened", node); > + ret = -1; > + goto handler_exit; > + } > + > + /* > + * Write image > + */ > + if (copyimage(&fdout, img, NULL) < 0) { > + ERROR("Error copying extracted file"); > + ret = -1; > + goto handler_close; > + } > + > +handler_close: > + close(fdout); > + > +handler_exit: > + if (tb) > + diskpart_unref_table(tb); > + if (cxt && fdisk_get_devfd(cxt) >= 0) > + if (fdisk_deassign_device(cxt, 0)) > + WARN("Error deassign device %s", img->device); > + > +handler_release: > + if (cxt) > + diskpart_unref_context(cxt); > + > + if (createtable) > + free(createtable); > + > + return ret; > +} > + > static int diskpart(struct img_type *img, > void __attribute__ ((__unused__)) *data) > { > @@ -1472,3 +1580,10 @@ void diskpart_gpt_swap_partition(void) > register_handler("gptswap", gpt_swap_partition, > SCRIPT_HANDLER | NO_DATA_HANDLER, NULL); > } > + > +__attribute__((constructor)) > +void diskpart_install_gpt_partition_image(void) > +{ > + register_handler("gptpart", install_gpt_partition_image, > + IMAGE_HANDLER, NULL); > +}
Hi Stefano, Le 18/06/2022 à 11:00, Stefano Babic a écrit : > > > On 16.06.22 14:40, Philippe Reynes wrote: >> Add a handler to write in a GPT partition. >> With the handler raw, the device of the parition > > ^-- partition > > is provided >> to the raw handler. This handler use a device on the disk that >> contains the GPT partition and the name of the GPT partition >> to found the device of the partition to write. >> >> For example: >> images: ( >> { >> filename = "u-boot.bin"; >> type = "gptpart"; >> device = "/dev/vdb"; >> volume = "u-boot-1"; >> }, >> { >> filename = "kernel.bin"; >> type = "gptpart"; >> device = "/dev/vdb"; >> volume = "kernel-1"; >> }, >> ); >> >> Signed-off-by: Philippe Reynes <philippe.reynes@softathome.com> >> --- >> > > IMO I think this can be reached better if you chain the handlers. This > handler is in fact a frontend for the "raw" handler. It finds which is > the device and, when this is found, it is convenient to call the raw > handler. > > I am thinking to some use cases that are drop by this implementation, > for example if there is an offset: > > { > filename = "u-boot.bin"; > type = "gptpart"; > device = "/dev/vdb"; > volume = "u-boot-1"; > offset = "1024"; > }, > > This can be reached easy if you: > > /* Find device + partition */ > partno = fdisk_partition_get_partno(pa); > snprintf(node, sizeof(node), "%s%zu", img->device, partno + 1); > > /* set device for next handler */ > strlcpy(img->device, node, sizeof(img->device)); > strcpy(img->type, "raw"); > // well, we are then not limited to raw > > hnd = find_handler(img); > if (hnd) > ==> hnd->installer(img,..); > > > What do you think ? > I think that you are right. It is interesting to chain on raw handler. Thanks for this idea/feedback. I just sent a v3 of my patches with this change (and some little cleaning). > Best regards, > Stefano > Best regards, Philippe > >> Changelog: >> v2: >> - rebase on master >> - add a constructor to register the handler install_gpt_partition_image >> >> doc/source/handlers.rst | 24 ++++++++ >> handlers/diskpart_handler.c | 115 ++++++++++++++++++++++++++++++++++++ >> 2 files changed, 139 insertions(+) >> >> diff --git a/doc/source/handlers.rst b/doc/source/handlers.rst >> index 01ec221..029a70c 100644 >> --- a/doc/source/handlers.rst >> +++ b/doc/source/handlers.rst >> @@ -963,6 +963,30 @@ if the partition table is DOS. It reports an >> error if the table is GPT. >> } >> } >> +gpt partition installer >> +....................... >> + >> +There is a handler gptpart that allows writing an image into a gpt >> partition selected by >> +the name. This handler do not modify the gpt partition (type, size, >> ...), it just writes >> +the image in the GPT partition. >> + >> +:: >> + >> + images: ( >> + { >> + filename = "u-boot.bin"; >> + type = "gptpart"; >> + device = "/dev/vdb"; >> + volume = "u-boot-1"; >> + }, >> + { >> + filename = "kernel.bin"; >> + type = "gptpart"; >> + device = "/dev/vdb"; >> + volume = "kernel-1"; >> + }, >> + ); >> + >> gpt partition swap >> .................. >> diff --git a/handlers/diskpart_handler.c b/handlers/diskpart_handler.c >> index 925976b..7408ee6 100644 >> --- a/handlers/diskpart_handler.c >> +++ b/handlers/diskpart_handler.c >> @@ -907,6 +907,114 @@ static int diskpart_reread_partition(char *device) >> return ret; >> } >> +static int install_gpt_partition_image(struct img_type *img, >> + void __attribute__ ((__unused__)) *data) >> +{ >> + struct fdisk_context *cxt = NULL; >> + struct diskpart_table *tb = NULL; >> + int ret = 0; >> + unsigned long hybrid = 0; >> + struct hnd_priv priv = { >> + .labeltype = FDISK_DISKLABEL_DOS, >> + }; >> + struct create_table *createtable = NULL; >> + struct fdisk_partition *pa; >> + size_t partno; >> + char node[64]; >> + int fdout; >> + >> + LIST_INIT(&priv.listparts); >> + if (!strlen(img->device)) { >> + ERROR("Partition handler without setting the device"); >> + return -EINVAL; >> + } >> + >> + createtable = calloc(1, sizeof(*createtable)); >> + if (!createtable) { >> + ERROR("OOM allocating createtable !"); >> + return -ENOMEM; >> + } >> + >> + /* >> + * Reads flags: nolock and noinuse >> + */ >> + priv.nolock = strtobool(dict_get_value(&img->properties, >> "nolock")); >> + priv.noinuse = strtobool(dict_get_value(&img->properties, >> "noinuse")); >> + >> + /* >> + * Create context >> + */ >> + ret = diskpart_assign_context(&cxt, img, priv, hybrid, >> createtable); >> + if (ret == -EACCES) >> + goto handler_release; >> + else if (ret) >> + goto handler_exit; >> + >> + tb = calloc(1, sizeof(*tb)); >> + if (!tb) { >> + ERROR("OOM loading partitions !"); >> + ret = -ENOMEM; >> + goto handler_exit; >> + } >> + >> + /* >> + * Fill the in-memory partition table from the disk. >> + */ >> + ret = diskpart_get_partitions(cxt, tb, createtable); >> + if (ret) >> + goto handler_exit; >> + >> + /* >> + * Search partition to update >> + */ >> + pa = diskpart_get_partition_by_name(tb, img->volname); >> + if (!pa) { >> + ERROR("Can't find partition %s", img->volname); >> + ret = -1; >> + goto handler_exit; >> + } >> + >> + /* >> + * Open the node of the partition >> + */ >> + partno = fdisk_partition_get_partno(pa); >> + snprintf(node, sizeof(node), "%s%zu", img->device, partno + 1); >> + fdout = open(node, O_RDWR); >> + if (fdout < 0) { >> + ERROR("Node %s cannot be opened", node); >> + ret = -1; >> + goto handler_exit; >> + } >> + >> + /* >> + * Write image >> + */ >> + if (copyimage(&fdout, img, NULL) < 0) { >> + ERROR("Error copying extracted file"); >> + ret = -1; >> + goto handler_close; >> + } >> + >> +handler_close: >> + close(fdout); >> + >> +handler_exit: >> + if (tb) >> + diskpart_unref_table(tb); >> + if (cxt && fdisk_get_devfd(cxt) >= 0) >> + if (fdisk_deassign_device(cxt, 0)) >> + WARN("Error deassign device %s", img->device); >> + >> +handler_release: >> + if (cxt) >> + diskpart_unref_context(cxt); >> + >> + if (createtable) >> + free(createtable); >> + >> + return ret; >> +} >> + >> static int diskpart(struct img_type *img, >> void __attribute__ ((__unused__)) *data) >> { >> @@ -1472,3 +1580,10 @@ void diskpart_gpt_swap_partition(void) >> register_handler("gptswap", gpt_swap_partition, >> SCRIPT_HANDLER | NO_DATA_HANDLER, NULL); >> } >> + >> +__attribute__((constructor)) >> +void diskpart_install_gpt_partition_image(void) >> +{ >> + register_handler("gptpart", install_gpt_partition_image, >> + IMAGE_HANDLER, NULL); >> +}
diff --git a/doc/source/handlers.rst b/doc/source/handlers.rst index 01ec221..029a70c 100644 --- a/doc/source/handlers.rst +++ b/doc/source/handlers.rst @@ -963,6 +963,30 @@ if the partition table is DOS. It reports an error if the table is GPT. } } +gpt partition installer +....................... + +There is a handler gptpart that allows writing an image into a gpt partition selected by +the name. This handler do not modify the gpt partition (type, size, ...), it just writes +the image in the GPT partition. + +:: + + images: ( + { + filename = "u-boot.bin"; + type = "gptpart"; + device = "/dev/vdb"; + volume = "u-boot-1"; + }, + { + filename = "kernel.bin"; + type = "gptpart"; + device = "/dev/vdb"; + volume = "kernel-1"; + }, + ); + gpt partition swap .................. diff --git a/handlers/diskpart_handler.c b/handlers/diskpart_handler.c index 925976b..7408ee6 100644 --- a/handlers/diskpart_handler.c +++ b/handlers/diskpart_handler.c @@ -907,6 +907,114 @@ static int diskpart_reread_partition(char *device) return ret; } +static int install_gpt_partition_image(struct img_type *img, + void __attribute__ ((__unused__)) *data) +{ + struct fdisk_context *cxt = NULL; + struct diskpart_table *tb = NULL; + int ret = 0; + unsigned long hybrid = 0; + struct hnd_priv priv = { + .labeltype = FDISK_DISKLABEL_DOS, + }; + struct create_table *createtable = NULL; + struct fdisk_partition *pa; + size_t partno; + char node[64]; + int fdout; + + LIST_INIT(&priv.listparts); + if (!strlen(img->device)) { + ERROR("Partition handler without setting the device"); + return -EINVAL; + } + + createtable = calloc(1, sizeof(*createtable)); + if (!createtable) { + ERROR("OOM allocating createtable !"); + return -ENOMEM; + } + + /* + * Reads flags: nolock and noinuse + */ + priv.nolock = strtobool(dict_get_value(&img->properties, "nolock")); + priv.noinuse = strtobool(dict_get_value(&img->properties, "noinuse")); + + /* + * Create context + */ + ret = diskpart_assign_context(&cxt, img, priv, hybrid, createtable); + if (ret == -EACCES) + goto handler_release; + else if (ret) + goto handler_exit; + + tb = calloc(1, sizeof(*tb)); + if (!tb) { + ERROR("OOM loading partitions !"); + ret = -ENOMEM; + goto handler_exit; + } + + /* + * Fill the in-memory partition table from the disk. + */ + ret = diskpart_get_partitions(cxt, tb, createtable); + if (ret) + goto handler_exit; + + /* + * Search partition to update + */ + pa = diskpart_get_partition_by_name(tb, img->volname); + if (!pa) { + ERROR("Can't find partition %s", img->volname); + ret = -1; + goto handler_exit; + } + + /* + * Open the node of the partition + */ + partno = fdisk_partition_get_partno(pa); + snprintf(node, sizeof(node), "%s%zu", img->device, partno + 1); + fdout = open(node, O_RDWR); + if (fdout < 0) { + ERROR("Node %s cannot be opened", node); + ret = -1; + goto handler_exit; + } + + /* + * Write image + */ + if (copyimage(&fdout, img, NULL) < 0) { + ERROR("Error copying extracted file"); + ret = -1; + goto handler_close; + } + +handler_close: + close(fdout); + +handler_exit: + if (tb) + diskpart_unref_table(tb); + if (cxt && fdisk_get_devfd(cxt) >= 0) + if (fdisk_deassign_device(cxt, 0)) + WARN("Error deassign device %s", img->device); + +handler_release: + if (cxt) + diskpart_unref_context(cxt); + + if (createtable) + free(createtable); + + return ret; +} + static int diskpart(struct img_type *img, void __attribute__ ((__unused__)) *data) { @@ -1472,3 +1580,10 @@ void diskpart_gpt_swap_partition(void) register_handler("gptswap", gpt_swap_partition, SCRIPT_HANDLER | NO_DATA_HANDLER, NULL); } + +__attribute__((constructor)) +void diskpart_install_gpt_partition_image(void) +{ + register_handler("gptpart", install_gpt_partition_image, + IMAGE_HANDLER, NULL); +}
Add a handler to write in a GPT partition. With the handler raw, the device of the parition is provided to the raw handler. This handler use a device on the disk that contains the GPT partition and the name of the GPT partition to found the device of the partition to write. For example: images: ( { filename = "u-boot.bin"; type = "gptpart"; device = "/dev/vdb"; volume = "u-boot-1"; }, { filename = "kernel.bin"; type = "gptpart"; device = "/dev/vdb"; volume = "kernel-1"; }, ); Signed-off-by: Philippe Reynes <philippe.reynes@softathome.com> --- Changelog: v2: - rebase on master - add a constructor to register the handler install_gpt_partition_image doc/source/handlers.rst | 24 ++++++++ handlers/diskpart_handler.c | 115 ++++++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+)