[PATCH 1/1] bg_utils: Use own code of used parted functions

58 views
Skip to first unread message

Reichel Andreas

unread,
Jul 3, 2017, 8:35:42 AM7/3/17
to efibootg...@googlegroups.com, Reichel Andreas
Due to license conflict between libparted and efibootguard,
libparted cannot be used. Instead, needed code is reimplemented
from scratch.

Signed-off-by: Andreas Reichel <andreas.r...@siemens.com>
---
Makefile.am | 4 +-
swupdate-adapter/Makefile | 54 -----
tools/bg_utils.h | 2 +-
tools/ebgpart.c | 447 ++++++++++++++++++++++++++++++++++++++++++
tools/ebgpart.h | 132 +++++++++++++
tools/tests/Makefile | 10 +-
tools/tests/test_partitions.c | 27 +--
7 files changed, 591 insertions(+), 85 deletions(-)
delete mode 100644 swupdate-adapter/Makefile
create mode 100644 tools/ebgpart.c
create mode 100644 tools/ebgpart.h

diff --git a/Makefile.am b/Makefile.am
index 73da593..7745bb1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -42,6 +42,7 @@ lib_LIBRARIES = libebgenv.a libbg_utils.a

libebgenv_a_SOURCES = \
tools/bg_utils.c \
+ tools/ebgpart.c \
swupdate-adapter/ebgenv.c

libebgenv_a_CPPFLAGS = \
@@ -52,6 +53,7 @@ libebgenv_a_CFLAGS = \
$(AM_CFLAGS)

libbg_utils_a_SOURCES = \
+ tools/ebgpart.c \
tools/bg_utils.c

libbg_utils_a_CFLAGS = \
@@ -67,6 +69,7 @@ pkginclude_HEADERS = \
bin_PROGRAMS = bg_setenv

bg_setenv_SOURCES = \
+ tools/ebgpart.c \
tools/bg_setenv.c

bg_setenv_CFLAGS = \
@@ -74,7 +77,6 @@ bg_setenv_CFLAGS = \

bg_setenv_LDADD = \
-lbg_utils \
- -lparted \
-lz

bg_setenv_DEPENDENCIES = \
diff --git a/swupdate-adapter/Makefile b/swupdate-adapter/Makefile
deleted file mode 100644
index bd826e3..0000000
--- a/swupdate-adapter/Makefile
+++ /dev/null
@@ -1,54 +0,0 @@
-#
-# EFI Boot Guard FAT Environment Tool
-#
-# Copyright (c) Siemens AG, 2017
-#
-# Authors:
-# Andreas Reichel <andreas.r...@siemens.com>
-#
-# This work is licensed under the terms of the GNU GPL, version 2. See
-# the COPYING file in the top-level directory.
-#
-
-ARCH := $(shell uname -m)
-
-CC = $(CROSS_COMPILE)gcc
-LD = $(CROSS_COMPILE)ld
-AR = $(CROSS_COMPILE)ar
-OBJCOPY = $(CROSS_COMPILE)objcopy
-
-INCLUDE = /usr/include
-
-CFLAGS = \
- -I$(shell pwd) \
- -I$(shell pwd)/../include \
- -I$(shell pwd)/../tools \
- -I$(INCLUDE) \
- -std=gnu99 \
-
-DEFINES = \
- -DHAVE_ENDIAN_H \
- -D_GNU_SOURCE
-
-ifneq ($(DEBUG),)
-DEFINES += -DDEBUG
-endif
-
-CFLAGS += \
- -fshort-wchar
-
-LIBS = -lparted \
- -lbg_utils
-
-OBJS = ../tools/bg_utils.o
-
-libebgenv.a: $(OBJS) ebgenv.o
- $(AR) rcs $@ $^
-
-%.o: %.c
- $(CC) $(CFLAGS) $(DEFINES) -c $< -o $@
-
-clean:
- @rm -rf *.o *.a
-
-.PHONY: clean
diff --git a/tools/bg_utils.h b/tools/bg_utils.h
index eb52877..70727e9 100644
--- a/tools/bg_utils.h
+++ b/tools/bg_utils.h
@@ -27,7 +27,7 @@
#include <sys/file.h>
#include <sys/mount.h>

-#include <parted/parted.h>
+#include "ebgpart.h"

