Fill in the function that finds the GPIO base

Finds the GPIO base value to use in the GPIO number calculation.

This is most likely specific to ASPEED BMCs, though as with
the calling code additional support can be added in the
future if required.

Change-Id: Ie0d2b87286ab4bf6b05b61245bd821ab2a9d602a
Signed-off-by: Matt Spinler <spinler@us.ibm.com>
diff --git a/libopenbmc_intf/gpio.c b/libopenbmc_intf/gpio.c
index 2fe1421..a33348b 100644
--- a/libopenbmc_intf/gpio.c
+++ b/libopenbmc_intf/gpio.c
@@ -9,6 +9,7 @@
 #include <argp.h>
 #include <sys/stat.h>
 #include <sys/mman.h>
+#include <dirent.h>
 #include "openbmc_intf.h"
 #include "gpio.h"
 #include "gpio_json.h"
@@ -106,10 +107,97 @@
 	return r;
 }
 
+/**
+ * Determine the GPIO base number for the system.  It is found in
+ * the 'base' file in the /sys/class/gpio/gpiochipX/ directory where the
+ * /sys/class/gpio/gpiochipX/label file has a '1e780000.gpio' in it.
+ *
+ * Note: This method is ASPEED specific.  Could add support for
+ * additional SOCs in the future.
+ *
+ * @return int - the GPIO base number, or < 0 if not found
+ */
 int get_gpio_base()
 {
-	/* TODO */
-	return 0;
+	int gpio_base = -1;
+
+	DIR* dir = opendir(GPIO_BASE_PATH);
+	if (dir == NULL)
+	{
+		fprintf(stderr, "Unable to open directory %s\n",
+				GPIO_BASE_PATH);
+		return -1;
+	}
+
+	struct dirent* entry;
+	while ((entry = readdir(dir)) != NULL)
+	{
+		/* Look in the gpiochip<X> directories for a file called 'label' */
+		/* that contains '1e780000.gpio', then in that directory read */
+		/* the GPIO base out of the 'base' file. */
+
+		if (strncmp(entry->d_name, "gpiochip", 8) != 0)
+		{
+			continue;
+		}
+
+		gboolean is_bmc = FALSE;
+		char* label_name;
+		asprintf(&label_name, "%s/%s/label",
+				GPIO_BASE_PATH, entry->d_name);
+
+		FILE* fd = fopen(label_name, "r");
+		free(label_name);
+
+		if (!fd)
+		{
+			continue;
+		}
+
+		char label[14];
+		if (fgets(label, 14, fd) != NULL)
+		{
+			if (strcmp(label, "1e780000.gpio") == 0)
+			{
+				is_bmc = TRUE;
+			}
+		}
+		fclose(fd);
+
+		if (!is_bmc)
+		{
+			continue;
+		}
+
+		char* base_name;
+		asprintf(&base_name, "%s/%s/base",
+				GPIO_BASE_PATH, entry->d_name);
+
+		fd = fopen(base_name, "r");
+		free(base_name);
+
+		if (!fd)
+		{
+			continue;
+		}
+
+		if (fscanf(fd, "%d", &gpio_base) != 1)
+		{
+			gpio_base = -1;
+		}
+		fclose(fd);
+
+		/* We found the right file. No need to continue. */
+		break;
+	}
+	closedir(dir);
+
+	if (gpio_base == -1)
+	{
+		fprintf(stderr, "Could not find GPIO base\n");
+	}
+
+	return gpio_base;
 }
 
 /**