Re: [PATCH v7 01/12] tools: mkeficapsule: rework the code a little bit

2021-11-16 Thread AKASHI Takahiro
On Tue, Nov 16, 2021 at 01:19:10PM +0100, Heinrich Schuchardt wrote:
> On 11/16/21 05:32, AKASHI Takahiro wrote:
> > Abstract common routines to make the code easily understandable.
> > No functional change.
> > 
> > Signed-off-by: AKASHI Takahiro 
> > Reviewed-by: Simon Glass 
> > ---
> >   tools/mkeficapsule.c | 223 ++-
> >   1 file changed, 159 insertions(+), 64 deletions(-)
> > 
> > diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
> > index 4995ba4e0c2a..afdcaf7e7933 100644
> > --- a/tools/mkeficapsule.c
> > +++ b/tools/mkeficapsule.c
> > @@ -61,17 +61,122 @@ static void print_usage(void)
> >tool_name);
> >   }
> > 
> > +/**
> > + * read_bin_file - read a firmware binary file
> > + * @bin:   Path to a firmware binary file
> > + * @data:  Pointer to pointer of allocated buffer
> > + * @bin_size:  Size of allocated buffer
> > + *
> > + * Read out a content of binary, @bin, into @data.
> > + * A caller should free @data.
> > + *
> > + * Return:
> > + * * 0  - on success
> > + * * -1 - on failure
> > + */
> > +static int read_bin_file(char *bin, void **data, off_t *bin_size)
> > +{
> > +   FILE *g;
> > +   struct stat bin_stat;
> > +   void *buf;
> > +   size_t size;
> > +   int ret = 0;
> > +
> > +   g = fopen(bin, "r");
> > +   if (!g) {
> > +   printf("cannot open %s\n", bin);
> 
> Error messages should be written to stderr. Use perror(bin) to get a
> message like:
> 
> : No such file or directory
> 
> Or use fprintf(stderr, ...).

OK.
But remember that I have used printf() throughout mkeficapsule.c
even before this patch.
So I will add similar changes in patch#1 for consistency. 

> > +   return -1;
> > +   }
> > +   if (stat(bin, _stat) < 0) {
> > +   printf("cannot determine the size of %s\n", bin);
> > +   ret = -1;
> > +   goto err;
> > +   }
> > +   if (bin_stat.st_size > (u32)~0U) {
> > +   printf("file size is too large: %s\n", bin);
> > +   ret = -1;
> > +   goto err;
> > +   }
> > +   buf = malloc(bin_stat.st_size);
> 
> For a symbolic link st_size is the length of the pathname it contains.
> So this function is of no help here.

Not true.
According to stat() manpage,

"lstat() is identical to stat(), except that if pathname is  a  symbolic
 link,  then  it returns information about the link itself, not the file
 that it refers to."

So stat() is a right system call.


> > +   if (!buf) {
> > +   printf("cannot allocate memory: %zx\n",
> > +  (size_t)bin_stat.st_size);
> > +   ret = -1;
> > +   goto err;
> > +   }
> > +
> > +   size = fread(buf, 1, bin_stat.st_size, g);
> > +   if (size < bin_stat.st_size) {
> 
> fread() reads from a stream which is not necessarily a file but can be a
> named pipe. stat() does not indicate when the stream will end.
> 
> You have to run fread() in a loop until feof() or ferror() indicate that
> there is nothing more to be read from the stream.

No.
"a stream which is not necessarily a file but can be a named pipe"
may be true, but we don't handle such a use case with this tool.

-Takahiro Akashi

> Best regards
> 
> Heinrich
> 
> > +   printf("read failed (%zx)\n", size);
> > +   ret = -1;
> > +   goto err;
> > +   }
> > +
> > +   *data = buf;
> > +   *bin_size = bin_stat.st_size;
> > +err:
> > +   fclose(g);
> > +
> > +   return ret;
> > +}
> > +
> > +/**
> > + * write_capsule_file - write a capsule file
> > + * @bin:   FILE stream
> > + * @data:  Pointer to data
> > + * @bin_size:  Size of data
> > + *
> > + * Write out data, @data, with the size @bin_size.
> > + *
> > + * Return:
> > + * * 0  - on success
> > + * * -1 - on failure
> > + */
> > +static int write_capsule_file(FILE *f, void *data, size_t size, const char 
> > *msg)
> > +{
> > +   size_t size_written;
> > +
> > +   size_written = fwrite(data, 1, size, f);
> > +   if (size_written < size) {
> > +   printf("%s: write failed (%zx != %zx)\n", msg,
> > +  size_written, size);
> > +   return -1;
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +/**
> > + * create_fwbin - create an uefi capsule file
> > + * @path:  Path to a created capsule file
> > + * @bin:   Path to a firmware binary to encapsulate
> > + * @guid:  GUID of related FMP driver
> > + * @index: Index number in capsule
> > + * @instance:  Instance number in capsule
> > + * @mcount:Monotonic count in authentication information
> > + * @private_file:  Path to a private key file
> > + * @cert_file: Path to a certificate file
> > + *
> > + * This function actually does the job of creating an uefi capsule file.
> > + * All the arguments must be supplied.
> > + * If either @private_file ror @cert_file is NULL, the capsule file
> > + * won't be signed.
> > + *
> > + * Return:
> > + * * 0  - on success
> > + * * -1 - on failure
> > + */
> >   static int create_fwbin(char *path, char *bin, efi_guid_t 

Re: [PATCH v7 01/12] tools: mkeficapsule: rework the code a little bit

2021-11-16 Thread Heinrich Schuchardt

On 11/16/21 05:32, AKASHI Takahiro wrote:

Abstract common routines to make the code easily understandable.
No functional change.

Signed-off-by: AKASHI Takahiro 
Reviewed-by: Simon Glass 
---
  tools/mkeficapsule.c | 223 ++-
  1 file changed, 159 insertions(+), 64 deletions(-)

diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
index 4995ba4e0c2a..afdcaf7e7933 100644
--- a/tools/mkeficapsule.c
+++ b/tools/mkeficapsule.c
@@ -61,17 +61,122 @@ static void print_usage(void)
   tool_name);
  }

+/**
+ * read_bin_file - read a firmware binary file
+ * @bin:   Path to a firmware binary file
+ * @data:  Pointer to pointer of allocated buffer
+ * @bin_size:  Size of allocated buffer
+ *
+ * Read out a content of binary, @bin, into @data.
+ * A caller should free @data.
+ *
+ * Return:
+ * * 0  - on success
+ * * -1 - on failure
+ */
+static int read_bin_file(char *bin, void **data, off_t *bin_size)
+{
+   FILE *g;
+   struct stat bin_stat;
+   void *buf;
+   size_t size;
+   int ret = 0;
+
+   g = fopen(bin, "r");
+   if (!g) {
+   printf("cannot open %s\n", bin);


Error messages should be written to stderr. Use perror(bin) to get a
message like:

: No such file or directory

Or use fprintf(stderr, ...).


+   return -1;
+   }
+   if (stat(bin, _stat) < 0) {
+   printf("cannot determine the size of %s\n", bin);
+   ret = -1;
+   goto err;
+   }
+   if (bin_stat.st_size > (u32)~0U) {
+   printf("file size is too large: %s\n", bin);
+   ret = -1;
+   goto err;
+   }
+   buf = malloc(bin_stat.st_size);


For a symbolic link st_size is the length of the pathname it contains.
So this function is of no help here.


+   if (!buf) {
+   printf("cannot allocate memory: %zx\n",
+  (size_t)bin_stat.st_size);
+   ret = -1;
+   goto err;
+   }
+
+   size = fread(buf, 1, bin_stat.st_size, g);
+   if (size < bin_stat.st_size) {


fread() reads from a stream which is not necessarily a file but can be a
named pipe. stat() does not indicate when the stream will end.

You have to run fread() in a loop until feof() or ferror() indicate that
there is nothing more to be read from the stream.

Best regards

Heinrich


+   printf("read failed (%zx)\n", size);
+   ret = -1;
+   goto err;
+   }
+
+   *data = buf;
+   *bin_size = bin_stat.st_size;
+err:
+   fclose(g);
+
+   return ret;
+}
+
+/**
+ * write_capsule_file - write a capsule file
+ * @bin:   FILE stream
+ * @data:  Pointer to data
+ * @bin_size:  Size of data
+ *
+ * Write out data, @data, with the size @bin_size.
+ *
+ * Return:
+ * * 0  - on success
+ * * -1 - on failure
+ */
+static int write_capsule_file(FILE *f, void *data, size_t size, const char 
*msg)
+{
+   size_t size_written;
+
+   size_written = fwrite(data, 1, size, f);
+   if (size_written < size) {
+   printf("%s: write failed (%zx != %zx)\n", msg,
+  size_written, size);
+   return -1;
+   }
+
+   return 0;
+}
+
+/**
+ * create_fwbin - create an uefi capsule file
+ * @path:  Path to a created capsule file
+ * @bin:   Path to a firmware binary to encapsulate
+ * @guid:  GUID of related FMP driver
+ * @index: Index number in capsule
+ * @instance:  Instance number in capsule
+ * @mcount:Monotonic count in authentication information
+ * @private_file:  Path to a private key file
+ * @cert_file: Path to a certificate file
+ *
+ * This function actually does the job of creating an uefi capsule file.
+ * All the arguments must be supplied.
+ * If either @private_file ror @cert_file is NULL, the capsule file
+ * won't be signed.
+ *
+ * Return:
+ * * 0  - on success
+ * * -1 - on failure
+ */
  static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
unsigned long index, unsigned long instance)
  {
struct efi_capsule_header header;
struct efi_firmware_management_capsule_header capsule;
struct efi_firmware_management_capsule_image_header image;
-   FILE *f, *g;
-   struct stat bin_stat;
-   u8 *data;
-   size_t size;
+   FILE *f;
+   void *data;
+   off_t bin_size;
u64 offset;
+   int ret;

  #ifdef DEBUG
printf("For output: %s\n", path);
@@ -79,25 +184,28 @@ static int create_fwbin(char *path, char *bin, efi_guid_t 
*guid,
printf("\tindex: %ld\n\tinstance: %ld\n", index, instance);
  #endif

-   g = fopen(bin, "r");
-   if (!g) {
-   printf("cannot open %s\n", bin);
-   return -1;
-   }
-   if (stat(bin, _stat) < 0) {
-   printf("cannot determine the size of %s\n", bin);
-   goto err_1;
-   }
-   data = 

[PATCH v7 01/12] tools: mkeficapsule: rework the code a little bit

2021-11-15 Thread AKASHI Takahiro
Abstract common routines to make the code easily understandable.
No functional change.

Signed-off-by: AKASHI Takahiro 
Reviewed-by: Simon Glass 
---
 tools/mkeficapsule.c | 223 ++-
 1 file changed, 159 insertions(+), 64 deletions(-)

diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
index 4995ba4e0c2a..afdcaf7e7933 100644
--- a/tools/mkeficapsule.c
+++ b/tools/mkeficapsule.c
@@ -61,17 +61,122 @@ static void print_usage(void)
   tool_name);
 }
 