#include <zlib.h>
#include "envdata.h"
diff --git a/tools/ebgpart.c b/tools/ebgpart.c
new file mode 100644
index 0000000..5ed67bd
--- /dev/null
+++ b/tools/ebgpart.c
@@ -0,0 +1,447 @@
+/*
+ * EFI Boot Guard
+ *
+ * Copyright (c) Siemens AG, 2017
+ *
+ * Authors:
+ * Andreas Reichel <andreas.r...@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ *
+ * This code replaces libparted and provides reimplemented routines to
+ * be able to scan for FAT partitions in DOS/GPT partition tables.
+ */
+
+#include "ebgpart.h"
+
+PedDevice *firstDevice = NULL;
+PedDisk g_ped_dummy_disk;
+char buffer[37];
+
+bool verbosity = false;
+
+void ebgpart_beverbose(bool v)
+{
+ verbosity = v;
+}
+
+void addBlockDev(PedDevice *dev)
+{
+ if (!firstDevice) {
+ firstDevice = dev;
+ return;
+ }
+ PedDevice *d = firstDevice;
+ while (d->next) {
+ d = d->next;
+ }
+ d->next = dev;
+}
+
+char *GUIDtoStr(uint8_t *g)
+{
+ snprintf(buffer, 37, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%"
+ "02X%02X%02X%02X%02X",
+ g[3], g[2], g[1], g[0], g[5], g[4], g[7], g[6], g[8], g[9],
+ g[10], g[11], g[12], g[13], g[14], g[15]);
+ return buffer;
+}
+
+char *typeToName(char t)
+{
+ switch (t) {
+ case MBR_TYPE_FAT12:
+ return "fat12";
+ break;
+ case MBR_TYPE_FAT16A:
+ case MBR_TYPE_FAT16:
+ case MBR_TYPE_FAT16_LBA:
+ return "fat16";
+ break;
+ case MBR_TYPE_FAT32:
+ case MBR_TYPE_FAT32_LBA:
+ return "fat32";
+ break;
+ case MBR_TYPE_EXTENDED_LBA:
+ case MBR_TYPE_EXTENDED:
+ return "extended";
+ break;
+ default:
+ return "not supported";
+ break;
+ }
+}
+
+bool checkGPTFATEntry(int fd, struct EFIpartitionentry *e,
+ PedFileSystemType *pfst, uint32_t i)
+{
+ if (strcmp(GPT_PARTITION_GUID_FAT_NTFS, GUIDtoStr(e->type_GUID)) != 0 &&
+ strcmp(GPT_PARTITION_GUID_ESP, GUIDtoStr(e->type_GUID)) != 0) {
+ asprintf(&pfst->name, "not supported");
+ return true;
+ }
+ VERBOSE(stdout, "GPT Partition #%u is FAT/NTFS.\n", i);
+ /* Save current file offset */
+ errno = 0;
+ off64_t curr = lseek64(fd, 0, SEEK_CUR);
+ if (errno) {
+ VERBOSE(stderr, "Error getting current seek position: %s\n",
+ strerror(errno));
+ return false;
+ }
+ /* Look if it is a FAT12 or FAT16 */
+ errno = 0;
+ lseek64(fd, e->start_LBA * LB_SIZE + 0x36, SEEK_SET);
+ if (errno) {
+ VERBOSE(stderr, "Error seeking FAT12/16 Id String: %s\n",
+ strerror(errno));
+ return false;
+ }
+ char FATname[9];
+ if (read(fd, FATname, 8) != 8) {
+ VERBOSE(stderr, "Error reading FAT12/16 Id String: %s\n",
+ strerror(errno));
+ return false;
+ };
+ FATname[9] = 0;
+ if (strcmp(FATname, "FAT12 ") != 0 &&
+ strcmp(FATname, "FAT16 ") != 0) {
+ /* No FAT12/16 so read ID field for FAT32 */
+ errno = 0;
+ lseek64(fd, e->start_LBA * LB_SIZE + 0x52, SEEK_SET);
+ if (errno) {
+ VERBOSE(stderr, "Error seeking FAT32 Id String: %s\n",
+ strerror(errno));
+ return false;
+ }
+ errno = 0;
+ if (read(fd, FATname, 8) != 8) {
+ VERBOSE(stderr, "Error reading FAT32 Id String: %s\n",
+ strerror(errno));
+ return false;
+ }
+ }
+ if (strcmp(FATname, "FAT12 ") == 0) {
+ asprintf(&pfst->name, "fat12");
+ } else if (strcmp(FATname, "FAT16 ") == 0) {
+ asprintf(&pfst->name, "fat16");
+ } else {
+ asprintf(&pfst->name, "fat32");
+ }
+ VERBOSE(stdout, "GPT Partition #%u is %s.\n", i, pfst->name);
+ errno = 0;
+ lseek64(fd, curr, SEEK_SET);
+ if (errno) {
+ VERBOSE(stderr, "Error restoring seek position (%s)",
+ strerror(errno));
+ return false;
+ }
+ return true;
+}
+
+void readGPTEntries(int fd, uint64_t tableLBA, uint32_t num, PedDevice *dev)
+{
+ off64_t offset;
+ struct EFIpartitionentry e;
+ PedPartition *partition = NULL, *tmpp;
+ PedFileSystemType *pfst = NULL;
+
+ offset = LB_SIZE * tableLBA;
+ if (lseek64(fd, offset, SEEK_SET) != offset) {
+ VERBOSE(stderr, "Error seeking EFI partition table\n");
+ return;
+ }
+
+ for (uint32_t i = 0; i < num; i++) {
+ errno = 0;
+ if (read(fd, &e, sizeof(e)) != sizeof(e)) {
+ VERBOSE(stderr, "Error reading partition entry\n");
+ VERBOSE(stderr, "(%s)\n", strerror(errno));
+ return;
+ }
+ if ((*((uint64_t *)&e.type_GUID[0]) == 0) &&
+ (*((uint64_t *)&e.type_GUID[8]) == 0)) {
+ return;
+ }
+ VERBOSE(stdout, "%u: %s\n", i, GUIDtoStr(e.type_GUID));
+ pfst = calloc(sizeof(PedFileSystemType), 1);
+ if (!pfst) {
+ VERBOSE(stderr, "Out of memory\n");
+ return;
+ }
+ tmpp = partition;
+ if (!partition) {
+ partition = calloc(sizeof(PedPartition), 1);
+ if (!partition) {
+ VERBOSE(stderr, "Out of memory\n");
+ free(pfst);
+ return;
+ }
+ dev->part_list = partition;
+ } else {
+ partition->next = calloc(sizeof(PedPartition), 1);
+ if (!partition->next) {
+ VERBOSE(stderr, "Out of memory\n");
+ free(pfst);
+ return;
+ }
+ partition = partition->next;
+ }
+ partition->num = i + 1;
+ partition->fs_type = pfst;
+ if (!checkGPTFATEntry(fd, &e, pfst, i)) {
+ if (pfst->name) free(pfst->name);
+ free(pfst);
+ free(partition);
+ partition = tmpp;
+ if (!partition) {
+ dev->part_list = NULL;
+ }
+ }
+ }
+}
+
+void scanLogicalVolumes(int fd, off64_t extended_start_LBA,
+ struct Masterbootrecord *ebr, int i,
+ PedPartition *partition, int lognum)
+{
+ struct Masterbootrecord next_ebr;
+ PedFileSystemType *pfst;
+
+ off64_t offset = extended_start_LBA + ebr->parttable[i].start_LBA;
+ if (extended_start_LBA == 0) {
+ extended_start_LBA = offset;
+ }
+ VERBOSE(stdout, "Seeking to LBA %u\n", offset);
+ errno = 0;
+ off64_t res = lseek64(fd, offset * LB_SIZE, SEEK_SET);
+ if (errno) {
+ VERBOSE(stderr, "(%s)\n", strerror(errno));
+ return;
+ }
+ VERBOSE(stdout, "Seek returned %llu\n", res);
+ errno = 0;
+ read(fd, &next_ebr, sizeof(next_ebr));
+ if (errno) {
+ VERBOSE(stderr, "Error reading next EBR (%s)\n",
+ strerror(errno));
+ return;
+ }
+ if (next_ebr.mbrsignature != 0xaa55) {
+ VERBOSE(stderr, "Wrong signature of extended boot record.\n");
+ return;
+ }
+
+ for (uint8_t j = 0; j < 4; j++) {
+ uint8_t t = next_ebr.parttable[j].partition_type;
+ if (t == 0) {
+ return;
+ }
+ if (t == MBR_TYPE_EXTENDED || t == MBR_TYPE_EXTENDED_LBA) {
+ VERBOSE(stdout, "Next EBR found.\n");
+ scanLogicalVolumes(fd, extended_start_LBA, &next_ebr, j,
+ partition, lognum + 1);
+ continue;
+ }
+ partition->next = calloc(sizeof(PedPartition), 1);
+ if (!partition->next) {
+ VERBOSE(stderr, "Out of memory\n");
+ return;
+ }
+ pfst = calloc(sizeof(PedFileSystemType), 1);
+ if (!pfst) {
+ VERBOSE(stderr, "Out of memory\n");
+ free(partition->next);
+ return;
+ }
+ if (asprintf(&pfst->name, typeToName(t)) == -1) {
+ VERBOSE(stderr, "Out of memory\n");
+ free(partition->next);
+ free(pfst);
+ return;
+ };
+ partition = partition->next;
+ partition->num = lognum;
+ partition->fs_type = pfst;
+ }
+}
+
+bool checkPartitionTable(PedDevice *dev)
+{
+ int fd;
+ struct Masterbootrecord mbr;
+
+ if ((fd = open(dev->path, O_RDONLY)) == 0) {
+ VERBOSE(stderr, "Error opening block device.\n");
+ return false;
+ }
+ if (read(fd, &mbr, sizeof(mbr)) != sizeof(mbr)) {
+ VERBOSE(stderr, "Error reading mbr.\n");
+ close(fd);
+ return false;
+ };
+ if (mbr.mbrsignature != 0xaa55) {
+ VERBOSE(stderr, "Error, MBR has wrong signature.\n");
+ close(fd);
+ return false;
+ }
+ int partitions = 0;
+ PedFileSystemType *pfst;
+ PedPartition *partition = NULL;
+ for (int i = 0; i < 4; i++) {
+ if (mbr.parttable[i].partition_type == 0) {
+ continue;
+ }
+ partitions++;
+ VERBOSE(stdout, "Partition %u: Type %X\n", i,
+ mbr.parttable[i].partition_type);
+ uint8_t t = mbr.parttable[i].partition_type;
+ if (t == MBR_TYPE_GPT) {
+ VERBOSE(stdout, "GPT header at %X\n",
+ mbr.parttable[i].start_LBA);
+ off64_t offset = LB_SIZE * mbr.parttable[i].start_LBA;
+ errno = 0;
+ if (lseek64(fd, offset, SEEK_SET) != offset) {
+ VERBOSE(stderr, "Error seeking EFI Header\n.");
+ VERBOSE(stderr, "(%s)", strerror(errno));
+ return false;
+ }
+ struct EFIHeader efihdr;
+ errno = 0;
+ if (read(fd, &efihdr, sizeof(efihdr)) !=
+ sizeof(efihdr)) {
+ VERBOSE(stderr, "Error reading EFI Header\n.");
+ VERBOSE(stderr, "(%s)", strerror(errno));
+ return false;
+ }
+ VERBOSE(stdout, "EFI Header: %X %X %X %X %X %X %X %X\n",
+ efihdr.signature[0], efihdr.signature[1],
+ efihdr.signature[2], efihdr.signature[3],
+ efihdr.signature[4], efihdr.signature[5],
+ efihdr.signature[6], efihdr.signature[7]);
+ VERBOSE(stdout, "Number of partition entries: %u\n",
+ efihdr.partitions);
+ VERBOSE(stdout, "Partition Table @ LBA %llu\n",
+ efihdr.partitiontable_LBA);
+ readGPTEntries(fd, efihdr.partitiontable_LBA,
+ efihdr.partitions, dev);
+ break;
+ } else {
+ pfst = calloc(sizeof(PedFileSystemType), 1);
+ if (!partition) {
+ partition = calloc(sizeof(PedPartition), 1);
+ dev->part_list = partition;
+ } else {
+ partition->next =
+ calloc(sizeof(PedPartition), 1);
+ partition = partition->next;
+ }
+ partition->num = i + 1;
+ partition->fs_type = pfst;
+
+ if (t == MBR_TYPE_EXTENDED ||
+ t == MBR_TYPE_EXTENDED_LBA) {
+ asprintf(&pfst->name, "extended");
+ scanLogicalVolumes(fd, 0, &mbr, i, partition,
+ 5);
+ } else {
+ asprintf(&pfst->name, typeToName(t));
+ }
+ }
+ }
+ (void)close(fd);
+ if (partitions == 0) {
+ return false;
+ }
+ return true;
+}
+
+void ped_device_probe_all()
+{
+ int blkdev;
+ struct dirent *devfile;
+ char fullname[256];
+
+ DIR *devdir = opendir("/dev");
+ if (!devdir) {
+ VERBOSE(stderr, "Could not open /dev\n");
+ return;
+ }
+
+ /* get all files from devdir */
+ while ((devfile = readdir(devdir)) != NULL) {
+ struct stat s;
+ char lastletter = devfile->d_name[strlen(devfile->d_name) - 1];
+ if (lastletter <= '9') {
+ /* do not handle linux partition block devices, i.e.
+ * /dev/sda5, but only /dev/sda */
+ continue;
+ }
+ snprintf(fullname, 255, "%s/%s", DEVDIRNAME, devfile->d_name);
+ if (lstat(fullname, &s) != 0) {
+ continue;
+ };
+ if (S_ISBLK(s.st_mode)) {
+ /* This is a block device, so add it to the list*/
+ PedDevice *dev = calloc(sizeof(PedDevice), 1);
+ asprintf(&dev->model, "N/A");
+ asprintf(&dev->path, "%s", fullname);
+ if (checkPartitionTable(dev)) {
+ addBlockDev(dev);
+ } else {
+ free(dev->model);
+ free(dev->path);
+ free(dev);
+ }
+ }
+ }
+ (void)closedir(devdir);
+}
+
+PedDevice *ped_device_get_next(PedDevice *dev)
+{
+ if (!dev) {
+ return firstDevice;
+ }
+ if (dev->next != NULL) {
+ return dev->next;
+ }
+ /* free all memory */
+ PedDevice *d = firstDevice;
+ PedDevice *tmpd;
+
+ while (d) {
+ tmpd = d;
+ d = d->next;
+ if (tmpd->model) free(tmpd->model);
+ if (tmpd->path) free(tmpd->path);
+ PedPartition *p = tmpd->part_list;
+ PedPartition *tmpp;
+ while (p) {
+ tmpp = p;
+ p = p->next;
+ if (tmpp->fs_type) {
+ if (tmpp->fs_type->name)
+ free(tmpp->fs_type->name);
+ free(tmpp->fs_type);
+ }
+ free(tmpp);
+ }
+ free(tmpd);
+ }
+ return NULL;
+}
+
+PedDisk *ped_disk_new(PedDevice *dev)
+{
+ g_ped_dummy_disk.part_list = dev->part_list;
+ return &g_ped_dummy_disk;
+}
+
+PedPartition *ped_disk_next_partition(PedDisk *pd, PedPartition *part)
+{
+ (void)pd;
+ return part->next;
+}
diff --git a/tools/ebgpart.h b/tools/ebgpart.h
new file mode 100644
index 0000000..44effb5
--- /dev/null
+++ b/tools/ebgpart.h
@@ -0,0 +1,132 @@
+/*
+ * EFI Boot Guard
+ *
+ * Copyright (c) Siemens AG, 2017
+ *
+ * Authors:
+ * Andreas Reichel <andreas.r...@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ *
+ * This code replaces libparted and provides reimplemented routines to
+ * be able to scan for FAT partitions in DOS/GPT partition tables.
+ */
+
+#ifndef __EBGPART_H__
+#define __EBGPART_H__
+
+#ifndef _LARGEFILE64_SOURCE
+#define _LARGEFILE64_SOURCE
+#endif
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#ifndef VERBOSE
+#define VERBOSE(o, ...) \
+ if (verbosity) fprintf(o, __VA_ARGS__)
+#endif
+
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <string.h>
+#include <stdlib.h>
+
+#define DEVDIRNAME "/dev"
+
+#define LB_SIZE 512
+
+#define MBR_TYPE_GPT 0xEE
+#define MBR_TYPE_FAT12 0x01
+#define MBR_TYPE_FAT16A 0x04
+#define MBR_TYPE_FAT16 0x06
+#define MBR_TYPE_EXTENDED 0x05
+#define MBR_TYPE_FAT32 0x0B
+#define MBR_TYPE_FAT32_LBA 0x0C
+#define MBR_TYPE_FAT16_LBA 0x0E
+#define MBR_TYPE_EXTENDED_LBA 0x0F
+
+#define GPT_PARTITION_GUID_FAT_NTFS "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7"
+#define GPT_PARTITION_GUID_ESP "C12A7328-F81F-11D2-BA4B-00A0C93EC93B"
+
+#pragma pack(push)
+#pragma pack(1)
+struct MBRentry {
+ uint8_t boot_flag;
+ uint8_t first_sector_chs[3];
+ uint8_t partition_type;
+ uint8_t last_sector_chs[3];
+ uint32_t start_LBA;
+ uint32_t num_Sectors;
+};
+struct Masterbootrecord {
+ char bootloader[0x1B8];
+ char devsignature[4];
+ char mbr_padding[2];
+ struct MBRentry parttable[4];
+ uint16_t mbrsignature;
+};
+struct EFIHeader {
+ char signature[8];
+ uint32_t revision;
+ uint32_t header_size;
+ uint32_t header_crc32;
+ uint32_t reserved;
+ uint64_t this_LBA;
+ uint64_t backup_LBA;
+ uint64_t firstentry_LBA;
+ uint64_t lastentry_LBA;
+ uint8_t GUID[16];
+ uint64_t partitiontable_LBA;
+ uint32_t partitions;
+ uint32_t partitionentrysize;
+ uint32_t partitiontable_CRC32;
+ uint32_t reserved2[420];
+};
+struct EFIpartitionentry {
+ uint8_t type_GUID[16];
+ uint8_t partition_GUID[16];
+ uint64_t start_LBA;
+ uint64_t end_LBA;
+ uint64_t attribute;
+ uint16_t name[36];
+};
+#pragma pack(pop)
+
+/* Implementing a minimalistic API replacing used libparted functions */
+typedef struct _PedFileSystemType {
+ char *name;
+} PedFileSystemType;
+
+typedef struct _PedPartition {
+ PedFileSystemType *fs_type;
+ uint16_t num;
+ struct _PedPartition *next;
+} PedPartition;
+
+typedef struct _PedDevice {
+ char *model;
+ char *path;
+ PedPartition *part_list;
+ struct _PedDevice *next;
+} PedDevice;
+
+typedef struct _PedDisk {
+ PedPartition *part_list;
+} PedDisk;
+
+void ped_device_probe_all();
+PedDevice *ped_device_get_next(PedDevice *dev);
+PedDisk *ped_disk_new(PedDevice *dev);
+PedPartition *ped_disk_next_partition(PedDisk *pd, PedPartition *part);
+
+#endif // __EBGPART_H__
diff --git a/tools/tests/Makefile b/tools/tests/Makefile
index 68c1495..ff66742 100644
--- a/tools/tests/Makefile
+++ b/tools/tests/Makefile
@@ -38,10 +38,9 @@ endif
CFLAGS += \
-fshort-wchar

-LIBS = -L.. \
+LIBS = -L../.. \
-L../../swupdate-adapter \
-lcmocka \
- -lparted \
-lebgenv \
-lz

