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

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