Blame SOURCES/0027-emmc_parser-add-emmc_parser.patch

5e6fc3
From d6a526a0c819c439a894af625f45b657576f8744 Mon Sep 17 00:00:00 2001
5e6fc3
From: Alek Du <alek.du@intel.com>
5e6fc3
Date: Fri, 27 Jul 2018 21:31:01 +0800
5e6fc3
Subject: [PATCH 27/39] emmc_parser: add emmc_parser
5e6fc3
5e6fc3
Signed-off-by: Alek Du <alek.du@intel.com>
5e6fc3
---
5e6fc3
 src/dp-message.c               |  18 +++++
5e6fc3
 src/linux-emmc.c               | 129 +++++++++++++++++++++++++++++++++
5e6fc3
 src/linux.c                    |   1 +
5e6fc3
 src/include/efivar/efivar-dp.h |   2 +
5e6fc3
 src/linux.h                    |   7 ++
5e6fc3
 src/libefivar.map.in           |   1 +
5e6fc3
 6 files changed, 158 insertions(+)
5e6fc3
 create mode 100644 src/linux-emmc.c
5e6fc3
5e6fc3
diff --git a/src/dp-message.c b/src/dp-message.c
5e6fc3
index 5af66438bfc..3724e5f57bd 100644
5e6fc3
--- a/src/dp-message.c
5e6fc3
+++ b/src/dp-message.c
5e6fc3
@@ -826,3 +826,21 @@ efidp_make_nvdimm(uint8_t *buf, ssize_t size, efi_guid_t *uuid)
5e6fc3
 
5e6fc3
 	return sz;
5e6fc3
 }