@@ -52,11 +51,11 @@ LIBS = -L.. \
# dependency recipes.
# All targets' '.target' extensions get removed within the target recipes.
#
-OBJS_test_partitions = test_partitions.O bg_utils.O
-OBJS_test_environment = test_environment.O bg_utils.O
+OBJS_test_partitions = test_partitions.O bg_utils.O ebgpart.O
+OBJS_test_environment = test_environment.O bg_utils.O ebgpart.O
OBJS_test_api = test_api.O bg_utils.O ebgenv.O

-MOCKOBJS_test_partitions = bg_utils
+MOCKOBJS_test_partitions = bg_utils ebgpart
MOCKOBJS_test_environment = bg_utils
MOCKOBJS_test_api = bg_utils

@@ -66,6 +65,7 @@ MOCKOBJS_test_api = bg_utils
MOCKOBJS_SYMBOLS_bg_utils-test_partitions = probe_config_file
MOCKOBJS_SYMBOLS_bg_utils-test_environment = oldenvs configparts fopen fclose fread fwrite feof mount_partition
MOCKOBJS_SYMBOLS_bg_utils-test_api = bgenv_init bgenv_write bgenv_close bgenv_get_latest bgenv_get_by_index bgenv_get_oldest
+MOCKOBJS_SYMBOLS_ebgpart-test_partitions = ped_device_probe_all ped_device_get_next ped_disk_next_partition

TEST_TARGETS = test_partitions.target test_environment.target test_api.target

diff --git a/tools/tests/test_partitions.c b/tools/tests/test_partitions.c
index 93c0aef..05b6b41 100644
--- a/tools/tests/test_partitions.c
+++ b/tools/tests/test_partitions.c
@@ -16,13 +16,9 @@
#include <stdbool.h>
#include <setjmp.h>
#include <cmocka.h>
-#include <parted/device.h>
-#include <parted/disk.h>
#include "bg_utils.h"

static PedDevice ped_devices[32] = {0};
-static PedDisk ped_disks[32] = {0};
-static PedDiskType ped_disktypes[32] = {0};
static int num_simulated_devices = 2;
static int curr_ped_device = 0;
static PedPartition ped_parts[32] = {0};
@@ -30,7 +26,6 @@ static int num_simulated_partitions_per_disk = 2;
static PedFileSystemType ped_fstypes[32] = {0};

static const char *const fsname = "fat16";
-static const char *const disktypename = "gpt";

static char *fakemodel = "Mocked Disk Drive";
static char *fakedevice = "/dev/nobrain";
@@ -44,9 +39,7 @@ void ped_device_probe_all()
for (int i = 0; i < 32; i++) {
ped_devices[i].model = fakemodel;
ped_devices[i].path = fakedevice;
- ped_disktypes[i].name = disktypename;
- ped_disks[i].type = &ped_disktypes[i];
- ped_disks[i].part_list = &ped_parts[0];
+ ped_devices[i].part_list = &ped_parts[0];
}

for (int i = 0; i < 32; i++) {
@@ -62,7 +55,7 @@ void ped_device_probe_all()
}
}