+/**
+ * read_bin_file - read a firmware binary file
+ * @bin:   Path to a firmware binary file
+ * @data:  Pointer to pointer of allocated buffer
+ * @bin_size:  Size of allocated buffer
+ *
+ * Read out a content of binary, @bin, into @data.
+ * A caller should free @data.
+ *
+ * Return:
+ * * 0  - on success
+ * * -1 - on failure
+ */
+static int read_bin_file(char *bin, void **data, off_t *bin_size)
+{
+   FILE *g;
+   struct stat bin_stat;
+   void *buf;
+   size_t size;
+   int ret = 0;
+
+   g = fopen(bin, "r");
+   if (!g) {
+   printf("cannot open %s\n", bin);
+   return -1;
+   }
+   if (stat(bin, _stat) < 0) {
+   printf("cannot determine the size of %s\n", bin);
+   ret = -1;
+   goto err;
+   }
+   if (bin_stat.st_size > (u32)~0U) {
+   printf("file size is too large: %s\n", bin);
+   ret = -1;
+   goto err;
+   }
+   buf = malloc(bin_stat.st_size);
+   if (!buf) {
+   printf("cannot allocate memory: %zx\n",
+  (size_t)bin_stat.st_size);
+   ret = -1;
+   goto err;
+   }
+
+   size = fread(buf, 1, bin_stat.st_size, g);
+   if (size < bin_stat.st_size) {
+   printf("read failed (%zx)\n", size);
+   ret = -1;
+   goto err;
+   }
+
+   *data = buf;
+   *bin_size = bin_stat.st_size;
+err:
+   fclose(g);
+
+   return ret;
+}
+
+/**
+ * write_capsule_file - write a capsule file
+ * @bin:   FILE stream
+ * @data:  Pointer to data
+ * @bin_size:  Size of data
+ *
+ * Write out data, @data, with the size @bin_size.
+ *
+ * Return:
+ * * 0  - on success
+ * * -1 - on failure
+ */
+static int write_capsule_file(FILE *f, void *data, size_t size, const char 
*msg)
+{
+   size_t size_written;
+
+   size_written = fwrite(data, 1, size, f);
+   if (size_written < size) {
+   printf("%s: write failed (%zx != %zx)\n", msg,
+  size_written, size);
+   return -1;
+   }
+
+   return 0;
+}
+
+/**
+ * create_fwbin - create an uefi capsule file
+ * @path:  Path to a created capsule file
+ * @bin:   Path to a firmware binary to encapsulate
+ * @guid:  GUID of related FMP driver
+ * @index: Index number in capsule
+ * @instance:  Instance number in capsule
+ * @mcount:Monotonic count in authentication information
+ * @private_file:  Path to a private key file
+ * @cert_file: Path to a certificate file
+ *
+ * This function actually does the job of creating an uefi capsule file.
+ * All the arguments must be supplied.
+ * If either @private_file ror @cert_file is NULL, the capsule file
+ * won't be signed.
+ *
+ * Return:
+ * * 0  - on success
+ * * -1 - on failure
+ */
 static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