5e6fc3
+
5e6fc3
+ssize_t PUBLIC
5e6fc3
+efidp_make_emmc(uint8_t *buf, ssize_t size, uint32_t slot_id)
5e6fc3
+{
5e6fc3
+	efidp_emmc *emmc = (efidp_emmc *)buf;
5e6fc3
+	ssize_t req = sizeof (*emmc);
5e6fc3
+	ssize_t sz;
5e6fc3
+
5e6fc3
+	sz = efidp_make_generic(buf, size, EFIDP_MESSAGE_TYPE,
5e6fc3
+					EFIDP_MSG_NVME, sizeof (*emmc));
5e6fc3
+	if (size && sz == req)
5e6fc3
+		emmc->slot = slot_id;
5e6fc3
+
5e6fc3
+	if (sz < 0)
5e6fc3
+		efi_error("efidp_make_generic failed");
5e6fc3
+
5e6fc3
+	return sz;
5e6fc3
+}
5e6fc3
diff --git a/src/linux-emmc.c b/src/linux-emmc.c
5e6fc3
new file mode 100644
5e6fc3
index 00000000000..f0c9e635cb6
5e6fc3
--- /dev/null
5e6fc3
+++ b/src/linux-emmc.c
5e6fc3
@@ -0,0 +1,129 @@
5e6fc3
+/*
5e6fc3
+ * libefiboot - library for the manipulation of EFI boot variables
5e6fc3
+ * Copyright 2012-2018 Red Hat, Inc.
5e6fc3
+ *
5e6fc3
+ * This library is free software; you can redistribute it and/or
5e6fc3
+ * modify it under the terms of the GNU Lesser General Public License as
5e6fc3
+ * published by the Free Software Foundation; either version 2.1 of the
5e6fc3
+ * License, or (at your option) any later version.
5e6fc3
+ *
5e6fc3
+ * This library is distributed in the hope that it will be useful,
5e6fc3
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
5e6fc3
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
5e6fc3
+ * Lesser General Public License for more details.
5e6fc3
+ *
5e6fc3
+ * You should have received a copy of the GNU Lesser General Public
5e6fc3
+ * License along with this library; if not, see
5e6fc3
+ * <http://www.gnu.org/licenses/>.
5e6fc3
+ *
5e6fc3
+ */
5e6fc3
+
5e6fc3
+#include "fix_coverity.h"
5e6fc3
+
5e6fc3
+#include <errno.h>
5e6fc3
+#include <fcntl.h>
5e6fc3
+#include <inttypes.h>
5e6fc3
+#include <stdint.h>
5e6fc3
+#include <unistd.h>
5e6fc3
+
5e6fc3
+#include "efiboot.h"
5e6fc3
+
5e6fc3
+/*
5e6fc3
+ * support for emmc devices
5e6fc3
+ *
5e6fc3
+ * /sys/dev/block/$major:$minor looks like:
5e6fc3
+ * 179:0 -> ../../devices/pci0000:00/0000:00:1c.0/mmc_host/mmc0/mmc0:0001/block/mmcblk0
5e6fc3
+ * 179:1 -> ../../devices/pci0000:00/0000:00:1c.0/mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0p1
5e6fc3
+ *
5e6fc3
+ * /sys/dev/block/179:0/device looks like:
5e6fc3
+ * device -> ../../../mmc0:0001
5e6fc3
+ *
5e6fc3
+ * /sys/dev/block/179:1/partition looks like:
5e6fc3
+ * $ cat partition
5e6fc3
+ * 1
5e6fc3
+ *
5e6fc3
+ */
5e6fc3
+
5e6fc3
+static ssize_t
5e6fc3
+parse_emmc(struct device *dev, const char *current, const char *root UNUSED)
5e6fc3
+{
5e6fc3
+        int rc;
5e6fc3
+        int32_t tosser0, tosser1, tosser2, tosser3, slot_id, partition;
5e6fc3
+        int pos0 = 0, pos1 = 0;
5e6fc3
+        char *spaces;
5e6fc3
+
5e6fc3
+        pos0 = strlen(current);
5e6fc3
+        spaces = alloca(pos0+1);
5e6fc3
+        memset(spaces, ' ', pos0+1);
5e6fc3
+        spaces[pos0] = '\0';
5e6fc3
+        pos0 = 0;
5e6fc3
+
5e6fc3
+        debug(DEBUG, "entry");
5e6fc3
+
5e6fc3
+        debug(DEBUG, "searching for mmc_host/mmc0/mmc0:0001/block/mmcblk0 or mmc_host/mmc0/mmc0:0001/block/mmcblk0/mmcblk0p1");
5e6fc3
+        rc = sscanf(current, "mmc_host/mmc%d/mmc%d:%d/block/mmcblk%d%n/mmcblk%dp%d%n",
5e6fc3
+                    &tosser0, &tosser1, &tosser2, &slot_id,
5e6fc3
+                    &pos0, &tosser3, &partition, &pos1);
5e6fc3
+        debug(DEBUG, "current:\"%s\" rc:%d pos0:%d pos1:%d\n", current, rc, pos0, pos1);
5e6fc3
+        arrow(DEBUG, spaces, 9, pos0, rc, 4);
5e6fc3
+        arrow(DEBUG, spaces, 9, pos1, rc, 6);
5e6fc3
+        /*
5e6fc3
+         * If it isn't of that form, it's not one of our emmc devices.
5e6fc3
+         */
5e6fc3
+        if (rc != 4 && rc != 6)
5e6fc3
+                return 0;
5e6fc3
+
5e6fc3
+        dev->emmc_info.slot_id = slot_id;
5e6fc3
+        dev->interface_type = emmc;
5e6fc3
+
5e6fc3
+        if (rc == 6) {
5e6fc3
+                if (dev->part == -1)
5e6fc3
+                        dev->part = partition;
5e6fc3
+
5e6fc3
+                pos0 = pos1;
5e6fc3
+        }
5e6fc3
+
5e6fc3
+        return pos0;
5e6fc3
+}
5e6fc3
+
5e6fc3
+static ssize_t
5e6fc3
+dp_create_emmc(struct device *dev,
5e6fc3
+               uint8_t *buf,  ssize_t size, ssize_t off)
5e6fc3
+{
5e6fc3
+        ssize_t sz;
5e6fc3
+
5e6fc3
+        debug(DEBUG, "entry");
5e6fc3
+
5e6fc3
+        sz = efidp_make_emmc(buf + off, size ? size - off : 0,
5e6fc3
+                             dev->emmc_info.slot_id);
5e6fc3
+        return sz;
5e6fc3
+}
5e6fc3
+
5e6fc3
+static char *
5e6fc3
+make_part_name(struct device *dev)
5e6fc3
+{
5e6fc3
+        char *ret = NULL;
5e6fc3
+        ssize_t rc;
5e6fc3
+
5e6fc3
+        if (dev->part < 1)
5e6fc3
+                return NULL;
5e6fc3
+
5e6fc3
+        rc = asprintf(&ret, "%sp%d", dev->disk_name, dev->part);
5e6fc3
+        if (rc < 0) {
5e6fc3
+                efi_error("could not allocate memory");
5e6fc3
+                return NULL;
5e6fc3
+        }
5e6fc3
+
5e6fc3
+        return ret;
5e6fc3
+}
5e6fc3
+
5e6fc3
+static enum interface_type emmc_iftypes[] = { emmc, unknown };
5e6fc3
+
5e6fc3
+struct dev_probe HIDDEN emmc_parser = {
5e6fc3
+        .name = "emmc",
5e6fc3
+        .iftypes = emmc_iftypes,
5e6fc3
+        .flags = DEV_PROVIDES_HD,
5e6fc3
+        .parse = parse_emmc,
5e6fc3
+        .create = dp_create_emmc,
5e6fc3
+        .make_part_name = make_part_name,
5e6fc3
+};
5e6fc3
diff --git a/src/linux.c b/src/linux.c
5e6fc3
index 7fac339c50e..ff8db812ad3 100644
5e6fc3
--- a/src/linux.c
5e6fc3
+++ b/src/linux.c
5e6fc3
@@ -246,6 +246,7 @@ static struct dev_probe *dev_probes[] = {
5e6fc3
         &ata_parser,
5e6fc3
         &scsi_parser,
5e6fc3
         &i2o_parser,
5e6fc3
+        &emmc_parser,
5e6fc3
         NULL
5e6fc3
 };