-PedDevice *ped_device_get_next(const PedDevice *dev)
+PedDevice *ped_device_get_next(PedDevice *dev)
{
if (dev == NULL) {
return &ped_devices[0];
@@ -75,21 +68,7 @@ PedDevice *ped_device_get_next(const PedDevice *dev)
return NULL;
}

-PedDisk *ped_disk_new(PedDevice *dev)
-{
- if (dev == NULL) {
- return NULL;
- }
- for (int i = 0; i < 32; i++) {
- if (dev == &ped_devices[i]) {
- return &ped_disks[i];
- }
- }
- return NULL;
-}
-
-PedPartition *ped_disk_next_partition(const PedDisk *disk,
- const PedPartition *part)
+PedPartition *ped_disk_next_partition(PedDisk *disk, PedPartition *part)
{
if (disk == NULL) {
return NULL;
--
2.11.0

Reichel Andreas

unread,
Jul 3, 2017, 8:35:42 AM7/3/17
to efibootg...@googlegroups.com, Reichel Andreas
Due to a license conflict between libparted and efibootguard
(GPL v3 vs. v2), efibootguard may not link against libparted.
To resolve this issue, used functions for partition table
scanning have been reimplemented from scratch using the same
API.

Signed-off-by: Andreas Reichel <andreas.r...@siemens.com>

Reichel Andreas (1):
bg_utils: Use own code for used parted functions

Makefile.am | 4 +-
swupdate-adapter/Makefile | 54 -----
tools/bg_utils.h | 2 +-
tools/ebgpart.c | 447 ++++++++++++++++++++++++++++++++++++++++++
tools/ebgpart.h | 132 +++++++++++++
tools/tests/Makefile | 10 +-
tools/tests/test_partitions.c | 27 +--
7 files changed, 591 insertions(+), 85 deletions(-)
delete mode 100644 swupdate-adapter/Makefile
create mode 100644 tools/ebgpart.c
create mode 100644 tools/ebgpart.h

--
2.11.0

Jan Kiszka

unread,
Jul 3, 2017, 9:04:29 AM7/3/17
to [ext] Reichel Andreas, efibootg...@googlegroups.com
I don't think it makes sense to talk about "replacing" here. The
reasoning for reimplementations belongs into the changelog, here (more
consistent would be at the top) should just be a brief statement what
this module is.

> + */
> +
> +#include "ebgpart.h"
> +
> +PedDevice *firstDevice = NULL;
> +PedDisk g_ped_dummy_disk;
> +char buffer[37];
> +
> +bool verbosity = false;

Those vars all need to be public, rather than static?

> +
> +void ebgpart_beverbose(bool v)
> +{
> + verbosity = v;
> +}

Given this accessor, I bet that at least verbosity is a candidate for
static.
The proper pattern would be checking the return code of the service, not
clearing errno and doing this indirectly. That would also avoid this
unneeded "errno = 0;" boilerplate code.
No assignments in if clauses. Separate statements, please.
Which compliler setting enforces this ugly (void)?

> + if (partitions == 0) {
> + return false;
> + }
> + return true;
> +}
> +
> +void ped_device_probe_all()
> +{
> + int blkdev;
> + struct dirent *devfile;
> + char fullname[256];
> +
> + DIR *devdir = opendir("/dev");
> + if (!devdir) {
> + VERBOSE(stderr, "Could not open /dev\n");
> + return;
> + }
> +
> + /* get all files from devdir */
> + while ((devfile = readdir(devdir)) != NULL) {

I'm inclined to request to break this up for the same reasons as if
statements shouldn't do this.
Same here: can we avoid the void?

> +}
> +
> +PedDevice *ped_device_get_next(PedDevice *dev)
> +{
> + if (!dev) {
> + return firstDevice;
> + }
> + if (dev->next != NULL) {
> + return dev->next;
> + }
> + /* free all memory */
> + PedDevice *d = firstDevice;
> + PedDevice *tmpd;
> +
> + while (d) {
> + tmpd = d;
> + d = d->next;
> + if (tmpd->model) free(tmpd->model);
> + if (tmpd->path) free(tmpd->path);

Two lines, for each of the two. This quickly becomes unparsable
There are attributes for declare parameters unused in a nicer way than
this. Or just turn off the compiler switch, it's generally less useful.
Why no longer const?

> {
> if (dev == NULL) {
> return &ped_devices[0];
> @@ -75,21 +68,7 @@ PedDevice *ped_device_get_next(const PedDevice *dev)
> return NULL;
> }
>
> -PedDisk *ped_disk_new(PedDevice *dev)
> -{
> - if (dev == NULL) {
> - return NULL;
> - }
> - for (int i = 0; i < 32; i++) {
> - if (dev == &ped_devices[i]) {
> - return &ped_disks[i];
> - }
> - }
> - return NULL;
> -}
> -
> -PedPartition *ped_disk_next_partition(const PedDisk *disk,
> - const PedPartition *part)
> +PedPartition *ped_disk_next_partition(PedDisk *disk, PedPartition *part)
> {
> if (disk == NULL) {
> return NULL;
>

Thanks for the quick replacement.

Jan

--
Siemens AG, Corporate Technology, CT RDA ITP SES-DE
Corporate Competence Center Embedded Linux

Claudius Heine

unread,
Jul 3, 2017, 10:14:28 AM7/3/17
to [ext] Reichel Andreas, efibootg...@googlegroups.com
Hi Andreas,
errno is only of importance if an error value was returned. So I would
first check the return value (-1 here) and then echo the error string
using errno.
Why is that outside the loop?

> + PedPartition *partition = NULL;

`partition` and `partitions`? Do you really like to make life difficult? ;)

> + for (int i = 0; i < 4; i++) {
> + if (mbr.parttable[i].partition_type == 0) {
> + continue;
> + }
> + partitions++;

Why do you have 2 counter variables? 'i' and 'partitions'
This does look strange. Don't think I ever saw that before. Especially
on a close. The close systemcall is the only (AFAIK) one where ignoring
errors is pretty much normal.

> + if (partitions == 0) {
> + return false;
> + }
> + return true;
> +}
> +
> +void ped_device_probe_all()
> +{
> + int blkdev;
> + struct dirent *devfile;
> + char fullname[256];
> +
> + DIR *devdir = opendir("/dev");

You have a define to this path somewhere. Why not use it?

> + if (!devdir) {
> + VERBOSE(stderr, "Could not open /dev\n");
> + return;
> + }
> +
> + /* get all files from devdir */
> + while ((devfile = readdir(devdir)) != NULL) {

That just hurts. Please seperate assignment and comparison.
Do you like pyramids? Freeing memory is the one place in C where forward
jumping gotos are still acceptable, because they are more readable than
such pyramids.
Are all of these defines necessary for the API you are exporting?
Why are you removing consts?

Cheers,
Claudius

Reichel Andreas

unread,
Jul 3, 2017, 11:28:55 AM7/3/17
to efibootg...@googlegroups.com, Reichel Andreas
Due to a license conflict between libparted and efibootguard
(GPL v3 vs. v2), efibootguard may not link against libparted.
To resolve this issue, used functions for partition table
scanning have been reimplemented from scratch using the same
API.

Signed-off-by: Andreas Reichel <andreas.r...@siemens.com>

Reichel Andreas (1):
bg_utils: Use own code for used parted functions

Makefile.am | 4 +-
swupdate-adapter/Makefile | 54 -----
tools/bg_utils.c | 1 +
tools/bg_utils.h | 2 +-
tools/ebgpart.c | 450 ++++++++++++++++++++++++++++++++++++++++++
tools/ebgpart.h | 135 +++++++++++++
tools/tests/Makefile | 12 +-
tools/tests/test_partitions.c | 25 +--
8 files changed, 598 insertions(+), 85 deletions(-)
delete mode 100644 swupdate-adapter/Makefile
create mode 100644 tools/ebgpart.c
create mode 100644 tools/ebgpart.h

--
2.11.0

Reichel Andreas

unread,
Jul 3, 2017, 11:28:55 AM7/3/17
to efibootg...@googlegroups.com, Reichel Andreas
Due to license conflict between libparted and efibootguard,
libparted cannot be used. Instead, needed code is reimplemented
from scratch.

Signed-off-by: Andreas Reichel <andreas.r...@siemens.com>
---
Makefile.am | 4 +-
swupdate-adapter/Makefile | 54 -----
tools/bg_utils.c | 1 +
tools/bg_utils.h | 2 +-
tools/ebgpart.c | 450 ++++++++++++++++++++++++++++++++++++++++++
tools/ebgpart.h | 135 +++++++++++++
tools/tests/Makefile | 12 +-
tools/tests/test_partitions.c | 25 +--
8 files changed, 598 insertions(+), 85 deletions(-)
delete mode 100644 swupdate-adapter/Makefile
create mode 100644 tools/ebgpart.c
create mode 100644 tools/ebgpart.h

diff --git a/tools/bg_utils.c b/tools/bg_utils.c
index b23b361..36ee279 100644
--- a/tools/bg_utils.c
+++ b/tools/bg_utils.c
@@ -19,6 +19,7 @@ static bool verbosity = false;
void be_verbose(bool v)
{
verbosity = v;
+ ebgpart_beverbose(v);
}

/* UEFI uses 16-bit wide unicode strings.
diff --git a/tools/bg_utils.h b/tools/bg_utils.h
index eb52877..70727e9 100644
--- a/tools/bg_utils.h
+++ b/tools/bg_utils.h
@@ -27,7 +27,7 @@
#include <sys/file.h>
#include <sys/mount.h>

-#include <parted/parted.h>
+#include "ebgpart.h"

#include <zlib.h>
#include "envdata.h"
diff --git a/tools/ebgpart.c b/tools/ebgpart.c
new file mode 100644
index 0000000..edcac3c
--- /dev/null
+++ b/tools/ebgpart.c
@@ -0,0 +1,450 @@
+/*
+ * EFI Boot Guard
+ *
+ * Copyright (c) Siemens AG, 2017
+ *
+ * Authors:
+ * Andreas Reichel <andreas.r...@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ *
+ * This code implements functions to scan for FAT partitions in DOS/GPT
+ * partition tables.
+ */
+
+#include "ebgpart.h"
+
+static PedDevice *firstDevice = NULL;
+static PedDisk g_ped_dummy_disk;
+static char buffer[37];
+
+static bool verbosity = false;
+ off64_t curr = lseek64(fd, 0, SEEK_CUR);
+ if (curr == -1) {
+ VERBOSE(stderr, "Error getting current seek position: %s\n",
+ strerror(errno));
+ return false;
+ }
+ /* Look if it is a FAT12 or FAT16 */
+ off64_t dest = e->start_LBA * LB_SIZE + 0x36;
+ if (lseek64(fd, dest, SEEK_SET) != -1) {
+ VERBOSE(stderr, "Error seeking FAT12/16 Id String: %s\n",
+ strerror(errno));
+ return false;
+ }
+ char FATname[9];
+ if (read(fd, FATname, 8) != 8) {
+ VERBOSE(stderr, "Error reading FAT12/16 Id String: %s\n",
+ strerror(errno));
+ return false;
+ };
+ FATname[9] = 0;
+ if (strcmp(FATname, "FAT12 ") != 0 &&
+ strcmp(FATname, "FAT16 ") != 0) {
+ /* No FAT12/16 so read ID field for FAT32 */
+ dest = e->start_LBA * LB_SIZE + 0x52;
+ if (lseek64(fd, dest, SEEK_SET) == -1) {
+ VERBOSE(stderr, "Error seeking FAT32 Id String: %s\n",
+ strerror(errno));
+ return false;
+ }
+ if (read(fd, FATname, 8) != 8) {
+ VERBOSE(stderr, "Error reading FAT32 Id String: %s\n",
+ strerror(errno));
+ return false;
+ }
+ }
+ if (strcmp(FATname, "FAT12 ") == 0) {
+ asprintf(&pfst->name, "fat12");
+ } else if (strcmp(FATname, "FAT16 ") == 0) {
+ asprintf(&pfst->name, "fat16");
+ } else {
+ asprintf(&pfst->name, "fat32");
+ }
+ VERBOSE(stdout, "GPT Partition #%u is %s.\n", i, pfst->name);
+ if (lseek64(fd, curr, SEEK_SET) != -1) {
+ VERBOSE(stderr, "Error restoring seek position (%s)",
+ strerror(errno));
+ return false;
+ }
+ return true;
+}
+
+void readGPTEntries(int fd, uint64_t tableLBA, uint32_t num, PedDevice *dev)
+{
+ off64_t offset;
+ struct EFIpartitionentry e;
+ PedPartition *partition = NULL, *tmpp;
+ PedFileSystemType *pfst = NULL;
+
+ offset = LB_SIZE * tableLBA;
+ if (lseek64(fd, offset, SEEK_SET) != offset) {
+ VERBOSE(stderr, "Error seeking EFI partition table\n");
+ return;
+ }
+
+ for (uint32_t i = 0; i < num; i++) {
+ off64_t res = lseek64(fd, offset * LB_SIZE, SEEK_SET);
+ if (res == -1) {
+ VERBOSE(stderr, "(%s)\n", strerror(errno));
+ return;
+ }
+ VERBOSE(stdout, "Seek returned %llu\n", res);
+ if (read(fd, &next_ebr, sizeof(next_ebr)) != sizeof(next_ebr)) {
+ fd = open(dev->path, O_RDONLY);
+ if (fd == 0) {
+ VERBOSE(stderr, "Error opening block device.\n");
+ return false;
+ }
+ if (read(fd, &mbr, sizeof(mbr)) != sizeof(mbr)) {
+ VERBOSE(stderr, "Error reading mbr.\n");
+ close(fd);
+ return false;
+ };
+ if (mbr.mbrsignature != 0xaa55) {
+ VERBOSE(stderr, "Error, MBR has wrong signature.\n");
+ close(fd);
+ return false;
+ }
+ int numpartitions = 0;
+ PedPartition *partition = NULL;
+ for (int i = 0; i < 4; i++) {
+ if (mbr.parttable[i].partition_type == 0) {
+ continue;
+ }
+ numpartitions++;
+ VERBOSE(stdout, "Partition %u: Type %X\n", i,
+ mbr.parttable[i].partition_type);
+ uint8_t t = mbr.parttable[i].partition_type;
+ if (t == MBR_TYPE_GPT) {
+ VERBOSE(stdout, "GPT header at %X\n",
+ mbr.parttable[i].start_LBA);
+ off64_t offset = LB_SIZE * mbr.parttable[i].start_LBA;
+ if (lseek64(fd, offset, SEEK_SET) != offset) {
+ VERBOSE(stderr, "Error seeking EFI Header\n.");
+ VERBOSE(stderr, "(%s)", strerror(errno));
+ return false;
+ }
+ struct EFIHeader efihdr;
+ if (read(fd, &efihdr, sizeof(efihdr)) !=
+ sizeof(efihdr)) {
+ VERBOSE(stderr, "Error reading EFI Header\n.");
+ VERBOSE(stderr, "(%s)", strerror(errno));
+ return false;
+ }
+ VERBOSE(stdout, "EFI Header: %X %X %X %X %X %X %X %X\n",
+ efihdr.signature[0], efihdr.signature[1],
+ efihdr.signature[2], efihdr.signature[3],
+ efihdr.signature[4], efihdr.signature[5],
+ efihdr.signature[6], efihdr.signature[7]);
+ VERBOSE(stdout, "Number of partition entries: %u\n",
+ efihdr.partitions);
+ VERBOSE(stdout, "Partition Table @ LBA %llu\n",
+ efihdr.partitiontable_LBA);
+ readGPTEntries(fd, efihdr.partitiontable_LBA,
+ efihdr.partitions, dev);
+ break;
+ } else {
+ PedFileSystemType *pfst =
+ calloc(sizeof(PedFileSystemType), 1);
+ if (!partition) {
+ partition = calloc(sizeof(PedPartition), 1);
+ dev->part_list = partition;
+ } else {
+ partition->next =
+ calloc(sizeof(PedPartition), 1);
+ partition = partition->next;
+ }
+ partition->num = i + 1;
+ partition->fs_type = pfst;
+
+ if (t == MBR_TYPE_EXTENDED ||
+ t == MBR_TYPE_EXTENDED_LBA) {
+ asprintf(&pfst->name, "extended");
+ scanLogicalVolumes(fd, 0, &mbr, i, partition,
+ 5);
+ } else {
+ asprintf(&pfst->name, typeToName(t));
+ }
+ }
+ }
+ close(fd);
+ if (numpartitions == 0) {
+ return false;
+ }
+ return true;
+}
+
+void ped_device_probe_all()
+{
+ int blkdev;
+ struct dirent *devfile;
+ char fullname[256];
+
+ DIR *devdir = opendir(DEVDIRNAME);
+ if (!devdir) {
+ VERBOSE(stderr, "Could not open /dev\n");
+ return;
+ }
+
+ /* get all files from devdir */
+ do {
+ devfile = readdir(devdir);
+ if (!devfile) break;
+ struct stat s;
+ char lastletter = devfile->d_name[strlen(devfile->d_name) - 1];
+ if (lastletter <= '9') {
+ /* do not handle linux partition block devices, i.e.
+ * /dev/sda5, but only /dev/sda */
+ continue;
+ }
+ snprintf(fullname, 255, "%s/%s", DEVDIRNAME, devfile->d_name);
+ if (lstat(fullname, &s) != 0) {
+ continue;
+ };
+ if (S_ISBLK(s.st_mode)) {
+ /* This is a block device, so add it to the list*/
+ PedDevice *dev = calloc(sizeof(PedDevice), 1);
+ asprintf(&dev->model, "N/A");
+ asprintf(&dev->path, "%s", fullname);
+ if (checkPartitionTable(dev)) {
+ addBlockDev(dev);
+ } else {
+ free(dev->model);
+ free(dev->path);
+ free(dev);
+ }
+ }
+ } while (devfile);
+
+ closedir(devdir);
+}
+
+void freePedPartition(PedPartition *p)
+{
+ if (!p) return;
+ if (!p->fs_type) goto fs_type_Null;
+ if (p->fs_type->name) free(p->fs_type->name);
+ free(p->fs_type);
+fs_type_Null:
+ free(p);
+}
+
+void freePedDevice(PedDevice *d)
+{
+ if (!d) return;
+ if (d->model) free(d->model);
+ if (d->path) free(d->path);
+ PedPartition *p = d->part_list;
+ PedPartition *tmpp;
+ while (p) {
+ tmpp = p;
+ p = p->next;
+ freePedPartition(tmpp);
+ }
+ free(d);
+}
+
+PedDevice *ped_device_get_next(const PedDevice *dev)
+{
+ if (!dev) {
+ return firstDevice;
+ }
+ if (dev->next != NULL) {
+ return dev->next;
+ }
+ /* free all memory */
+ PedDevice *d = firstDevice;
+ PedDevice *tmpd;
+
+ while (d) {
+ tmpd = d;
+ d = d->next;
+ freePedDevice(tmpd);
+ }
+ return NULL;
+}
+
+PedDisk *ped_disk_new(const PedDevice *dev)
+{
+ g_ped_dummy_disk.part_list = dev->part_list;
+ return &g_ped_dummy_disk;
+}
+
+PedPartition *ped_disk_next_partition(const PedDisk *pd,
+ const PedPartition *part)
+{
+ return part->next;
+}
diff --git a/tools/ebgpart.h b/tools/ebgpart.h
new file mode 100644
index 0000000..75e7604
--- /dev/null
+++ b/tools/ebgpart.h
@@ -0,0 +1,135 @@
+/*
+ * EFI Boot Guard
+ *
+ * Copyright (c) Siemens AG, 2017
+ *
+ * Authors:
+ * Andreas Reichel <andreas.r...@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ *
+ * This code implements functions to scan for FAT partitions in DOS/GPT
+ * partition tables.
+PedDevice *ped_device_get_next(const PedDevice *dev);
+PedDisk *ped_disk_new(const PedDevice *dev);
+PedPartition *ped_disk_next_partition(const PedDisk *pd,
+ const PedPartition *part);
+
+void ebgpart_beverbose(bool v);
+
+#endif // __EBGPART_H__
diff --git a/tools/tests/Makefile b/tools/tests/Makefile
index 68c1495..d52deaa 100644
@@ -66,12 +65,13 @@ MOCKOBJS_test_api = bg_utils
MOCKOBJS_SYMBOLS_bg_utils-test_partitions = probe_config_file
MOCKOBJS_SYMBOLS_bg_utils-test_environment = oldenvs configparts fopen fclose fread fwrite feof mount_partition
MOCKOBJS_SYMBOLS_bg_utils-test_api = bgenv_init bgenv_write bgenv_close bgenv_get_latest bgenv_get_by_index bgenv_get_oldest
+MOCKOBJS_SYMBOLS_ebgpart-test_partitions = ped_device_probe_all ped_device_get_next ped_disk_next_partition

TEST_TARGETS = test_partitions.target test_environment.target test_api.target

define WEAKEN_SYMBOL =
objcopy --weaken-symbol $(1) $(2)
-
+
endef

define WEAKEN_SYMBOLS =
diff --git a/tools/tests/test_partitions.c b/tools/tests/test_partitions.c
index 93c0aef..dd82f53 100644
@@ -75,21 +68,7 @@ PedDevice *ped_device_get_next(const PedDevice *dev)
return NULL;
}

-PedDisk *ped_disk_new(PedDevice *dev)
-{
- if (dev == NULL) {
- return NULL;
- }
- for (int i = 0; i < 32; i++) {
- if (dev == &ped_devices[i]) {
- return &ped_disks[i];
- }
- }
- return NULL;
-}
-
-PedPartition *ped_disk_next_partition(const PedDisk *disk,
- const PedPartition *part)
+PedPartition *ped_disk_next_partition(const PedDisk *disk, const PedPartition *part)
{
if (disk == NULL) {
return NULL;
--
2.11.0

Jan Kiszka

unread,
Jul 4, 2017, 2:37:00 AM7/4/17
to [ext] Reichel Andreas, efibootg...@googlegroups.com
Please make sure your editor is properly configured to report this.
Fixing it up while applying.
Merged, thanks.

Claudius Heine

unread,
Jul 4, 2017, 3:43:53 AM7/4/17
to [ext] Reichel Andreas, efibootg...@googlegroups.com
Hi Andreas,
One pattern I try to follow is to limit the exit points of a function,
so memory management become less redundant and more maintainable.

While I am not sure, it does look like there might be a memory leak in
some cases.

> + partition = partition->next;
> + }


Maybe you should read this:
https://medium.com/@bartobri/applying-the-linus-tarvolds-good-taste-coding-requirement-99749f37684a

I could imagine that this `if` could be completely eliminated.
This again looks like a place where a goto to an error section of the
function makes the code less redundant and easier to maintain.
You are mixing different naming conventions. Sometimes I see camelCase,
sometimes underscore_function_names. Is there a reason for this?

Jan Kiszka

unread,
Jul 4, 2017, 4:57:07 AM7/4/17
to [ext] Claudius Heine, [ext] Reichel Andreas, efibootg...@googlegroups.com
Looks like reasonable remarks - cleanup patches welcome, whoever finds
time for this first.

Thanks,

Reichel Andreas

unread,
Jul 4, 2017, 7:40:26 AM7/4/17
to efibootg...@googlegroups.com, Reichel Andreas
Due to a license conflict between libparted and efibootguard
(GPL v3 vs. v2), efibootguard may not link against libparted.
To resolve this issue, used functions for partition table
scanning have been reimplemented from scratch using the same
API.

Signed-off-by: Andreas Reichel <andreas.r...@siemens.com>

Reichel Andreas (1):
bg_utils: Use own code for used parted functions

Makefile.am | 4 +-
swupdate-adapter/Makefile | 54 -----
tools/bg_utils.c | 1 +
tools/bg_utils.h | 2 +-
tools/ebgpart.c | 461 ++++++++++++++++++++++++++++++++++++++++++
tools/ebgpart.h | 135 +++++++++++++
tools/tests/Makefile | 12 +-
tools/tests/test_partitions.c | 22 +-
8 files changed, 608 insertions(+), 83 deletions(-)
delete mode 100644 swupdate-adapter/Makefile
create mode 100644 tools/ebgpart.c
create mode 100644 tools/ebgpart.h

--
2.11.0

Reichel Andreas

unread,
Jul 4, 2017, 7:40:27 AM7/4/17
to efibootg...@googlegroups.com, Reichel Andreas
Due to license conflict between libparted and efibootguard,
libparted cannot be used. Instead, needed code is reimplemented
from scratch.

Signed-off-by: Andreas Reichel <andreas.r...@siemens.com>
---
Makefile.am | 4 +-
swupdate-adapter/Makefile | 54 -----
tools/bg_utils.c | 1 +
tools/bg_utils.h | 2 +-
tools/ebgpart.c | 461 ++++++++++++++++++++++++++++++++++++++++++
tools/ebgpart.h | 135 +++++++++++++
tools/tests/Makefile | 12 +-
tools/tests/test_partitions.c | 22 +-
8 files changed, 608 insertions(+), 83 deletions(-)
delete mode 100644 swupdate-adapter/Makefile
create mode 100644 tools/ebgpart.c
create mode 100644 tools/ebgpart.h

index 0000000..36a58a8
--- /dev/null
+++ b/tools/ebgpart.c
@@ -0,0 +1,461 @@
+/*
+ * EFI Boot Guard
+ *
+ * Copyright (c) Siemens AG, 2017
+ *
+ * Authors:
+ * Andreas Reichel <andreas.r...@siemens.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ *
+ * This code implements functions to scan for FAT partitions in DOS/GPT
+ * partition tables.
+ */
+
+#include "ebgpart.h"
+
+static PedDevice *first_device = NULL;
+static PedDisk g_ped_dummy_disk;
+static char buffer[37];
+
+static bool verbosity = false;
+
+void ebgpart_beverbose(bool v)
+{
+ verbosity = v;
+}
+
+void add_block_dev(PedDevice *dev)
+{
+ if (!first_device) {
+ first_device = dev;
+ return;
+ }
+ PedDevice *d = first_device;
+ while (d->next) {
+ d = d->next;
+ }
+ d->next = dev;
+}
+
+char *GUID_to_str(uint8_t *g)
+{
+ snprintf(buffer, 37, "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%"
+ "02X%02X%02X%02X%02X",
+ g[3], g[2], g[1], g[0], g[5], g[4], g[7], g[6], g[8], g[9],
+ g[10], g[11], g[12], g[13], g[14], g[15]);
+ return buffer;
+}
+
+char *type_to_name(char t)
+{
+ switch (t) {
+ case MBR_TYPE_FAT12:
+ return "fat12";
+ break;
+ case MBR_TYPE_FAT16A:
+ case MBR_TYPE_FAT16:
+ case MBR_TYPE_FAT16_LBA:
+ return "fat16";
+ break;
+ case MBR_TYPE_FAT32:
+ case MBR_TYPE_FAT32_LBA:
+ return "fat32";
+ break;
+ case MBR_TYPE_EXTENDED_LBA:
+ case MBR_TYPE_EXTENDED:
+ return "extended";
+ break;
+ default:
+ return "not supported";
+ break;
+ }
+}
+
+bool check_GPT_FAT_entry(int fd, struct EFIpartitionentry *e,
+ PedFileSystemType *pfst, uint32_t i)
+{
+ if (strcmp(GPT_PARTITION_GUID_FAT_NTFS, GUID_to_str(e->type_GUID)) != 0 &&
+ strcmp(GPT_PARTITION_GUID_ESP, GUID_to_str(e->type_GUID)) != 0) {
+ asprintf(&pfst->name, "not supported");
+ return true;
+ }
+ VERBOSE(stdout, "GPT Partition #%u is FAT/NTFS.\n", i);
+ /* Save current file offset */
+ off64_t curr = lseek64(fd, 0, SEEK_CUR);
+ if (curr == -1) {
+ VERBOSE(stderr, "Error getting current seek position: %s\n",
+ strerror(errno));
+ return false;
+ }
+ /* Look if it is a FAT12 or FAT16 */
+ off64_t dest = e->start_LBA * LB_SIZE + 0x36;
+ if (lseek64(fd, dest, SEEK_SET) == -1) {
+ VERBOSE(stderr, "Error seeking FAT12/16 Id String: %s\n",
+ strerror(errno));
+ return false;
+ }
+ char FAT_id[9];
+ if (read(fd, FAT_id, 8) != 8) {
+ VERBOSE(stderr, "Error reading FAT12/16 Id String: %s\n",
+ strerror(errno));
+ return false;
+ };
+ FAT_id[8] = 0;
+ if (strcmp(FAT_id, "FAT12 ") != 0 &&
+ strcmp(FAT_id, "FAT16 ") != 0) {
+ /* No FAT12/16 so read ID field for FAT32 */
+ dest = e->start_LBA * LB_SIZE + 0x52;
+ if (lseek64(fd, dest, SEEK_SET) == -1) {
+ VERBOSE(stderr, "Error seeking FAT32 Id String: %s\n",
+ strerror(errno));
+ return false;
+ }
+ if (read(fd, FAT_id, 8) != 8) {
+ VERBOSE(stderr, "Error reading FAT32 Id String: %s\n",
+ strerror(errno));
+ return false;
+ }
+ }
+ if (strcmp(FAT_id, "FAT12 ") == 0) {
+ asprintf(&pfst->name, "fat12");
+ } else if (strcmp(FAT_id, "FAT16 ") == 0) {
+ asprintf(&pfst->name, "fat16");
+ } else {
+ asprintf(&pfst->name, "fat32");
+ }
+ VERBOSE(stdout, "GPT Partition #%u is %s.\n", i, pfst->name);
+ if (lseek64(fd, curr, SEEK_SET) == -1) {
+ VERBOSE(stderr, "Error restoring seek position (%s)",
+ strerror(errno));
+ return false;
+ }
+ return true;
+}
+
+void read_GPT_entries(int fd, uint64_t table_LBA, uint32_t num, PedDevice *dev)
+{
+ off64_t offset;
+ struct EFIpartitionentry e;
+ PedPartition *partition = NULL, *tmpp;
+ PedFileSystemType *pfst = NULL;
+
+ offset = LB_SIZE * table_LBA;
+ if (lseek64(fd, offset, SEEK_SET) != offset) {
+ VERBOSE(stderr, "Error seeking EFI partition table\n");
+ return;
+ }
+
+ PedPartition **list_end = &dev->part_list;
+
+ for (uint32_t i = 0; i < num; i++) {
+ if (read(fd, &e, sizeof(e)) != sizeof(e)) {
+ VERBOSE(stderr, "Error reading partition entry\n");
+ VERBOSE(stderr, "(%s)\n", strerror(errno));
+ return;
+ }
+ if ((*((uint64_t *)&e.type_GUID[0]) == 0) &&
+ (*((uint64_t *)&e.type_GUID[8]) == 0)) {
+ return;
+ }
+ VERBOSE(stdout, "%u: %s\n", i, GUID_to_str(e.type_GUID));
+ pfst = calloc(sizeof(PedFileSystemType), 1);
+ if (!pfst) {
+ VERBOSE(stderr, "Out of memory\n");
+ return;
+ }
+
+ tmpp = calloc(sizeof(PedPartition), 1);
+ if (!tmpp) {
+ VERBOSE(stderr, "Out of memory\n");
+ free(pfst);
+ return;
+ }
+ tmpp->num = i + 1;
+ tmpp->fs_type = pfst;
+
+ if (!check_GPT_FAT_entry(fd, &e, pfst, i)) {
+ if (pfst->name)
+ free(pfst->name);
+ free(pfst);
+ free(tmpp);
+ if (!partition) {
+ dev->part_list = NULL;
+ }
+ continue;
+ }
+
+ *list_end = tmpp;
+ list_end = &((*list_end)->next);
+ }
+}
+
+void scanLogicalVolumes(int fd, off64_t extended_start_LBA,
+ struct Masterbootrecord *ebr, int i,
+ PedPartition *partition, int lognum)
+{
+ struct Masterbootrecord next_ebr;
+ PedFileSystemType *pfst;
+
+ off64_t offset = extended_start_LBA + ebr->parttable[i].start_LBA;
+ if (extended_start_LBA == 0) {
+ extended_start_LBA = offset;
+ }
+ VERBOSE(stdout, "Seeking to LBA %lld\n", offset);
+ off64_t res = lseek64(fd, offset * LB_SIZE, SEEK_SET);
+ if (res == -1) {
+ VERBOSE(stderr, "(%s)\n", strerror(errno));
+ return;
+ }
+ VERBOSE(stdout, "Seek returned %lld\n", res);
+ if (read(fd, &next_ebr, sizeof(next_ebr)) != sizeof(next_ebr)) {
+ VERBOSE(stderr, "Error reading next EBR (%s)\n",
+ strerror(errno));
+ return;
+ }
+ if (next_ebr.mbrsignature != 0xaa55) {
+ VERBOSE(stderr, "Wrong signature of extended boot record.\n");
+ return;
+ }
+
+ for (uint8_t j = 0; j < 4; j++) {
+ uint8_t t = next_ebr.parttable[j].partition_type;
+ if (t == 0) {
+ return;
+ }
+ if (t == MBR_TYPE_EXTENDED || t == MBR_TYPE_EXTENDED_LBA) {
+ VERBOSE(stdout, "Next EBR found.\n");
+ scanLogicalVolumes(fd, extended_start_LBA, &next_ebr, j,
+ partition, lognum + 1);
+ continue;
+ }
+ partition->next = calloc(sizeof(PedPartition), 1);
+ if (!partition->next) {
+ goto scl_out_of_mem;
+ }
+ pfst = calloc(sizeof(PedFileSystemType), 1);
+ if (!pfst) {
+ goto scl_out_of_mem;
+ }
+ if (asprintf(&pfst->name, type_to_name(t)) == -1) {
+ goto scl_out_of_mem;
+ };
+ partition = partition->next;
+ partition->num = lognum;
+ partition->fs_type = pfst;
+ }
+ return;
+scl_out_of_mem:
+ VERBOSE(stderr, "Out of memory\n");
+ if (pfst)
+ free(pfst);
+ if (partition->next)
+ free(partition->next);
+}
+
+bool check_partition_table(PedDevice *dev)
+{
+ int fd;
+ struct Masterbootrecord mbr;
+
+ fd = open(dev->path, O_RDONLY);
+ if (fd == 0) {
+ VERBOSE(stderr, "Error opening block device.\n");
+ return false;
+ }
+ if (read(fd, &mbr, sizeof(mbr)) != sizeof(mbr)) {
+ VERBOSE(stderr, "Error reading mbr.\n");
+ close(fd);
+ return false;
+ };
+ if (mbr.mbrsignature != 0xaa55) {
+ VERBOSE(stderr, "Error, MBR has wrong signature.\n");
+ close(fd);
+ return false;
+ }
+ int numpartitions = 0;
+ PedPartition **list_end = &dev->part_list;
+ for (int i = 0; i < 4; i++) {
+ if (mbr.parttable[i].partition_type == 0) {
+ continue;
+ }
+ numpartitions++;
+ VERBOSE(stdout, "Partition %d: Type %X\n", i,
+ read_GPT_entries(fd, efihdr.partitiontable_LBA,
+ efihdr.partitions, dev);
+ break;
+ }
+ PedFileSystemType *pfst =
+ calloc(sizeof(PedFileSystemType), 1);
+ if (!pfst) {
+ goto cpt_out_of_mem;
+ }
+
+ PedPartition *tmp = calloc(sizeof(PedPartition), 1);
+ if (!tmp) {
+ goto cpt_out_of_mem;
+ }
+
+ tmp->num = i + 1;
+ tmp->fs_type = pfst;
+
+ *list_end = tmp;
+ list_end = &((*list_end)->next);
+
+ if (t == MBR_TYPE_EXTENDED ||
+ t == MBR_TYPE_EXTENDED_LBA) {
+ asprintf(&pfst->name, "extended");
+ scanLogicalVolumes(fd, 0, &mbr, i, tmp,
+ 5);
+ /* Could be we still have MBR entries after
+ * logical volumes */
+ while ((*list_end)->next) {
+ list_end = &((*list_end)->next);
+ }
+ } else {
+ asprintf(&pfst->name, type_to_name(t));
+ }
+ continue;
+cpt_out_of_mem:
+ if (pfst)
+ free(pfst);
+ if (tmp)
+ free(tmp);
+ return false;
+ }
+ close(fd);
+ if (numpartitions == 0) {
+ return false;
+ }
+ return true;
+}
+
+void ped_device_probe_all()
+{
+ if (check_partition_table(dev)) {
+ add_block_dev(dev);
+ } else {
+ free(dev->model);
+ free(dev->path);
+ free(dev);
+ }
+ }
+ } while (devfile);
+
+ closedir(devdir);
+}
+
+void ped_partition_destroy(PedPartition *p)
+{
+ if (!p) return;
+ if (!p->fs_type) goto fs_type_Null;
+ if (p->fs_type->name) free(p->fs_type->name);
+ free(p->fs_type);
+fs_type_Null:
+ free(p);
+}
+
+void ped_device_destroy(PedDevice *d)
+{
+ if (!d) return;
+ if (d->model) free(d->model);
+ if (d->path) free(d->path);
+ PedPartition *p = d->part_list;
+ PedPartition *tmpp;
+ while (p) {
+ tmpp = p;
+ p = p->next;
+ ped_partition_destroy(tmpp);
+ }
+ free(d);
+}
+
+PedDevice *ped_device_get_next(const PedDevice *dev)
+{
+ if (!dev) {
+ return first_device;
+ }
+ if (dev->next != NULL) {
+ return dev->next;
+ }
+ /* free all memory */
+ PedDevice *d = first_device;
+ PedDevice *tmpd;
+
+ while (d) {
+ tmpd = d;
+ d = d->next;
+ ped_device_destroy(tmpd);
index 93c0aef..bb2bff3 100644
@@ -75,19 +68,6 @@ PedDevice *ped_device_get_next(const PedDevice *dev)
return NULL;
}

-PedDisk *ped_disk_new(PedDevice *dev)
-{
- if (dev == NULL) {
- return NULL;
- }
- for (int i = 0; i < 32; i++) {
- if (dev == &ped_devices[i]) {
- return &ped_disks[i];
- }
- }
- return NULL;
-}
-
PedPartition *ped_disk_next_partition(const PedDisk *disk,
const PedPartition *part)
{
--
2.11.0

Jan Kiszka

unread,
Jul 4, 2017, 7:54:35 AM7/4/17
to [ext] Reichel Andreas, efibootg...@googlegroups.com, Claudius Heine
OK, thanks, replacing in next.

Claudius, tested-by?

Claudius Heine

unread,
Jul 4, 2017, 9:30:22 AM7/4/17
to [ext] Jan Kiszka, [ext] Reichel Andreas, efibootg...@googlegroups.com, Claudius Heine
Hi,
You didn't. Thats the old patch.

> Claudius, tested-by?

I tested the new patch, but its still not working.

Already talked with Andreas and new patch is coming.

Cheers,
Claudius

Andreas Reichel

unread,
Jul 4, 2017, 9:39:37 AM7/4/17
to Claudius Heine, efibootg...@googlegroups.com
"Still not working" is too general to me. The problem is, that if the
configuration is on a "mmcblk0" device, the device is skipped by the
current algorithm, because it thinks it is a partition (i.e. /dev/sdc
does not
end on a number.) That means everything is working fine without having
configs on mmcblk devices.

Thus I suggest that we merge my patch 3 and then I send
a new upcoming patch with support for this mmcblk naming scheme.

Cheers,
Andreas
> Cheers,
> Claudius

--
Andreas Reichel, Dipl.-Phys. (Univ.), Software Consultant
+49-174-3180074

TNG Technology Consulting GmbH, Betastr. 13a, 85774 Unterfoehring
Geschaeftsfuehrer: Henrik Klagges, Christoph Stock, Dr. Robert Dahlke
Sitz: Unterfoehring * Amtsgericht Muenchen * HRB 135082

Jan Kiszka

unread,
Jul 4, 2017, 9:43:40 AM7/4/17
to Claudius Heine, [ext] Reichel Andreas, efibootg...@googlegroups.com, Claudius Heine
See, it would have been too early to push ;).

Thanks,
Jan

Claudius Heine

unread,
Jul 4, 2017, 9:47:54 AM7/4/17
to Andreas Reichel, efibootg...@googlegroups.com
Ok next time I write "Still not working for me", if thats better :)

Cheers,
Claudius

Jan Kiszka

unread,
Jul 4, 2017, 9:58:12 AM7/4/17
to [ext] Andreas Reichel, Claudius Heine, efibootg...@googlegroups.com
Except that there is no /dev/mmcblk in Linux. ;)

>
> Thus I suggest that we merge my patch 3 and then I send
> a new upcoming patch with support for this mmcblk naming scheme.

It's a regression compared to libparted. Let's fix it directly. Do you
have a good algorithm that does need to encode this as special case
(because I'm unsure if it is actually special, more sure that it isn't)?

For me it is important that our own test cases work all the time.

Reichel Andreas

unread,
Jul 4, 2017, 11:06:07 AM7/4/17
to efibootg...@googlegroups.com, Reichel Andreas
Due to license conflict between libparted and efibootguard,
libparted cannot be used. Instead, needed code is reimplemented
from scratch.

Signed-off-by: Andreas Reichel <andreas.r...@siemens.com>
Tested-by: Claudius Heine <c...@denx.de>
---
Makefile.am | 4 +-
swupdate-adapter/Makefile | 54 -----
tools/bg_utils.c | 1 +
tools/bg_utils.h | 2 +-
tools/ebgpart.c | 448 ++++++++++++++++++++++++++++++++++++++++++
tools/ebgpart.h | 135 +++++++++++++
tools/tests/Makefile | 12 +-
tools/tests/test_partitions.c | 22 +--
8 files changed, 595 insertions(+), 83 deletions(-)
index 0000000..095055f
--- /dev/null
+++ b/tools/ebgpart.c
@@ -0,0 +1,448 @@
+ 0 &&
+ if (pfst->name) free(pfst->name);
+ if (pfst) free(pfst);
+ if (partition->next) free(partition->next);
+}
+
+bool check_partition_table(PedDevice *dev)
+{
+ int fd;
+ struct Masterbootrecord mbr;
+
+ VERBOSE(stdout, "Checking %s\n", dev->path);
+ fd = open(dev->path, O_RDONLY);
+ if (fd == 0) {
+ VERBOSE(stderr, "Error opening block device.\n");
+ return false;
+ }
+ if (read(fd, &mbr, sizeof(mbr)) != sizeof(mbr)) {
+ VERBOSE(stderr, "Error reading mbr on %s.\n", dev->path);
+ PedFileSystemType *pfst = calloc(sizeof(PedFileSystemType), 1);
+ if (!pfst) {
+ goto cpt_out_of_mem;
+ }
+
+ PedPartition *tmp = calloc(sizeof(PedPartition), 1);
+ if (!tmp) {
+ goto cpt_out_of_mem;
+ }
+
+ tmp->num = i + 1;
+ tmp->fs_type = pfst;
+
+ *list_end = tmp;
+ list_end = &((*list_end)->next);
+
+ if (t == MBR_TYPE_EXTENDED || t == MBR_TYPE_EXTENDED_LBA) {
+ asprintf(&pfst->name, "extended");
+ scanLogicalVolumes(fd, 0, &mbr, i, tmp, 5);
+ /* Could be we still have MBR entries after
+ * logical volumes */
+ while ((*list_end)->next) {
+ list_end = &((*list_end)->next);
+ }
+ } else {
+ asprintf(&pfst->name, type_to_name(t));
+ }
+ continue;
+ cpt_out_of_mem:
+ if (pfst) free(pfst);
+ if (tmp) free(tmp);
+ return false;
+ }
+ close(fd);
+ if (numpartitions == 0) {
+ return false;
+ }
+ return true;
+}
+
+void ped_device_probe_all()
+{
+ struct dirent *devfile;
+ char fullname[256];
+
+ DIR *devdir = opendir(DEVDIRNAME);
+ if (!devdir) {
+ VERBOSE(stderr, "Could not open %s\n", DEVDIRNAME);
+ return;
+ }
+
+ /* get all files from devdir */
+ do {
+ devfile = readdir(devdir);
+ if (!devfile)
+ break;
+ if (strcmp(devfile->d_name, ".") == 0 ||
+ strcmp(devfile->d_name, "..") == 0)
+ continue;
+
+ snprintf(fullname, 255, "/dev/%s", devfile->d_name);
index 0000000..76fee9d
+#define DEVDIRNAME "/sys/block"
--
2.11.0

Reichel Andreas

unread,
Jul 4, 2017, 11:06:07 AM7/4/17
to efibootg...@googlegroups.com, Reichel Andreas
Due to a license conflict between libparted and efibootguard
(GPL v3 vs. v2), efibootguard may not link against libparted.
To resolve this issue, used functions for partition table
scanning have been reimplemented from scratch using the same
API.

Signed-off-by: Andreas Reichel <andreas.r...@siemens.com>
Tested-by: Claudius Heine <c...@denx.de>

Reichel Andreas (1):
bg_utils: Use own code for used parted functions

Makefile.am | 4 +-
swupdate-adapter/Makefile | 54 -----
tools/bg_utils.c | 1 +
tools/bg_utils.h | 2 +-
tools/ebgpart.c | 448 ++++++++++++++++++++++++++++++++++++++++++
tools/ebgpart.h | 135 +++++++++++++
tools/tests/Makefile | 12 +-
tools/tests/test_partitions.c | 22 +--
8 files changed, 595 insertions(+), 83 deletions(-)
delete mode 100644 swupdate-adapter/Makefile
create mode 100644 tools/ebgpart.c
create mode 100644 tools/ebgpart.h

--
2.11.0

Claudius Heine

unread,
Jul 4, 2017, 11:17:17 AM7/4/17
to Reichel Andreas, efibootg...@googlegroups.com
Hi,

On Jul 4, 2017 5:01 PM, Reichel Andreas <andreas.r...@siemens.com> wrote:
>
> Due to a license conflict between libparted and efibootguard
> (GPL v3 vs. v2), efibootguard may not link against libparted.
> To resolve this issue, used functions for partition table
> scanning have been reimplemented from scratch using the same
> API.
>
> Signed-off-by: Andreas Reichel <andreas.r...@siemens.com>
> Tested-by: Claudius Heine <c...@denx.de>

The standalone tools are working now, but using it with swupdate does not.

I will post a log tomorrow.


>
> Reichel Andreas (1):
>   bg_utils: Use own code for used parted functions
>
> Makefile.am                   |   4 +-
> swupdate-adapter/Makefile     |  54 -----
> tools/bg_utils.c              |   1 +
> tools/bg_utils.h              |   2 +-
> tools/ebgpart.c               | 448 ++++++++++++++++++++++++++++++++++++++++++
> tools/ebgpart.h               | 135 +++++++++++++
> tools/tests/Makefile          |  12 +-
> tools/tests/test_partitions.c |  22 +--
> 8 files changed, 595 insertions(+), 83 deletions(-)
> delete mode 100644 swupdate-adapter/Makefile
> create mode 100644 tools/ebgpart.c
> create mode 100644 tools/ebgpart.h
>
> --
> 2.11.0
>

> --
> You received this message because you are subscribed to the Google Groups "EFI Boot Guard" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to efibootguard-d...@googlegroups.com.
> To post to this group, send email to efibootg...@googlegroups.com.
> To view this discussion on the web visit https://groups.google.com/d/msgid/efibootguard-dev/20170704150158.28634-1-andreas.reichel.ext%40siemens.com.
> For more options, visit https://groups.google.com/d/optout.

Claudius Heine

unread,
Jul 5, 2017, 2:27:21 AM7/5/17
to Claudius Heine, Reichel Andreas <andreas.reichel.ext@siemens.com>; STORM CHRISTIAN Z003KY2V, efibootg...@googlegroups.com
Hi,

On 07/04/2017 05:17 PM, Claudius Heine wrote:
> Hi,
>
> On Jul 4, 2017 5:01 PM, Reichel Andreas <andreas.r...@siemens.com> wrote:
>>
>> Due to a license conflict between libparted and efibootguard
>> (GPL v3 vs. v2), efibootguard may not link against libparted.
>> To resolve this issue, used functions for partition table
>> scanning have been reimplemented from scratch using the same
>> API.
>>
>> Signed-off-by: Andreas Reichel <andreas.r...@siemens.com>
>> Tested-by: Claudius Heine <c...@denx.de>
>
> The standalone tools are working now, but using it with swupdate does not.
>
> I will post a log tomorrow.

Here is the log:

[NOTIFY] : SWUPDATE running : [install_single_image] : Found installer
for stream ssi-image-mpart-iot2000-ebs.ext4.gz raw
[NOTIFY] : SWUPDATE running : [update_bootloader_env] : Updating
bootloader environment
Checking /dev/md0
Error reading mbr on /dev/md0.
Checking /dev/ram0
Error, MBR has wrong signature.
Checking /dev/ram1
Error, MBR has wrong signature.
Checking /dev/ram2
Error, MBR has wrong signature.
Checking /dev/ram3
Error, MBR has wrong signature.
Checking /dev/ram4
Error, MBR has wrong signature.
Checking /dev/ram5
Error, MBR has wrong signature.
Checking /dev/ram6
Error, MBR has wrong signature.
Checking /dev/ram7
Error, MBR has wrong signature.
Checking /dev/ram8
Error, MBR has wrong signature.
Checking /dev/ram9
Error, MBR has wrong signature.
Checking /dev/loop0
Error reading mbr on /dev/loop0.
Checking /dev/loop1
Error reading mbr on /dev/loop1.
Checking /dev/loop2
Error reading mbr on /dev/loop2.
Checking /dev/loop3
Error reading mbr on /dev/loop3.
Checking /dev/loop4
Error reading mbr on /dev/loop4.
Checking /dev/loop5
Error reading mbr on /dev/loop5.
Checking /dev/loop6
Error reading mbr on /dev/loop6.
Checking /dev/loop7
Error reading mbr on /dev/loop7.
Checking /dev/ram10
Error, MBR has wrong signature.
Checking /dev/ram11
Error, MBR has wrong signature.
Checking /dev/ram12
Error, MBR has wrong signature.
Checking /dev/ram13
Error, MBR has wrong signature.
Checking /dev/ram14
Error, MBR has wrong signature.
Checking /dev/ram15
Error, MBR has wrong signature.
Checking /dev/mmcblk0
Partition 0: Type EE
GPT header at 1
EFI Header: 45 46 49 20 50 41 52 54
Number of partition entries: 128
Partition Table @ LBA 2
0: C12A7328-F81F-11D2-BA4B-00A0C93EC93B
GPT Partition #0 is FAT/NTFS.
GPT Partition #0 is fat16.
1: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7
GPT Partition #1 is FAT/NTFS.
GPT Partition #1 is fat16.
2: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7
GPT Partition #2 is FAT/NTFS.
GPT Partition #2 is fat16.
3: 0FC63DAF-8483-4772-8E79-3D69D8477DE4
4: 0FC63DAF-8483-4772-8E79-3D69D8477DE4
5: 0FC63DAF-8483-4772-8E79-3D69D8477DE4
Partition /dev/mmcblk0p1 is not mounted.
Partition /dev/mmcblk0p1 is mounted to /tmp/mnt-8kF0zN.
Probing config file at /tmp/mnt-8kF0zN/BGENV.DAT.
Partition /dev/mmcblk0p2 is not mounted.
Partition /dev/mmcblk0p2 is mounted to /tmp/mnt-sFTayv.
Probing config file at /tmp/mnt-sFTayv/BGENV.DAT.
Partition /dev/mmcblk0p3 is not mounted.
Partition /dev/mmcblk0p3 is mounted to /tmp/mnt-wnKKZg.
Probing config file at /tmp/mnt-wnKKZg/BGENV.DAT.
Probing config file at /tmp/mnt-6vITI6/BGENV.DAT.
Probing config file at /tmp/mnt-KspvD1/BGENV.DAT.
Probing config file at /tmp/mnt-4KMQq4/BGENV.DAT.
Checking /dev/md0
Error reading mbr on /dev/md0.
Checking /dev/ram0
Error, MBR has wrong signature.
Checking /dev/ram1
Error, MBR has wrong signature.
Checking /dev/ram2
Error, MBR has wrong signature.
Checking /dev/ram3
Error, MBR has wrong signature.
Checking /dev/ram4
Error, MBR has wrong signature.
Checking /dev/ram5
Error, MBR has wrong signature.
Checking /dev/ram6
Error, MBR has wrong signature.
Checking /dev/ram7
Error, MBR has wrong signature.
Checking /dev/ram8
Error, MBR has wrong signature.
Checking /dev/ram9
Error, MBR has wrong signature.
Checking /dev/loop0
Error reading mbr on /dev/loop0.
Checking /dev/loop1
Error reading mbr on /dev/loop1.
Checking /dev/loop2
Error reading mbr on /dev/loop2.
Checking /dev/loop3
Error reading mbr on /dev/loop3.
Checking /dev/loop4
Error reading mbr on /dev/loop4.
Checking /dev/loop5
Error reading mbr on /dev/loop5.
Checking /dev/loop6
Error reading mbr on /dev/loop6.
Checking /dev/loop7
Error reading mbr on /dev/loop7.
Checking /dev/ram10
Error, MBR has wrong signature.
Checking /dev/ram11
Error, MBR has wrong signature.
Checking /dev/ram12
Error, MBR has wrong signature.
Checking /dev/ram13
Error, MBR has wrong signature.
Checking /dev/ram14
Error, MBR has wrong signature.
Checking /dev/ram15
Error, MBR has wrong signature.
Checking /dev/mmcblk0
Partition 0: Type EE
GPT header at 1
EFI Header: 45 46 49 20 50 41 52 54
Number of partition entries: 128
Partition Table @ LBA 2
0: C12A7328-F81F-11D2-BA4B-00A0C93EC93B
GPT Partition #0 is FAT/NTFS.
GPT Partition #0 is fat16.
1: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7
GPT Partition #1 is FAT/NTFS.
GPT Partition #1 is fat16.
2: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7
GPT Partition #2 is FAT/NTFS.
GPT Partition #2 is fat16.
3: 0FC63DAF-8483-4772-8E79-3D69D8477DE4
4: 0FC63DAF-8483-4772-8E79-3D69D8477DE4
5: 0FC63DAF-8483-4772-8E79-3D69D8477DE4
Partition /dev/mmcblk0p1 is not mounted.
Partition /dev/mmcblk0p1 is mounted to /tmp/mnt-7qba3l.
Probing config file at /tmp/mnt-7qba3l/BGENV.DAT.
Partition /dev/mmcblk0p2 is not mounted.
Partition /dev/mmcblk0p2 is mounted to /tmp/mnt-I8XXoJ.
Probing config file at /tmp/mnt-I8XXoJ/BGENV.DAT.
Partition /dev/mmcblk0p3 is not mounted.
Partition /dev/mmcblk0p3 is mounted to /tmp/mnt-NRzP7a.
Probing config file at /tmp/mnt-NRzP7a/BGENV.DAT.
Partition /dev/mmcblk0p1 is not mounted.
Partition /dev/mmcblk0p1 is mounted to /tmp/mnt-e6ZBRH.
Probing config file at /tmp/mnt-e6ZBRH/BGENV.DAT.
Partition /dev/mmcblk0p2 is not mounted.
Partition /dev/mmcblk0p2 is mounted to /tmp/mnt-3yHcXi.
Probing config file at /tmp/mnt-3yHcXi/BGENV.DAT.
Error, there are more than 2 config partitions.
Error finding config partitions.
[NOTIFY] : SWUPDATE failed [0] ERROR bootloader/ebg.c :
bootloader_env_set : 84 : Error: cannot open/create new bootloader
environment: Input/output error.

Software updated failed

That was the error from yesterday. Today I got this:

[NOTIFY] : SWUPDATE running : [update_bootloader_env] : Updating
bootloader environment
Checking /dev/md0
Error reading mbr on /dev/md0.
Checking /dev/ram0
Error, MBR has wrong signature.
Checking /dev/ram1
Error, MBR has wrong signature.
Checking /dev/ram2
Error, MBR has wrong signature.
Checking /dev/ram3
Error, MBR has wrong signature.
Checking /dev/ram4
Error, MBR has wrong signature.
Checking /dev/ram5
Error, MBR has wrong signature.
Checking /dev/ram6
Error, MBR has wrong signature.
Checking /dev/ram7
Error, MBR has wrong signature.
Checking /dev/ram8
Error, MBR has wrong signature.
Checking /dev/ram9
Error, MBR has wrong signature.
Checking /dev/loop0
Error reading mbr on /dev/loop0.
Checking /dev/loop1
Error reading mbr on /dev/loop1.
Checking /dev/loop2
Error reading mbr on /dev/loop2.
Checking /dev/loop3
Error reading mbr on /dev/loop3.
Checking /dev/loop4
Error reading mbr on /dev/loop4.
Checking /dev/loop5
Error reading mbr on /dev/loop5.
Checking /dev/loop6
Error reading mbr on /dev/loop6.
Checking /dev/loop7
Error reading mbr on /dev/loop7.
Checking /dev/ram10
Error, MBR has wrong signature.
Checking /dev/ram11
Error, MBR has wrong signature.
Checking /dev/ram12
Error, MBR has wrong signature.
Checking /dev/ram13
Error, MBR has wrong signature.
Checking /dev/ram14
Error, MBR has wrong signature.
Checking /dev/ram15
Error, MBR has wrong signature.
Checking /dev/mmcblk0
Partition 0: Type EE
GPT header at 1
EFI Header: 45 46 49 20 50 41 52 54
Number of partition entries: 128
Partition Table @ LBA 2
0: C12A7328-F81F-11D2-BA4B-00A0C93EC93B
GPT Partition #0 is FAT/NTFS.
GPT Partition #0 is fat16.
1: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7
GPT Partition #1 is FAT/NTFS.
GPT Partition #1 is fat16.
2: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7
GPT Partition #2 is FAT/NTFS.
GPT Partition #2 is fat16.
3: 0FC63DAF-8483-4772-8E79-3D69D8477DE4
4: 0FC63DAF-8483-4772-8E79-3D69D8477DE4
5: 0FC63DAF-8483-4772-8E79-3D69D8477DE4
Partition /dev/mmcblk0p1 is not mounted.
Partition /dev/mmcblk0p1 is mounted to /tmp/mnt-T8ldLH.
Probing config file at /tmp/mnt-T8ldLH/BGENV.DAT.
Partition /dev/mmcblk0p2 is not mounted.
Partition /dev/mmcblk0p2 is mounted to /tmp/mnt-AcLVYj.
Probing config file at /tmp/mnt-AcLVYj/BGENV.DAT.
Partition /dev/mmcblk0p3 is not mounted.
Partition /dev/mmcblk0p3 is mounted to /tmp/mnt-3WHM23.
Probing config file at /tmp/mnt-3WHM23/BGENV.DAT.
Probing config file at /tmp/mnt-mOQWGS/BGENV.DAT.
Probing config file at /tmp/mnt-rAABBK/BGENV.DAT.
Probing config file at /tmp/mnt-sMeGmI/BGENV.DAT.
Checking /dev/md0
Error reading mbr on /dev/md0.
Checking /dev/ram0
Error, MBR has wrong signature.
Checking /dev/ram1
Error, MBR has wrong signature.
Checking /dev/ram2
Error, MBR has wrong signature.
Checking /dev/ram3
Error, MBR has wrong signature.
Checking /dev/ram4
Error, MBR has wrong signature.
Checking /dev/ram5
Error, MBR has wrong signature.
Checking /dev/ram6
Error, MBR has wrong signature.
Checking /dev/ram7
Error, MBR has wrong signature.
Checking /dev/ram8
Error, MBR has wrong signature.
Checking /dev/ram9
Error, MBR has wrong signature.
Checking /dev/loop0
Error reading mbr on /dev/loop0.
Checking /dev/loop1
Error reading mbr on /dev/loop1.
Checking /dev/loop2
Error reading mbr on /dev/loop2.
Checking /dev/loop3
Error reading mbr on /dev/loop3.
Checking /dev/loop4
Error reading mbr on /dev/loop4.
Checking /dev/loop5
Error reading mbr on /dev/loop5.
Checking /dev/loop6
Error reading mbr on /dev/loop6.
Checking /dev/loop7
Error reading mbr on /dev/loop7.
Checking /dev/ram10
Error, MBR has wrong signature.
Checking /dev/ram11
Error, MBR has wrong swupdate[703]: segfault at 496d0c ip 0804caba sp
bfd21470 error 4signature.
Chec in swupdate[8048000+16000]king /dev/ram12

Error, MBR has wrong signature.
Checking /dev/ram13
Error, MBR has wrong signature.
Checking /dev/ram14
Error, MBR has wrong signature.
Checking /dev/ram15
Error, MBR has wrong signature.
Checking /dev/mmcblk0
Partition 0: Type EE
GPT header at 1
EFI Header: 45 46 49 20 50 41 52 54
Number of partition entries: 128
Partition Table @ LBA 2
0: C12A7328-F81F-11D2-BA4B-00A0C93EC93B
GPT Partition #0 is FAT/NTFS.
GPT Partition #0 is fat16.
1: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7
GPT Partition #1 is FAT/NTFS.
GPT Partition #1 is fat16.
2: EBD0A0A2-B9E5-4433-87C0-68B6B72699C7
GPT Partition #2 is FAT/NTFS.
GPT Partition #2 is fat16.
3: 0FC63DAF-8483-4772-8E79-3D69D8477DE4
4: 0FC63DAF-8483-4772-8E79-3D69D8477DE4
5: 0FC63DAF-8483-4772-8E79-3D69D8477DE4
/usr/bin/swupdate-manual.sh: line 22: 703 Segmentation fault
swupdate -v -e stable,sys${SYS_NO} -i $ARTIFACT

After this again:

Partition /dev/mmcblk0p2 is not mounted.
Partition /dev/mmcblk0p2 is mounted to /tmp/mnt-BNARH9.
Probing config file at /tmp/mnt-BNARH9/BGENV.DAT.
Error, there are more than 2 config partitions.
Error finding config partitions.
[NOTIFY] : SWUPDATE failed [0] ERROR bootloader/ebg.c :
bootloader_env_set : 84 : Error: cannot open/create new bootloader
environment: Input/output error.

Software updated failed

So it might be an issue with the bootloader/ebg.c from swupdate or there
is still an issue with this patchset.

Cheers,
Claudius

Reichel Andreas

unread,
Jul 5, 2017, 4:52:59 AM7/5/17
to efibootg...@googlegroups.com, Reichel Andreas
Due to license conflict between libparted and efibootguard,
libparted cannot be used. Instead, needed code is reimplemented
from scratch.

Signed-off-by: Andreas Reichel <andreas.r...@siemens.com>
---
Makefile.am | 4 +-
swupdate-adapter/Makefile | 54 -----
tools/bg_utils.c | 1 +
tools/bg_utils.h | 2 +-
tools/ebgpart.c | 449 ++++++++++++++++++++++++++++++++++++++++++
tools/ebgpart.h | 135 +++++++++++++
tools/tests/Makefile | 12 +-
tools/tests/test_partitions.c | 22 +--
8 files changed, 596 insertions(+), 83 deletions(-)
delete mode 100644 swupdate-adapter/Makefile
create mode 100644 tools/ebgpart.c
create mode 100644 tools/ebgpart.h

index 0000000..07edb05
--- /dev/null
+++ b/tools/ebgpart.c
@@ -0,0 +1,449 @@
+ first_device = NULL;

Reichel Andreas

unread,
Jul 5, 2017, 4:52:59 AM7/5/17
to efibootg...@googlegroups.com, Reichel Andreas
Due to a license conflict between libparted and efibootguard
(GPL v3 vs. v2), efibootguard may not link against libparted.
To resolve this issue, used functions for partition table
scanning have been reimplemented from scratch using the same
API.

Diff to patchset v4: Fix destructor of device list.

Signed-off-by: Andreas Reichel <andreas.r...@siemens.com>

Reichel Andreas (1):
bg_utils: Use own code for used parted functions

Makefile.am | 4 +-
swupdate-adapter/Makefile | 54 -----
tools/bg_utils.c | 1 +
tools/bg_utils.h | 2 +-
tools/ebgpart.c | 449 ++++++++++++++++++++++++++++++++++++++++++
tools/ebgpart.h | 135 +++++++++++++
tools/tests/Makefile | 12 +-
tools/tests/test_partitions.c | 22 +--
8 files changed, 596 insertions(+), 83 deletions(-)
delete mode 100644 swupdate-adapter/Makefile
create mode 100644 tools/ebgpart.c
create mode 100644 tools/ebgpart.h

--
2.11.0

Claudius Heine

unread,
Jul 5, 2017, 4:56:40 AM7/5/17
to [ext] Reichel Andreas, efibootg...@googlegroups.com
On 07/05/2017 10:48 AM, [ext] Reichel Andreas wrote:
> Due to license conflict between libparted and efibootguard,
> libparted cannot be used. Instead, needed code is reimplemented
> from scratch.
>
> Signed-off-by: Andreas Reichel <andreas.r...@siemens.com>

Tested-by: Claudius Heine <c...@denx.de>

Jan Kiszka

unread,
Jul 5, 2017, 5:01:14 AM7/5/17
to [ext] Claudius Heine, [ext] Reichel Andreas, efibootg...@googlegroups.com
On 2017-07-05 10:56, [ext] Claudius Heine wrote:
> On 07/05/2017 10:48 AM, [ext] Reichel Andreas wrote:
>> Due to license conflict between libparted and efibootguard,
>> libparted cannot be used. Instead, needed code is reimplemented
>> from scratch.
>>
>> Signed-off-by: Andreas Reichel <andreas.r...@siemens.com>
>
> Tested-by: Claudius Heine <c...@denx.de>

This revision also resolves the earlier reported issue with swupdate?

Andreas Reichel

unread,
Jul 5, 2017, 5:24:33 AM7/5/17
to Jan Kiszka, [ext] Claudius Heine, efibootg...@googlegroups.com


On 07/05/2017 11:01 AM, Jan Kiszka wrote:
> On 2017-07-05 10:56, [ext] Claudius Heine wrote:
>> On 07/05/2017 10:48 AM, [ext] Reichel Andreas wrote:
>>> Due to license conflict between libparted and efibootguard,
>>> libparted cannot be used. Instead, needed code is reimplemented
>>> from scratch.
>>>
>>> Signed-off-by: Andreas Reichel <andreas.r...@siemens.com>
>> Tested-by: Claudius Heine <c...@denx.de>
> This revision also resolves the earlier reported issue with swupdate?
>
> Jan
Yes it does.

Andreas

Jan Kiszka

unread,
Jul 5, 2017, 8:28:07 AM7/5/17
to Andreas Reichel, [ext] Claudius Heine, efibootg...@googlegroups.com
On 2017-07-05 11:20, Andreas Reichel wrote:
>
>
> On 07/05/2017 11:01 AM, Jan Kiszka wrote:
>> On 2017-07-05 10:56, [ext] Claudius Heine wrote:
>>> On 07/05/2017 10:48 AM, [ext] Reichel Andreas wrote:
>>>> Due to license conflict between libparted and efibootguard,
>>>> libparted cannot be used. Instead, needed code is reimplemented
>>>> from scratch.
>>>>
>>>> Signed-off-by: Andreas Reichel <andreas.r...@siemens.com>
>>> Tested-by: Claudius Heine <c...@denx.de>
>> This revision also resolves the earlier reported issue with swupdate?
>>
>> Jan
> Yes it does.
>

Perfect. Applied to next and pushed.

Jan Kiszka

unread,
Jul 20, 2017, 12:22:25 PM7/20/17
to [ext] Reichel Andreas, efibootg...@googlegroups.com
On 2017-07-04 17:01, [ext] Reichel Andreas wrote:
^^^^^^^^^^^^^^^^^^^^^

> Due to license conflict between libparted and efibootguard,
> libparted cannot be used. Instead, needed code is reimplemented
> from scratch.

Andreas, please make sure in your scripts that patches carry the proper,
non-mangled From: line in their body. Just fixed up in next, will
force-push later.

Jan Kiszka

unread,
Jul 20, 2017, 12:23:49 PM7/20/17
to [ext] Reichel Andreas, efibootg...@googlegroups.com
On 2017-07-20 18:22, [ext] Jan Kiszka wrote:
> On 2017-07-04 17:01, [ext] Reichel Andreas wrote:
> ^^^^^^^^^^^^^^^^^^^^^
>
>> Due to license conflict between libparted and efibootguard,
>> libparted cannot be used. Instead, needed code is reimplemented
>> from scratch.
>
> Andreas, please make sure in your scripts that patches carry the proper,
> non-mangled From: line in their body. Just fixed up in next, will
> force-push later.
>

Commented on last-1 version by mistake - the push will contain v5, of
course. Slowly resuming my duty of maintenance here...
Reply all
Reply to author
Forward
0 new messages