unsigned long index, unsigned long instance)
 {
struct efi_capsule_header header;
struct efi_firmware_management_capsule_header capsule;
struct efi_firmware_management_capsule_image_header image;
-   FILE *f, *g;
-   struct stat bin_stat;
-   u8 *data;
-   size_t size;
+   FILE *f;
+   void *data;
+   off_t bin_size;
u64 offset;
+   int ret;
 
 #ifdef DEBUG
printf("For output: %s\n", path);
@@ -79,25 +184,28 @@ static int create_fwbin(char *path, char *bin, efi_guid_t 
*guid,
printf("\tindex: %ld\n\tinstance: %ld\n", index, instance);
 #endif
 
-   g = fopen(bin, "r");
-   if (!g) {
-   printf("cannot open %s\n", bin);
-   return -1;
-   }
-   if (stat(bin, _stat) < 0) {
-   printf("cannot determine the size of %s\n", bin);
-   goto err_1;
-   }
-   data = malloc(bin_stat.st_size);
-   if (!data) {
-   printf("cannot allocate memory: %zx\n", 
(size_t)bin_stat.st_size);
-   goto err_1;
-   }
+   f = NULL;
+   data = NULL;
+   ret = -1;
+
+   /*
+* read a firmware binary
+*/
+   if (read_bin_file(bin, , _size))
+   goto err;
+
+   /*
+* write a capsule file
+*/
f = fopen(path, "w");
if (!f) {
printf("cannot open %s\n", path);
-   goto err_2;
+   goto err;
}
+
+   /*
+*