5e6fc3
 
5e6fc3
diff --git a/src/include/efivar/efivar-dp.h b/src/include/efivar/efivar-dp.h
5e6fc3
index 1b05775ae7e..f9ebb059d06 100644
5e6fc3
--- a/src/include/efivar/efivar-dp.h
5e6fc3
+++ b/src/include/efivar/efivar-dp.h
5e6fc3
@@ -689,6 +689,8 @@ typedef struct {
5e6fc3
 	uint8_t		slot;
5e6fc3
 } EFIVAR_PACKED efidp_emmc;
5e6fc3
 
5e6fc3
+extern ssize_t efidp_make_emmc(uint8_t *buf, ssize_t size, uint32_t slot_id);
5e6fc3
+
5e6fc3
 #define EFIDP_MSG_BTLE		0x1e
5e6fc3
 typedef struct {
5e6fc3
 	efidp_header	header;
5e6fc3
diff --git a/src/linux.h b/src/linux.h
5e6fc3
index 99d61013e02..7c7ea91e771 100644
5e6fc3
--- a/src/linux.h
5e6fc3
+++ b/src/linux.h
5e6fc3
@@ -93,6 +93,10 @@ struct nvdimm_info {
5e6fc3
         efi_guid_t nvdimm_label;
5e6fc3
 };
5e6fc3
 
5e6fc3
+struct emmc_info {
5e6fc3
+       int32_t slot_id;
5e6fc3
+};
5e6fc3
+
5e6fc3
 enum interface_type {
5e6fc3
         unknown,
5e6fc3
         isa, acpi_root, pci_root, soc_root, pci, network,
5e6fc3
@@ -100,6 +104,7 @@ enum interface_type {
5e6fc3
         usb, i1394, fibre, i2o,
5e6fc3
         md, virtblk,
5e6fc3
         nvme, nd_pmem,
5e6fc3
+        emmc,
5e6fc3
 };
5e6fc3
 
5e6fc3
 struct dev_probe;
5e6fc3
@@ -139,6 +144,7 @@ struct device {
5e6fc3
                                 struct sata_info sata_info;
5e6fc3
                                 struct ata_info ata_info;
5e6fc3
                                 struct nvme_info nvme_info;
5e6fc3
+                                struct emmc_info emmc_info;
5e6fc3
                                 struct nvdimm_info nvdimm_info;
5e6fc3
                         };
5e6fc3
                 };
5e6fc3
@@ -277,5 +283,6 @@ extern struct dev_probe virtblk_parser;
5e6fc3
 extern struct dev_probe i2o_parser;
5e6fc3
 extern struct dev_probe scsi_parser;
5e6fc3
 extern struct dev_probe ata_parser;
5e6fc3
+extern struct dev_probe emmc_parser;
5e6fc3
 
5e6fc3
 #endif /* _EFIBOOT_LINUX_H */
5e6fc3
diff --git a/src/libefivar.map.in b/src/libefivar.map.in
5e6fc3
index 31f696d3cb5..b5ee1ce334a 100644
5e6fc3
--- a/src/libefivar.map.in
5e6fc3
+++ b/src/libefivar.map.in
5e6fc3
@@ -51,6 +51,7 @@ libefivar.so.0 {
5e6fc3
 		efidp_make_sata;
5e6fc3
 		efidp_make_scsi;
5e6fc3
 		efidp_make_vendor;
5e6fc3
+		efidp_make_emmc;
5e6fc3
 		efidp_parse_device_node;
5e6fc3
 		efidp_parse_device_path;
5e6fc3
 		efidp_set_node_data;
5e6fc3
-- 
5e6fc3
2.17.1
5e6fc3